From f45ab27774aadeee28f093a9f074892e9bebb586 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sun, 5 Apr 2026 08:42:00 +0800 Subject: [PATCH 1/5] ARM: xen: validate hypervisor compatible before parsing its version fdt_find_hyper_node() reads the raw compatible property and then derives hyper_node.version from a prefix match before later printing it with %s. Flat DT properties are external boot input, and this path does not prove that the first compatible entry is NUL-terminated within the returned property length. Keep the existing flat-DT lookup path, but verify that the first compatible entry terminates within the returned property length before deriving the version suffix from it. Signed-off-by: Pengpeng Hou Reviewed-by: Stefano Stabellini Signed-off-by: Juergen Gross Message-ID: <20260405094005.5-arm-xen-v2-pengpeng@iscas.ac.cn> --- arch/arm/xen/enlighten.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 4feed2c2498d..25a0ce3b4584 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -218,8 +218,9 @@ static __initdata struct { static int __init fdt_find_hyper_node(unsigned long node, const char *uname, int depth, void *data) { - const void *s = NULL; + const char *s = NULL; int len; + size_t prefix_len = strlen(hyper_node.prefix); if (depth != 1 || strcmp(uname, "hypervisor") != 0) return 0; @@ -228,9 +229,10 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname, hyper_node.found = true; s = of_get_flat_dt_prop(node, "compatible", &len); - if (strlen(hyper_node.prefix) + 3 < len && - !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix))) - hyper_node.version = s + strlen(hyper_node.prefix); + if (s && len > 0 && strnlen(s, len) < len && + len > prefix_len + 3 && + !strncmp(hyper_node.prefix, s, prefix_len)) + hyper_node.version = s + prefix_len; /* * Check if Xen supports EFI by checking whether there is the From 7f8862d2873d8b0e0df805a9aef1972d8ad4f08e Mon Sep 17 00:00:00 2001 From: GuoHan Zhao Date: Tue, 7 Apr 2026 10:24:43 +0800 Subject: [PATCH 2/5] xen/manage: unwind partial shutdown watcher setup on error setup_shutdown_watcher() registers shutdown_watch first, then the sysrq watch, and finally publishes the supported feature-* nodes in xenstore. If sysrq watch registration fails, or xenbus_printf() fails after one or more feature nodes were created, the function returns immediately without undoing the earlier setup. This leaves the system in a partially initialized state, with registered watches and/or stale xenstore entries despite the function reporting failure. Unwind the partial setup before returning an error by unregistering any watches that were already registered and removing feature nodes that were already published. Signed-off-by: GuoHan Zhao Reviewed-by: Stefano Stabellini Signed-off-by: Juergen Gross Message-ID: <20260407022443.12971-1-zhaoguohan@kylinos.cn> --- drivers/xen/manage.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index e20c40a62e64..05d7de128e71 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -343,12 +343,11 @@ static int setup_shutdown_watcher(void) return err; } - #ifdef CONFIG_MAGIC_SYSRQ err = register_xenbus_watch(&sysrq_watch); if (err) { pr_err("Failed to set sysrq watcher\n"); - return err; + goto err_unregister_shutdown; } #endif @@ -361,11 +360,26 @@ static int setup_shutdown_watcher(void) if (err) { pr_err("%s: Error %d writing %s\n", __func__, err, node); - return err; + goto err_remove_features; } } return 0; + +err_remove_features: + while (--idx >= 0) { + if (!shutdown_handlers[idx].flag) + continue; + snprintf(node, FEATURE_PATH_SIZE, "feature-%s", + shutdown_handlers[idx].command); + xenbus_rm(XBT_NIL, "control", node); + } +#ifdef CONFIG_MAGIC_SYSRQ + unregister_xenbus_watch(&sysrq_watch); +err_unregister_shutdown: +#endif + unregister_xenbus_watch(&shutdown_watch); + return err; } static int shutdown_event(struct notifier_block *notifier, From fdfdd01e801f4e808cba27b3e78504cfeca610d9 Mon Sep 17 00:00:00 2001 From: Kexin Sun Date: Sat, 21 Mar 2026 19:00:39 +0800 Subject: [PATCH 3/5] xen/swiotlb: fix stale reference to swiotlb_unmap_page() Commit af85de5a9f00 ("xen: swiotlb: Switch to physical address mapping callbacks") renamed xen_swiotlb_unmap_page() to xen_swiotlb_unmap_phys(). The comment in xen_swiotlb_unmap_sg() had already been missing the xen_ prefix (reading swiotlb_unmap_page()), and the rename only changed _page to _phys without correcting this, leaving it as swiotlb_unmap_phys(). Fix the reference to use the correct function name xen_swiotlb_unmap_phys(). Assisted-by: unnamed:deepseek-v3.2 coccinelle Signed-off-by: Kexin Sun Signed-off-by: Juergen Gross Message-ID: <20260321110039.8905-1-kexinsun@smail.nju.edu.cn> --- drivers/xen/swiotlb-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index ccf25027bec1..4a734ee38994 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -340,7 +340,7 @@ xen_swiotlb_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, /* * Unmap a set of streaming mode DMA translations. Again, cpu read rules - * concerning calls here are the same as for swiotlb_unmap_phys() above. + * concerning calls here are the same as for xen_swiotlb_unmap_phys() above. */ static void xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, From bdd5de3d9e2da45852d0d21313af3a02f0e0626e Mon Sep 17 00:00:00 2001 From: Jason Andryuk Date: Wed, 18 Mar 2026 19:53:26 -0400 Subject: [PATCH 4/5] hvc/xen: Check console connection flag When the console out buffer is filled, __write_console() will return 0 as it cannot send any data. domU_write_console() will then spin in `while (len)` as len doesn't decrement until xenconsoled attaches. This would block a domU and nullify the parallelism of Hyperlaunch until dom0 userspace starts xenconsoled, which empties the buffer. Xen 4.21 added a connection field to the xen console page. This is set to XENCONSOLE_DISCONNECTED (1) when a domain is built, and xenconsoled will set it to XENCONSOLE_CONNECTED (0) when it connects. Update the hvc_xen driver to check the field. When the field is disconnected, drop the write with -ENOTCONN. We only drop the write when the field is XENCONSOLE_DISCONNECTED (1) to try for maximum compatibility. The Xen toolstack has historically zero initialized the console, so it should see XENCONSOLE_CONNECTED (0) by default. If an implemenation used uninitialized memory, only checking for XENCONSOLE_DISCONNECTED could have the lowest chance of not connecting. This lets the hyperlaunched domU boot without stalling. Once dom0 starts xenconsoled, xl console can be used to access the domU's hvc0. Paritally sync console.h from xen.git to bring in the new field. Reviewed-by: Stefano Stabellini Signed-off-by: Jason Andryuk Signed-off-by: Juergen Gross Message-ID: <20260318235326.14568-1-jason.andryuk@amd.com> --- drivers/tty/hvc/hvc_xen.c | 3 +++ include/xen/interface/io/console.h | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 7f0b6262488c..c407592442cd 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -139,6 +139,9 @@ static ssize_t domU_write_console(uint32_t vtermno, const u8 *data, size_t len) if (cons == NULL) return -EINVAL; + if (cons->intf->connection == XENCONSOLE_DISCONNECTED) + return -ENOTCONN; + /* * Make sure the whole buffer is emitted, polling if * necessary. We don't ever want to rely on the hvc daemon diff --git a/include/xen/interface/io/console.h b/include/xen/interface/io/console.h index cf17e89ed861..687949bdebb1 100644 --- a/include/xen/interface/io/console.h +++ b/include/xen/interface/io/console.h @@ -19,6 +19,19 @@ struct xencons_interface { char out[2048]; XENCONS_RING_IDX in_cons, in_prod; XENCONS_RING_IDX out_cons, out_prod; +/* + * Flag values signaling from backend to frontend whether the console is + * connected. i.e. Whether it will be serviced and emptied. + * + * The flag starts as disconnected. + */ +#define XENCONSOLE_DISCONNECTED 1 +/* + * The flag is set to connected when the backend connects and the console + * will be serviced. + */ +#define XENCONSOLE_CONNECTED 0 + uint8_t connection; }; #endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */ From 3f100dd61ad4ee7c1fb6a44775a928dcdba7515b Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Tue, 10 Mar 2026 08:08:00 +0000 Subject: [PATCH 5/5] xen/grant-table: guard gnttab_suspend/resume with CONFIG_HIBERNATE_CALLBACKS In current linux.git, gnttab_suspend() and gnttab_resume() are defined and declared unconditionally. However, their only in-tree callers reside in drivers/xen/manage.c, which are guarded by CONFIG_HIBERNATE_CALLBACKS. Match the helper scope to their callers by wrapping the definitions in CONFIG_HIBERNATE_CALLBACKS and providing no-op stubs in the header. This fixes the config-scope mismatch and reduces the code footprint when hibernation callbacks are disabled. Signed-off-by: Pengpeng Hou Signed-off-by: Juergen Gross Message-ID: <20260310080800.742223-1-pengpeng.hou@isrc.iscas.ac.cn> --- drivers/xen/grant-table.c | 3 ++- include/xen/grant_table.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 97e27f754d39..a6abf1ccd54c 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -1579,7 +1579,7 @@ static int gnttab_setup(void) } return gnttab_map(0, nr_grant_frames - 1); } - +#ifdef CONFIG_HIBERNATE_CALLBACKS int gnttab_resume(void) { gnttab_request_version(); @@ -1592,6 +1592,7 @@ int gnttab_suspend(void) gnttab_interface->unmap_frames(); return 0; } +#endif static int gnttab_expand(unsigned int req_entries) { diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 69ac6d80a006..a33a60a2ea72 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -84,8 +84,20 @@ struct gntab_unmap_queue_data }; int gnttab_init(void); +#ifdef CONFIG_HIBERNATE_CALLBACKS int gnttab_suspend(void); int gnttab_resume(void); +#else +static inline int gnttab_suspend(void) +{ + return 0; +} + +static inline int gnttab_resume(void) +{ + return 0; +} +#endif int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly);