Version in base suite: 4.20.3+127-gc42374a105-0+deb13u1 Version in overlay suite: 4.20.4+39-gf1e1321c87-0+deb13u1 Base version: xen_4.20.4+39-gf1e1321c87-0+deb13u1 Target version: xen_4.20.4+63-g7abfd2bce2-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/x/xen/xen_4.20.4+39-gf1e1321c87-0+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/x/xen/xen_4.20.4+63-g7abfd2bce2-0+deb13u1.dsc debian/changelog | 9 +++ xen/arch/x86/acpi/cpu_idle.c | 18 +++++++ xen/arch/x86/hvm/dom0_build.c | 1 xen/arch/x86/hvm/emulate.c | 1 xen/arch/x86/hvm/io.c | 2 xen/arch/x86/hvm/svm/entry.S | 40 +++++++++++++---- xen/arch/x86/hvm/svm/svm.c | 21 ++++----- xen/arch/x86/hvm/vpt.c | 7 ++- xen/arch/x86/include/asm/hvm/vpt.h | 1 xen/arch/x86/include/asm/msr.h | 4 - xen/arch/x86/include/asm/shstk.h | 4 - xen/arch/x86/mm.c | 19 +++++--- xen/arch/x86/mm/p2m-pod.c | 72 +++++++++++++------------------ xen/arch/x86/setup.c | 5 ++ xen/arch/x86/x86_64/asm-offsets.c | 9 +++ xen/arch/x86/x86_64/domain.c | 5 ++ xen/common/domain.c | 9 +++ xen/common/efi/boot.c | 11 +++- xen/common/grant_table.c | 20 +++----- xen/common/ioreq.c | 3 - xen/common/page_alloc.c | 2 xen/common/rangeset.c | 5 +- xen/common/sched/core.c | 14 +++--- xen/common/sched/credit2.c | 4 + xen/drivers/passthrough/amd/iommu_acpi.c | 4 - xen/drivers/passthrough/amd/iommu_cmd.c | 2 xen/include/public/vcpu.h | 3 - xen/tools/symbols.c | 5 ++ 28 files changed, 198 insertions(+), 102 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp92fgaowz/xen_4.20.4+39-gf1e1321c87-0+deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp92fgaowz/xen_4.20.4+63-g7abfd2bce2-0+deb13u1.dsc: no acceptable signature found diff -Nru xen-4.20.4+39-gf1e1321c87/debian/changelog xen-4.20.4+63-g7abfd2bce2/debian/changelog --- xen-4.20.4+39-gf1e1321c87/debian/changelog 2026-10-16 14:28:47.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/debian/changelog 2026-11-03 20:11:50.000000000 +0000 @@ -1,3 +1,12 @@ +xen (4.20.4+63-g7abfd2bce2-0+deb13u1) trixie-security; urgency=medium + + * Update to new upstream version 4.20.4+63-g7abfd2bce2, which also contains + security fixes for the following issues: + - arbitrary read/write via grant copy + XSA-523 CVE-2026-102703 CVE-2026-102704 + + -- Hans van Kranenburg Tue, 03 Nov 2026 21:11:50 +0100 + xen (4.20.4+39-gf1e1321c87-0+deb13u1) trixie-security; urgency=medium * Update to new upstream version 4.20.4+39-gf1e1321c87, which also contains diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/acpi/cpu_idle.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/acpi/cpu_idle.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/acpi/cpu_idle.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/acpi/cpu_idle.c 2026-11-03 12:06:11.000000000 +0000 @@ -1073,6 +1073,24 @@ if ( c->x86_vendor == X86_VENDOR_INTEL && (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 14)) ) flags->bm_control = 0; + + if ( (c->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) && + c->x86 >= 0x17 ) + { + /* + * For all AMD Zen or newer CPUs that support C3, caches + * should not be flushed by software while entering C3 + * type state. Set bm_check to 1 so that Xen doesn't + * need to execute cache flush operation. + */ + flags->bm_check = 1; + /* + * In current AMD C state implementation ARB_DIS is no longer + * used. So set bm_control to zero to indicate ARB_DIS is not + * required while entering C3 type state. + */ + flags->bm_control = 0; + } } #define VENDOR_INTEL (1) diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/dom0_build.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/dom0_build.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/dom0_build.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/dom0_build.c 2026-11-03 12:06:11.000000000 +0000 @@ -229,6 +229,7 @@ if ( rs == e && d->arch.e820[i].type == type ) { d->arch.e820[i].addr = s; + d->arch.e820[i].size += e - s; return 0; } diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/emulate.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/emulate.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/emulate.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/emulate.c 2026-11-03 12:06:11.000000000 +0000 @@ -2343,6 +2343,7 @@ case 2: curr->arch.hvm.guest_cr[2] = val; + hvm_update_guest_cr(curr, 2); rc = X86EMUL_OKAY; break; diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/io.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/io.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/io.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/io.c 2026-11-03 12:06:11.000000000 +0000 @@ -136,7 +136,7 @@ default: gprintk(XENLOG_ERR, "Unexpected PIO status %d, port %#x %s 0x%0*x\n", rc, port, dir == IOREQ_WRITE ? "write" : "read", - size * 2, data & ((1u << (size * 8)) - 1)); + size * 2, data & (UINT32_MAX >> (32 - size * 8))); domain_crash(curr->domain); return false; } diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/svm/entry.S xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/svm/entry.S --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/svm/entry.S 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/svm/entry.S 2026-11-03 12:06:11.000000000 +0000 @@ -57,6 +57,37 @@ clgi + /* + * Interrupts need enabling prior to VMRUN. Anywhere after CLGI is + * safe. + * + * On all Zen CPUs to date, VMRUN has a bug and mixes up the host and + * guest INTR_SHADOW state. If there is a VMExit during VMRUN + * (e.g. taking NPT_FAULT during event injection), then the host's + * INTR_SHADOW gets written back into the VMCB, corrupting guest + * state. + * + * This is believed to go unnoticed for pre-FRED guests (injecting + * events cancels INTR_SHADOW), but FRED changes this behaviour to be + * able to observe and restore the shadow via the STB field in a FRED + * frame. + * + * In order to fix, arrange for Xen's INTR_SHADOW at the point of + * VMRUN to match the guest's INTR_SHADOW. This way, if a VMExit + * occurs, the VMCB is corrupted with the "correct" value. + * + * Commonly the guest will not be in an INTR_SHADOW. In this case, + * execute STI early to get Xen's INTR_SHADOW over and done with; the + * second STI does nothing as INTR_SHADOW only occurs when IF changes + * from 0 to 1. If the guest is in an INTR_SHADOW, skip the early STI + * so the late STI does trigger INTR_SHADOW and cover VMRUN. + */ + mov VCPU_svm_vmcb(%rbx), %rax + testb $1, VMCB_int_stat(%rax) + jnz 1f + sti +1: + /* WARNING! `ret`, `call *`, `jmp *` not safe beyond this point. */ /* SPEC_CTRL_EXIT_TO_SVM Req: b=curr %rsp=regs/cpuinfo, Clob: acd */ .macro svm_vmentry_spec_ctrl @@ -74,14 +105,6 @@ ALTERNATIVE "", svm_vmentry_spec_ctrl, X86_FEATURE_SC_MSR_HVM ALTERNATIVE "", DO_SPEC_CTRL_DIV, X86_FEATURE_SC_DIV - /* - * Set EFLAGS.IF after CLGI covers us from real interrupts, but not - * immediately prior to VMRUN. The VMRUN instruction leaks it's - * INTR_SHADOW into guest state if a VMExit occurs before VMRUN - * completes (e.g. taking #NPF during event injecting.) - */ - sti - pop %r15 pop %r14 pop %r13 @@ -101,6 +124,7 @@ SPEC_CTRL_COND_VERW /* Req: %rsp=eframe Clob: efl */ + sti vmrun SAVE_ALL diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/svm/svm.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/svm/svm.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/svm/svm.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/svm/svm.c 2026-11-03 12:06:11.000000000 +0000 @@ -1190,6 +1190,17 @@ if ( !(vmcb_get_cr0(vmcb) & X86_CR0_PE) ) goto raise_exception; /* TODO: support real-mode injection? */ + /* + * In vm86 mode, INT $N is subject to IOPL. + * + * TODO: It is also subject to CR4.VME=1, which would require reading the + * TSS Software Interrupt Redirection bitmap. + */ + if ( type == X86_ET_SW_INT && + regs->eflags & X86_EFLAGS_VM && + MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 ) + goto raise_exception; + idte_size = lm ? 16 : 8; idte_offset = trap * idte_size; @@ -1198,16 +1209,6 @@ (type == X86_ET_PRIV_SW_EXC ? X86_XEC_EXT : 0); /* - * TODO: This does not cover the v8086 mode with CR4.VME case - * correctly, but falls on the safe side from the point of view of a - * 32bit OS. Someone with many TUITs can see about reading the TSS - * Software Interrupt Redirection bitmap. - */ - if ( (regs->eflags & X86_EFLAGS_VM) && - MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 ) - goto raise_exception; - - /* * Read all 8/16 bytes so the idtr limit check is applied properly to * this entry, even though we don't look at all the words read. */ diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/vpt.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/vpt.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/hvm/vpt.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/hvm/vpt.c 2026-11-03 12:06:11.000000000 +0000 @@ -317,7 +317,7 @@ { struct list_head *head = &v->arch.hvm.tm_list; struct periodic_time *pt, *temp, *earliest_pt; - uint64_t max_lag; + uint64_t max_lag, generation; int irq, pt_vector = -1; bool level; @@ -356,6 +356,7 @@ } earliest_pt->irq_issued = 1; + generation = earliest_pt->generation; irq = earliest_pt->irq; level = earliest_pt->level; @@ -411,6 +412,9 @@ list_for_each_entry ( pt, &v->arch.hvm.tm_list, list ) if ( pt == earliest_pt ) { + if ( pt->generation != generation ) + break; + pt_irq_fired(v, pt); cb = pt->cb; cb_priv = pt->priv; @@ -550,6 +554,7 @@ set_timer(&pt->timer, pt->scheduled); pt_vcpu_lock(v); + pt->generation++; pt->on_list = 1; list_add(&pt->list, &v->arch.hvm.tm_list); pt_vcpu_unlock(v); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/include/asm/hvm/vpt.h xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/include/asm/hvm/vpt.h --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/include/asm/hvm/vpt.h 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/include/asm/hvm/vpt.h 2026-11-03 12:06:11.000000000 +0000 @@ -32,6 +32,7 @@ u8 irq; struct vcpu *vcpu; /* vcpu timer interrupt delivers to */ u32 pending_intr_nr; /* pending timer interrupts */ + uint64_t generation; /* distinguish two armings of the same timer */ u64 period; /* frequency in ns */ s_time_t scheduled; /* scheduled timer interrupt */ u64 last_plt_gtime; /* platform time when last IRQ is injected */ diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/include/asm/msr.h xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/include/asm/msr.h --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/include/asm/msr.h 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/include/asm/msr.h 2026-11-03 12:06:11.000000000 +0000 @@ -39,7 +39,7 @@ } /* Non-serialising WRMSR, when available. Falls back to a serialising WRMSR. */ -static inline void wrmsr_ns(uint32_t msr, uint32_t lo, uint32_t hi) +static always_inline void wrmsr_ns(uint32_t msr, uint32_t lo, uint32_t hi) { /* * WRMSR is 2 bytes. WRMSRNS is 3 bytes. Pad WRMSR with a redundant CS @@ -67,7 +67,7 @@ rc_; }) /* wrmsr with exception handling */ -static inline int wrmsr_safe(unsigned int msr, uint64_t val) +static always_inline int wrmsr_safe(unsigned int msr, uint64_t val) { int rc; uint32_t lo, hi; diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/include/asm/shstk.h xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/include/asm/shstk.h --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/include/asm/shstk.h 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/include/asm/shstk.h 2026-11-03 12:06:11.000000000 +0000 @@ -15,7 +15,7 @@ */ #define SSP_NO_SHSTK 1 -static inline unsigned long rdssp(void) +static always_inline unsigned long rdssp(void) { unsigned long ssp; @@ -24,7 +24,7 @@ return ssp; } -static inline void wrss(unsigned long val, unsigned long *ptr) +static always_inline void wrss(unsigned long val, unsigned long *ptr) { asm ( "wrssq %[val], %[ptr]" : [ptr] "=m" (*ptr) diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/mm/p2m-pod.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/mm/p2m-pod.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/mm/p2m-pod.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/mm/p2m-pod.c 2026-11-03 12:06:11.000000000 +0000 @@ -898,9 +898,10 @@ { mfn_t mfns[POD_SWEEP_STRIDE]; p2m_type_t types[POD_SWEEP_STRIDE]; - unsigned long *map[POD_SWEEP_STRIDE]; + unsigned int check = 0; + const unsigned long *map; struct domain *d = p2m->domain; - unsigned int i, j, max_ref = 1; + unsigned int j, max_ref = 1; BUG_ON(count > POD_SWEEP_STRIDE); @@ -908,8 +909,11 @@ if ( paging_mode_shadow(d) ) max_ref++; - /* First, get the gfn list, translate to mfns, and map the pages. */ - for ( i = 0; i < count; i++ ) + /* + * First, get the gfn list, translate to mfns, and check for being a + * plausible candidate. + */ + for ( unsigned int i = 0; i < count; i++ ) { p2m_access_t a; @@ -918,9 +922,8 @@ /* * If this is ram, and not a pagetable or a special page, and - * probably not mapped elsewhere, map it; otherwise, skip. + * probably not mapped elsewhere, check it; otherwise, skip. */ - map[i] = NULL; if ( p2m_is_ram(types[i]) ) { const struct page_info *pg = mfn_to_page(mfns[i]); @@ -929,7 +932,7 @@ (pg->count_info & PGC_allocated) && !(pg->count_info & PGC_shadowed_pt) && ((pg->count_info & PGC_count_mask) <= max_ref) ) - map[i] = map_domain_page(mfns[i]); + __set_bit(i, &check); } } @@ -937,20 +940,23 @@ * Then, go through and check for zeroed pages, removing write permission * for those with zeroes. */ - for ( i = 0; i < count; i++ ) + for_each_set_bit ( i, check ) { - if ( !map[i] ) - continue; - /* Quick zero-check */ + map = map_domain_page(mfns[i]); for ( j = 0; j < 16; j++ ) - if ( *(map[i] + j) != 0 ) - goto skip; + if ( map[j] != 0 ) + break; + unmap_domain_page(map); /* Try to remove the page, restoring old mapping if it fails. */ - if ( p2m_set_entry(p2m, gfns[i], INVALID_MFN, PAGE_ORDER_4K, + if ( j < 16 || + p2m_set_entry(p2m, gfns[i], INVALID_MFN, PAGE_ORDER_4K, p2m_populate_on_demand, p2m->default_access) ) - goto skip; + { + __clear_bit(i, &check); + continue; + } /* * See if the page was successfully unmapped. (Allow one refcount @@ -958,6 +964,8 @@ */ if ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) > 1 ) { + __clear_bit(i, &check); + /* * If the previous p2m_set_entry call succeeded, this one shouldn't * be able to fail. If it does, crashing the domain should be safe. @@ -967,38 +975,27 @@ { ASSERT_UNREACHABLE(); domain_crash(d); - goto out_unmap; + return; } - - skip: - unmap_domain_page(map[i]); - map[i] = NULL; - - continue; } } p2m_tlb_flush_sync(p2m); /* Now check each page for real */ - for ( i = 0; i < count; i++ ) + for_each_set_bit ( i, check ) { - if ( !map[i] ) - continue; - - for ( j = 0; j < (PAGE_SIZE / sizeof(*map[i])); j++ ) - if ( *(map[i] + j) != 0 ) + map = map_domain_page(mfns[i]); + for ( j = 0; j < (PAGE_SIZE / sizeof(*map)); j++ ) + if ( map[j] != 0 ) break; - - unmap_domain_page(map[i]); - - map[i] = NULL; + unmap_domain_page(map); /* * See comment in p2m_pod_zero_check_superpage() re gnttab * check timing. */ - if ( j < (PAGE_SIZE / sizeof(*map[i])) ) + if ( j < (PAGE_SIZE / sizeof(*map)) ) { /* * If the previous p2m_set_entry call succeeded, this one shouldn't @@ -1009,14 +1006,7 @@ { ASSERT_UNREACHABLE(); domain_crash(d); - out_unmap: - /* - * Something went wrong, probably crashing the domain. Unmap - * everything and return. - */ - for ( i = 0; i < count; i++ ) - if ( map[i] ) - unmap_domain_page(map[i]); + return; } } else diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/mm.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/mm.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/mm.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/mm.c 2026-11-03 12:06:11.000000000 +0000 @@ -1092,6 +1092,7 @@ * more information. */ #define PTF_partial_set (1 << 0) +#define PTF_recovery (1 << 1) #define PTF_preemptible (1 << 2) #define PTF_defer (1 << 3) #define PTF_retain_ref_on_restart (1 << 4) @@ -2849,15 +2850,21 @@ * *not* fully validated, continuing would almost certainly * open up a security hole. An exception to this is during * domain destruction, where PGT_validated can be dropped - * without dropping a type ref. + * without dropping a type ref. Another exception is on error + * paths from _get_page_type(), where the type ref was already + * put in place, but PGT_validated isn't set yet (page + * validation still pending). * - * If the latter, do nothing unless type PGT_partial is set. - * If it is set, the type count must be 1. + * In the domain destruction case, do nothing unless PGT_partial + * is set. If it is set, the type count must be 1. + * + * In the _get_page_type() error path case operate normally, + * again also including the type count sanity check. */ - if ( !(flags & PTF_partial_set) ) + if ( !(flags & (PTF_partial_set | PTF_recovery)) ) BUG_ON((x & PGT_partial) || !((x & PGT_validated) || page_get_owner(page)->is_dying)); - else if ( !(x & PGT_partial) ) + else if ( (flags & PTF_partial_set) && !(x & PGT_partial) ) return 0; else BUG_ON((x & PGT_count_mask) != 1); @@ -3134,7 +3141,7 @@ if ( unlikely(rc) ) { - _put_page_type(page, 0, NULL); + _put_page_type(page, PTF_recovery, NULL); goto out; } } diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/setup.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/setup.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/setup.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/setup.c 2026-11-03 12:06:11.000000000 +0000 @@ -913,6 +913,11 @@ wrmsrl(MSR_PL0_SSP, (unsigned long)stack + (PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8); + /* + * There must be no CALL or RET instructions between writing + * MSR_S_CET.SHSTK_EN and establishing SSP with SETSSBSY below. + * All helpers must be forced inline. + */ wrmsrl(MSR_S_CET, xen_msr_s_cet_value()); asm volatile ("setssbsy" ::: "memory"); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/x86_64/asm-offsets.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/x86_64/asm-offsets.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/x86_64/asm-offsets.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/x86_64/asm-offsets.c 2026-11-03 12:06:11.000000000 +0000 @@ -20,6 +20,10 @@ # include "../boot/video.h" #endif +#ifdef CONFIG_AMD_SVM +# include +#endif + #define DEFINE(_sym, _val) \ asm volatile ( "\n.ascii\"==>#define " #_sym " %0 /* " #_val " */<==\""\ :: "i" (_val) ) @@ -132,6 +136,11 @@ BLANK(); #endif +#ifdef CONFIG_AMD_SVM + OFFSET(VMCB_int_stat, struct vmcb_struct, int_stat); + BLANK(); +#endif + #ifdef CONFIG_PV32 OFFSET(DOMAIN_is_32bit_pv, struct domain, arch.pv.is_32bit); BLANK(); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/arch/x86/x86_64/domain.c xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/x86_64/domain.c --- xen-4.20.4+39-gf1e1321c87/xen/arch/x86/x86_64/domain.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/arch/x86/x86_64/domain.c 2026-11-03 12:06:11.000000000 +0000 @@ -58,6 +58,11 @@ rc = 0; guest_from_compat_handle(v->runstate_guest.compat, area.addr.h); + /* NULL handle is deregistering the address. */ + if ( compat_handle_is_null(area.addr.h) ) + break; + + /* Update the newly-registered runstate area, best-effort. */ if ( v == current ) { XLAT_vcpu_runstate_info(&info, &v->runstate); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/domain.c xen-4.20.4+63-g7abfd2bce2/xen/common/domain.c --- xen-4.20.4+39-gf1e1321c87/xen/common/domain.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/domain.c 2026-11-03 12:06:11.000000000 +0000 @@ -2079,12 +2079,21 @@ if ( copy_from_guest(&area, arg, 1) ) break; + /* NULL handle is deregistering the address. */ + if ( guest_handle_is_null(area.addr.h) ) + { + runstate_guest(v) = area.addr.h; + rc = 0; + break; + } + if ( !guest_handle_okay(area.addr.h, 1) ) break; rc = 0; runstate_guest(v) = area.addr.h; + /* Update the newly-registered runstate area, best-effort. */ if ( v == current ) { __copy_to_guest(runstate_guest(v), &v->runstate, 1); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/efi/boot.c xen-4.20.4+63-g7abfd2bce2/xen/common/efi/boot.c --- xen-4.20.4+39-gf1e1321c87/xen/common/efi/boot.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/efi/boot.c 2026-11-03 12:06:11.000000000 +0000 @@ -783,8 +783,13 @@ { file->addr = min(1UL << (32 + PAGE_SHIFT), HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START); - /* For config files allocate an extra byte to put a NUL there. */ - ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, + /* + * For config files allocate an extra byte to put a NUL there. There's + * also no constraint on addresses for them. + */ + ret = efi_bs->AllocatePages(file != &cfg ? AllocateMaxAddress + : AllocateAnyPages, + EfiLoaderData, PFN_UP(size + (file == &cfg)), &file->addr); } if ( EFI_ERROR(ret) ) @@ -836,7 +841,7 @@ if ( file == &cfg && file->size && !iscntrl(file->str[file->size - 1]) ) { EFI_PHYSICAL_ADDRESS addr; - EFI_STATUS ret = efi_bs->AllocatePages(AllocateMaxAddress, + EFI_STATUS ret = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData, PFN_UP(file->size + 1), &addr); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/grant_table.c xen-4.20.4+63-g7abfd2bce2/xen/common/grant_table.c --- xen-4.20.4+39-gf1e1321c87/xen/common/grant_table.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/grant_table.c 2026-11-03 12:06:11.000000000 +0000 @@ -2935,13 +2935,8 @@ bool have_type; }; -static int gnttab_copy_lock_domain(domid_t domid, bool is_gref, - struct gnttab_copy_buf *buf) +static int gnttab_copy_lock_domain(domid_t domid, struct gnttab_copy_buf *buf) { - /* Only DOMID_SELF may reference via frame. */ - if ( domid != DOMID_SELF && !is_gref ) - return GNTST_permission_denied; - buf->domain = rcu_lock_domain_by_any_id(domid); if ( !buf->domain ) @@ -2973,12 +2968,10 @@ { int rc; - rc = gnttab_copy_lock_domain(op->source.domid, - op->flags & GNTCOPY_source_gref, src); + rc = gnttab_copy_lock_domain(op->source.domid, src); if ( rc < 0 ) goto error; - rc = gnttab_copy_lock_domain(op->dest.domid, - op->flags & GNTCOPY_dest_gref, dest); + rc = gnttab_copy_lock_domain(op->dest.domid, dest); if ( rc < 0 ) goto error; @@ -3041,6 +3034,9 @@ buf->ptr.u.ref = ptr->u.ref; buf->have_grant = 1; } + /* Only DOMID_SELF may reference via frame. */ + else if ( ptr->domid != DOMID_SELF ) + return GNTST_permission_denied; else { rc = get_paged_frame(ptr->u.gmfn, &buf->mfn, &buf->page, @@ -3082,10 +3078,10 @@ const struct gnttab_copy_ptr *p, const struct gnttab_copy_buf *b, bool has_gref) { - if ( !b->virt ) + if ( !b->virt || b->have_grant != has_gref ) return 0; if ( has_gref ) - return b->have_grant && p->u.ref == b->ptr.u.ref; + return p->u.ref == b->ptr.u.ref; return p->u.gmfn == b->ptr.u.gmfn; } diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/ioreq.c xen-4.20.4+63-g7abfd2bce2/xen/common/ioreq.c --- xen-4.20.4+39-gf1e1321c87/xen/common/ioreq.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/ioreq.c 2026-11-03 12:06:11.000000000 +0000 @@ -595,7 +595,7 @@ rc = ioreq_server_alloc_rangesets(s, id); if ( rc ) - return rc; + goto fail_rangesets; s->bufioreq_handling = bufioreq_handling; @@ -614,6 +614,7 @@ ioreq_server_free_rangesets(s); + fail_rangesets: put_domain(s->emulator); return rc; } diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/page_alloc.c xen-4.20.4+63-g7abfd2bce2/xen/common/page_alloc.c --- xen-4.20.4+39-gf1e1321c87/xen/common/page_alloc.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/page_alloc.c 2026-11-03 12:06:11.000000000 +0000 @@ -2941,7 +2941,7 @@ if ( need_scrub ) { /* TODO: asynchronous scrubbing for pages of static memory. */ - scrub_one_page(pg); + scrub_one_page(&pg[i]); } pg[i].count_info |= PGC_static; diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/rangeset.c xen-4.20.4+63-g7abfd2bce2/xen/common/rangeset.c --- xen-4.20.4+39-gf1e1321c87/xen/common/rangeset.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/rangeset.c 2026-11-03 12:06:11.000000000 +0000 @@ -239,9 +239,10 @@ destroy_range(r, t); } - x->s = e + 1; - if ( x->s > x->e ) + if ( x->e <= e ) destroy_range(r, x); + else + x->s = e + 1; } out: diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/sched/core.c xen-4.20.4+63-g7abfd2bce2/xen/common/sched/core.c --- xen-4.20.4+39-gf1e1321c87/xen/common/sched/core.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/sched/core.c 2026-11-03 12:06:11.000000000 +0000 @@ -459,18 +459,17 @@ static void sched_domain_insert_unit(struct sched_unit *unit, struct domain *d) { - struct sched_unit **prev_unit; + struct sched_unit **next_unit; unit->domain = d; - for ( prev_unit = &d->sched_unit_list; *prev_unit; - prev_unit = &(*prev_unit)->next_in_list ) - if ( (*prev_unit)->next_in_list && - (*prev_unit)->next_in_list->unit_id > unit->unit_id ) + for ( next_unit = &d->sched_unit_list; *next_unit; + next_unit = &(*next_unit)->next_in_list ) + if ( (*next_unit)->unit_id > unit->unit_id ) break; - unit->next_in_list = *prev_unit; - *prev_unit = unit; + unit->next_in_list = *next_unit; + *next_unit = unit; } static struct sched_unit *sched_alloc_unit(struct vcpu *v) @@ -3019,6 +3018,7 @@ printk("scheduler %s misses .%s, dropped\n", \ schedulers[i]->opt_name, #f); \ schedulers[i] = NULL; \ + continue; \ } sched_test_func(init); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/common/sched/credit2.c xen-4.20.4+63-g7abfd2bce2/xen/common/sched/credit2.c --- xen-4.20.4+39-gf1e1321c87/xen/common/sched/credit2.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/common/sched/credit2.c 2026-11-03 12:06:11.000000000 +0000 @@ -3513,9 +3513,11 @@ /* * If this is on a different processor, don't pull it unless - * its credit is at least CSCHED2_MIGRATE_RESIST higher. + * its credit is at least CSCHED2_MIGRATE_RESIST higher, or the + * processor was tickled for it. */ if ( sched_unit_master(svc->unit) != cpu + && svc->tickled_cpu != cpu && snext->credit + CSCHED2_MIGRATE_RESIST > svc->credit ) { SCHED_STAT_CRANK(migrate_resisted); diff -Nru xen-4.20.4+39-gf1e1321c87/xen/drivers/passthrough/amd/iommu_acpi.c xen-4.20.4+63-g7abfd2bce2/xen/drivers/passthrough/amd/iommu_acpi.c --- xen-4.20.4+39-gf1e1321c87/xen/drivers/passthrough/amd/iommu_acpi.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/drivers/passthrough/amd/iommu_acpi.c 2026-11-03 12:06:11.000000000 +0000 @@ -414,8 +414,8 @@ exclusion = true; else if ( ivmd_block->header.flags & ACPI_IVMD_UNITY ) { - iw = ivmd_block->header.flags & ACPI_IVMD_READ; - ir = ivmd_block->header.flags & ACPI_IVMD_WRITE; + iw = ivmd_block->header.flags & ACPI_IVMD_WRITE; + ir = ivmd_block->header.flags & ACPI_IVMD_READ; } else { diff -Nru xen-4.20.4+39-gf1e1321c87/xen/drivers/passthrough/amd/iommu_cmd.c xen-4.20.4+63-g7abfd2bce2/xen/drivers/passthrough/amd/iommu_cmd.c --- xen-4.20.4+39-gf1e1321c87/xen/drivers/passthrough/amd/iommu_cmd.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/drivers/passthrough/amd/iommu_cmd.c 2026-11-03 12:06:11.000000000 +0000 @@ -212,7 +212,7 @@ set_field_in_reg_u32(sflag, 0, IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK, - IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK, &entry); + IOMMU_INV_IOTLB_PAGES_S_FLAG_SHIFT, &entry); set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, entry, IOMMU_INV_IOTLB_PAGES_ADDR_LOW_MASK, diff -Nru xen-4.20.4+39-gf1e1321c87/xen/include/public/vcpu.h xen-4.20.4+63-g7abfd2bce2/xen/include/public/vcpu.h --- xen-4.20.4+39-gf1e1321c87/xen/include/public/vcpu.h 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/include/public/vcpu.h 2026-11-03 12:06:11.000000000 +0000 @@ -112,6 +112,7 @@ * VCPU was last scheduled to run. * 3. New code wants to prefer VCPUOP_register_runstate_phys_area, and only * fall back to the operation here for backwards compatibility. + * 4. Passing a NULL handle will deregister the region. * @extra_arg == pointer to vcpu_register_runstate_memory_area structure. */ #define VCPUOP_register_runstate_memory_area 5 @@ -233,7 +234,7 @@ * area. Note that as long as an area is registered by physical address, the * linear address based area will not be serviced (updated) by the hypervisor. * - * Note that the area registered via VCPUOP_register_runstate_memory_area will + * Note that the area registered via VCPUOP_register_runstate_phys_area will * be updated in the same manner as the one registered via virtual address PLUS * VMASST_TYPE_runstate_update_flag engaged by the domain. * diff -Nru xen-4.20.4+39-gf1e1321c87/xen/tools/symbols.c xen-4.20.4+63-g7abfd2bce2/xen/tools/symbols.c --- xen-4.20.4+39-gf1e1321c87/xen/tools/symbols.c 2026-10-13 13:02:22.000000000 +0000 +++ xen-4.20.4+63-g7abfd2bce2/xen/tools/symbols.c 2026-11-03 12:06:11.000000000 +0000 @@ -208,6 +208,11 @@ (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) || (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext"))) return 0; + /* Same for non-text aliases of _sinittext. */ + if (toupper(*s->sym) != 'T' + && s->addr == _sinittext + && strcmp((const char *)s->sym + offset, "_sinittext")) + return 0; } /* Exclude symbols which vary between passes. */