From 4c5ba7acd74f950fbff1e4fb9c038c4446635659 Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Fri, 6 Jun 2025 20:44:26 +0800 Subject: [PATCH 01/15] um: virtio_pcidev: Rename UM_PCI_STAT_WAITING Rename it to VIRTIO_PCIDEV_STAT_WAITING to make the code slightly more consistent. It was missed when refactoring virtio_pcidev into a separate module. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250606124428.148164-3-tiwei.btw@antgroup.com Signed-off-by: Johannes Berg --- arch/um/drivers/virtio_pcidev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/um/drivers/virtio_pcidev.c b/arch/um/drivers/virtio_pcidev.c index 3c4c4c928fdd..e9e23cc3f357 100644 --- a/arch/um/drivers/virtio_pcidev.c +++ b/arch/um/drivers/virtio_pcidev.c @@ -42,7 +42,7 @@ struct virtio_pcidev_device { void *extra_ptrs[VIRTIO_PCIDEV_WRITE_BUFS + 1]; DECLARE_BITMAP(used_bufs, VIRTIO_PCIDEV_WRITE_BUFS); -#define UM_PCI_STAT_WAITING 0 +#define VIRTIO_PCIDEV_STAT_WAITING 0 unsigned long status; bool platform; @@ -172,7 +172,7 @@ static int virtio_pcidev_send_cmd(struct virtio_pcidev_device *dev, } /* kick and poll for getting a response on the queue */ - set_bit(UM_PCI_STAT_WAITING, &dev->status); + set_bit(VIRTIO_PCIDEV_STAT_WAITING, &dev->status); virtqueue_kick(dev->cmd_vq); ret = 0; @@ -193,7 +193,7 @@ static int virtio_pcidev_send_cmd(struct virtio_pcidev_device *dev, } udelay(1); } - clear_bit(UM_PCI_STAT_WAITING, &dev->status); + clear_bit(VIRTIO_PCIDEV_STAT_WAITING, &dev->status); if (bounce_out) memcpy(out, buf->data, out_size); @@ -439,7 +439,7 @@ static void virtio_pcidev_cmd_vq_cb(struct virtqueue *vq) void *cmd; int len; - if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) + if (test_bit(VIRTIO_PCIDEV_STAT_WAITING, &dev->status)) return; while ((cmd = virtqueue_get_buf(vq, &len))) From c36e5eb9dd3258f654d05d8c1f09d03126dc2488 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Mon, 30 Jun 2025 08:51:16 +0200 Subject: [PATCH 02/15] um: virt-pci: Switch to msi_create_parent_irq_domain() Move away from the legacy MSI domain setup, switch to use msi_create_parent_irq_domain(). Signed-off-by: Nam Cao Acked-by: Johannes Berg Tested-by: Johannes Berg Link: https://patch.msgid.link/5f0bd8e877e7bfdfb1a7e99d6b126caf6a7eea48.1751266049.git.namcao@linutronix.de Signed-off-by: Johannes Berg --- arch/um/drivers/Kconfig | 1 + arch/um/drivers/virt-pci.c | 43 +++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/um/drivers/Kconfig b/arch/um/drivers/Kconfig index 34085bfc6d41..6a0354ca032f 100644 --- a/arch/um/drivers/Kconfig +++ b/arch/um/drivers/Kconfig @@ -160,6 +160,7 @@ config UML_RTC config UML_PCI bool select FORCE_PCI + select IRQ_MSI_LIB select UML_IOMEM_EMULATION select UML_DMA_EMULATION select PCI_MSI diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index 0fe207ca4b72..557d93aea00a 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ static struct um_pci_device *um_pci_platform_device; static struct um_pci_device_reg um_pci_devices[MAX_DEVICES]; static struct fwnode_handle *um_pci_fwnode; static struct irq_domain *um_pci_inner_domain; -static struct irq_domain *um_pci_msi_domain; static unsigned long um_pci_msi_used[BITS_TO_LONGS(MAX_MSI_VECTORS)]; static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, @@ -400,21 +400,24 @@ static void um_pci_inner_domain_free(struct irq_domain *domain, } static const struct irq_domain_ops um_pci_inner_domain_ops = { + .select = msi_lib_irq_domain_select, .alloc = um_pci_inner_domain_alloc, .free = um_pci_inner_domain_free, }; -static struct irq_chip um_pci_msi_irq_chip = { - .name = "UM virtual PCIe MSI", - .irq_mask = pci_msi_mask_irq, - .irq_unmask = pci_msi_unmask_irq, -}; +#define UM_PCI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_NO_AFFINITY) +#define UM_PCI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX) -static struct msi_domain_info um_pci_msi_domain_info = { - .flags = MSI_FLAG_USE_DEF_DOM_OPS | - MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_PCI_MSIX, - .chip = &um_pci_msi_irq_chip, +static const struct msi_parent_ops um_pci_msi_parent_ops = { + .required_flags = UM_PCI_MSI_FLAGS_REQUIRED, + .supported_flags = UM_PCI_MSI_FLAGS_SUPPORTED, + .bus_select_token = DOMAIN_BUS_NEXUS, + .bus_select_mask = MATCH_PCI_MSI, + .prefix = "UM-virtual-", + .init_dev_msi_info = msi_lib_init_dev_msi_info, }; static struct resource busn_resource = { @@ -559,17 +562,14 @@ static int __init um_pci_init(void) goto free; } - um_pci_inner_domain = irq_domain_create_linear(um_pci_fwnode, MAX_MSI_VECTORS, - &um_pci_inner_domain_ops, NULL); - if (!um_pci_inner_domain) { - err = -ENOMEM; - goto free; - } + struct irq_domain_info info = { + .fwnode = um_pci_fwnode, + .ops = &um_pci_inner_domain_ops, + .size = MAX_MSI_VECTORS, + }; - um_pci_msi_domain = pci_msi_create_irq_domain(um_pci_fwnode, - &um_pci_msi_domain_info, - um_pci_inner_domain); - if (!um_pci_msi_domain) { + um_pci_inner_domain = msi_create_parent_irq_domain(&info, &um_pci_msi_parent_ops); + if (!um_pci_inner_domain) { err = -ENOMEM; goto free; } @@ -611,7 +611,6 @@ device_initcall(um_pci_init); static void __exit um_pci_exit(void) { - irq_domain_remove(um_pci_msi_domain); irq_domain_remove(um_pci_inner_domain); pci_free_resource_list(&bridge->windows); pci_free_host_bridge(bridge); From 32a15664efe9b44b64a7179b47cc7742af5098c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 3 Jul 2025 14:38:54 +0200 Subject: [PATCH 03/15] um/x86: Add system call table to header file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generic system call tracing infrastructure requires access to the system call table. The symbol is already visible to the linker but is lacking a public declaration. Add a public declaration. Signed-off-by: Thomas Weißschuh Reviewed-by: Nam Cao Link: https://patch.msgid.link/20250703-uml-have_syscall_tracepoints-v1-1-23c1d3808578@linutronix.de Signed-off-by: Johannes Berg --- arch/x86/um/asm/syscall.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/um/asm/syscall.h b/arch/x86/um/asm/syscall.h index 56a2f0913e3c..d6208d0fad51 100644 --- a/arch/x86/um/asm/syscall.h +++ b/arch/x86/um/asm/syscall.h @@ -9,6 +9,8 @@ typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); +extern const sys_call_ptr_t sys_call_table[]; + static inline int syscall_get_arch(struct task_struct *task) { #ifdef CONFIG_X86_32 From 2a713f04eddd97f5893de73b1ccd789e69ac0a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 3 Jul 2025 14:38:55 +0200 Subject: [PATCH 04/15] um/ptrace: Implement HAVE_SYSCALL_TRACEPOINTS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement syscall tracepoints through the generic tracing infrastructure. Signed-off-by: Thomas Weißschuh Reviewed-by: Nam Cao Link: https://patch.msgid.link/20250703-uml-have_syscall_tracepoints-v1-2-23c1d3808578@linutronix.de Signed-off-by: Johannes Berg --- arch/um/Kconfig | 1 + arch/um/include/asm/thread_info.h | 2 ++ arch/um/kernel/ptrace.c | 9 +++++++++ 3 files changed, 12 insertions(+) diff --git a/arch/um/Kconfig b/arch/um/Kconfig index f08e8a7fac93..c2d2d2d99bbe 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -35,6 +35,7 @@ config UML select HAVE_RUST select ARCH_HAS_UBSAN select HAVE_ARCH_TRACEHOOK + select HAVE_SYSCALL_TRACEPOINTS select THREAD_INFO_IN_TASK config MMU diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index f9ad06fcc991..b8c021f97bd1 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -43,6 +43,8 @@ struct thread_info { #define TIF_NOTIFY_RESUME 8 #define TIF_SECCOMP 9 /* secure computing */ #define TIF_SINGLESTEP 10 /* single stepping userspace */ +#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ + #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 2124624b7817..fdbb37b5c399 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -9,6 +9,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + void user_enable_single_step(struct task_struct *child) { set_tsk_thread_flag(child, TIF_SINGLESTEP); @@ -126,6 +129,9 @@ int syscall_trace_enter(struct pt_regs *regs) UPT_SYSCALL_ARG3(®s->regs), UPT_SYSCALL_ARG4(®s->regs)); + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + trace_sys_enter(regs, UPT_SYSCALL_NR(®s->regs)); + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return 0; @@ -142,6 +148,9 @@ void syscall_trace_leave(struct pt_regs *regs) if (test_thread_flag(TIF_SINGLESTEP)) send_sigtrap(®s->regs, 0); + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + trace_sys_exit(regs, PT_REGS_SYSCALL_RET(regs)); + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; From ac1ad16f10523c2c60aef0abeb8a850ea6d06ced Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Jul 2025 14:12:42 +0200 Subject: [PATCH 05/15] um: simplify syscall header files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since Thomas's recent commit 2af10530639b ("um/x86: Add system call table to header file") , we now have two extern declarations of the syscall table, one internal and one external, and they don't even match on 32-bit. Clean this up and remove all the extra code. Reviewed-by: Thomas Weißschuh Link: https://patch.msgid.link/20250704141243.a68366f6acc3.If8587a4aafdb90644fc6d0b2f5e31a2d1887915f@changeid Signed-off-by: Johannes Berg --- arch/um/kernel/skas/syscall.c | 11 ++++++++-- arch/x86/um/shared/sysdep/ptrace.h | 12 ----------- arch/x86/um/shared/sysdep/syscalls.h | 6 ------ arch/x86/um/shared/sysdep/syscalls_32.h | 14 ------------- arch/x86/um/shared/sysdep/syscalls_64.h | 28 ------------------------- 5 files changed, 9 insertions(+), 62 deletions(-) delete mode 100644 arch/x86/um/shared/sysdep/syscalls.h delete mode 100644 arch/x86/um/shared/sysdep/syscalls_32.h delete mode 100644 arch/x86/um/shared/sysdep/syscalls_64.h diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index a5beaea2967e..ba7494f9bfe4 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include #include #include @@ -43,7 +43,14 @@ void handle_syscall(struct uml_pt_regs *r) tt_extra_sched_jiffies += 1; if (syscall >= 0 && syscall < __NR_syscalls) { - unsigned long ret = EXECUTE_SYSCALL(syscall, regs); + unsigned long ret; + + ret = (*sys_call_table[syscall])(UPT_SYSCALL_ARG1(®s->regs), + UPT_SYSCALL_ARG2(®s->regs), + UPT_SYSCALL_ARG3(®s->regs), + UPT_SYSCALL_ARG4(®s->regs), + UPT_SYSCALL_ARG5(®s->regs), + UPT_SYSCALL_ARG6(®s->regs)); PT_REGS_SET_SYSCALL_RETURN(regs, ret); diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h index 8f7476ff6e95..572ea2d79131 100644 --- a/arch/x86/um/shared/sysdep/ptrace.h +++ b/arch/x86/um/shared/sysdep/ptrace.h @@ -44,18 +44,6 @@ #include "ptrace_64.h" #endif -struct syscall_args { - unsigned long args[6]; -}; - -#define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) - extern unsigned long host_fp_size; struct uml_pt_regs { diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h deleted file mode 100644 index b2060ac707f0..000000000000 --- a/arch/x86/um/shared/sysdep/syscalls.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifdef __i386__ -#include "syscalls_32.h" -#else -#include "syscalls_64.h" -#endif diff --git a/arch/x86/um/shared/sysdep/syscalls_32.h b/arch/x86/um/shared/sysdep/syscalls_32.h deleted file mode 100644 index f6e9f84397e7..000000000000 --- a/arch/x86/um/shared/sysdep/syscalls_32.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include -#include - -typedef long syscall_handler_t(struct syscall_args); - -extern syscall_handler_t *sys_call_table[]; - -#define EXECUTE_SYSCALL(syscall, regs) \ - ((*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) diff --git a/arch/x86/um/shared/sysdep/syscalls_64.h b/arch/x86/um/shared/sysdep/syscalls_64.h deleted file mode 100644 index b6b997225841..000000000000 --- a/arch/x86/um/shared/sysdep/syscalls_64.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __SYSDEP_X86_64_SYSCALLS_H__ -#define __SYSDEP_X86_64_SYSCALLS_H__ - -#include -#include - -typedef long syscall_handler_t(long, long, long, long, long, long); - -extern syscall_handler_t *sys_call_table[]; - -#define EXECUTE_SYSCALL(syscall, regs) \ - (((*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(®s->regs), \ - UPT_SYSCALL_ARG2(®s->regs), \ - UPT_SYSCALL_ARG3(®s->regs), \ - UPT_SYSCALL_ARG4(®s->regs), \ - UPT_SYSCALL_ARG5(®s->regs), \ - UPT_SYSCALL_ARG6(®s->regs))) - -extern syscall_handler_t sys_modify_ldt; -extern syscall_handler_t sys_arch_prctl; - -#endif From b9e2f2246eb2b5617d53af7b5e4e1b8c916f26a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 4 Jul 2025 14:34:47 +0200 Subject: [PATCH 06/15] um: Re-evaluate thread flags repeatedly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The thread flags may change during their processing. For example a task_work can queue a new signal to be sent. This signal should be delivered before returning to usespace again. Evaluate the flags repeatedly similar to other architectures. Signed-off-by: Thomas Weißschuh Reviewed-by: Nam Cao Link: https://patch.msgid.link/20250704-uml-thread_flags-v1-1-0e293fd8d627@linutronix.de Signed-off-by: Johannes Berg --- arch/um/include/asm/thread_info.h | 4 ++++ arch/um/kernel/process.c | 18 +++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index b8c021f97bd1..545d298c1b23 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -52,7 +52,11 @@ struct thread_info { #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) #define _TIF_MEMDIE (1 << TIF_MEMDIE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) +#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \ + _TIF_NOTIFY_RESUME) + #endif diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 0cd6fad3d908..1be644de9e41 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -82,14 +82,18 @@ struct task_struct *__switch_to(struct task_struct *from, struct task_struct *to void interrupt_end(void) { struct pt_regs *regs = ¤t->thread.regs; + unsigned long thread_flags; - if (need_resched()) - schedule(); - if (test_thread_flag(TIF_SIGPENDING) || - test_thread_flag(TIF_NOTIFY_SIGNAL)) - do_signal(regs); - if (test_thread_flag(TIF_NOTIFY_RESUME)) - resume_user_mode_work(regs); + thread_flags = read_thread_flags(); + while (thread_flags & _TIF_WORK_MASK) { + if (thread_flags & _TIF_NEED_RESCHED) + schedule(); + if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) + do_signal(regs); + if (thread_flags & _TIF_NOTIFY_RESUME) + resume_user_mode_work(regs); + thread_flags = read_thread_flags(); + } } int get_current_pid(void) From 159e76514b9565f92ca5beebc1f92faed21a03aa Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Tue, 8 Jul 2025 17:04:00 +0800 Subject: [PATCH 07/15] um: Make unscheduled_userspace_iterations static It's only used within process.c. Make it static. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250708090403.1067440-2-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/os-Linux/skas/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index e42ffac23e3c..d3dd4fb559cf 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -548,7 +548,7 @@ out_close: return err; } -int unscheduled_userspace_iterations; +static int unscheduled_userspace_iterations; extern unsigned long tt_extra_sched_jiffies; void userspace(struct uml_pt_regs *regs) From 409a0c00c490d3b7c077e316a9261462241acda7 Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Tue, 8 Jul 2025 17:04:01 +0800 Subject: [PATCH 08/15] um: Make mm_list and mm_list_lock static They are only used within mmu.c. Make them static. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250708090403.1067440-3-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/kernel/skas/mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 849fafa4b54f..afe9a2f251ef 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -20,8 +20,8 @@ /* Ensure the stub_data struct covers the allocated area */ static_assert(sizeof(struct stub_data) == STUB_DATA_PAGES * UM_KERN_PAGE_SIZE); -spinlock_t mm_list_lock; -struct list_head mm_list; +static spinlock_t mm_list_lock; +static struct list_head mm_list; int init_new_context(struct task_struct *task, struct mm_struct *mm) { From 5d2c5b8c410c13995aeee7fdf52b7184a084d506 Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Tue, 8 Jul 2025 17:04:02 +0800 Subject: [PATCH 09/15] um: Avoid redefining ARCH_HAS_CACHE_LINE_SIZE There is a generic ARCH_HAS_CACHE_LINE_SIZE option introduced by commit c2280be81de4 ("mm: generalize ARCH_HAS_CACHE_LINE_SIZE") in mm/Kconfig. Select that instead. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250708090403.1067440-4-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/um/Kconfig b/arch/um/Kconfig index c2d2d2d99bbe..9083bfdb7735 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -6,6 +6,7 @@ config UML bool default y select ARCH_WANTS_DYNAMIC_TASK_STRUCT + select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL @@ -83,9 +84,6 @@ config NR_CPUS range 1 1 default 1 -config ARCH_HAS_CACHE_LINE_SIZE - def_bool y - source "arch/$(HEADER_ARCH)/um/Kconfig" config MAY_HAVE_RUNTIME_DEPS From 4c916e3b224a02019b3cc3983a15f32bfd9a22df Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Tue, 8 Jul 2025 17:04:03 +0800 Subject: [PATCH 10/15] um: rtc: Avoid shadowing err in uml_rtc_start() Remove the declaration of 'err' inside the 'if (timetravel)' block, as it would otherwise be unavailable outside that block, potentially leading to uml_rtc_start() returning an uninitialized value. Fixes: dde8b58d5127 ("um: add a pseudo RTC") Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250708090403.1067440-5-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/drivers/rtc_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/drivers/rtc_user.c b/arch/um/drivers/rtc_user.c index 51e79f3148cd..67912fcf7b28 100644 --- a/arch/um/drivers/rtc_user.c +++ b/arch/um/drivers/rtc_user.c @@ -28,7 +28,7 @@ int uml_rtc_start(bool timetravel) int err; if (timetravel) { - int err = os_pipe(uml_rtc_irq_fds, 1, 1); + err = os_pipe(uml_rtc_irq_fds, 1, 1); if (err) goto fail; } else { From 8129b9e8e32cb1a8976bbe5d7d14f215639758d2 Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Wed, 9 Jul 2025 09:00:21 +0800 Subject: [PATCH 11/15] um: vfio: Support adding devices via mconsole It can be used when we want to pass through PCI devices to UML while it's up and running. PCI devices can be passed through to UML using the same syntax as the command line option: (mconsole) config vfio_uml.device= Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250709010021.1076902-1-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/drivers/vfio_kern.c | 62 ++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/arch/um/drivers/vfio_kern.c b/arch/um/drivers/vfio_kern.c index 13b971a2bd43..915812a79bfc 100644 --- a/arch/um/drivers/vfio_kern.c +++ b/arch/um/drivers/vfio_kern.c @@ -16,6 +16,7 @@ #include #include +#include "mconsole_kern.h" #include "virt-pci.h" #include "vfio_user.h" @@ -60,6 +61,7 @@ static LIST_HEAD(uml_vfio_groups); static DEFINE_MUTEX(uml_vfio_groups_mtx); static LIST_HEAD(uml_vfio_devices); +static DEFINE_MUTEX(uml_vfio_devices_mtx); static int uml_vfio_set_container(int group_fd) { @@ -581,32 +583,44 @@ static struct uml_vfio_device *uml_vfio_find_device(const char *device) return NULL; } -static int uml_vfio_cmdline_set(const char *device, const struct kernel_param *kp) +static struct uml_vfio_device *uml_vfio_add_device(const char *device) { struct uml_vfio_device *dev; int fd; + guard(mutex)(¨_vfio_devices_mtx); + if (uml_vfio_container.fd < 0) { fd = uml_vfio_user_open_container(); if (fd < 0) - return fd; + return ERR_PTR(fd); uml_vfio_container.fd = fd; } if (uml_vfio_find_device(device)) - return -EEXIST; + return ERR_PTR(-EEXIST); dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) - return -ENOMEM; + return ERR_PTR(-ENOMEM); dev->name = kstrdup(device, GFP_KERNEL); if (!dev->name) { kfree(dev); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } list_add_tail(&dev->list, ¨_vfio_devices); + return dev; +} + +static int uml_vfio_cmdline_set(const char *device, const struct kernel_param *kp) +{ + struct uml_vfio_device *dev; + + dev = uml_vfio_add_device(device); + if (IS_ERR(dev)) + return PTR_ERR(dev); return 0; } @@ -629,6 +643,42 @@ __uml_help(uml_vfio_cmdline_param_ops, " through multiple PCI devices to UML.\n\n" ); +static int uml_vfio_mc_config(char *str, char **error_out) +{ + struct uml_vfio_device *dev; + + if (*str != '=') { + *error_out = "Invalid config"; + return -EINVAL; + } + str += 1; + + dev = uml_vfio_add_device(str); + if (IS_ERR(dev)) + return PTR_ERR(dev); + uml_vfio_open_device(dev); + return 0; +} + +static int uml_vfio_mc_id(char **str, int *start_out, int *end_out) +{ + return -EOPNOTSUPP; +} + +static int uml_vfio_mc_remove(int n, char **error_out) +{ + return -EOPNOTSUPP; +} + +static struct mc_device uml_vfio_mc = { + .list = LIST_HEAD_INIT(uml_vfio_mc.list), + .name = "vfio_uml.device", + .config = uml_vfio_mc_config, + .get_config = NULL, + .id = uml_vfio_mc_id, + .remove = uml_vfio_mc_remove, +}; + static int __init uml_vfio_init(void) { struct uml_vfio_device *dev, *n; @@ -639,6 +689,8 @@ static int __init uml_vfio_init(void) list_for_each_entry_safe(dev, n, ¨_vfio_devices, list) uml_vfio_open_device(dev); + mconsole_register_dev(¨_vfio_mc); + return 0; } late_initcall(uml_vfio_init); From cba737fa595f076f4b11df045d74bf6dfbc8db2f Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Fri, 11 Jul 2025 14:50:19 +0800 Subject: [PATCH 12/15] um: Use err consistently in userspace() Avoid declaring a new variable 'ret' inside the 'if (using_seccomp)' block, as the existing 'err' variable declared at the top of the function already serves the same purpose. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250711065021.2535362-2-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/os-Linux/skas/process.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index d3dd4fb559cf..79541574f70d 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -592,12 +592,11 @@ void userspace(struct uml_pt_regs *regs) if (using_seccomp) { struct mm_id *mm_id = current_mm_id(); struct stub_data *proc_data = (void *) mm_id->stack; - int ret; - ret = set_stub_state(regs, proc_data, singlestepping()); - if (ret) { + err = set_stub_state(regs, proc_data, singlestepping()); + if (err) { printk(UM_KERN_ERR "%s - failed to set regs: %d", - __func__, ret); + __func__, err); fatal_sigsegv(); } @@ -623,10 +622,10 @@ void userspace(struct uml_pt_regs *regs) mm_id->syscall_data_len = 0; mm_id->syscall_fd_num = 0; - ret = get_stub_state(regs, proc_data, NULL); - if (ret) { + err = get_stub_state(regs, proc_data, NULL); + if (err) { printk(UM_KERN_ERR "%s - failed to get regs: %d", - __func__, ret); + __func__, err); fatal_sigsegv(); } From b3fb0eb5c28766e3768f9f5b2968d33da00c4cea Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Fri, 11 Jul 2025 14:50:20 +0800 Subject: [PATCH 13/15] um: Remove the pid parameter of handle_trap() It's no longer used. Remove it. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250711065021.2535362-3-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/os-Linux/skas/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 79541574f70d..861ac00a07de 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -267,7 +267,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); } -static void handle_trap(int pid, struct uml_pt_regs *regs) +static void handle_trap(struct uml_pt_regs *regs) { if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END)) fatal_sigsegv(); @@ -755,7 +755,7 @@ void userspace(struct uml_pt_regs *regs) handle_syscall(regs); break; case SIGTRAP + 0x80: - handle_trap(pid, regs); + handle_trap(regs); break; case SIGTRAP: relay_signal(SIGTRAP, (struct siginfo *)si, regs, NULL); From f7e9077a1649877d4b33ce91d58711d393a63c1b Mon Sep 17 00:00:00 2001 From: Tiwei Bie Date: Fri, 11 Jul 2025 14:50:21 +0800 Subject: [PATCH 14/15] um: Stop tracking stub's PID via userspace_pid[] The PID of the stub process can be obtained from current_mm_id(). There is no need to track it via userspace_pid[]. Stop doing that to simplify the code. Signed-off-by: Tiwei Bie Link: https://patch.msgid.link/20250711065021.2535362-4-tiwei.bie@linux.dev Signed-off-by: Johannes Berg --- arch/um/include/asm/mmu_context.h | 9 +-------- arch/um/include/shared/skas/mm_id.h | 2 -- arch/um/include/shared/skas/skas.h | 1 - arch/um/kernel/exec.c | 2 -- arch/um/kernel/skas/process.c | 2 -- arch/um/os-Linux/skas/process.c | 16 ++++++---------- arch/x86/um/tls_32.c | 2 +- 7 files changed, 8 insertions(+), 26 deletions(-) diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h index 23dcc914d44e..0bbb24868557 100644 --- a/arch/um/include/asm/mmu_context.h +++ b/arch/um/include/asm/mmu_context.h @@ -16,11 +16,6 @@ #define activate_mm activate_mm static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) { - /* - * This is called by fs/exec.c and sys_unshare() - * when the new ->mm is used for the first time. - */ - __switch_mm(&new->context.id); } static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, @@ -28,11 +23,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, { unsigned cpu = smp_processor_id(); - if(prev != next){ + if (prev != next) { cpumask_clear_cpu(cpu, mm_cpumask(prev)); cpumask_set_cpu(cpu, mm_cpumask(next)); - if(next != &init_mm) - __switch_mm(&next->context.id); } } diff --git a/arch/um/include/shared/skas/mm_id.h b/arch/um/include/shared/skas/mm_id.h index 89df9a55fbea..4f977ef5dda5 100644 --- a/arch/um/include/shared/skas/mm_id.h +++ b/arch/um/include/shared/skas/mm_id.h @@ -19,8 +19,6 @@ struct mm_id { int syscall_fd_map[STUB_MAX_FDS]; }; -void __switch_mm(struct mm_id *mm_idp); - void notify_mm_kill(int pid); #endif diff --git a/arch/um/include/shared/skas/skas.h b/arch/um/include/shared/skas/skas.h index 7d1de4cab551..807514e10538 100644 --- a/arch/um/include/shared/skas/skas.h +++ b/arch/um/include/shared/skas/skas.h @@ -9,7 +9,6 @@ #include extern int using_seccomp; -extern int userspace_pid[]; extern void new_thread_handler(void); extern void handle_syscall(struct uml_pt_regs *regs); diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index cb8b5cd9285c..13812fa97eee 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -26,8 +26,6 @@ void flush_thread(void) get_safe_registers(current_pt_regs()->regs.gp, current_pt_regs()->regs.fp); - - __switch_mm(¤t->mm->context.id); } void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 05dcdc057af9..5881b17eb987 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -26,8 +26,6 @@ static int __init start_kernel_proc(void *unused) return 0; } -extern int userspace_pid[]; - static char cpu0_irqstack[THREAD_SIZE] __aligned(THREAD_SIZE); int __init start_uml(void) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 861ac00a07de..78f48fa9db8b 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -434,7 +434,6 @@ static int __init init_stub_exe_fd(void) __initcall(init_stub_exe_fd); int using_seccomp; -int userspace_pid[NR_CPUS]; /** * start_userspace() - prepare a new userspace process @@ -553,7 +552,7 @@ extern unsigned long tt_extra_sched_jiffies; void userspace(struct uml_pt_regs *regs) { - int err, status, op, pid = userspace_pid[0]; + int err, status, op; siginfo_t si_ptrace; siginfo_t *si; int sig; @@ -562,6 +561,8 @@ void userspace(struct uml_pt_regs *regs) interrupt_end(); while (1) { + struct mm_id *mm_id = current_mm_id(); + /* * When we are in time-travel mode, userspace can theoretically * do a *lot* of work without being scheduled. The problem with @@ -590,7 +591,6 @@ void userspace(struct uml_pt_regs *regs) current_mm_sync(); if (using_seccomp) { - struct mm_id *mm_id = current_mm_id(); struct stub_data *proc_data = (void *) mm_id->stack; err = set_stub_state(regs, proc_data, singlestepping()); @@ -644,8 +644,10 @@ void userspace(struct uml_pt_regs *regs) GET_FAULTINFO_FROM_MC(regs->faultinfo, mcontext); } } else { + int pid = mm_id->pid; + /* Flush out any pending syscalls */ - err = syscall_stub_flush(current_mm_id()); + err = syscall_stub_flush(mm_id); if (err) { if (err == -ENOMEM) report_enomem(); @@ -776,7 +778,6 @@ void userspace(struct uml_pt_regs *regs) __func__, sig); fatal_sigsegv(); } - pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ @@ -901,8 +902,3 @@ void reboot_skas(void) block_signals_trace(); UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT); } - -void __switch_mm(struct mm_id *mm_idp) -{ - userspace_pid[0] = mm_idp->pid; -} diff --git a/arch/x86/um/tls_32.c b/arch/x86/um/tls_32.c index cb3f17627d16..1909c2e640b2 100644 --- a/arch/x86/um/tls_32.c +++ b/arch/x86/um/tls_32.c @@ -186,7 +186,7 @@ int arch_switch_tls(struct task_struct *to) /* * We have no need whatsoever to switch TLS for kernel threads; beyond * that, that would also result in us calling os_set_thread_area with - * userspace_pid[cpu] == 0, which gives an error. + * task->mm == NULL, which would cause a crash. */ if (likely(to->mm)) return load_TLS(O_FORCE, to); From fc9ed2f6589dc2c11f05883e5c323be5f39fd241 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 14 Mar 2025 08:10:06 +0100 Subject: [PATCH 15/15] um: Replace __ASSEMBLY__ with __ASSEMBLER__ in the usermode headers While the GCC and Clang compilers already define __ASSEMBLER__ automatically when compiling assembly code, __ASSEMBLY__ is a macro that only gets defined by the Makefiles in the kernel. This can be very confusing when switching between userspace and kernelspace coding, so let's standardize on the __ASSEMBLER__ macro that is provided by the compilers now. This is a completely mechanical patch (done with a simple "sed -i" statement). Cc: Richard Weinberger Cc: Anton Ivanov Cc: Johannes Berg Cc: linux-um@lists.infradead.org Signed-off-by: Thomas Huth Link: https://patch.msgid.link/20250314071013.1575167-36-thuth@redhat.com Signed-off-by: Johannes Berg --- arch/um/include/asm/cpufeature.h | 4 ++-- arch/um/include/asm/current.h | 4 ++-- arch/um/include/asm/page.h | 4 ++-- arch/um/include/asm/ptrace-generic.h | 2 +- arch/um/include/asm/thread_info.h | 2 +- arch/um/include/shared/as-layout.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/um/include/asm/cpufeature.h b/arch/um/include/asm/cpufeature.h index 1eb8b834fbec..4354f6984271 100644 --- a/arch/um/include/asm/cpufeature.h +++ b/arch/um/include/asm/cpufeature.h @@ -4,7 +4,7 @@ #include -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +#if defined(__KERNEL__) && !defined(__ASSEMBLER__) #include #include @@ -137,5 +137,5 @@ t_no: #define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ boot_cpu_data.x86_model -#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ +#endif /* defined(__KERNEL__) && !defined(__ASSEMBLER__) */ #endif /* _ASM_UM_CPUFEATURE_H */ diff --git a/arch/um/include/asm/current.h b/arch/um/include/asm/current.h index de64e032d66c..8accc6d6f502 100644 --- a/arch/um/include/asm/current.h +++ b/arch/um/include/asm/current.h @@ -5,7 +5,7 @@ #include #include -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct task_struct; extern struct task_struct *cpu_tasks[NR_CPUS]; @@ -18,6 +18,6 @@ static __always_inline struct task_struct *get_current(void) #define current get_current() -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif /* __ASM_CURRENT_H */ diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h index 3d516f3ca9c7..6f54254aaf44 100644 --- a/arch/um/include/asm/page.h +++ b/arch/um/include/asm/page.h @@ -11,7 +11,7 @@ #include -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct page; @@ -94,7 +94,7 @@ extern unsigned long uml_physmem; #include #include -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #ifdef CONFIG_X86_32 #define __HAVE_ARCH_GATE_AREA 1 diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index 4696f24d1492..86d74f9d33cf 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h @@ -6,7 +6,7 @@ #ifndef __UM_PTRACE_GENERIC_H #define __UM_PTRACE_GENERIC_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index 545d298c1b23..7a6f4dc99fa1 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -9,7 +9,7 @@ #define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER #define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include #include diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h index 4f44dcce8a7c..2f9bfd99460a 100644 --- a/arch/um/include/shared/as-layout.h +++ b/arch/um/include/shared/as-layout.h @@ -26,7 +26,7 @@ #define STUB_DATA_PAGES 2 /* must be a power of two */ #define STUB_END (STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include