Commit Graph
49634 Commits
Author SHA1 Message Date
Jan Beulich 060c68ab1d gnttab: cope with version changes racing other operations
Dropping and re-acquiring the grant table lock for a particular operation
requires special care, as in the meantime the grant table version can
change.

During a v2 -> v1 change, status frames going away means that pre-
calculated status pointers go stale, referencing freed (and possibly
already re-used) memory. Record in-flight v2 operations, permitting the
version change only when there are none of them. Recalculate "status" in
the one place (map_grant_ref()'s error path) where it could be stale, but
confine this to reserved entries.

This is CVE-2026-62436.

Reported-by: Mark Esler <mark@hexproof.dev>

During a v1 -> v2 change, the number of shared table entries reduces,
meaning that previously validated grant references may now be out of
bounds. Because of the checking of pin counts in gnttab_set_version()
(with the grant table lock held for writing), for now-out-of-bounds gref-s
neither active mappings can exist, nor can there be in-progress copy
operations. Nevertheless bounds checks are added there, just to be on the
safe side.

For gnttab_transfer(), to cover the gap between the lock being dropped by
gnttab_prepare_for_transfer() and it being re-acquired, have the helper
return the version it found, and fail the operation if the version turns
out to have changed after re-acquiring the lock.

Further avoid needless use of shared_entry_header(), as it involves
pointer arithmetic which, when using an out-of-bounds ref, is UB.

This is CVE-2026-62435.

Everything together is XSA-501.

Fixes: a98dc13703 ("Introduce a grant_entry_v2 structure")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Tested-by: Mark Esler <mark@hexproof.dev>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
(cherry picked from commit 96dfeb4177)
2026-07-28 13:07:36 +01:00
Jan Beulich 14558d435f gnttab: check values against active entry when copying an already-pinned one
acquire_grant_for_copy() passes to its caller both an MFN and a struct
page_info *. The two really need to be in sync for the get_page()
underlying get_paged_frame() and get_page_type() (both acting on the
passed back struct page_info *) and the map_domain_page() (acting on the
passed back MFN) to achieve the intended effect.

Go further and also check other properties: GTF_transitive / GTF_sub_page
may have been flipped in the shared entry, so respective fields / values
also may not match.

The one field which we can be sure does match (as it was checked earlier
in the function) is ->domid. Add an assertion nevertheless.

This is CVE-2026-62428 / XSA-500.

Fixes: d8cbecb1ee ("grant-tables: Use get_page_from_gfn() instead of get_gfn()/put_gfn")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
(cherry picked from commit 61b0a59ce2)
2026-07-28 13:07:36 +01:00
Jan Beulich 853343502a sysctl/XSM: drop .page_offline() hook
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 299de2aeda)
2026-07-28 13:07:36 +01:00
Jan Beulich c957b9a21b sysctl/XSM: drop .resource_{,un}plug_core() hooks
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask. Note that these were x86-
only, i.e. some dead/unreachable code gets eliminated for (in particular)
Arm.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 0501e1dc04)
2026-07-28 13:07:36 +01:00
Jan Beulich 53d73787d8 sysctl/XSM: drop .readconsole() hook
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 4b249cba4b)
2026-07-28 13:07:36 +01:00
Jan Beulich 1ef3886a18 sysctl/Flask: add preliminary check for XEN_SYSCTL_getdomaininfolist
To shield the sysctl lock from abuse by unauthorized domains, follow what
5154fdda11 ("domctl: protect locking for get_domain_state") did: Check
for permission to issue the operation against DOM_XEN in flask_sysctl().
The finer-grained xsm_getdomaininfo() later in the handling of the sub-op
remains unaltered.

In the in-tree policy respective permission therefore needs granting.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 3179bf2931)
2026-07-28 13:07:36 +01:00
Jan Beulich 2881e008a7 sysctl/XSM: drop .scheduler_op() hook
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 751e371c91)
2026-07-28 13:07:36 +01:00
Jan Beulich 36a22b6145 sysctl/XSM: pass full struct xen_sysctl to xsm_sysctl()
Subsequently some sub-ops will want to inspect their sub-sub-ops.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 9f4aa6d00a)
2026-07-28 13:07:36 +01:00
Jan Beulich 42d062839d platform-op/XSM: move resource-{,un}plug-core checks
Integrate the checking with flask_platform_op(); there never really was a
need to defer these checks, as the sub-op has always been known to the
function. As a positive side effect, permissions are then checked at the
same early point with and without Flask.

This is CVE-2026-62427 / part of XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 4ef45cbe31)
2026-07-28 13:07:36 +01:00
Syed Abdul Khaliq 4b52dc2021 libfsimage/iso9660: harden Rock Ridge SUSP parsing against malformed lengths
The directory and Rock Ridge / SUSP walk in iso9660_dir() derives several
lengths directly from attacker-controlled on-disk fields without validating
them.  libfsimage is used by pygrub, which parses the filesystem of an
untrusted guest disk image from dom0, so these are reachable across a trust
boundary.

Five related problems are addressed:

  * The directory record loop advances by

        idr = (char *)idr + idr->length.l

    and only stops on length.l == 0.  A record whose length is smaller than
    the fixed part of the on-disk layout cannot hold its own mandatory
    fields, yet the body still reads name_len/extent/size and computes the
    System Use area length from it.  Require length to cover at least the
    fixed record (sizeof(*idr) - sizeof(idr->name)) before entering the body.

    This is CVE-2026-42494.

  * The System Use area length is computed before the inner loop as

        rr_len = idr->length.l - idr->name_len.l
                 - sizeof(struct iso_directory_record) + sizeof(idr->name);

    in unsigned arithmetic.  If length.l is smaller than name_len.l plus the
    fixed record size, rr_len underflows to a huge value and the whole SUSP
    walk runs off the directory buffer.  Guard the subtraction and treat such
    records as having no System Use area.

    This is CVE-2026-42495.

  * Inside the loop, each entry is consumed with

        rr_len -= rr_ptr.rr->len;
        rr_ptr.ptr += rr_ptr.rr->len;

    with no lower or upper bound on the entry's own len byte.  A len of 0
    spins forever; a len greater than the remaining rr_len underflows it and
    walks past the buffer.  Validate 4 <= len <= rr_len at the top of the
    loop and stop on violation: a structurally broken entry stream cannot be
    advanced reliably, so continuing is not meaningful.

    This is CVE-2026-62423.

  * The NM handler subtracted the 5-byte SUSP/NM header from len without a
    lower-bound check, underflowing name_len (the original report).  The
    generic check above only guarantees len >= 4; NM has an extra flags byte,
    so keep an NM-specific len >= 5 check.

    This is CVE-2026-62424.

  * The CE continuation resets rr_ptr/rr_len from ce.offset and ce.size, both
    image-controlled, into the fixed single-sector RRCONT_BUF with no bounds
    check.  Reject a window that does not fit in the buffer.

    This is CVE-2026-62425.

This is XSA-497.

Signed-off-by: Syed Abdul Khaliq <abdul@bugqore.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit fd11acab3d)
2026-07-28 13:07:36 +01:00
Grygorii Strashko d836145598 evtchn: evtchn_bind_virq() error path unconditionally calls domain_deinit_states()
There is a corner case in the error path of evtchn_bind_virq() (handling
EVTCHNOP_bind_virq hypercall) which allows unprivileged domains to
interfere with privileged ones: If an unprivileged domain allocates all
available ports to reach "no more ports available" and then issues an
EVTCHNOP_bind_virq hypercall to bind any allowed VIRQ (e.g. VIRQ_DEBUG),
domain_deinit_states() will be called despite not having called
domain_init_states().

To fix the issue move domain_deinit_states(d) under the same condition as
used for the domain_init_states() call.

This is CVE-2026-42492 / XSA-496.

Fixes: f94360a7fe ("xen: add bitmap to indicate per-domain state changes")
Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
(cherry picked from commit 40c59b6c29)
2026-07-28 13:07:36 +01:00
Jan Beulich 49af80b3e0 x86: SHADOW_PAGING is deprecated
Addressing certain issues, in particular related to operations which may
take excessively long and therefore would need preemption, has turned out
overly costly. Since alternatives (HVM/PVH: HAP, PV: shim) are commonly
available, the decision was to deprecate the functionality, while still
retaining it for people to use at their own (security) risk. Memory-wise
small enough guests may still be okay to run.

Some CI testing depends on SHADOW_PAGING.  Explicitly enable it when needed.

This is CVE-2026-42493 / XSA-495.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
(cherry picked from commit f2cac32029)
2026-07-28 13:07:36 +01:00
Oleksandr Tyshchenko ade0c35777 xen/arm: Reject pseudo-domain foreign mappings in xenmem_add_to_physmap_one()
A privileged domain on Arm64 can trigger a data abort in the hypervisor
by issuing memory_op's XENMEM_add_to_physmap_batch sub-op with
space=XENMAPSPACE_gmfn_foreign, idx=0 and foreign_domid=DOMID_IO.

get_pg_owner(DOMID_IO) succeeds, returning a pointer to the dom_io
pseudo-domain. The subsequent get_page_from_gfn(dom_io, ...) then
attempts to walk dom_io's P2M table, which is not initialized for
pseudo-domains, resulting in a data abort in p2m_get_entry() when
it dereferences the invalid pointer returned by p2m_get_root_pointer().

Replace get_pg_owner() with explicit domain lookup logic matching
the x86 implementation: handle DOMID_XEN via rcu_lock_domain(dom_xen),
and resolve all other domain IDs via rcu_lock_remote_domain_by_id(),
which rejects pseudo-domains (DOMID_IO, etc.) that are not present in
the domain hash, returning -ESRCH before any P2M access occurs.

Fixes: 615897bc6c ("xen/arm: Allow a privileged domain to map foreign page from DOMID_XEN")
Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit f795a9c491)
2026-07-23 14:19:48 +02:00
Marek Marczykowski-Górecki d5ad2233bb x86/domctl: restore all registers in arch_{get,set}_info_guest()
Commit 9f892f84c2 ("x86/domctl: Stop using XLAT_cpu_user_regs()")
converted memcpy() of the cpu_user_regs structure to explicit copy of
its fields. In the compat case, it intentionally missed few of them,
named in the commit message. But the 64bit case missed also r8-r15
registers, which was not intentional. This, at least, caused Linux
6.18.x crash when resuming PVH domU.

Fix it by adding missing assignments.

Fixes: 9f892f84c2 ("x86/domctl: Stop using XLAT_cpu_user_regs()")
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
master commit: bedbc17d84
master date: 2026-07-20 11:11:37 +0200
2026-07-20 13:30:52 +02:00
Jan Beulich 7c27efebfc x86emul: V{,P}{COMPRESS,EXPAND}* can (wrongly) trigger assertion
AFL has pointed out that the op_bytes-is-not-0 assertion in common SIMD
handling can trigger for these insns. Indeed when the (relevant part of)
the controlling mask register is 0, no memory is accessed at all. Leave
op_bytes unaltered in this case, to engage the short-circuiting in common
SIMD handling when fault_suppression is true and op_bytes is 0.

While there also correct a related typo in the test harness.

Fixes: 65f82d4ce1 ("x86emul: support AVX512{F,_VBMI2} compress/expand insns")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: cf90c8a48a
master date: 2026-07-20 09:50:00 +0200
2026-07-20 13:30:29 +02:00
Andrew Cooper 16b79fbf28 x86/pv: Only use the guest frame in pv_map_ldt_shadow_page()
pv_map_ldt_shadow_page() takes the whole guest PTE, adds _PAGE_RW to it, then
installs it into Xen's pagetables.  It has had this behaviour ever since LDT
support was added in 2003.

However, it allows the guest to control the software available bits and
cacheability.  This happens to be benign right now, but is bad form.

Use only the guest frame, and construct the mapping as regular RW frame, and
notably includes NX.  This is how the GDT logic already works.

Fixes: 005c272397 ("Finished virtualisation of x86 LDT")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 1cc1f4d7a0
master date: 2026-07-14 17:31:08 +0100
2026-07-20 13:30:07 +02:00
Andrew Cooper 5dd8f03f8f x86/emul: Adjust handling of CR8_LEGACY
The APM description of the AltMovCR8 feature bit is:

  "LOCK MOV CR0 means MOV CR8"

Adjust the decode logic to behave like this.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
master commit: 7d48ef45b6
master date: 2026-07-10 19:35:49 +0100
2026-07-20 13:29:39 +02:00
Roger Pau Monné 94fa7e1626 xen/numa: fix setup of non-aligned memory affinity ranges
The logic to populate memnodemap in populate_memnodemap() assumes that all
ranges are aligned to the hash shift, this however is only true for the
first address in a memory affinity node.  Any subsequent ranges belonging
to the same node might not be aligned to the hash shift value.

Such lack of alignment causes issues to the logic in populate_memnodemap(),
as then the tail of the range might not be properly accounted for and setup
in memnodemap.  Fix this by forcing the start address of all regions to
be aligned to the hash shift; if such alignment causes a region overlap it
would always be between regions on the same node, and hence will never
cause setup issues of the memnodemap array.

Fixes: 1666086b00 ("x86/NUMA: improve memnode_shift calculation for multi node system")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: 188d530529
master date: 2026-06-05 19:13:47 +0200
2026-07-20 13:29:16 +02:00
Dmytro Prokopchuk1 137827d858 dom0less: Prevent division by zero in handle_passthrough_prop()
A malformed partial DTB specifying both '#address-cells = <0>' and
'#size-cells = <0>' causes '(address_cells * 2 + size_cells)' to
evaluate to 0. This sum is subsequently used as a divisor when
calculating the number of regions in the 'xen,reg' property inside
handle_passthrough_prop():

    len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) *
                                        sizeof(uint32_t));

This leads to a division by zero exception in the Xen hypervisor during
boot, causing a hypervisor panic/crash.

Fix this by validating that both 'address_cells' and 'size_cells'
are within the range of [1, 2] at the top of handle_passthrough_prop().
Any invalid cell size combination is safely rejected early with an error
message and return -EINVAL.

Furthermore, update handle_passthrough_prop() to use the sizeof(*cell)
instead of sizeof(uint32_t).

Fixes: 9ce974c475 ("xen/arm: assign devices to boot domains")
Signed-off-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit b83e1d9a1a)
2026-07-15 09:50:49 +02:00
Michal Orzel f26f5e8352 xen/arm: Fail domain construction if a secondary vCPU cannot be created
construct_domain() creates the secondary vCPUs in a loop, but on a
vcpu_create() failure it only prints a message and breaks out of the
loop returning success. As a result the domain can be partially
constructed with fewer vCPUs than d->max_vcpus. This causes two contract
violations:
 - Xen-Guest: domain's FDT is generated before vCPU creation - Xen exposes
   incorrect information (e.g. two vCPUs listed in a device tree while only
   one is actually created),
 - User-Xen: unlike x86, on Arm port we try to bail out as soon as
   possible on unsatisfied user requests (e.g. user requested two vCPUs
   for a domain but it was created with only one).

Return an error instead of breaking out of the loop. Both callers
(construct_domU() and construct_hwdom()) already propagate a negative
return value and fail domain construction.

Fixes: 6b0e8e4334 ("xen/arm: allocate secondaries dom0 vcpus")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
(cherry picked from commit e3aa330017)
2026-07-15 09:50:16 +02:00
Hirokazu Takahashi f53ec9edb6 xen/arm: fix sparse cpu_possible_map calculation on SMP boot
Currently, during ARM Xen's SMP initialization, if there is
a Device Tree error (such as an invalid 'enable-method'),
cpu_possible_map can end up being sparse.

The issue here is that nr_cpu_ids is calculated in a way that
doesn't properly account for the maximum CPU ID when the map is
sparse, causing a mismatch. For example, if cpu_possible_map is
0xff0f, nr_cpu_ids becomes 12, but the actual maximum CPU ID
is 15. Xen's common code is built on the assumption that
'CPU ID < nr_cpu_ids', so this mismatch can break things.

To fix this, modify dt_smp_init_cpus() so that if the
arch_cpu_init() call fails, we don't consume the CPU ID slot.

Fixes: 4557c22928 ("xen: arm: rewrite start of day page table and cpu bring up")
Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
(cherry picked from commit ccde3773c1)
2026-07-15 09:46:50 +02:00
Dmytro Prokopchuk1 a455b73ddb bootfdt: Fix infinite loop in device_tree_for_each_node()
When a node's depth exceeds DEVICE_TREE_MAX_DEPTH inside the
device_tree_for_each_node() loop, the code prints a warning and
executes 'continue;' statement, which jumps to condition check,
bypassing the iterator update step:

    node = fdt_next_node(fdt, node, &depth).

The node and depth are not updated, the loop repeatedly evaluates
the same too-deep node, causing a hang.

Fix this by wrapping the node processing logic in an 'else' block.
This ensures the loop update step is executed on every iteration,
safely skipping deeply nested nodes and doing the traversal.

Fixes: 40f2ea3df2 ("xen/arm: pass node to device_tree_for_each_node")
Signed-off-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleskii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit 3b717f57dc)
2026-07-15 09:46:50 +02:00
Oleksii Kurochko 60fc5ccb81 libfdt: fix UBSAN null pointer in fdt_property()
fdt_property() unconditionally calls memcpy(ptr, val, len) even when
len is zero and val is NULL.  This is a legitimate calling convention
for adding empty FDT properties such as "interrupt-controller", which
carry no payload.

However, compilers that treat memcpy as nonnull on its pointer arguments
will fire UBSAN before observing that len is zero.

Guard the memcpy() with a check on len so it is skipped entirely when
there is no payload to copy, bringing the code in line with the
nonnull contract.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Origin: git://git.kernel.org/pub/scm/utils/dtc/dtc.git f57e7df35df4

Fixes: f0ea065580 ("libfdt: add version 1.3.0")
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit be18ad502e)
2026-07-15 09:46:50 +02:00
Luca Fancellu 530406cf21 xen/arm: gic-v3: Fix redistributor wakeup polling
gicv3_enable_redist() clears GICR_WAKER.ProcessorSleep and then waits for
GICR_WAKER.ChildrenAsleep to clear, as required after waking a
redistributor.

However, the polling loop currently uses "while ( timeout )". Since
timeout is initially false, the loop runs only once unless the timeout
path has already been reached. As a result, Xen can continue before the
redistributor has completed wakeup.

Use an unconditional loop, matching the surrounding timeout/break pattern,
so the code polls until either ChildrenAsleep is clear or the deadline is
reached.

While there, also fix the timeout message. This path polls
GICR_WAKER.ChildrenAsleep, not an RWP bit, so "RWP timeout" is misleading.

Fixes: bc183a0235 ("xen/arm: Add support for GIC v3")
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit 941fdfc03e)
2026-07-15 09:46:50 +02:00
Mykola Kvach 3322c7355b 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>
(cherry picked from commit 961cc8cc0f)
2026-07-15 09:46:50 +02:00
Mykola Kvach 20c5792dc9 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>
(cherry picked from commit e63ba93511)
2026-07-15 09:46:50 +02:00
Mykola Kvach 08156620f1 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>
(cherry picked from commit d86cf3cbd4)
2026-07-15 09:46:50 +02:00
Oleksii Kurochko f593155e7c xen: arm: fix len type for guest copy functions
Widen the len argument of copy_to_guest_phys_flush_dcache() and the
copy_to_guest_phys_cb typedef from unsigned int to unsigned long, as
the function can be used to copy large blobs such as the initrd which
may exceed 4GB. Update the internal copy_guest() len argument to
unsigned long accordingly.

Change the type for local variable size in copy_guest() to avoid
compilation error because of type mismatch.

raw_* wrappers above copy_guest() keep returning unsigned long to
avoid type narrowing; it is not an issue for raw_*'s len argument
to remain 'unsigned int' since the assignment to copy_guest()'s wider
unsigned long parameter is safe and there is no raw_* users who
are using a value bigger than what can fit into 'unsigned int'.

Fixes: 2986481b3d ("xen/arm: guest_copy: Extend the prototype to pass the vCPU")
Fixes: 5302bd490b ("xen/arm: Introduce copy_to_guest_phys_flush_dcache")
Fixes: d07b7369aa ("xen/common: dom0less: introduce common domain-build.c")
Reported-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Acked-by: Michal Orzel <michal.orzel@amd.com>
(cherry picked from commit e4424b9a63)
2026-07-15 09:46:50 +02:00
Michal Orzel 483a3035fd xen/arm: sci: Don't create a domain with unsatisfied user requests
On Arm we stay on the safe side and refuse to create a domain on user
requests (e.g. via xl.cfg, DT options) that cannot be satisfied due to
the feature not being compiled in. SCI fall through the crack and does not
adhere to that i.e. a user request for SCI type other than NONE when
CONFIG_SCMI_SMC (and thus CONFIG_ARM_SCI) is not set would be silently
ignored. Fix it by not allowing anything else other than NONE if the
feature is not enabled.

Fixes: 10e7473d60 ("xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Bertrand Marquis <bertrand.marquis@arm.com>
(cherry picked from commit f7b9752dc8)
2026-07-15 09:46:50 +02:00
Mykola Kvach 715bf77ce1 xen/arm: gic-v2: disable interrupt bypass on CPU shutdown
The GICv2 CPU shutdown path currently writes 0 to GICC_CTLR.

Per IHI0048B.b section 2.3.1, clearing the architected bypass-disable
bits selects bypass rather than deasserted interrupt outputs when the
CPU interface stops driving them. Tables 2-2 and 2-3 show that a zeroed
GICC_CTLR can fall back to the legacy IRQ/FIQ inputs instead of fully
disabling the interface.

Fix this by reading GICC_CTLR, then setting the bypass-disable bits and
clearing the group-enable bits that are architecturally defined for the
current GICC_CTLR view before writing the value back. When Security
Extensions are implemented Xen accesses the Non-secure copy of
GICC_CTLR, where IRQBypDisGrp1 and FIQBypDisGrp1 are at bits [6:5] and
bits [8:7] are reserved.

Without Security Extensions (GICD_CTLR.DS=1), GICD_IGROUPR is RAZ/WI
and all interrupts are Group 0, so clearing EnableGrp0 alone is
sufficient to stop interrupt delivery through the CPU interface.

Section 2.3.2 also states that wakeup event signals remain available
even when both GIC interrupt signaling and interrupt bypass are
disabled, so disabling bypass does not break the power-management use
case, i.e. suspend modes.

Fixes: 5e40a1b435 ("arm: SMP CPU shutdown")
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>
(cherry picked from commit 6f00fd9d6c)
2026-07-15 09:46:50 +02:00
Edgar E. Iglesias 7d003af01d arm64/insn: Avoid undefined behaviour in branch offset decode
Branch offset decoding sign-extends the immediate by shifting it left into
bit 31 and back. Perform the left shift in uint32_t and cast to int32_t
only for the final right shift to avoid UBSAN failures on negative offsets.

Fixes: 6dbf3f0e30 ("xen/arm: arm64: Add helpers to decode and encode branch instructions")
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
(cherry picked from commit 65a99a4063)
2026-07-15 09:46:50 +02:00
Mykola Kvach 0927c7f348 xen/arm: gic-v3: disable Group 1 before CPU power-down
gicv3_cpu_disable() currently writes 0 to ICC_CTLR_EL1. Unlike
GICC_CTLR in the GICv2 path, ICC_CTLR_EL1 does not enable or disable
physical Group 1 interrupt signalling, so this write only clears
EOImode.

The GICv3 power management rules require the physical group enables in
the CPU interface to be cleared before the redistributor is driven into
ProcessorSleep, otherwise behaviour is UNPREDICTABLE. Xen only enables
Group 1 interrupts on this path, so disable the interface by clearing
ICC_IGRPEN1_EL1 instead.

This appears to be a copy of the GICv2 pattern where the enable control
lives in CTLR, but for GICv3 the enable moved to ICC_IGRPEN1_EL1.

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>
(cherry picked from commit 18b718b6af)
2026-07-15 09:46:50 +02:00
Michal Orzel c72fa34725 xen/arm: gic-v3: Use vsize instead of csize for virtual CPU interface
gicv3_iomem_deny_access() incorrectly uses csize (physical CPU
interface size) instead of vsize (virtual CPU interface size) when
calculating the number of pages to deny for the virtual CPU interface
region at vbase.

Fixes: 8300b3377e ("arm/gic: Add a new callback to deny Dom0 access to GIC regions")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
(cherry picked from commit 9af54b65a4)
2026-07-15 09:46:50 +02:00
Michal Orzel 8a615b0281 xen/arm: Fix off-by-one in iomem_deny_access() calls
iomem_deny_access() wraps rangeset_remove_range() which takes inclusive
endpoints.  All call sites in the GIC and ACPI code pass 'mfn + nr' (or
'mfn + 1' for single-page regions) as the end parameter, which causes
one extra page beyond each region to be denied.

For single-page regions, use 'mfn' as the end (denying exactly one page).
For all multi-page regions, use 'mfn + nr - 1'.

This matches the correct pattern used elsewhere, e.g. in device.c.

Fixes: 8300b3377e ("arm/gic: Add a new callback to deny Dom0 access to GIC regions")
Fixes: 66158be465 ("ARM: ITS: Deny hardware domain access to ITS")
Fixes: 97e9875646 ("arm/acpi: Permit MMIO access of Xen unused devices for Dom0")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@amd.com>
(cherry picked from commit f25fe2452b)
2026-07-15 09:46:50 +02:00
Oleksandr Tyshchenko d52eda2b09 xen/device-tree: Fix off-by-one bounds check in make_memory_node()
When building Xen with CONFIG_STATIC_SHM=n, booting a hardware
domain with exactly NR_MEM_BANKS (256) reserved-memory regions
causes a panic:

(XEN) Xen BUG at common/device-tree/domain-build.c:497
(XEN) Xen call trace:
(XEN)    [<00000a0000289aa8>] make_memory_node+0x178/0x234 (PC)

This occurs due to an off-by-one error in the bounds checking of
the reg array in make_memory_node(). The check:
    BUG_ON(nr_cells >= ARRAY_SIZE(reg));
incorrectly triggers when the array is exactly full (i.e., when
nr_cells == ARRAY_SIZE(reg)), preventing the 256th and final valid
memory region from being written.

When CONFIG_STATIC_SHM=y, this bug is usually hidden because
DT_MEM_NODE_REG_RANGE_SIZE adds extra space for SHM banks.
This extra capacity prevents the array from reaching its
maximum limit while processing the 256th memory region.
However, if a domain is configured with exactly NR_MEM_BANKS
and NR_SHMEM_BANKS, the array will completely fill up and trigger
the same panic.

Fix this by changing the condition to strictly greater than (>).
Apply the exact same fix to shm_mem_node_fill_reg_range() to
prevent the same error.

Fixes: cd8015b634 ("ARM/dom0: Avoid using a variable length array in make_memory_node()")
Fixes: 7846f7699f ("xen/arm: List static shared memory regions as /memory nodes")
Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
[michal: adjust for make_memory_node() living in a different file]
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
(cherry picked from commit fc453fef77)
2026-07-15 09:46:50 +02:00
Andrii Sultanov 00c0f66594 tools/ocaml/xb: Fix handling of requests with len = 0 for socket connections
Without this fix, the backend would be stuck waiting on the zero-sized
body until the next request comes in.

Instead return the request immediately after reading the header, there's
no need to wait for another call to .has_more_input and .input

Reported-by: George Dunlap <dunlapg@umich.edu>
Link: https://lore.kernel.org/xen-devel/CAFLBxZaeTMcF4tcV45MJdCVx4A6qbzQdjKei_Quh_iLrtARVFA@mail.gmail.com/
Signed-off-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Reviewed-by: Guillaume Thouvenin <guillaume.thouvenin@vates.tech>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit 7b98d94e75)
2026-07-14 19:06:19 +01:00
Marek Marczykowski-Górecki 4d824ccc3b CI: Add the new Panther Lake runner
For now run similar set of tests as ADL.

Exclude suspend test for now. While firmware claims S3 is supported,
suspend attempt fails (power LED blinks for a few seconds, and
then system reboots). With no messages on the serial console, even with
`sync_console`.

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
(cherry picked from commit 77ed730bfb)
2026-07-14 19:06:19 +01:00
Ross Lagerwall 559bfc641f nestedsvm: Allow destroying the domain fully
Unmapping the virtual VMCB is performed near the end of the domain
destroy procedure but the mapped guest frame prevents domain destroy
from getting to that point. This means guests that call VMRUN cannot
be fully destroyed.

Move the unmap of the virtual VMCB earlier to fix the issue.

Fixes: bcf557675d ("x86: properly use map_domain_page() in nested HVM code")
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 4d069a84ee
master date: 2026-06-30 09:41:35 +0200
2026-06-30 14:57:56 +02:00
Roger Pau Monné 4ef0e85a4a char/ns16550: bound execution time of ns16550_interrupt()
The current logic in ns16550_interrupt() will loop until the device sets
the NOINT in IIR.  At least on the Lenovo ThinkSystem SR630 V4 the flow
control of the serial-over-lan emulated UART seems to be broken, as it
doesn't set the NOINT bit consistently.  The Transmitter Holding Register
Empty in LSR also seems to not be properly signaled, as even with it set
writes to the transmit register take ~6ms.  This leads to the watchdog
triggering very easily on such system.

Introduce an upper bound on the execution time of ns16550_interrupt(), this
is currently set as 4x the polling interval, which is calculated as the
time to fill RX FIFO and/or empty TX FIFO.  The current maximum timeout is
either 5ms or the polling interval, whatever is higher.  Once the timeout
triggers the interrupt is disabled and the uart is switched to polling
mode.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: d1b72a9aed
master date: 2026-06-29 17:14:47 +0200
2026-06-30 14:57:33 +02:00
Roger Pau Monné 6fbfc4845e xen/irq: handle IRQ being disabled while executing its handler
It's possible for IRQ_DISABLED to be set while running the handler
execution loop in do_IRQ().  Such disabling can be done by the handler
itself, or from a remote CPU.

Check for IRQ_DISABLED not being set in the loop condition, as to not
execute the handler if the IRQ has been disabled.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: b5edd9c58e
master date: 2026-06-29 17:14:47 +0200
2026-06-30 14:57:14 +02:00
Roger Pau Monné 7aa8647037 ppc/irq: introduce a dummy irq_to_desc()
In preparation for irq_to_desc() being called by common IRQ code.
PowerPC doesn't have an irq_desc array defined, so it cannot use the
generic irq_to_desc macro in the common header.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
master commit: ed39935f50
master date: 2026-06-29 17:14:47 +0200
2026-06-30 14:56:59 +02:00
Roger Pau Monné 68053f7715 riscv/irq: define a per-arch irq_to_desc()
RISCV declares irq_desc as a static array, opposed to x86 that uses a
pointer allocated at boot time.  This creates issues when attempting to add
an extern declaration for irq_desc, as asm/irq.h is included by xen/irq.h where
the definition of struct irq_desc resides, and an empty forward declaration
doesn't make the compiler happy because it doesn't know the type
data-storage.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
master commit: b9b4c6a7ab
master date: 2026-06-29 17:14:47 +0200
2026-06-30 14:56:44 +02:00
Jan Beulich 565ad15eeb x86/boot: don't blindly mark VGA in graphics mode on MB2 path
Setting ->orig_video_isVGA to the specific marker should be done only when
the VBE tag is present and the FRAMEBUFFER is either absent or indicates
RGB type. Since the "video" variable now starts out non-NULL, this
property was broken when in particular neither of the tags are present. To
move back to at least close to original behavior, add a 2nd check to said
conditional.

Fixes: d5a73cdc6b ("x86/boot: Use boot_vid_info variable directly from C code")
Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
master commit: c7b7429854
master date: 2026-06-25 13:37:33 +0200
2026-06-30 14:56:22 +02:00
Oleksii Moisieiev e6f2903a31 sched/rtds: refill cur_budget when extratime is toggled on a depleted vCPU
XEN_DOMCTL_SCHEDOP_putvcpuinfo can flip the RTDS_extratime bit on a vCPU
that is currently depleted (cur_budget == 0, possibly sitting on the
depleted queue). rt_dom_cntl() touches only svc->flags; cur_budget is
left unchanged. As a result the next code path that calls runq_insert()
on this vCPU - rt_unit_wake() after a domain_unpause(),
rt_context_saved() following a delayed runq add, or repl_timer_handler()
after a replenishment - places the vCPU on the run queue, because
has_extratime(svc) is now true and runq_insert() admits extratime units
regardless of cur_budget:

    /* add svc to runq if svc still has budget or its extratime is set */
    if ( svc->cur_budget > 0 ||
         has_extratime(svc) )
        deadline_runq_insert(svc, &svc->q_elem, runq);
    else
        list_add(&svc->q_elem, &prv->depletedq);

The very next rt_schedule() iterates the run queue from runq_pick()
and trips the ASSERT(iter_svc->cur_budget > 0) at the bottom of the
loop, panicking the host. Observed trace:

    Assertion 'iter_svc->cur_budget > 0' failed at common/sched/rt.c:1035
    ----[ Xen-4.22-unstable  arm64  debug=y ubsan=y  Not tainted ]----
    [<...>] rt.c#rt_schedule+0x1558/0x33e0 (PC)
    [<...>] core.c#do_schedule+0x2e4/0x15b4
    [<...>] core.c#schedule+0xb14/0xe50
    [<...>] softirq.c#__do_softirq+0x20c/0x3d4
    [<...>] do_softirq+0x14/0x1c
    [<...>] domain.c#idle_loop+0x194/0x558

Minimal reproducer: pin a single-vCPU domU to a pCPU, program RTDS with
extratime off and a low utilisation (e.g. budget = 10ms / period = 100ms)
so the vCPU spends most of its time in the depleted queue, pause the
domain, issue a putvcpuinfo that sets XEN_DOMCTL_SCHEDRT_extra, then
unpause. As soon as the schedule softirq fires on the pCPU, the BUG
hits. The same sequence is reachable without an explicit pause: any
window in which rt_dom_cntl() runs between burn_budget()'s budget
exhaustion and rt_context_saved()'s runq_insert() also closes onto the
same broken state, because the per-scheduler lock is dropped between
those two points.

The semantics for "extratime gets exhausted budget refilled" already
live in burn_budget():

    if ( has_extratime(svc) )
    {
        svc->priority_level++;
        svc->cur_budget = svc->budget;
    }

Apply the same priority-demotion-and-refill in rt_dom_cntl() when the
flag transitions from off to on while the vCPU is depleted, clear
RTDS_depleted to match, and - if the vCPU is currently on the depleted
queue - move it to the run queue using the same q_remove() +
runq_insert() pattern already used by repl_timer_handler(). The vCPU
remains on the replenishment queue throughout, so its normal
replenishment cadence is preserved.

The complementary transition (on -> off) is already safe: clearing the
flag only narrows the runq_insert() admission condition, so subsequent
depleted insertions correctly route to the depleted queue.

No other call sites need changes: with cur_budget restored before the
flag is observable to runq_insert(), runq_pick()'s long-standing
invariant (every run-queue entry has cur_budget > 0) is preserved.

Fixes: 463b958317 ("xen:rtds: towards work conserving RTDS")
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
master commit: 37b49cb48e
master date: 2026-06-25 13:36:43 +0200
2026-06-30 14:56:01 +02:00
Andrew Cooper bc13e99ec6 x86/fred: Send an EVENT_CHECK IPI on exit from NMI
Returning from an NMI which hits guest context needs special casing in FRED
mode just like it does in IDT mode.

Break nmi_exit_to_guest() out of handle_ist_exception(), and use it in
entry_FRED_R3() also.

Expand the comment a little, and invert the conditional jump to
compat_restore_all_guest() to avoid needing an #else clause for CONFIG_PV32.

Fixes: 87cfcbe9f0 ("x86/pv: Guest exception handling in FRED mode")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 76fc776392
master date: 2026-06-25 11:08:02 +0100
2026-06-30 14:55:45 +02:00
Andrew Cooper 5597c9c564 x86/kexec: Check for a good per-cpu area before accessing IDTs
Prior to commit 9c20d3c591 ("x86/IDT: Make idt_tables[] be per_cpu(idt)"),
the global idt_tables[] was always safe to use for CPUs in any state.

However, not-yet-onlined CPUs (e.g. MADT with more entries than exist in
practice) or offlined CPUs (e.g. xen-hptool) have their per-cpu pointer
poisoned to detect incorrect uses.  machine_kexec() trips over the posion when
clobbering #MC entry paths.  Update the comment to discuss parked CPUs, and to
remove discussion which isn't particularly relevant to the actions at hand.

This fixes a fatal #GP (non-canonical memory reference) when trying to enter
the crash kernel.

Fixes: 9c20d3c591 ("x86/IDT: Make idt_tables[] be per_cpu(idt)")
Reported-by: Lin Liu <Lin.Liu01@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 2c9829a261
master date: 2026-06-23 19:15:51 +0100
2026-06-30 14:55:17 +02:00
Andrew Cooper c16597ec81 x86/kexec: Disable FRED earlier in kexec_reloc()
With FRED just as with IDT, it's unsafe to run the exception handlers after
switching stack.

To remove this unsafe window, %cr4 needs clearing earlier.  In turn, we may
need to switch to PCID 0 earlier too in order to be able to clear CR4.PCIDE.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 4665d17967
master date: 2026-06-23 19:15:51 +0100
2026-06-30 14:54:57 +02:00
Andrew Cooper 7f749b6948 x86/kexec: Invalidate the IDT earlier in kexec_reloc()
After switching stack, it is not safe to run any exception handlers, because
attempts to access the cpu_info block are out-of-bounds and will generate wild
accesses.

Invalidating the IDT in the common path means there's no need to do so again
in the 32bit path, so drop compat_mode_idt entirely.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: c3974cbf20
master date: 2026-06-23 19:15:51 +0100
2026-06-30 14:54:38 +02:00
Andrew Cooper 21b9b63f87 x86/kexec: Stop hooking NMIs with trap_nop()
When FRED is active, it is not possible to hook NMIs like this.

NMI hooking in the crash path has undergone several revisions since its
introduction.  Notably since commit e7f147bf4a ("x86/crash: Drop manual
hooking of exception_table[]") we use the regular nmi_callback()
infrastructure.

Instead of asserting that we don't enter do_nmi_crash() on the crashing CPU,
tolerate it and return early.  It's a marginally longer codepath but behaves
the same and is compatible with FRED.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: ad9c7d86c9
master date: 2026-06-23 19:15:51 +0100
2026-06-30 14:54:22 +02:00
Jan Beulich b09055b6d9 XSM: guard .sysctl() and .readconsole() hooks
Leaving the hook pointers in struct xsm_ops when !SYSCTL would lead to
the BUG_ON() in xsm_fixup_ops() triggering for respectively configured
hypervisors.

While moving the #ifdef for the corresponding xsm_*() wrappers, also move
those for xsm_page_offline() (where the hook pointer field already is
suitably guarded).

Fixes: c9eabaa03a ("xen/xsm: wrap around xsm_sysctl with CONFIG_SYSCTL")
Fixes: bddd9af604 ("xen/sysctl: wrap around XEN_SYSCTL_readconsole")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
master commit: 3270f9602d
master date: 2026-06-22 10:05:57 +0200
2026-06-30 14:54:01 +02:00