From 60deece08b32062faa4da67bcc835d7f61c36b1d Mon Sep 17 00:00:00 2001 From: Krystian Hebel Date: Fri, 11 Oct 2024 14:42:35 +0200 Subject: [PATCH] Remove unreferenced patches c664a5efde 'Update to Xen 4.19.0' removed references to 0317-0319 and 0500, but not the patches themselves. First three patches were later reintroduced as 0300-0302. Signed-off-by: Krystian Hebel --- ...xen-list-add-LIST_HEAD_RO_AFTER_INIT.patch | 35 -- ...or-marking-only-part-of-a-MMIO-page-.patch | 507 ------------------ ...-sub-page-ro-API-to-make-just-xhci-d.patch | 89 --- 0500-xsa458.patch | 38 -- 4 files changed, 669 deletions(-) delete mode 100644 0317-xen-list-add-LIST_HEAD_RO_AFTER_INIT.patch delete mode 100644 0318-x86-mm-add-API-for-marking-only-part-of-a-MMIO-page-.patch delete mode 100644 0319-drivers-char-Use-sub-page-ro-API-to-make-just-xhci-d.patch delete mode 100644 0500-xsa458.patch diff --git a/0317-xen-list-add-LIST_HEAD_RO_AFTER_INIT.patch b/0317-xen-list-add-LIST_HEAD_RO_AFTER_INIT.patch deleted file mode 100644 index 5600fce8..00000000 --- a/0317-xen-list-add-LIST_HEAD_RO_AFTER_INIT.patch +++ /dev/null @@ -1,35 +0,0 @@ -From efc9b6dbe429c64ea2b6c06964cf3d7be1bc68de Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= - -Date: Sat, 22 Jun 2024 18:08:09 +0200 -Subject: [PATCH] xen/list: add LIST_HEAD_RO_AFTER_INIT -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Similar to LIST_HEAD_READ_MOSTLY. - -Signed-off-by: Marek Marczykowski-Górecki ---- -New in v5 ---- - xen/include/xen/list.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/xen/include/xen/list.h b/xen/include/xen/list.h -index dc5a8c461b9c..6915a987cd1a 100644 ---- a/xen/include/xen/list.h -+++ b/xen/include/xen/list.h -@@ -42,6 +42,9 @@ struct list_head { - #define LIST_HEAD_READ_MOSTLY(name) \ - struct list_head __read_mostly name = LIST_HEAD_INIT(name) - -+#define LIST_HEAD_RO_AFTER_INIT(name) \ -+ struct list_head __ro_after_init name = LIST_HEAD_INIT(name) -+ - static inline void INIT_LIST_HEAD(struct list_head *list) - { - list->next = list; --- -2.45.2 - diff --git a/0318-x86-mm-add-API-for-marking-only-part-of-a-MMIO-page-.patch b/0318-x86-mm-add-API-for-marking-only-part-of-a-MMIO-page-.patch deleted file mode 100644 index 99b592dd..00000000 --- a/0318-x86-mm-add-API-for-marking-only-part-of-a-MMIO-page-.patch +++ /dev/null @@ -1,507 +0,0 @@ -From 224cb5c6751a1b9488dd1d09c81559123eab67be Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= - -Date: Mon, 20 Mar 2023 21:19:25 +0100 -Subject: [PATCH] x86/mm: add API for marking only part of a MMIO page read - only -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In some cases, only few registers on a page needs to be write-protected. -Examples include USB3 console (64 bytes worth of registers) or MSI-X's -PBA table (which doesn't need to span the whole table either), although -in the latter case the spec forbids placing other registers on the same -page. Current API allows only marking whole pages pages read-only, -which sometimes may cover other registers that guest may need to -write into. - -Currently, when a guest tries to write to an MMIO page on the -mmio_ro_ranges, it's either immediately crashed on EPT violation - if -that's HVM, or if PV, it gets #PF. In case of Linux PV, if access was -from userspace (like, /dev/mem), it will try to fixup by updating page -tables (that Xen again will force to read-only) and will hit that #PF -again (looping endlessly). Both behaviors are undesirable if guest could -actually be allowed the write. - -Introduce an API that allows marking part of a page read-only. Since -sub-page permissions are not a thing in page tables (they are in EPT, -but not granular enough), do this via emulation (or simply page fault -handler for PV) that handles writes that are supposed to be allowed. -The new subpage_mmio_ro_add() takes a start physical address and the -region size in bytes. Both start address and the size need to be 8-byte -aligned, as a practical simplification (allows using smaller bitmask, -and a smaller granularity isn't really necessary right now). -It will internally add relevant pages to mmio_ro_ranges, but if either -start or end address is not page-aligned, it additionally adds that page -to a list for sub-page R/O handling. The list holds a bitmask which -qwords are supposed to be read-only and an address where page is mapped -for write emulation - this mapping is done only on the first access. A -plain list is used instead of more efficient structure, because there -isn't supposed to be many pages needing this precise r/o control. - -The mechanism this API is plugged in is slightly different for PV and -HVM. For both paths, it's plugged into mmio_ro_emulated_write(). For PV, -it's already called for #PF on read-only MMIO page. For HVM however, EPT -violation on p2m_mmio_direct page results in a direct domain_crash() for -non hardware domains. To reach mmio_ro_emulated_write(), change how -write violations for p2m_mmio_direct are handled - specifically, check -if they relate to such partially protected page via -subpage_mmio_write_accept() and if so, call hvm_emulate_one_mmio() for -them too. This decodes what guest is trying write and finally calls -mmio_ro_emulated_write(). The EPT write violation is detected as -npfec.write_access and npfec.present both being true (similar to other -places), which may cover some other (future?) cases - if that happens, -emulator might get involved unnecessarily, but since it's limited to -pages marked with subpage_mmio_ro_add() only, the impact is minimal. -Both of those paths need an MFN to which guest tried to write (to check -which part of the page is supposed to be read-only, and where -the page is mapped for writes). This information currently isn't -available directly in mmio_ro_emulated_write(), but in both cases it is -already resolved somewhere higher in the call tree. Pass it down to -mmio_ro_emulated_write() via new mmio_ro_emulate_ctxt.mfn field. - -This may give a bit more access to the instruction emulator to HVM -guests (the change in hvm_hap_nested_page_fault()), but only for pages -explicitly marked with subpage_mmio_ro_add() - so, if the guest has a -passed through a device partially used by Xen. -As of the next patch, it applies only configuration explicitly -documented as not security supported. - -The subpage_mmio_ro_add() function cannot be called with overlapping -ranges, and on pages already added to mmio_ro_ranges separately. -Successful calls would result in correct handling, but error paths may -result in incorrect state (like pages removed from mmio_ro_ranges too -early). Debug build has asserts for relevant cases. - -Signed-off-by: Marek Marczykowski-Górecki ---- -Shadow mode is not tested, but I don't expect it to work differently than -HAP in areas related to this patch. - -Changes in v5: -- use subpage_mmio_find_page helper, simplifying several functions -- use LIST_HEAD_RO_AFTER_INIT -- don't use subpage_ro_lock in __init -- drop #ifdef in mm.h -- return error on unaligned size in subpage_mmio_ro_add() instead of - extending the size (in release build) -Changes in v4: -- rename SUBPAGE_MMIO_RO_ALIGN to MMIO_RO_SUBPAGE_GRAN -- guard subpage_mmio_write_accept with CONFIG_HVM, as it's used only - there -- rename ro_qwords to ro_elems -- use unsigned arguments for subpage_mmio_ro_remove_page() -- use volatile for __iomem -- do not set mmio_ro_ctxt.mfn for mmcfg case -- comment where fields of mmio_ro_ctxt are used -- use bool for result of __test_and_set_bit -- do not open-code mfn_to_maddr() -- remove leftover RCU -- mention hvm_hap_nested_page_fault() explicitly in the commit message -Changes in v3: -- use unsigned int for loop iterators -- use __set_bit/__clear_bit when under spinlock -- avoid ioremap() under spinlock -- do not cast away const -- handle unaligned parameters in release build -- comment fixes -- remove RCU - the add functions are __init and actual usage is only - much later after domains are running -- add checks overlapping ranges in debug build and document the - limitations -- change subpage_mmio_ro_add() so the error path doesn't potentially - remove pages from mmio_ro_ranges -- move printing message to avoid one goto in - subpage_mmio_write_emulate() -Changes in v2: -- Simplify subpage_mmio_ro_add() parameters -- add to mmio_ro_ranges from within subpage_mmio_ro_add() -- use ioremap() instead of caller-provided fixmap -- use 8-bytes granularity (largest supported single write) and a bitmap - instead of a rangeset -- clarify commit message -- change how it's plugged in for HVM domain, to not change the behavior for - read-only parts (keep it hitting domain_crash(), instead of ignoring - write) -- remove unused subpage_mmio_ro_remove() ---- - xen/arch/x86/hvm/emulate.c | 2 +- - xen/arch/x86/hvm/hvm.c | 4 +- - xen/arch/x86/include/asm/mm.h | 23 +++ - xen/arch/x86/mm.c | 262 ++++++++++++++++++++++++++++++++ - xen/arch/x86/pv/ro-page-fault.c | 6 +- - 5 files changed, 292 insertions(+), 5 deletions(-) - -diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c -index 27928dc3f3cb..296dfc4a3479 100644 ---- a/xen/arch/x86/hvm/emulate.c -+++ b/xen/arch/x86/hvm/emulate.c -@@ -2739,7 +2739,7 @@ int hvm_emulate_one_mmio(unsigned long mfn, unsigned long gla) - .write = mmio_ro_emulated_write, - .validate = hvmemul_validate, - }; -- struct mmio_ro_emulate_ctxt mmio_ro_ctxt = { .cr2 = gla }; -+ struct mmio_ro_emulate_ctxt mmio_ro_ctxt = { .cr2 = gla, .mfn = _mfn(mfn) }; - struct hvm_emulate_ctxt ctxt; - const struct x86_emulate_ops *ops; - unsigned int seg, bdf; -diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c -index a51d4c16cee8..02d1b3a3adcc 100644 ---- a/xen/arch/x86/hvm/hvm.c -+++ b/xen/arch/x86/hvm/hvm.c -@@ -1973,8 +1973,8 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla, - goto out_put_gfn; - } - -- if ( (p2mt == p2m_mmio_direct) && is_hardware_domain(currd) && -- npfec.write_access && npfec.present && -+ if ( (p2mt == p2m_mmio_direct) && npfec.write_access && npfec.present && -+ (is_hardware_domain(currd) || subpage_mmio_write_accept(mfn, gla)) && - (hvm_emulate_one_mmio(mfn_x(mfn), gla) == X86EMUL_OKAY) ) - { - rc = 1; -diff --git a/xen/arch/x86/include/asm/mm.h b/xen/arch/x86/include/asm/mm.h -index 5845b729c3f7..79a2b7f0d339 100644 ---- a/xen/arch/x86/include/asm/mm.h -+++ b/xen/arch/x86/include/asm/mm.h -@@ -518,9 +518,32 @@ extern struct rangeset *mmio_ro_ranges; - void memguard_guard_stack(void *p); - void memguard_unguard_stack(void *p); - -+/* -+ * Add more precise r/o marking for a MMIO page. Range specified here -+ * will still be R/O, but the rest of the page (not marked as R/O via another -+ * call) will have writes passed through. -+ * The start address and the size must be aligned to MMIO_RO_SUBPAGE_GRAN. -+ * -+ * This API cannot be used for overlapping ranges, nor for pages already added -+ * to mmio_ro_ranges separately. -+ * -+ * Since there is currently no subpage_mmio_ro_remove(), relevant device should -+ * not be hot-unplugged. -+ * -+ * Return values: -+ * - negative: error -+ * - 0: success -+ */ -+#define MMIO_RO_SUBPAGE_GRAN 8 -+int subpage_mmio_ro_add(paddr_t start, size_t size); -+bool subpage_mmio_write_accept(mfn_t mfn, unsigned long gla); -+ - struct mmio_ro_emulate_ctxt { - unsigned long cr2; -+ /* Used only for mmcfg case */ - unsigned int seg, bdf; -+ /* Used only for non-mmcfg case */ -+ mfn_t mfn; - }; - - int cf_check mmio_ro_emulated_write( -diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c -index 30ef59fbc5cd..8545ebed119d 100644 ---- a/xen/arch/x86/mm.c -+++ b/xen/arch/x86/mm.c -@@ -168,6 +168,17 @@ bool __read_mostly machine_to_phys_mapping_valid; - - struct rangeset *__read_mostly mmio_ro_ranges; - -+/* Handling sub-page read-only MMIO regions */ -+struct subpage_ro_range { -+ struct list_head list; -+ mfn_t mfn; -+ void __iomem *mapped; -+ DECLARE_BITMAP(ro_elems, PAGE_SIZE / MMIO_RO_SUBPAGE_GRAN); -+}; -+ -+static LIST_HEAD_RO_AFTER_INIT(subpage_ro_ranges); -+static DEFINE_SPINLOCK(subpage_ro_lock); -+ - static uint32_t base_disallow_mask; - /* Global bit is allowed to be set on L1 PTEs. Intended for user mappings. */ - #define L1_DISALLOW_MASK ((base_disallow_mask | _PAGE_GNTTAB) & ~_PAGE_GLOBAL) -@@ -4975,6 +4986,254 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) - return 0; - } - -+static void __iomem *subpage_mmio_find_page(mfn_t mfn) -+{ -+ struct subpage_ro_range *entry; -+ -+ list_for_each_entry(entry, &subpage_ro_ranges, list) -+ if ( mfn_eq(entry->mfn, mfn) ) -+ return entry; -+ -+ return NULL; -+} -+ -+/* -+ * Mark part of the page as R/O. -+ * Returns: -+ * - 0 on success - first range in the page -+ * - 1 on success - subsequent range in the page -+ * - <0 on error -+ */ -+static int __init subpage_mmio_ro_add_page( -+ mfn_t mfn, -+ unsigned int offset_s, -+ unsigned int offset_e) -+{ -+ struct subpage_ro_range *entry = NULL, *iter; -+ unsigned int i; -+ -+ entry = subpage_mmio_find_page(mfn); -+ if ( !entry ) -+ { -+ /* iter == NULL marks it was a newly allocated entry */ -+ iter = NULL; -+ entry = xzalloc(struct subpage_ro_range); -+ if ( !entry ) -+ return -ENOMEM; -+ entry->mfn = mfn; -+ } -+ -+ for ( i = offset_s; i <= offset_e; i += MMIO_RO_SUBPAGE_GRAN ) -+ { -+ bool oldbit = __test_and_set_bit(i / MMIO_RO_SUBPAGE_GRAN, -+ entry->ro_elems); -+ ASSERT(!oldbit); -+ } -+ -+ if ( !iter ) -+ list_add(&entry->list, &subpage_ro_ranges); -+ -+ return iter ? 1 : 0; -+} -+ -+static void __init subpage_mmio_ro_remove_page( -+ mfn_t mfn, -+ unsigned int offset_s, -+ unsigned int offset_e) -+{ -+ struct subpage_ro_range *entry = NULL; -+ unsigned int i; -+ -+ entry = subpage_mmio_find_page(mfn); -+ if ( !entry ) -+ return; -+ -+ for ( i = offset_s; i <= offset_e; i += MMIO_RO_SUBPAGE_GRAN ) -+ __clear_bit(i / MMIO_RO_SUBPAGE_GRAN, entry->ro_elems); -+ -+ if ( !bitmap_empty(entry->ro_elems, PAGE_SIZE / MMIO_RO_SUBPAGE_GRAN) ) -+ return; -+ -+ list_del(&entry->list); -+ if ( entry->mapped ) -+ iounmap(entry->mapped); -+ xfree(entry); -+} -+ -+int __init subpage_mmio_ro_add( -+ paddr_t start, -+ size_t size) -+{ -+ mfn_t mfn_start = maddr_to_mfn(start); -+ paddr_t end = start + size - 1; -+ mfn_t mfn_end = maddr_to_mfn(end); -+ unsigned int offset_end = 0; -+ int rc; -+ bool subpage_start, subpage_end; -+ -+ ASSERT(IS_ALIGNED(start, MMIO_RO_SUBPAGE_GRAN)); -+ ASSERT(IS_ALIGNED(size, MMIO_RO_SUBPAGE_GRAN)); -+ if ( !IS_ALIGNED(size, MMIO_RO_SUBPAGE_GRAN) ) -+ return -EINVAL; -+ -+ if ( !size ) -+ return 0; -+ -+ if ( mfn_eq(mfn_start, mfn_end) ) -+ { -+ /* Both starting and ending parts handled at once */ -+ subpage_start = PAGE_OFFSET(start) || PAGE_OFFSET(end) != PAGE_SIZE - 1; -+ subpage_end = false; -+ } -+ else -+ { -+ subpage_start = PAGE_OFFSET(start); -+ subpage_end = PAGE_OFFSET(end) != PAGE_SIZE - 1; -+ } -+ -+ if ( subpage_start ) -+ { -+ offset_end = mfn_eq(mfn_start, mfn_end) ? -+ PAGE_OFFSET(end) : -+ (PAGE_SIZE - 1); -+ rc = subpage_mmio_ro_add_page(mfn_start, -+ PAGE_OFFSET(start), -+ offset_end); -+ if ( rc < 0 ) -+ goto err_unlock; -+ /* Check if not marking R/W part of a page intended to be fully R/O */ -+ ASSERT(rc || !rangeset_contains_singleton(mmio_ro_ranges, -+ mfn_x(mfn_start))); -+ } -+ -+ if ( subpage_end ) -+ { -+ rc = subpage_mmio_ro_add_page(mfn_end, 0, PAGE_OFFSET(end)); -+ if ( rc < 0 ) -+ goto err_unlock_remove; -+ /* Check if not marking R/W part of a page intended to be fully R/O */ -+ ASSERT(rc || !rangeset_contains_singleton(mmio_ro_ranges, -+ mfn_x(mfn_end))); -+ } -+ -+ rc = rangeset_add_range(mmio_ro_ranges, mfn_x(mfn_start), mfn_x(mfn_end)); -+ if ( rc ) -+ goto err_remove; -+ -+ return 0; -+ -+ err_remove: -+ if ( subpage_end ) -+ subpage_mmio_ro_remove_page(mfn_end, 0, PAGE_OFFSET(end)); -+ err_unlock_remove: -+ if ( subpage_start ) -+ subpage_mmio_ro_remove_page(mfn_start, PAGE_OFFSET(start), offset_end); -+ err_unlock: -+ return rc; -+} -+ -+static void __iomem *subpage_mmio_map_page( -+ struct subpage_ro_range *entry) -+{ -+ void __iomem *mapped_page; -+ -+ if ( entry->mapped ) -+ return entry->mapped; -+ -+ mapped_page = ioremap(mfn_to_maddr(entry->mfn), PAGE_SIZE); -+ -+ spin_lock(&subpage_ro_lock); -+ /* Re-check under the lock */ -+ if ( entry->mapped ) -+ { -+ spin_unlock(&subpage_ro_lock); -+ if ( mapped_page ) -+ iounmap(mapped_page); -+ return entry->mapped; -+ } -+ -+ entry->mapped = mapped_page; -+ spin_unlock(&subpage_ro_lock); -+ return entry->mapped; -+} -+ -+static void subpage_mmio_write_emulate( -+ mfn_t mfn, -+ unsigned int offset, -+ const void *data, -+ unsigned int len) -+{ -+ struct subpage_ro_range *entry; -+ volatile void __iomem *addr; -+ -+ entry = subpage_mmio_find_page(mfn); -+ if ( !entry ) -+ /* Do not print message for pages without any writable parts. */ -+ return; -+ -+ if ( test_bit(offset / MMIO_RO_SUBPAGE_GRAN, entry->ro_elems) ) -+ { -+write_ignored: -+ gprintk(XENLOG_WARNING, -+ "ignoring write to R/O MMIO 0x%"PRI_mfn"%03x len %u\n", -+ mfn_x(mfn), offset, len); -+ return; -+ } -+ -+ addr = subpage_mmio_map_page(entry); -+ if ( !addr ) -+ { -+ gprintk(XENLOG_ERR, -+ "Failed to map page for MMIO write at 0x%"PRI_mfn"%03x\n", -+ mfn_x(mfn), offset); -+ return; -+ } -+ -+ switch ( len ) -+ { -+ case 1: -+ writeb(*(const uint8_t*)data, addr); -+ break; -+ case 2: -+ writew(*(const uint16_t*)data, addr); -+ break; -+ case 4: -+ writel(*(const uint32_t*)data, addr); -+ break; -+ case 8: -+ writeq(*(const uint64_t*)data, addr); -+ break; -+ default: -+ /* mmio_ro_emulated_write() already validated the size */ -+ ASSERT_UNREACHABLE(); -+ goto write_ignored; -+ } -+} -+ -+#ifdef CONFIG_HVM -+bool subpage_mmio_write_accept(mfn_t mfn, unsigned long gla) -+{ -+ unsigned int offset = PAGE_OFFSET(gla); -+ const struct subpage_ro_range *entry; -+ -+ entry = subpage_mmio_find_page(mfn); -+ if ( !entry ) -+ return false; -+ -+ if ( !test_bit(offset / MMIO_RO_SUBPAGE_GRAN, entry->ro_elems) ) -+ { -+ /* -+ * We don't know the write size at this point yet, so it could be -+ * an unaligned write, but accept it here anyway and deal with it -+ * later. -+ */ -+ return true; -+ } -+ -+ return false; -+} -+#endif -+ - int cf_check mmio_ro_emulated_write( - enum x86_segment seg, - unsigned long offset, -@@ -4993,6 +5252,9 @@ int cf_check mmio_ro_emulated_write( - return X86EMUL_UNHANDLEABLE; - } - -+ subpage_mmio_write_emulate(mmio_ro_ctxt->mfn, PAGE_OFFSET(offset), -+ p_data, bytes); -+ - return X86EMUL_OKAY; - } - -diff --git a/xen/arch/x86/pv/ro-page-fault.c b/xen/arch/x86/pv/ro-page-fault.c -index f23ad5d184ea..367cbc7a04c5 100644 ---- a/xen/arch/x86/pv/ro-page-fault.c -+++ b/xen/arch/x86/pv/ro-page-fault.c -@@ -345,8 +345,10 @@ static int mmio_ro_do_page_fault(struct x86_emulate_ctxt *ctxt, - ctxt->data = &mmio_ro_ctxt; - if ( pci_ro_mmcfg_decode(mfn_x(mfn), &mmio_ro_ctxt.seg, &mmio_ro_ctxt.bdf) ) - return x86_emulate(ctxt, &mmcfg_intercept_ops); -- else -- return x86_emulate(ctxt, &mmio_ro_emulate_ops); -+ -+ mmio_ro_ctxt.mfn = mfn; -+ -+ return x86_emulate(ctxt, &mmio_ro_emulate_ops); - } - - int pv_ro_page_fault(unsigned long addr, struct cpu_user_regs *regs) --- -2.45.2 - diff --git a/0319-drivers-char-Use-sub-page-ro-API-to-make-just-xhci-d.patch b/0319-drivers-char-Use-sub-page-ro-API-to-make-just-xhci-d.patch deleted file mode 100644 index 15cecfd5..00000000 --- a/0319-drivers-char-Use-sub-page-ro-API-to-make-just-xhci-d.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 5015db14c2076ea7617d3bcdc5f7ac81953f6df8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= - -Date: Fri, 24 Mar 2023 18:24:41 +0100 -Subject: [PATCH] drivers/char: Use sub-page ro API to make just xhci dbc cap - RO -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Not the whole page, which may contain other registers too. The XHCI -specification describes DbC as designed to be controlled by a different -driver, but does not mandate placing registers on a separate page. In fact -on Tiger Lake and newer (at least), this page do contain other registers -that Linux tries to use. And with share=yes, a domU would use them too. -Without this patch, PV dom0 would fail to initialize the controller, -while HVM would be killed on EPT violation. - -With `share=yes`, this patch gives domU more access to the emulator -(although a HVM with any emulated device already has plenty of it). This -configuration is already documented as unsafe with untrusted guests and -not security supported. - -Signed-off-by: Marek Marczykowski-Górecki ---- -Changes in v4: -- restore mmio_ro_ranges in the fallback case -- set XHCI_SHARE_NONE in the fallback case -Changes in v3: -- indentation fix -- remove stale comment -- fallback to pci_ro_device() if subpage_mmio_ro_add() fails -- extend commit message -Changes in v2: - - adjust for simplified subpage_mmio_ro_add() API ---- - xen/drivers/char/xhci-dbc.c | 36 ++++++++++++++++++++++-------------- - 1 file changed, 22 insertions(+), 14 deletions(-) - -diff --git a/xen/drivers/char/xhci-dbc.c b/xen/drivers/char/xhci-dbc.c -index c2a2129acf47..43ce96985c5d 100644 ---- a/xen/drivers/char/xhci-dbc.c -+++ b/xen/drivers/char/xhci-dbc.c -@@ -1215,20 +1215,28 @@ static void __init cf_check dbc_uart_init_postirq(struct serial_port *port) - break; - } - #ifdef CONFIG_X86 -- /* -- * This marks the whole page as R/O, which may include other registers -- * unrelated to DbC. Xen needs only DbC area protected, but it seems -- * Linux's XHCI driver (as of 5.18) works without writting to the whole -- * page, so keep it simple. -- */ -- if ( rangeset_add_range(mmio_ro_ranges, -- PFN_DOWN((uart->dbc.bar_val & PCI_BASE_ADDRESS_MEM_MASK) + -- uart->dbc.xhc_dbc_offset), -- PFN_UP((uart->dbc.bar_val & PCI_BASE_ADDRESS_MEM_MASK) + -- uart->dbc.xhc_dbc_offset + -- sizeof(*uart->dbc.dbc_reg)) - 1) ) -- printk(XENLOG_INFO -- "Error while adding MMIO range of device to mmio_ro_ranges\n"); -+ if ( subpage_mmio_ro_add( -+ (uart->dbc.bar_val & PCI_BASE_ADDRESS_MEM_MASK) + -+ uart->dbc.xhc_dbc_offset, -+ sizeof(*uart->dbc.dbc_reg)) ) -+ { -+ printk(XENLOG_WARNING -+ "Error while marking MMIO range of XHCI console as R/O, " -+ "making the whole device R/O (share=no)\n"); -+ uart->dbc.share = XHCI_SHARE_NONE; -+ if ( pci_ro_device(0, uart->dbc.sbdf.bus, uart->dbc.sbdf.devfn) ) -+ printk(XENLOG_WARNING -+ "Failed to mark read-only %pp used for XHCI console\n", -+ &uart->dbc.sbdf); -+ if ( rangeset_add_range(mmio_ro_ranges, -+ PFN_DOWN((uart->dbc.bar_val & PCI_BASE_ADDRESS_MEM_MASK) + -+ uart->dbc.xhc_dbc_offset), -+ PFN_UP((uart->dbc.bar_val & PCI_BASE_ADDRESS_MEM_MASK) + -+ uart->dbc.xhc_dbc_offset + -+ sizeof(*uart->dbc.dbc_reg)) - 1) ) -+ printk(XENLOG_INFO -+ "Error while adding MMIO range of device to mmio_ro_ranges\n"); -+ } - #endif - } - --- -2.45.2 - diff --git a/0500-xsa458.patch b/0500-xsa458.patch deleted file mode 100644 index 8be0a901..00000000 --- a/0500-xsa458.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Jan Beulich -Subject: x86/IRQ: avoid double unlock in map_domain_pirq() - -Forever since its introduction the main loop in the function dealing -with multi-vector MSI had error exit points ("break") with different -properties: In one case no IRQ descriptor lock is being held. -Nevertheless the subsequent error cleanup path assumed such a lock would -uniformly need releasing. Identify the case by setting "desc" to NULL, -thus allowing the unlock to be skipped as necessary. - -This is CVE-2024-31143 / XSA-458. - -Coverity ID: 1605298 -Fixes: d1b6d0a02489 ("x86: enable multi-vector MSI") -Signed-off-by: Jan Beulich -Reviewed-by: Roger Pau Monné - ---- a/xen/arch/x86/irq.c -+++ b/xen/arch/x86/irq.c -@@ -2273,6 +2273,7 @@ int map_domain_pirq( - - set_domain_irq_pirq(d, irq, info); - spin_unlock_irqrestore(&desc->lock, flags); -+ desc = NULL; - - info = NULL; - irq = create_irq(NUMA_NO_NODE, true); -@@ -2308,7 +2309,9 @@ int map_domain_pirq( - - if ( ret ) - { -- spin_unlock_irqrestore(&desc->lock, flags); -+ if ( desc ) -+ spin_unlock_irqrestore(&desc->lock, flags); -+ - pci_disable_msi(msi_desc); - if ( nr ) - {