stub_xc_domain_create() fails unconditionally with "Unhandled: ARM" for
the ARM variant of arch_domainconfig, so no OCaml toolstack (e.g.
xenopsd) can create an ARM domain.
To fix this, convert the two fields of xen_arm_arch_domainconfig,
gic_version and nr_spis, into the corresponding fields of struct
xen_arch_domainconfig and reject values that do not fit, as is already
done for other parameters. The remaining fields (sve_vl, tee_type,
arm_sci_type and v8r_el1_msa) aren't exposed to OCaml yet, so they stay
zero.
Also add a BUILD_BUG_ON() on the size of the createdomain struct, just
like the x86 case, to catch future ABI changes.
Signed-off-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Between writing MSR_S_CET.SHSTK_EN and establishing SSP using RSTORSSP or
SETSSBSY, there must not be any CALL or RET instructions.
Building Xen with -fno-early-inlining causes wrmsr() to become out-of-line,
and thus suffers #DF during boot.
Make the MSR and shstk helpers always_inline. They ought to have been this
way all along.
Fixes: b60ab42db2 ("x86/shstk: Activate Supervisor Shadow Stacks")
Fixes: 3037d8b7eb ("x86/boot: Use RSTORSSP to establish SSP")
Reported-by: Stefano Stabellini <sstabellini@kernel.org>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Roger Pau Monné <roger@xenproject.org>
If the memory region to be mapped does not start at the page boundary
and its end spans over the page boundary, map_range_to_domain() passes
a number of pages that is short by one to map_regions_p2mt(). Domain's
attempt to access memory within that page will fail. Fix it by calculating
the number of pages to be mapped taking into account the start offset.
Fixes: 88c10b0d6e ("arch/arm: let map_mmio_regions() use start and count")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Acked-by: Julien Grall <julien@xen.org>
Per the binding (docs/misc/arm/device-tree/guest.txt), region 0 for
mapping grant table is large enough to map the whole grant table. Xen
never checks that this holds:
- enhanced dom0less domUs are given GUEST_GNTTAB_SIZE (4096 frames),
while their limit comes from the max_grant_frames DT property or, if
absent, from the gnttab_max_frames command line option or default,
neither of which is bounded by the region size,
- a dom0less hardware domain is given gnttab_dom0_frames() frames,
while the max_grant_frames DT property can raise its limit above
that.
A guest growing its grant table past the end of the region ends up
mapping grant frames over whatever follows it in its address space,
e.g. the magic pages at GUEST_MAGIC_BASE for a domU.
Validate that the configured max frames can actually fit in the region
Xen exposes in make_hypervisor_node().
Fix find_gnttab_region() logic of setting the gnttab_size for hardware
domain to allow the max frames up until the size of the text section.
Otherwise, the DT setting would only allow to shrink it from the
default.
Fixes: 79eb2871f2 ("xen/arm: configure dom0less domain for enabling xenstore after boot")
Fixes: df68a4cb7e ("xen/arm: Add capabilities to dom0less")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
The device tree Xen builds for dom0/hwdom or for a dom0less domain is
only ever consumed by the guest, so a mistake in it surfaces as an
obscure failure inside the domain, far away from the code which
produced the tree.
Add device_tree_dump(). The output follows dtc's format so that a dump
can be diffed against the source DTS or fed back to dtc; the value
formatting heuristics are ported from dtc's utilfdt_print_data() for
that reason. The walk itself goes through libfdt rather than decoding
the tag stream by hand as dtc's fdtdump does.
Dumping a whole tree is only useful while debugging and costs both code
size and a lot of console output, so it is put under its own option,
CONFIG_DEVICE_TREE_DUMP. It is separate from CONFIG_DEVICE_TREE_DEBUG
because the generated tree is often all that is needed, without the rest
of the device tree debug messages.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
arch_sanitise_domain_config() validates the configuration requested by
the toolstack, and should not fill anything in. The config struct passed
to createdomain is supposed to be pure input. ARM used to abuse this
(GIC_NATIVE resolution, now removed) to smuggle output back to the
toolstack. Making the parameter const stops that type of abuse from
happening on any architecture.
The x86 implementation turned out to have its own instance of the same
issue. It set XEN_DOMCTL_CDF_oos_off into config->flags for non-HVM
guests. Since The sanitisation runs before the function domain_create()
copies config->flags into d->options, this relied on mutating the
toolstack's config to take effect. Move the default onto d->options
directly in arch_domain_create() (which runs after d->options is
populated), where all the remaining domain options are resolved. This
has the same effect and no mutation of the input config is required.
ARM, PPC and RISC-V need no equivalent change, Their implementations
were already read-only.
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Reviewed-by: Jan Beulich <jbeulich@suse.com> # x86
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@vates.tech> # riscv
The xen_arch_domainconfig.clock_frequency value is populated in
domain_vtimer_init() during XEN_DOMCTL_createdomain from the global
timer_dt_clock_frequency, which comes from the host's DT timer node and
has nothing to do with the domain being created. Like now removed
GIC_NATIVE resolution, this is a host-wide system property being
smuggled out through a domain-creation IN struct.
Expose it instead as a new arm_clock_frequency_hz field in
XEN_SYSCTL_physinfo, populated via arch_do_physinfo(), and mirroring how
the GIC capability bits were already moved there.
Rather than making the field dependant on DT boot, make Xen always
report the timer frequency, either via the DT "clock-frequency" node, or
directly via CNTFRQ_EL0. preinit_xen_time() already computes cpu_khz for
every boot path. The renamed timer_clock_frequency_hz now captures
whichever of the two produced that value, in full Hz precision, instead
of only recording the DT case. So, ACPI guests get a real value too,
allowing to drop the special case.
The DT "clock-frequency" property exists because firmware might leave
CNTFRQ_EL0 wrong, and since CNTFRQ_EL0 cannot be trapped the only fix is
to replicate the correct value into the guest DT. To keep that signal, a
new XEN_SYSCTL_PHYSCAP_ARM_TIMER_DT_FREQ capability bit records whether
arm_clock_frequency_hz came from the DT property. Then libxl only emits
a "clock-frequency" property into the guest timer node when that bit is
set. A guest whose CNTFRQ_EL0 is already correct keeps an unmodified
timer node, exactly as before.
Although the CNTFRQ_EL0 register is 64 bits wide, and some current timer
implementations run at 1GHz, a 32bit value is sufficient to store the
timer value, because it only mirrors the DT 'clock-frequency' property,
which the bindings define as a single 32-bit cell.
In struct xen_sysctl_physinfo the new field just reuses the former pad
word, so sysctl consumers are unaffected. struct xen_arch_domainconfig
however loses clock_frequency from its middle, which shrinks the struct
and shifts every field after it, so bump XEN_DOMCTL_INTERFACE_VERSION.
The xen_arch_domainconfig parameter passed to domain_vtimer_init() is no
longer needed, so drop that parameter entirely. libxl now fetches the
frequency via libxl_get_physinfo() in libxl__arch_domain_save_config()
instead of reading it back out of the createdomain reply. The OCaml
xen_arch_domainconfig mirror drops the field too.
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Now that the toolstack always resolves a concrete GIC_V2 or GIC_V3
before calling createdomain, nothing on the Xen side needs to resolve
GIC_NATIVE either:
* A new gic_domctl_hw_version() helper returns the
XEN_DOMCTL_CONFIG_GIC_* value matching the host's gic_hw_version().
* arch_sanitise_domain_config() uses it to validate the requested
version against the hardware, rather than resolving GIC_NATIVE and
writing the result back into config->arch.gic_version. A guest must
use the host's GIC version, except that a GICv3 host with the GICv2
compatibility mode enabled may also run GICv2 guests. This is the
same information that XEN_SYSCTL_physinfo reports to the toolstack.
* create_dom0() and arch_parse_dom0less_node(), which both always want
a vGIC that exactly matches the hardware, use the same helper instead
of GIC_NATIVE.
With nothing left resolving or relying on it, drop
XEN_DOMCTL_CONFIG_GIC_NATIVE from the public ABI. Every caller must now
request a concrete GIC_V2 or GIC_V3.
This is an incompatible change for any toolstack still passing 0
(formerly GIC_NATIVE) expecting Xen to auto-select a version. Add a
CHANGELOG.md entry, noting that available GIC versions can be queried
via XEN_SYSCTL_physinfo.
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
XEN_DOMCTL_CONFIG_GIC_NATIVE lets the toolstack ask Xen to silently
resolve the domain's GIC version to whatever the host hardware has. Xen
then writes the resolved value back into the same in/out
xen_arch_domainconfig the toolstack used as input, which is the kind of
API abuse we're trying to get rid of. The struct passed to createdomain
should only be an input parameter.
Move the "pick the best available GIC version" decision to the
toolstack, using the XEN_SYSCTL_PHYSCAP_ARM_GIC_V2/V3 capability bits
already exposed via XEN_SYSCTL_physinfo:
* libxl__arch_domain_build_info_setdefault() resolves the GIC version
against those bits before the config is built. An unspecified version
becomes v3 if available, else v2, else fails. An explicitly requested
v2/v3 is validated against the same bits, so a version the host
cannot provide is directly rejected in the toolstack.
* The Python xc.domain_create() binding does the same via a call to
xc_physinfo().
* libxl__arch_domain_prepare_config() therefore only ever sees a
concrete v2/v3 request and just validates it. The GIC_NATIVE case is
dropped since setdefault() always resolves it first.
LIBXL_GIC_VERSION_DEFAULT keeps its name and value: xl.cfg still accepts
"default" as the C<gic_version> keyword, and setdefault() resolves it to
a concrete v2/v3 before anything else can observe it.
This guarantees no toolstack path can still produce
XEN_DOMCTL_CONFIG_GIC_NATIVE, in preparation for removing it from the
Xen side and from the ABI entirely.
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Acked-by: Michal Orzel <michal.orzel@amd.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
In preparation to simplify the domain creation logic surrounding GIC
version.
On a GICv3 host, also report support for GICv2-compatible guests when
the hardware's vGICv2 compatibility mode is enabled, rather than just
the native GIC version.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Include PCI IDs of UART ports on Intel RPL - PTL. Based on Linux driver
and hwdata, they all share the same parameters.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
There's a potential 32bit left-shift (when size is 4) to a 32bit value,
which would trigger UB and tickle UBSAN the wrong way. Shifting right an
all-ones mask fixes the issue.
Fixes: 4609fc8eb0 ("x86/hvm: Improve error information in handle_pio()")
Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
As of the referenced commit v won't be returned from the function anymore.
Yet that was the sole reason for it to not be pointer-to-const. curr,
which was introduced by that change, had no reason to be pointer-to-non-
const from the start.
Amends: 622c9a5ba9 ("x86/mm: accurately track which vCPU page-tables are loaded")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger@xenproject.org>
memcpy_to_guest_ring() bounds the copy against the ring size with
if ( len + offset > XEN_ARGO_MAX_RING_SIZE )
where len and offset are unsigned int. offset is masked below
PAGE_SIZE just above, but a len close to UINT_MAX makes len + offset
wrap below XEN_ARGO_MAX_RING_SIZE and pass the check. The head_len
computation in the loop wraps the same way, so the copy length is no
longer bounded.
All current callers bound len via iov_count(), so this is not
reachable in practice.
No functional change for in-range inputs.
Signed-off-by: Weiqi Wang <weiqi.wang-2@postgrad.manchester.ac.uk>
Acked-by: Jan Beulich <jbeulich@suse.com>
MISRA C Rule 10.1 states: "Operands shall not be of an inappropriate
essential type".
bar_write() and guest_mem_bar_write() added the boolean 'hi' to a
pointer difference when printing the ignored BAR index. These handlers
are registered only for the memory BAR registers, so print
(reg - PCI_BASE_ADDRESS_0) / 4 instead. The expression has type
unsigned int, so use %u.
No functional changes.
Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger@xenproject.org>
Due to a typo the state record for a watch specifying a depth is
written only partially. Instead of using the correct length of the
xs_state_watch_ext structure only the length of the xs_state_watch
structure was used when writing the data.
Fix that by using the correct length.
This is XSA-514 / CVE-2026-79607
Fixes: db98de120c ("tools/xenstored: add depth information to watches")
Reported-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Signed-off-by: Juergen Gross <jgross@suse.com>
Grants can be offered read-only by the owning domain. While a domain mapping
a RO grant may have a need to invalidate the cache, it must not modify the
other-guests data while doing so. Force-upgrade to a clean operation in this
case.
This is CVE-2026-102702, part of XSA-519.
Fixes: 18e8d22fe7 ("introduce GNTTABOP_cache_flush")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
When the start address is not cacheline aligned, the bytes covered by
the first, partial cacheline are subtracted from 'size'. Nothing checks
that the region actually extends beyond that cacheline, so if it does
not, the unsigned subtraction underflows and the loop that follows walks
practically the entire address space.
For example, with a 64-byte cacheline, p = 0x40000001 and size = 1:
p & cacheline_mask -> 1, so the partial head is taken
size -= 64 - 1 -> 1 - 63 underflows to 0xffffffffffffffc2
Instead of a single "dc civac" at 0x40000000, the loop then runs
288230376151711743 times, issuing "dc ivac" from 0x40000040 upwards.
Invalidating without cleaning discards dirty cachelines, so this
corrupts whatever is mapped along the way until Xen takes a data abort.
Moreover, _cache_flush() in common/grant_table.c, reachable from a guest
via GNTTABOP_cache_flush, bounds 'offset' and 'length' against the page
size but requires no alignment, so GNTTAB_CACHE_INVAL with offset = 1
and length = 1 is enough to trigger this. Note that the page may belong
to a different domain (the d != owner path), so the data being discarded
is not necessarily the caller's own.
The subtraction dates back to the fix for XSA-437, so this is a regression
in that change.
Fix this by detecting the underflow instead of letting it happen: if the
region ends inside the first cacheline, there is nothing left to flush
and the function bails out right after cleaning it. Partially covered
cachelines are still cleaned as well as invalidated, so that data outside
of the region is not discarded.
Additionally, drop 'idx' and advance 'p' directly instead. It simplifies
the logic while using fewer variables and less arithmetic.
Note that the partial head is now cleaned using the unaligned start of the
region instead of the start of its cacheline. This is permitted by the
architecture; the Arm ARM (DDI 0487) states:
"When a DC instruction requires an address argument this takes the form
of a 64-bit register that holds the VA argument. No alignment
restrictions apply for this address."
The same applies on Arm32.
Also, switch the asm() in the loop to asm_inline, like the neighbouring
ones: the wrapper expands to a single instruction with a trailing
semicolon, which GCC counts as two statements, overestimating the size
of the function when deciding whether to inline it.
This is CVE-2026-102699, part of XSA-519.
Fixes: 9a216e92de ("xen/arm: page: Handle cache flush of an element at the top of the address space")
Signed-off-by: Leonid Komarianskyi <leonid_komarianskyi@epam.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <julien@xen.org>
The consistency checks in effect when Blocked-by-STI/MovSS are active includes
DEBUGCTL.BTF too. Take this into account when editing PENDING_DBG.BS.
This ends up narrowing the cases where PENDING_DBG is modified. Rework the
comment to be more precise.
This is XSA-518 / CVE-2026-79611.
Fixes: 1d3eb82598 ("x86/vtx: Work around SingleStep + STI/MovSS VMEntry failures")
Reported-by: Teddy Astie <teddy.astie@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
A v1 -> v2 change isn't the only scenario where "status" may go stale in
map_grant_ref(). Across a v2 -> v1 -> v2 change the status pages would
have been freed and re-populated, possibly changing the pages used for the
array. Check the pointer against the expected version-dependent value.
This is XSA-517 / CVE-2026-79610.
Fixes: 96dfeb4177 ("gnttab: cope with version changes racing other operations")
Assisted-by: Claude
Reported-by: Teddy Astie <teddy.astie@vates.tech>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
For XPTI enabled VMs, restore_all_guest() copies most of the active L4
pagetable into the per-CPU root_pgt. The L4 is read via the
directmap.
Unfortunately, there was no accounting for the fact that PV guests
have short directmaps. For an L4 living beyond the 5T boundary (3.5T
for CONFIG_BIGMEM), Xen will copy arbitrary data from guest-controlled
virtual address space into the per-CPU root_pgt, instead of the
intended L4.
Xen has per-domain mappings for the LDT and GDT, with two pages
reserved for Xen's use in the GDT but only one in use. Reuse GDT page
15 to map the effective L4. The GDT limit keeps implicit accesses out
of this page.
We update this mapping in make_cr3(), the only place a non-empty value
of v->arch.cr3 is written into a guest's vcpu struct, for two reasons.
First is reference counting: this makes it easier to argue that the
reference for v->arch.cr3 itself covers the reference for the mapping.
Secondly, this guarantees that all updates, even updates made in
shadow mode, result in an update to the mapping. During live
migration, it's possible for guest_get_eff_kern_l1e() to result in a
modified value of v->arch.cr3 (sketch below); placing the mapping
update at make_cr3() catches this, while other candidate locations
like write_ptbase() and toggle_guest_mode() don't.
Note that we introduce the idea of an "effective L4" here, to mean
"guest L4 after any transformations": XPTI copies either the actual
guest L4 if not shadowed, or the shadow L4 (transformed) if shadowed.
Sketch: guest_get_eff_kern_l1e() has a pair of toggle_guest_pt() calls
which happen if the guest is in user mode. During live migration, a
log-dirty clean will do a domain_pause and then call
shadow_blow_tables(), unpinning the shadow of the guest user root
pagetable. After execution resumes, the first toggle_guest_pt() could
then cause that page to become unshadowed. The second
toggle_guest_pt() would then re-shadow it, possibly with a different
backing shadow page.
This is XSA-516 / CVE-2026-79609.
Fixes: 5784de3e20 ("x86: Meltdown band-aid against malicious 64-bit PV guests")
Assisted-by: Claude Code:claude-fable-5-1
Signed-off-by: George Dunlap <gwd@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
The identified commit inverted the condition under which Xen chooses
to set the Zenbleed chickenbit.
Undo that, and leave a better comment explaining why.
Found by AI review of the referenced commit.
This is XSA-515 / CVE-2026-79608.
Fixes: d0c75dc4c0 ("x86/amd: Fix race editing DE_CFG")
Assisted-by: Sashiko + Opus 5.0
Reported-by: George Dunlap <dunlapg@umich.edu>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Error path of failed sidtab_map() leaves global sidtab in shutdown state and
from that point system is unable to allocate new SIDs in sidtab_context_to_sid().
To restore sidtab state new function sidtab_cancel_shutdown() is introduced,
which only resets shutdown flag, rewinding effect of sidtab_shutdown().
Signed-off-by: Sergiy Kibrik <Sergiy_Kibrik@epam.com>
Acked-by: Daniel P. Smith <dpsmith@apertussoutions.com>
We already have two instances of this, and we're about to gain a third.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <gwd@xenproject.org>
As of the referenced commit there's no reason to open-code the loop
anymore. With that replaced by a single call, there's then also no point
in using the local "mfn" in this code.
Amends: 5260e8fb93 ("xen: re-define assign_pages and introduce a new function assign_page")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <gwd@xenproject.org>
NextRIP is consumed on VMRUN as the return address pushed onto the
stack for injected soft exceptions/interrupts. nsvm_vmcb_prepare4vmrun()
builds n2vmcb from the virtual VMCB on every entry to the L2 guest, but
never copied this field, leaving n2vmcb->nextrip stale. Injecting an
event in this state can wedge the L2 vCPU, as the APM does not define
behaviour for a VMRUN with a garbage NextRIP.
Nested virt is only offered on NRIPS-capable hardware, and NRIPS is
required to be advertised to L1 (see start_nested_svm()), so the L1
hypervisor is required to keep NextRIP correct. Therefore no
conditional logic is needed here; an unconditional sync suffices.
Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Chunjie Zhu <chunjie.zhu@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Do not wait indefinitely for XHCI to configure console connection. If
the cable is not plugged in, timeout after about 1s and continue boot.
If the cable is plugged in later, the console will be activated then
(see final part of dbc_ensure_running()). When timeout occurs, print a
warning message - it will be saved in the console ring buffer, to be
later retrieved from dom0, or possibly later printed when the cable is
finally connected. But, do not print the warning when waiting after
controller reset, as that may have been called from from console
dbc_putc() and printing here would result in (possibly infinite)
recursion.
Try the timeout to be about 1s, which is way above time needed for
configuring already connected cable. But, since this part runs very
early in the Xen startup, time is not calibrated yet, and functions like
NOW() do not work yet. Use raw TSC and estimate needed time to be at
least 1s on a fast CPU (5GHz), and possibly longer on a slower one. This
is not very accurate method, but fortunately it doesn't need to be.
This also helps with similar situation on resuming from suspend - if
cable got unplugged in the meantime, system will not hang waiting for
the console anymore. And finally, on some systems, when dom0 is also
allowed to access the USB controller, it may put the device into low
power mode that in some older controllers (for example Kaby Lake)
disables also debug capability. In such a case, adding a timeout allows
the system to resume, then dom0 can wake up the controller and Xen will
resume XHCI console.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Valgrind reports that 21 bytes are "still reachable" from the (XEN_LOG_DIR "/console") allocation:
HEAP SUMMARY:
in use at exit: 21 bytes in 1 blocks
total heap usage: 9 allocs, 8 frees, 4,799 bytes allocated
Since the dynamic memory allocation for the default log directory path happens before the process
forks into the background, the parent and intermediate processes exit during daemonize()
with the memory still reachable.
Move the strdup() allocation down below the daemonize() block. This ensures only the final
background daemon allocates the default path, matching the lifetime of the free(log_dir)
cleanup loop at the exit of main().
With this change, Valgrind reports a clean heap summary
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 8 allocs, 8 frees, 4,778 bytes allocated
Signed-off-by: Andrew Mbugua <andrewprecious388@gmail.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
xentop parses -d/--delay and -i/--iterations with atoi(), so invalid
input is silently accepted with surprising results: a fractional delay
such as "-d 2.5" is truncated to 2; "-d abc" parses as 0, which in
batch mode turns the output loop into a busy loop; "-d -1" wraps to an
effective delay of about 136 years; and "-i 0" (or any unparsable
iterations count) decrements an unsigned counter from zero, running
for about 2^32 iterations. atoi() also has undefined behaviour on
out-of-range input.
Parse both options with strtoull() instead, and reject anything that
is not a plain decimal integer in range: a sign, a fractional part,
trailing junk or overflow now produce an error and exit rather than a
silently wrong value.
Compatibility considerations: "--delay 0" remains accepted, since
updating as fast as possible is a plausible deliberate choice and
works today; "--iterations 0" is rejected, since running the loop
2^32 times cannot be what the caller meant. The interactive 'D'
prompt already validates its input and is unchanged. The only
previously useful invocation this breaks is a fractional delay, which
now fails loudly instead of silently rounding down - which is the
point of the change.
A patch documenting the --delay truncation was posted in 2010 but
never applied:
Link: https://lore.kernel.org/xen-devel/01ea26d2420e3562eb30.1292604768@chilopoda.uk.xensource.com/
Signed-off-by: Matthias Goergens <matthias.goergens@gmail.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
xenstat_collect_networks() looks for a Linux bridge (a
/sys/class/net/*/bridge directory) so that, with bonding, dom0 can be
given the bridge's counters. When there is none, as on hosts using Open
vSwitch (the XCP-ng default), routed networking or only libvirt's
virbr0 (which is excluded on purpose), getBridge() leaves devBridge
empty. strstr(iface, "") then matches every interface, and devNoBridge
is just "p", so every VIF with a standard name (vifN.M, vifN.M-emu)
takes the bridge branch instead of being attached to its domain. Every
domain ends up with zero networks, and xentop shows NETS 0.
Only take the bridge branch when a bridge was actually found.
Fixes: 1fd93d4f8c ("xenstat: Linux dom0 statistics for case we use network bonding")
Assisted-by: Claude-Code:claude-opus-5-5
Signed-off-by: Olivier Lambert <olivier.lambert@vates.tech>
Tested-by: Jason Andryuk <jason.andryuk@amd.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Add a new directory linux-bridge-vlan with example files showing
how to configure systemd-networkd to support a bridge VLAN
configuration.
Signed-off-by: Leigh Brown <leigh@solinno.co.uk>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
Update add_to_bridge shell function to read the vlan parameter from
xenstore and set the bridge VLAN configuration for the VID.
Add additional helper functions to parse the vlan specification,
which consists of one or more of the following:
a) single VLAN (e.g. 10).
b) contiguous range of VLANs (e.g. 10-15).
c) discontiguous range with base, increment and count
(e.g. 100+10x9 which gives VLAN IDs 100, 110, ... 190).
A single VLAN can be suffixed with "p" to indicate the PVID, or
"u" to indicate untagged. A range of VLANs can be suffixed with
"u" to indicate untagged. A complex example would be:
vlan=1p/10-15/20-25u
This capability requires the iproute2 bridge command to be
installed. An error will be generated if the vlan parameter is
set and the bridge command is not available.
Signed-off-by: Leigh Brown <leigh@solinno.co.uk>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
RFC 791 sets the minimum acceptable mtu to 68:
Every internet module must be able to forward a datagram of 68
octets without further fragmentation. This is because an internet
header may be up to 60 octets, and the minimum fragment is 8 octets.
In the Linux kernel source:
include/net/ip.h:#define IPV4_MIN_MTU 68 /* RFC 791 */
While there is no reason to expect a value <68 to be read from xenstore or
from the bridge make the value test require a number >= this minimum.
Signed-off-by: James Dingwall <james@dingwall.me.uk>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
The set_mtu() function of xen-network-common.sh currently has this code:
if [ ${type_if} = vif ]
then
local dev_=${dev#vif}
local domid=${dev_%.*}
local devid=${dev_#*.}
local FRONTEND_PATH="/local/domain/$domid/device/vif/$devid"
xenstore_write "$FRONTEND_PATH/mtu" ${mtu}
fi
This works fine if the device has its default name but if the xen config
defines the vifname parameter the FRONTEND_PATH is incorrectly constructed.
Learn the frontend path by reading the appropriate value from the backend.
Also change use of `...` to $(...) for a consistent style in the script.
Signed-off-by: James Dingwall <james@dingwall.me.uk>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Wire the per-cpupool admission-control switch through libxl
to xl sched-rtds, and document it.
Add -s/--schedparam to list or set pool-wide RTDS scheduler
parameters, and -a/--admission to enable or disable admission
control for a cpupool ("-c pool -s -a 0/1").
Signed-off-by: Furkan Caliskan <frn1furkan10@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
Everything discard_initial_modules() touches is already common code:
bootinfo.modules, using_static_heap and fw_unreserved_regions(). Move it
out of Arm into common/device-tree/bootinfo.c, next to the boot allocator
handling of the same memory, and declare it in xen/bootinfo.h, so that
other device-tree based architectures can reuse it instead of growing a
copy of their own.
The arch-specific remove_early_mappings() is not moved along with it:
how the early FDT mapping is torn down is up to the architecture. As the
DTB is one of the boot modules being released, the mapping has to go once
they are discarded, so call it from start_xen() right after
discard_initial_modules(), which keeps the common function free of any
arch dependency.
While moving it, use unsigned int for the loop counter and replace the
"goto out" by a plain return, as there is nothing left to do at the label.
No functional change.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
We require memory to allocate for a domain as RAM to be a multiple of a
page size. However, we neither document this nor sanity test. Specifying
memory size that does not conform to this requirement fails the domain
memory allocation in the non-obvious way that is difficult to parse for
the user (printing over-allocation messages followed by the panic that Xen
could not allocate the requested amount of memory).
While there, fix indentation from tabs to spaces for "memory" parameter in
booting.txt.
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com>
find_text_region() tests whether an arbitrary address lies inside
[text_start, text_end). The address and those bounds are not known to
point into one object, so relational operators on the pointers are
undefined behaviour and violate Misra C:2012 rule 18.3.
The bounds are cast to unsigned long because addr already has that
type. The type is wide enough to hold a pointer, so the comparison
result stays the same.
No functional changes.
Signed-off-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
When sorting and merging overlapping ranges in
pfn_pdx_compression_setup(), the merged range is set to end where the
second range ends. If the second range is fully contained in the first,
this truncates the first range, and the tail of it is then neither
compressible nor translated correctly.
Keep the end of the merged range as the maximum of both ends.
On x86 the ranges come from the SRAT memory affinity entries, and
overlapping entries for the same node are tolerated with a warning by the
NUMA code. The caller's subsequent coverage check catches the truncated
range, so the effect is that PDX compression is disabled with a "RAM
region ... not covered" message rather than memory being mistranslated.
Add a test case that fails without this change.
Found with the ESBMC bounded model checker, and confirmed by running the
failing case natively against the unmodified code.
Fixes: c5c45bcbd6 ("pdx: introduce a new compression algorithm based on region offsets")
Assisted-by: Claude Code:claude-opus-5-5 # finding the issue with ESBMC, patch creation
Signed-off-by: Weiqi Wang <weiqi.wang-2@postgrad.manchester.ac.uk>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
vstimecmp is a 64-bit CSR independently of XLEN, which is why it is
written with csr_write64(). On RV32 that macro splits the value into
the vstimecmp/vstimecmph pair, so passing ULONG_MAX (0xffffffff there)
writes all ones to the low half and zero to the high half, leaving the
CSR at 0x00000000ffffffff rather than at its maximum. A VS-timer irq
would then become pending as soon as (time + htimedelta) reaches 2^32,
which is exactly what the code is trying to avoid.
Use ~0 instead: csr_write64() converts its argument to uint64_t, and the
conversion of the signed -1 sign-extends to all ones, so both halves get
0xffffffff. On RV64 the result is equal to ULONG_MAX, so no functional
change there.
Fixes: 25e0327306 ("xen/riscv: allow Xen to use SSTC while hiding it from guests")
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Acked-by: Jan Beulich <jbeulich@suse.com>
vmid_handle_vmenter() reports that no flush is needed when VMIDs are
unavailable (e.g. vmid=off, or hardware with no more than one VMID bit).
Every domain then runs under VMID 0 with nothing flushed in between, so as
soon as a hart runs more than one domain, a domain entered there can use
the G-stage translations left behind by the domain which ran before it.
Report that a flush is needed on every entry instead.
Update the comment in p2m_handle_vmenter() accordingly: without VMIDs the
VS-stage TLB doesn't need a separate flush either, as the G-stage flush now
done on every entry already covers it.
While at it, spell the other early return as a bool literal.
Fixes: bff3b9ea46 ("xen/riscv: introduce VMID allocation and manegement")
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Acked-by: Jan Beulich <jbeulich@suse.com>
kernel_image64_probe() never set info->type, so every domain kept the
DOMAIN_32BIT value a zeroed KERNEL_INFO_INIT leaves behind, even though
Xen on RISC-V is only built for RV64 and accepts nothing but a 64-bit
Image.
Nothing consumes d->type on RISC-V yet, so there is no functional change.
Fixes: f6a20eda92 ("xen/riscv: add Linux kernel loading support")
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Acked-by: Jan Beulich <jbeulich@suse.com>
Both constants were inherited from OpenSBI and their names are misleading.
The length of an instruction is encoded in its low bits: bits[1:0] != 11
means 16 bits, otherwise bits[4:2] != 111 means 32 bits, and anything else
is 48 bits or wider. 0x3 and 0x1c are the patterns compared against in
these two tests, not masks selecting a 16-bit or a 32-bit instruction. As
each constant is needed in one place only, once INSN_IS_16BIT() and
INSN_IS_32BIT() encapsulate the tests, drop them and spell the values out
in those two macros instead.
While at it, make INSN_LEN() cover the case both macros already knew about:
an encoding of 48 bits or wider now yields 0 rather than being silently
taken for a 32-bit instruction. No ratified extension defines an instruction
of such a length, so rather than open-coding a decoder for encodings which
cannot legitimately occur, leave it to the caller to treat the 0 as an
illegal instruction.
No functional change: the only present caller applies INSN_LEN() to a bug
frame, i.e. to an instruction emitted by Xen itself, which is either 16 or
32 bits wide.
Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Acked-by: Jan Beulich <jbeulich@suse.com>
While avoiding casts would be preferable here, the subtraction ends up
violating "Subtraction between pointers shall only be applied to pointers
that address elements of the same array". Use long arithmetic instead.
No functional change intended.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
While casting to pointer types may be more natural there, the subtraction
then ends up violating "Subtraction between pointers shall only be applied
to pointers that address elements of the same array". Use long arithmetic
instead.
No functional change intended.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
Add a Kconfig option that lets an integrator hard-code the number of
GICv3 List Registers Xen uses. The default (0) keeps reading the count
from ICH_VTR_EL2.ListRegs at boot. A non-zero value is validated
against the hardware count in gicv3_hyp_init() and replaces
gicv3_info.nr_lrs.
gicv3_hyp_init() now panics if CONFIG_GICV3_NR_LRS exceeds the
hardware count, and zeroes all hardware LRs (once per CPU) as defensive
hardening, so any interrupt left in an LR that Xen will not manage
cannot be picked up by the GIC.
gicv3_ich_read_lr()/gicv3_ich_write_lr() now reject out-of-range
indices with an error message, ASSERT_UNREACHABLE() and WARN() instead
of silently returning RAZ/WI; reaching this path indicates a bug.
Signed-off-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
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>
The arch_init_idle_domain() initializes struct arch_csw idle_csw as:
static const struct arch_csw idle_csw = {
.from = paravirt_ctxt_switch_from,
.to = paravirt_ctxt_switch_to,
.tail = idle_loop,
};
but only place where d->arch.ctxt_switch->{to,from}() are used is
__context_switch() where they are both guarded by !is_idle_domain(pd)
which makes the callbacks in idle_csw unreachable.
Introduce a new poison value to be used in unreachable function hooks, and
set the from/to fields of idle_csw to it. Use a different value from the
currently defined ones for easy differentiation.
Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Roger Pau Monné <roger@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
XENFEAT_pae_pgdir_above_4gb is only used by 32bit PV guests, hence limit
its setting in XENVER_get_features to the is_pv_domain() guarded section,
with the rest of the PV specific features. Add an additional build time
guard to short-circuit the setting of XENFEAT_pae_pgdir_above_4gb if the
hypervisor has no PV 32bit support.
Signed-off-by: Roger Pau Monné <roger@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Since the firmware may initialize eSPIs before Xen, and without
CONFIG_GICV3_ESPI enabled, Xen would not reinitialize them properly
during boot. In such cases, once the GIC is re-enabled in Xen,
interrupts may be received that cannot be handled.
To ensure proper operation on hardware with eSPI feature, even when the eSPI
config is disabled, gicv3_dist_espi_common_init() should be invoked
regardless of whether CONFIG_GICV3_ESPI is enabled or not. This will not
affect hardware without eSPI support, as the function checks if the
hardware supports eSPIs by reading the GICD_TYPER.ESPI field (using
GICD_TYPER_ESPIS_NUM macro), which indicates whether the extended SPI
range is supported. If the hardware does not support eSPI, the function
will not perform any actions.
There are no functional changes for setups where CONFIG_GICV3_ESPI=y.
Suggested-by: Julien Grall <jgrall@amazon.com>
Signed-off-by: Leonid Komarianskyi <leonid_komarianskyi@epam.com>
Acked-by: Julien Grall <jgrall@amazon.com>
Reviewed-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>