Commit Graph
50234 Commits
Author SHA1 Message Date
Mykola Kvach f8523357f0 docs/arm: Document GICv3 vCPU limit for host-layout domains
The number of vCPUs requested for a boot-time Arm domain is not bounded
solely by Xen's generic domain limits. For GICv3 domains using the host
memory layout, Xen can only create vCPUs whose virtual redistributor
frame is covered by redistributor MMIO regions exposed for that layout.

This can affect the hardware domain and direct-mapped domains. Document
the GICv3-specific limit in the `cpus` property description in the Arm
device-tree booting guide. Also add a generic domain-limit caveat to the
`dom0_max_vcpus` command-line documentation.

Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
2026-05-27 08:56:26 +02:00
Mykola Kvach 961cc8cc0f xen/arm: propagate vGIC vCPU init failures
The vGIC per-vCPU init callback can fail. In particular, GICv3 rejects
a vCPU when the domain's redistributor layout has no MMIO slot covering
that vCPU. However, the generic vGIC init path ignored the callback
return value, so vcpu_create() could succeed with an invalid vGICv3
per-vCPU state.

This can be reproduced on FVP Base RevC by exposing a 2 MiB GICv3
redistributor region to Dom0 and booting Xen with:

    maxcpus=1 dom0_max_vcpus=64

The host GICv3 redistributor range is:

    region 0: 0x0000002f100000 - 0x0000002f300000

With Xen's guest redistributor frame size of 128 KiB, that range covers
16 guest redistributors. vCPU16 and above have no corresponding
redistributor slot.

Before this fix, Xen detected the missing redistributors:

    d0: Unable to find a re-distributor for VCPU 16
    ...
    d0: Unable to find a re-distributor for VCPU 63

but ignored the error and continued as if the secondary vCPUs had been
created correctly. Dom0 then saw 64 possible CPUs and could hang during
secondary CPU bring-up:

    smp: Bringing up secondary CPUs ...
    d0v15: vGICR: SGI: unhandled word write ... to ICACTIVER0

Propagate the vGIC vcpu_init() error so the caller can stop creating
secondary vCPUs. With this fix, Dom0 construction reports:

    d0: Unable to find a re-distributor for VCPU 16
    Failed to allocate d0v16

and the guest continues booting with the vCPUs created before the
failure:

    smp: Brought up 1 node, 16 CPUs

Free the private IRQ rank allocated by vcpu_vgic_init() on this error
path. The caller will still run the generic vCPU creation cleanup, but
XFREE() clears the pointer so that cleanup remains idempotent.

Also fix the host-layout redistributor region count for the case where
the requested vCPU count is larger than the capacity of all host
redistributor regions. The old code always stored i + 1 after the loop.
That is correct when the loop stops inside a valid region because the
requested vCPU count is covered. If the loop exits after consuming all
hardware regions, i is already equal to the number of allocated regions,
so i + 1 records one region too many.

In the same FVP setup, that off-by-one made Xen describe host-layout
GICR state beyond the populated redistributor region list. Dom0 then
accessed the GICR MMIO window described in its device tree, but Xen could
not match the access to a valid emulated redistributor frame. During
debugging this was seen as an unexpected vGICR access followed by a
guest panic:

    d0v0: vGICR: unknown gpa read address 000000002f10ffe8
    pc : gic_iterate_rdists+0x4c/0x104
    Kernel panic - not syncing: Attempted to kill the idle task!

Keep the existing construct_domain() policy used by Dom0 and dom0less
domain construction: a failure to create a secondary vCPU stops the
secondary vCPU creation loop, but does not fail the whole domain
construction.

Fixes: ea37fd2111 ("xen/arm: split vgic driver into generic and vgic-v2 driver")
Fixes: 54ec59f6b0 ("xen/arm: vgic-v3: Don't create empty re-distributor regions")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
2026-05-27 08:54:48 +02:00
Mykola Kvach 2fca0ebcd1 xen/arm: scan CLIDR Ctype fields upwards when probing LLC
get_llc_way_size() currently scans CLIDR_EL1 Ctype fields from the
highest level downwards and stops at the first unified cache it finds.

However, CLIDR_EL1 describes the cache hierarchy from Ctype1 upwards.
Arm ARM DDI 0487J.a, D19.2.27 says that once software has seen a
Ctype value of 0b000 while reading from Ctype1 upwards, no caches
manageable by the architected set/way maintenance instructions exist at
further-out levels, and the higher Ctype fields must be ignored.

The current reverse scan can therefore select a unified cache level from
a Ctype field above the first no-cache level. Such a field is not part of
the architecturally described CLIDR/CCSIDR cache hierarchy and should not
be used for selecting the CCSIDR level.

Scan Ctype fields from L1 upwards, stop at the first no-cache level, and
keep the outermost unified cache observed before that point.

This preserves the result for regular cache hierarchies, while avoiding
selection of an architecturally ignored Ctype field.

Fixes: f4985fce6f ("xen/arm: add initial support for LLC coloring on arm64")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-27 08:53:10 +02:00
Mykola Kvach e63ba93511 xen/arm: gic-v3: Preserve ARE_NS when disabling the distributor
gicv3_dist_init() disables the distributor before reprogramming the
global interrupt state. It used to do this by writing 0 to GICD_CTLR.

On a system where firmware has already enabled Non-secure affinity
routing, a zero write clears the Non-secure view's GICD_CTLR.ARE_NS bit.
Arm IHI 0069H.b, section 2.3.3 ("Changing affinity routing enables"),
states that changing GICD_CTLR.ARE_NS from 1 to 0 is UNPREDICTABLE. The
GICD_CTLR register description in section 12.9.4 carries the same rule
for the ARE_NS field.

Preserve ARE_NS while clearing the group enable bits. If firmware left
ARE_NS clear, the value written is still 0, preserving the existing
initialization flow.

Fixes: bc183a0235 ("xen/arm: Add support for GIC v3")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-25 16:06:35 +02:00
Mykola Kvach 174381dfbc xen/common: llc-coloring: reject empty color tokens
parse_color_config() currently accepts delimiters where a color value
is expected because simple_strtoul() returns zero without advancing the
input pointer. This makes strings such as ",2-6", "-10,19-20" or
"1,,2" look as if an empty value was color 0.

Also fix the DT color parsing error message by adding the missing
newline and including the domain ID, matching the style of the color
validation error below.

Fixes: 6cdea3444e ("xen/arm: add Dom0 cache coloring support")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Denis Mukhin <dmukhin@ford.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-25 12:49:54 +02:00
Mykola Kvach 16558646c8 xen/common: llc-coloring: clear color count on parse failure
parse_color_config() updates the caller-provided color count while
parsing. If parsing later fails, leave the count at zero so callers
do not consume a partially parsed configuration.

The bug is reachable in practice: cmdline_parse() ignores the -EINVAL
from a custom_param callback, so boot continues with the partial
xen_num_colors / dom0_num_colors that llc_coloring_init() and
dom0_set_llc_colors() then consume.

Fixes: 6cdea3444e ("xen/arm: add Dom0 cache coloring support")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Denis Mukhin <dmukhin@ford.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-25 12:49:54 +02:00
Teddy Astie 03878fba4a x86/pv32: Fix bogus CR2 in pagefault for gate emulation
__{put,get}_guest() returns -EFAULT on access faults which causes
the injected CR2 to be off by 14 bytes (as EFAULT is 14) which is
incorrect.

Fix the computation by relying on __copy_{from,to}_guest_pv() which
reports the number of remaining bytes instead of a negative errno,
such that we can compute the offset properly.

Fixes: 70ad570b27 ("x86/64: paravirt 32-on-64 call gate support")
Signed-off-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2026-05-22 14:33:44 +01:00
Alejandro Vallejo c0e548d920 xen/gnttab: Fix TOCTOU race in gnttab_set_version()
Move first read of gt->gt_version inside the critical region of the
rwlock, otherwise concurrent gnttab operations (silly as they would be)
may get mutually confused as to the actual current version.

Fixes: c1488502c949("grant-tables: do not fail attempts to...")
Reported-by: Oleksandr Tyshchenko <Oleksandr_Tyshchenko@epam.com>
Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
2026-05-22 13:32:44 +02:00
Jan Beulich f04da199a9 crypto/vmac: adjust for Misra C:2012 rule 17.5
... ("The function argument corresponding to a parameter declared to have
an array type shall have an appropriate number of elements"). Instead of
casts, (ab)use unions.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 13:20:20 +02:00
Jan Beulich 7d4a266fdd x86/PV: address Misra C:2012 rule 16.2
... ("A switch label shall only be used when the most closely-enclosing
compound statement is the body of a `switch' statement"). While I don't
really like doing so, use a few "goto" instead. No change in generated
code (somewhat to my surprise).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
2026-05-22 13:19:46 +02:00
Jan Beulich 16de5ab8f6 x86/mm: address Misra C:2012 rule 16.2
... ("A switch label shall only be used when the most closely-enclosing
compound statement is the body of a `switch' statement"). Use a form of
fall-through instead. No difference in generated code, except for some
line number changes.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
2026-05-22 13:19:17 +02:00
Jan Beulich ef69700ea0 x86/shadow: rename a parameter of shadow_l<N>_index()
... shadowing a file scope one, thus violating Misra C:2012 rule 5.3
("An identifier declared in an inner scope shall not hide an identifier
declared in an outer scope").

While there,
- replace u32 by uint32_t,
- reduce the number of cf_check by aliasing shadow_l<N>_index() to
  shadow_l1_index() for N > 1 and GUEST_PAGING_LEVELS > 2.

No difference in generated code, except of course the removal of the
duplicate function instances.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
2026-05-22 13:18:38 +02:00
Jan Beulich 8c394de102 x86/shadow: conditionalize / rename local variables
... shadowing a function scope one in one case and the global _end[] in
another, thus violating Misra C:2012 rule 5.3 ("An identifier declared in
an inner scope shall not hide an identifier declared in an outer scope").
No difference in generated code.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
2026-05-22 13:18:10 +02:00
Jan Beulich aaa34f23ac x86/time: don't exclude from Eclair scanning
The justification is wrong, and the file hence shouldn't really be
excluded.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-22 12:18:00 +02:00
Jan Beulich 9c2e34b1a3 x86/time: address Misra C:2012 rule 8.3
Before we can enable scanning of time.c, it needs to be clean wrt blocking
rules. Bring boot_tsc_stamp's definition in line with its declaration. For
get_s_time_fixed() go a little farther and move it to the x86 header (the
function only exists in x86) and do, along with correcting the parameter
name, the u64 -> uint64_t a little more widely than strictly necessary.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-22 12:17:24 +02:00
Jan Beulich eff88c4d35 gnttab: simplify (really: drop) gnttab_set_frame_gfn()
It's not really doing anything for valid GFNs, which renders its one use
site pretty pointless. The other isn't so much about setting anything, but
rather about clearing.

The main point here, however, is about Rafal spotting the double
fetching of the GFN (first in gnttab_unpopulate_status_frames(), then
again in gnttab_set_frame_gfn()). Re-purpose the macro parameter to pass
in the already fetched GFN, while dropping the no longer used parameters.

As the result is a mere wrapper around guest_physmap_remove_page(), drop
the hook altogether.

Suggested-by: Rafal Wojtczuk <rafal.wojtczuk@7bulls.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-22 08:21:14 +02:00
Luca Fancellu 71f8fd5a64 tools/tests: Fix paging-mempool xen_pfn_t format strings
xen_pfn_t is not an unsigned long on all architectures. In particular,
Arm32 builds see it as a 64-bit type, so printing it with %lx triggers
a -Werror=format build failure.

Use PRI_xen_pfn for the GFN diagnostics instead.

Fixes: 66c982a5d3 ("tests/paging-mempool: Extend to test P2M relocation")
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 08:20:44 +02:00
Jan Beulich bcbef3bdbd x86/PV: split a get_unsafe() invocation
Misra C:2012 rule 13.6 takes issue with the gdt_ldt_desc_ptr() call
appearing (deep) inside sizeof(), as used by get_unsafe().

No functional change intended.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 08:19:54 +02:00
Jan Beulich 91ea85ec12 x86/P2M: split a read_atomic() invocation
Misra C:2012 rule 13.6 takes issue with pfn_to_pdx() and mfn_x() uses
(deep) inside sizeof(), as used by read_atomic(). Break out the MFN ->
struct page_info * translation.

No difference in generated code, except for a line number change.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 08:19:34 +02:00
Jan Beulich 6621fa6708 x86/shadow: avoid sizeof(this_cpu(...))
Misra C:2012 rule 13.6 takes issue with RELOC_HIDE() uses inside sizeof(),
as used by this_cpu(). Latch the address of the per-CPU variable into a
local variable, and use that in the two sizeof().

No difference in generated code for 2- and 4-level code. There's a small
improvement for the 3-level case.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 08:19:00 +02:00
Jan Beulich f71a3e1d3c x86/shadow: split get_unsafe() invocations
Misra C:2012 rule 13.6 takes issue with is_hvm_vcpu() uses (deep) inside
sizeof(), as used by get_unsafe(). While sh_linear_l1_table() doesn't
involve is_hvm_vcpu(), the rule there kicks in for "call to function
`__builtin_expect(long, long)' (unevaluated `nothrow' call effect)".
Break out the address calculations.

This, overall, turns out to also improve generated code (with gcc15 at
least). No functional change intended.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 08:18:38 +02:00
Jan Beulich 1615934e29 CI: collect certain intermediate files as artifacts (part 2)
Build issues may also surface for analysis jobs. Collect intermediate
files (if any) there as well. Include xen/.config too, since it's not
otherwise collected.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
2026-05-22 08:17:34 +02:00
Jan Beulich 35de7285d5 Arm: do a 4th linking pass if necessary
The .rodata growth between 1st and 2nd linking passes may affect the
number of stubs the linker wants to insert, which in turn affects the
number of symbols. If symbol table sizes change after the 2nd linking
pass, insert another one before the final one. (As a comment in Linux puts
it, "In theory it's possible this results in even more stubs, but
unlikely.")

To use the $(compare-symbol-tables) macro in a shell "if", it needs
slightly adjusting (and then wrapping to be run in a sub-shell).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Acked-by: Bertrand Marquis <bertrand.marquis@arm.com>
2026-05-22 08:16:25 +02:00
Jan Beulich b74e973b96 x86: strip debug info for intermediate linking steps
Linking debug info takes time, especially for xen.efi. At the same time
symbol table contents aren't affected by presence / absence of debug info
in the linked binaries (the ELF and COFF symbol tables would have extra
section symbols, but tools/symbols omits those anyway).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-22 08:15:55 +02:00
Oleksii Moisieiev 8969e435d4 xen/sched: rtds: assert replq is empty on timer (re-)init
In RTDS, removing the last eligible pCPU kills repl_timer. When a pCPU
is later re-added, rt_switch_sched() reinitializes the timer object.

cpupool_unassign_cpu_start() refuses to remove the last pCPU from a
populated cpupool: if any domain is still alive while the system is
active it returns -EBUSY, otherwise all domains are first moved to
cpupool0. Consequently, by the time the killed-timer branch runs, no
units remain in the pool and replq is guaranteed to be empty.

Document this invariant by asserting list_empty(replq) right after
init_timer(). This catches any future regression in cpupool semantics
that would leave pending replenishment events behind across a
TIMER_STATUS_killed -> init_timer() transition, where the timer would
otherwise stay disarmed until an unrelated event reprogrammed it.

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-22 08:14:48 +02:00
Oleksii Moisieiev 410d44fcf3 xen/sched: rtds: prevent extratime priority_level wraparound
In RTDS, burn_budget() increments priority_level for extratime units
whenever cur_budget is exhausted. As priority_level is unsigned and was
unbounded, it could eventually overflow to 0.

A wrapped value of 0 is the highest RTDS priority, so an extratime unit
could unexpectedly regain top priority and preempt units with active
real-time reservations, violating EDF intent.

Fix this by saturating priority_level at RTDS_MAX_PRIORITY_LEVEL instead
of incrementing unconditionally. Budget refill semantics are unchanged.

Normal behavior is unchanged. Once saturated, priority_level remains at
the lowest priority until the next period update resets it.

Fixes: 463b958317 (xen:rtds: towards work conserving RTDS)
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-22 08:13:59 +02:00
Abdelkareem Abdelsaamad 86a203ab8d x86/svm: Support vNMI on capable hardware
Starting with Zen4, AMD CPUs can virtualise NMIs for a guest.  On older
hardware, determining when an NMI is safe to deliver is a challenge and Xen
does not handle all corner cases correctly.

With vNMI, there is an enablement bit and two new bits of state in the VMCB; a
pending bit, and a blocked bit.  These directly map to the CPU state for
handling NMIs, and are maintained by hardware during the running of the vCPU.

When vNMI is enabled, have svm_{get,set}_interrupt_shadow() work in terms of
the vnmi_blocking bit rather than the IRET intercept.  This allows an emulated
IRET instruction to re-enable NMIs.

When injecting a new NMI, simply set the vnmi_pending bit; hardware will
deliver the NMI to the guest at the next suitable juncture.

One complication is that, when delivering a second NMI before the first has
completed, the mix between common HVM logic and SVM specific logic will try to
open an NMI window, malfunctioning as it does so.  When vNMI is enabled, short
circuit this to not consider NMIs blocked.

Signed-off-by: Abdelkareem Abdelsaamad <abdelkareem.abdelsaamad@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-21 16:43:01 +01:00
Andrew Cooper 614825f0d0 x86/time: Drop unused parameter from soft_rdtsc()
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-21 16:43:01 +01:00
Teddy Astie f47c2e96ab docs: Update console=pv requirement
PV console doesn't require Xen to be running as a shim and only
requires CONFIG_XEN_GUEST and running as a Xen guest. Update the
documentation accordingly.

Fixes: 4f6609d6a6 ("x86/guest: use PV console for Xen/Dom0 I/O")
Signed-off-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
2026-05-21 09:13:42 +02:00
Mykyta Poturai 9ae6772f13 tools: Fix helpers build
Init helpers sometimes fail to rebuild after switching branches,
which results in runtime faults.

Fix this by adding missing DEPS_INCLUDE to the Makefile.

Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
Reviewed-by: Denis Mukhin <dmukhin@ford.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
2026-05-21 09:13:27 +02:00
Juergen Gross cdbcfd5d05 tools/xenstored: remove permissions related to dead domain
With unprivileged domains now capable to use the @releaseDomain watch,
there is no reason not to remove any node permissions which relate to
a domain which has been removed.

This resolves a complex scenario where a new domain could inherit the
permissions of an old one with the same domid.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-21 09:13:05 +02:00
Juergen Gross 258263a4fb tools/xenstored: allow @releaseDomain watch for all domains
Currently the @releaseDomain watch is allowed for dom0 only. This is
problematic for guests which want to give other domains access to
Xenstore entries, as they have no simple way to tell when such a
domain is stopped.

Allow @releaseDomain to be usable by all domains as the default.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-21 09:13:00 +02:00
Juergen Gross 42aeed3b53 tools/xenstored: add support for "all domains" node permission
Add support for using DOMID_ANY in node permissions to indicate that
all domains are allowed to access the node.

Add a new feature bit for indicating the support of DOMID_ANY.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-21 09:12:54 +02:00
Jan Beulich 1146b4f524 x86/shadow: reduce flush_tlb's scope in shadow_track_dirty_vram()
It's set only in the main "else", so the declaration as well as the sole
consumer can also move into that more narrow scope. This may in particular
help with possible future locking changes.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
2026-05-21 09:11:33 +02:00
Jan Beulich 2965f75ebd x86/shadow: VRAM last_dirty tagging
->last_dirty holding a valid value (one other than -1) is solely an
indication of the bitmap being entirely clean. (The opposite isn't true,
because of _sh_propagate() setting the field to a valid value without
setting a bit in the bitmap.) As a consequence
- setting the field to a valid value right after having allocated zero-
  filled space is pointless,
- copying the all empty bitmap to the output array is pointless; with the
  output array also having been allocated zero-filled, not even a memset()
  is needed there,
- after restoring bitmap contents when dealing with copy_to_guest() having
  failed, the field needs setting to a valid value again.

Furthermore invoking NOW() in perhaps many loop iterations of the main
loop is wasteful, too. Record whether any bit was set, and record a new
->last_dirty only once, after the loop. Then use the same NOW() value also
for the subsequent check.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
2026-05-21 09:10:58 +02:00
Mykola Kvach d86cf3cbd4 xen/arm: gic-v3: Wait for redistributor RWP using the right bit
gicv3_do_wait_for_rwp() is used for both distributor and
redistributor writes. The CTLR register is at offset 0 for both,
but the RWP bit is not in the same position.

For GICD_CTLR, RWP is bit 31. For GICR_CTLR, bit 31 is UWP,
while RWP is bit 3. The redistributor wait path was therefore
polling UWP instead of RWP.

UWP covers upstream writes, including Generate SGI packets, and is
not a substitute for redistributor register write completion. The
existing redistributor callers need RWP semantics for redistributor
register writes such as GICR_ICENABLER0 and GICR_CTLR updates.

Add GICR_CTLR_RWP and pass the expected RWP bit to the shared
helper.

Fixes: bc183a0235 ("xen/arm: Add support for GIC v3")
Reported-by: Luca Fancellu <luca.fancellu@arm.com>
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
2026-05-19 22:30:35 -05:00
Mykola Kvach 98bea5e531 arm/gicv3: Detect normal NC ITS command queues
GITS_CBASER.InnerCache uses the GIC BASER cacheability encoding.
Both 0b000 (Device-nGnRnE) and 0b001 (Normal Inner
Non-cacheable) describe non-cacheable accesses to the command queue.

its_map_cbaser() only checked whether the shifted field was zero,
so an ITS that reports Normal Inner Non-cacheable would not set
HOST_ITS_FLUSH_CMD_QUEUE. Decode the field before comparing it with
the unshifted enum value, matching the handling of ITS BASER tables
and GICR_PROPBASER.

Fixes: 8ed8d21373 ("ARM: GICv3 ITS: map ITS command buffer")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
2026-05-19 22:30:00 -05:00
Denis Mukhin 23e2479ff9 xen/domain: introduce DOMID_ANY
Add a new symbol DOMID_ANY to improve the readability of the code.

Update all relevant domid_alloc() call sites and harden the domid_alloc()
input value check.

Also, fix problem with passing invalid domain IDs in
XEN_DOMCTL_createdomain: turns out libxl__domain_make() (toolstack)
uses 0xffff as domain ID.

Fix failing tools tests too.

Amends: 2d50650607 ("xen/domain: unify domain ID allocation")
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
2026-05-19 22:29:10 -05:00
Baptiste Le Duc a472f640dd xen/riscv: Fix SSTC init to write VSTIMECMP instead of STIMECMP
According to the preceeding comment, CSR_VSTIMECMP should be written rather
than CSR_STIMECMP.

Fixes: 25e0327306 ("xen/riscv: allow Xen to use SSTC while hiding it from guests")
Signed-off-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Reviewed-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-05-19 22:29:31 +01:00
Andrew Cooper 2b51691c8c xen/vmac: Delete STDINT block in vmac.h
Eclair reports that _MSC_VER is undefined, a MISRA Rule 20.9 violation.

This could be fixed by inserting an "&& defined(_MSC_VER)" clause, but the
whole block is entirely useless (it comments out the include of stdint) and
users pull in xen/types.h transitively.

Delete the whole block, and include xen/types.h to make it standalone.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 22:29:31 +01:00
Jan Beulich d6fb54fa71 x86/shim: annotate for Misra C:2012 rule 20.12
... ("A macro parameter used as an operand to the `#' or `##' operators,
which is itself subject to further macro replacement, shall only be used
as an operand to these operators"). Leverage the SAF-6 annotation we have
available.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
2026-05-19 10:59:46 +02:00
Jan Beulich 5e1f756fb7 x86/MCE: adjust ID2COOKIE() for Misra C:2012 rule 11.2
... ("Conversions shall not be performed between a pointer to an
incomplete type and any other type"): Add an intermediate cast to void *.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
2026-05-19 10:59:46 +02:00
Oleksii Kurochko f2c7c9004a xen/riscv: enable DOMAIN_BUILD_HELPERS
Everything is ready to enable DOMAIN_BUILD_HELPER which are necessary
for dom0less common code. So enable it.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 09:32:57 +02:00
Oleksii Kurochko 157b67ca64 xen/riscv: add definition of guest RAM banks
The dom0less solution uses defined RAM banks as compile-time constants,
so introduce macros to describe guest RAM banks.

The reason for 2 banks is that there is typically always a use case for
low memory under 4 GB, but the bank under 4 GB ends up being small because
there are other things under 4 GB it can conflict with (interrupt
controller, PCI BARs, etc.). So a second bank is added above that MMIO
region (starting at 8 GiB) to provide the remaining RAM; the gap between
the two banks also exercises code paths handling discontiguous memory.
For Sv32 guests (34-bit GPA, 16 GiB addressable), bank0 provides 2 GB
(2–4 GB) and the first 8 GB of bank1 (8–16 GB) is accessible.

Extended regions are useful for RISC-V: they could be used to provide a
"space" for Linux to map grant mappings.

Despite the fact that for every guest MMU mode the GPA could be up
to 56 bits wide (except Sv32 whose GPA is 34 bits), the combined size
of both banks is limited to 1018 GB as it is more than enough for most
use cases.

Add inclusion of asm/guest-layout.h to asm/domain.h to make dom0less
common code build happy.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 09:32:44 +02:00
Oleksii Kurochko 7fe5505481 xen/riscv: introduce p2m_gpa_bits
common/device-tree/domain-build.c uses p2m_gpa_bits to determine the
upper bound of the GPA space when searching for unused regions, so it
must be defined when CONFIG_DOMAIN_BUILD_HELPERS=y.

The variable is initialised to PADDR_BITS and narrowed in p2m_init() to
the GPA width of the selected G-stage mode, allowing an external entity
(e.g. an IOMMU) to restrict it further if needed.

p2m_gpa_bits is a global rather than a per-domain value, which is
acceptable for now because all domains are required to use the same
G-stage MMU mode, as dom0less common code allocates it per all
domains.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 09:32:27 +02:00
Oleksii Kurochko 551e864360 xen/riscv: rework G-stage mode handling
Rework G-stage mode handling to make the selected mode descriptor
reusable outside of p2m initialization, both for filling CPU nodes in
the device tree passed to dom0less guests and for per-domain G-stage
mode selection at domain creation time.

Promote gstage_modes[] from a local __initconst variable inside
gstage_mode_detect() to a file-scope static const array, and convert
max_gstage_mode from an embedded struct (assigned by value) to a global
const pointer into gstage_modes[]. This allows referencing both the mode
identifier and the mode name after init without copying the descriptor.
Remove get_max_supported_mode(); its callers now dereference
max_gstage_mode->mode directly.

Change struct p2m_domain::mode from an embedded gstage_mode_desc to a
const pointer into gstage_modes[], so each domain shares the descriptor
rather than carrying its own copy.

Adjust the gstage_modes[] entries in three ways:
 - Use lowercase names without the "x4" suffix (e.g. "sv39" instead of
   "Sv39x4"). The DT mmu-type binding [1] does not include the suffix,
   so the name can now be passed directly to the guest without
   transformation. The suffix is appended only in the diagnostic
   printk, where it remains informative.
 - Use "none" for Bare mode (HGATP_MODE_OFF) to match the DT binding.
 - Change paging_levels to represent the root page-table level index
   (i.e. total paging levels minus one) rather than the total count.
   P2M_ROOT_LEVEL() now returns the correct VPN index directly, without
   requiring callers to subtract one or use hardcoded offsets.

Add gstage_mode to xen_arch_domainconfig so the toolstack can
request a specific G-stage mode at domain creation time. Introduce
find_gstage_mode() to resolve a mode descriptor by HGATP_MODE_*,
capping the result at max_gstage_mode to prevent requesting a mode
the hardware does not support. Update p2m_init() to accept a
xen_domctl_createdomain pointer and call find_gstage_mode()
instead of hardcoding Sv39x4.

Add arch_parse_dom0less_node() in a new dom0less-build.c to read the
"mmu-type" DT property from a guest domain node and store it in
boot_domain::create_cfg.arch.gstage_mode, falling back to maximum
supported mode when the property is absent.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/riscv/cpus.yaml?h=v6.19-rc3#n82

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 09:32:15 +02:00
Oleksii Kurochko f6a20eda92 xen/riscv: add Linux kernel loading support
Introduce support for loading a Linux kernel Image which is got by
uncompressing of Image.gz on RISC-V.

kernel_image_load() and place_modules() currently call panic() on
failure rather than returning an error. This is because the common
kernel_load() in common/device-tree/kernel.c does not expect a
return code. Handling errors gracefully would require a separate
refactor.

The implementation is based on the Xen Arm kernel loading code.

text_offset is available for both 32-bit and 64-bit Image, so fix
that.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 09:32:02 +02:00
Oleksii Kurochko e74b6fc473 xen/riscv: implement copy_to_guest_phys()
Introduce copy_to_guest_phys() for RISC-V, based on the Arm implementation.

Add a generic copy_guest() helper for copying to and from guest physical
(and potentially virtual addresses in the future), and implement
translate_get_page() to translate a guest physical address into a struct
page_info via the domain p2m.

Compared to the Arm code:
- Drop COPY_flush_dcache(), as no such use cases exist on RISC-V.
- Do not implement the linear mapping case, which is currently unused.
- Use PAGE_OFFSET() to initialize the local offset variable in copy_guest().

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
2026-05-19 09:31:32 +02:00
Jan Beulich 6d2fa82c26 x86: address Misra C:2012 rule 8.4
... ("A compatible declaration shall be visible when an object or function
with external linkage is defined"). Three variables lack asmlinkage
annotations.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
2026-05-18 09:02:32 +02:00
Jan Beulich fa2544bbe4 x86/shadow: deviate guest_va_t wrt Misra C:2012 rule 5.6
... ("A `typedef' name shall be a unique identifier"). Much like already
done for guest_intpte_t and guest_l[12]e_t, but limited to shadow/multi.c.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
2026-05-18 09:01:56 +02:00