All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/10] simplified UML/NOMMU approach
@ 2026-07-23  9:35 Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 01/10] x86/um: nommu: elf loader for fdpic Johannes Berg
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

Prior RFC/v1 was here:
https://lore.kernel.org/linux-um/20260720185103.530603-11-johannes@sipsolutions.net/

I cleaned up and added the docs commit now, other changes:
 - fixed futex implementation after discussions
 - fixed regression in earlier uname change

johannes



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 01/10] x86/um: nommu: elf loader for fdpic
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 02/10] um: decouple MMU specific code from the common part Johannes Berg
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller, Kees Cook

From: Hajime Tazaki <thehajime@gmail.com>

As UML supports CONFIG_MMU=n case, it has to use an alternate ELF
loader, FDPIC ELF loader.  In this commit, we added necessary
definitions in the arch, as UML has not been used so far.  It also
updates Kconfig file to use BINFMT_ELF_FDPIC under !MMU environment.

Acked-by: Kees Cook <kees@kernel.org>
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Ricardo Koller <ricarkol@google.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/um/include/asm/mmu.h            | 5 +++++
 arch/um/include/asm/ptrace-generic.h | 6 ++++++
 arch/x86/um/asm/elf.h                | 8 ++++++--
 fs/Kconfig.binfmt                    | 2 +-
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h
index 07d48738b402..82a919132aff 100644
--- a/arch/um/include/asm/mmu.h
+++ b/arch/um/include/asm/mmu.h
@@ -21,6 +21,11 @@ typedef struct mm_context {
 	spinlock_t sync_tlb_lock;
 	unsigned long sync_tlb_range_from;
 	unsigned long sync_tlb_range_to;
+
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+	unsigned long   exec_fdpic_loadmap;
+	unsigned long   interp_fdpic_loadmap;
+#endif
 } mm_context_t;
 
 #define INIT_MM_CONTEXT(mm)						\
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index 86d74f9d33cf..62e9916078ec 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -29,6 +29,12 @@ struct pt_regs {
 
 #define PTRACE_OLDSETOPTIONS 21
 
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+#define PTRACE_GETFDPIC		31
+#define PTRACE_GETFDPIC_EXEC	0
+#define PTRACE_GETFDPIC_INTERP	1
+#endif
+
 struct task_struct;
 
 extern long subarch_ptrace(struct task_struct *child, long request,
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index 22d0111b543b..388fe669886c 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -9,6 +9,7 @@
 #include <skas.h>
 
 #define CORE_DUMP_USE_REGSET
+#define ELF_FDPIC_CORE_EFLAGS  0
 
 #ifdef CONFIG_X86_32
 
@@ -158,8 +159,11 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 
 extern unsigned long um_vdso_addr;
 #define AT_SYSINFO_EHDR 33
-#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
-
+#define ARCH_DLINFO						\
+do {								\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr);		\
+	NEW_AUX_ENT(AT_MINSIGSTKSZ, 0);			\
+} while (0)
 #endif
 
 typedef unsigned long elf_greg_t;
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 1949e25c7741..0a92bebd5f75 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -58,7 +58,7 @@ config ARCH_USE_GNU_PROPERTY
 config BINFMT_ELF_FDPIC
 	bool "Kernel support for FDPIC ELF binaries"
 	default y if !BINFMT_ELF
-	depends on ARM || ((M68K || RISCV || SUPERH || XTENSA) && !MMU)
+	depends on ARM || ((M68K || RISCV || SUPERH || UML || XTENSA) && !MMU)
 	select ELFCORE
 	help
 	  ELF FDPIC binaries are based on ELF, but allow the individual load
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 02/10] um: decouple MMU specific code from the common part
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 01/10] x86/um: nommu: elf loader for fdpic Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 03/10] um: nommu: memory handling Johannes Berg
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

From: Hajime Tazaki <thehajime@gmail.com>

This splits the memory, process related code with common and MMU
specific parts in order to avoid ifdefs in .c file and duplication
between MMU and !MMU.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
[drop many unnecessary changes]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/um/kernel/Makefile      |  3 +-
 arch/um/kernel/mem-pgtable.c | 55 ++++++++++++++++++++++++++++++++++++
 arch/um/kernel/mem.c         | 35 -----------------------
 3 files changed, 57 insertions(+), 36 deletions(-)
 create mode 100644 arch/um/kernel/mem-pgtable.c

diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index be60bc451b3f..d56fe6d829cc 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -16,9 +16,10 @@ always-$(KBUILD_BUILTIN) := vmlinux.lds
 
 obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
 	physmem.o process.o ptrace.o reboot.o sigio.o \
-	signal.o sysrq.o time.o tlb.o trap.o \
+	signal.o sysrq.o time.o trap.o \
 	um_arch.o umid.o kmsg_dump.o capflags.o skas/
 obj-y += load_file.o
+obj-$(CONFIG_MMU) += mem-pgtable.o tlb.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
diff --git a/arch/um/kernel/mem-pgtable.c b/arch/um/kernel/mem-pgtable.c
new file mode 100644
index 000000000000..549da1d3bff0
--- /dev/null
+++ b/arch/um/kernel/mem-pgtable.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ */
+
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/memblock.h>
+#include <linux/swap.h>
+#include <linux/slab.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <as-layout.h>
+#include <init.h>
+#include <kern.h>
+#include <kern_util.h>
+#include <mem_user.h>
+#include <os.h>
+#include <um_malloc.h>
+
+
+/* Allocate and free page tables. */
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+	if (pgd) {
+		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+		memcpy(pgd + USER_PTRS_PER_PGD,
+		       swapper_pg_dir + USER_PTRS_PER_PGD,
+		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+	}
+	return pgd;
+}
+
+static const pgprot_t protection_map[16] = {
+	[VM_NONE]					= PAGE_NONE,
+	[VM_READ]					= PAGE_READONLY,
+	[VM_WRITE]					= PAGE_COPY,
+	[VM_WRITE | VM_READ]				= PAGE_COPY,
+	[VM_EXEC]					= PAGE_READONLY,
+	[VM_EXEC | VM_READ]				= PAGE_READONLY,
+	[VM_EXEC | VM_WRITE]				= PAGE_COPY,
+	[VM_EXEC | VM_WRITE | VM_READ]			= PAGE_COPY,
+	[VM_SHARED]					= PAGE_NONE,
+	[VM_SHARED | VM_READ]				= PAGE_READONLY,
+	[VM_SHARED | VM_WRITE]				= PAGE_SHARED,
+	[VM_SHARED | VM_WRITE | VM_READ]		= PAGE_SHARED,
+	[VM_SHARED | VM_EXEC]				= PAGE_READONLY,
+	[VM_SHARED | VM_EXEC | VM_READ]			= PAGE_READONLY,
+	[VM_SHARED | VM_EXEC | VM_WRITE]		= PAGE_SHARED,
+	[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ]	= PAGE_SHARED
+};
+DECLARE_VM_GET_PAGE_PROT
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 1eef0e42ef5d..4b84760b5e55 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -6,7 +6,6 @@
 #include <linux/stddef.h>
 #include <linux/module.h>
 #include <linux/memblock.h>
-#include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -91,45 +90,11 @@ void free_initmem(void)
 {
 }
 
-/* Allocate and free page tables. */
-
-pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	pgd_t *pgd = __pgd_alloc(mm, 0);
-
-	if (pgd)
-		memcpy(pgd + USER_PTRS_PER_PGD,
-		       swapper_pg_dir + USER_PTRS_PER_PGD,
-		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-
-	return pgd;
-}
-
 void *uml_kmalloc(int size, int flags)
 {
 	return kmalloc(size, flags);
 }
 
-static const pgprot_t protection_map[16] = {
-	[VM_NONE]					= PAGE_NONE,
-	[VM_READ]					= PAGE_READONLY,
-	[VM_WRITE]					= PAGE_COPY,
-	[VM_WRITE | VM_READ]				= PAGE_COPY,
-	[VM_EXEC]					= PAGE_READONLY,
-	[VM_EXEC | VM_READ]				= PAGE_READONLY,
-	[VM_EXEC | VM_WRITE]				= PAGE_COPY,
-	[VM_EXEC | VM_WRITE | VM_READ]			= PAGE_COPY,
-	[VM_SHARED]					= PAGE_NONE,
-	[VM_SHARED | VM_READ]				= PAGE_READONLY,
-	[VM_SHARED | VM_WRITE]				= PAGE_SHARED,
-	[VM_SHARED | VM_WRITE | VM_READ]		= PAGE_SHARED,
-	[VM_SHARED | VM_EXEC]				= PAGE_READONLY,
-	[VM_SHARED | VM_EXEC | VM_READ]			= PAGE_READONLY,
-	[VM_SHARED | VM_EXEC | VM_WRITE]		= PAGE_SHARED,
-	[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ]	= PAGE_SHARED
-};
-DECLARE_VM_GET_PAGE_PROT
-
 void mark_rodata_ro(void)
 {
 	unsigned long rodata_start = PFN_ALIGN(__start_rodata);
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 03/10] um: nommu: memory handling
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 01/10] x86/um: nommu: elf loader for fdpic Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 02/10] um: decouple MMU specific code from the common part Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 04/10] um: change machine name for uname output Johannes Berg
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

From: Hajime Tazaki <thehajime@gmail.com>

This commit adds memory operations on UML under !MMU environment.

Some part of the original UML code relying on CONFIG_MMU are excluded
from compilation when !CONFIG_MMU.  Additionally, generic functions such as
uaccess, futex, memcpy/strnlen/strncpy can be used as user- and
kernel-space share the address space in !CONFIG_MMU mode.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Ricardo Koller <ricarkol@google.com>
[drop unnecessary bits]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/um/include/asm/futex.h       | 4 ++++
 arch/um/include/asm/mmu.h         | 3 +++
 arch/um/include/asm/mmu_context.h | 2 ++
 arch/um/include/asm/uaccess.h     | 6 ++++--
 arch/um/kernel/mem.c              | 3 ++-
 5 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h
index 780aa6bfc050..785fd6649aa2 100644
--- a/arch/um/include/asm/futex.h
+++ b/arch/um/include/asm/futex.h
@@ -7,8 +7,12 @@
 #include <asm/errno.h>
 
 
+#ifdef CONFIG_MMU
 int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr);
 int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 			      u32 oldval, u32 newval);
+#else
+#include <asm-generic/futex.h>
+#endif
 
 #endif
diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h
index 82a919132aff..c0b9ce3215c4 100644
--- a/arch/um/include/asm/mmu.h
+++ b/arch/um/include/asm/mmu.h
@@ -22,10 +22,13 @@ typedef struct mm_context {
 	unsigned long sync_tlb_range_from;
 	unsigned long sync_tlb_range_to;
 
+#ifndef CONFIG_MMU
+	unsigned long   end_brk;
 #ifdef CONFIG_BINFMT_ELF_FDPIC
 	unsigned long   exec_fdpic_loadmap;
 	unsigned long   interp_fdpic_loadmap;
 #endif
+#endif /* !CONFIG_MMU */
 } mm_context_t;
 
 #define INIT_MM_CONTEXT(mm)						\
diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h
index c727e56ba116..528b217da285 100644
--- a/arch/um/include/asm/mmu_context.h
+++ b/arch/um/include/asm/mmu_context.h
@@ -18,11 +18,13 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
 }
 
+#ifdef CONFIG_MMU
 #define init_new_context init_new_context
 extern int init_new_context(struct task_struct *task, struct mm_struct *mm);
 
 #define destroy_context destroy_context
 extern void destroy_context(struct mm_struct *mm);
+#endif
 
 #include <asm-generic/mmu_context.h>
 
diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h
index 4417c8b1d37a..e493596f6663 100644
--- a/arch/um/include/asm/uaccess.h
+++ b/arch/um/include/asm/uaccess.h
@@ -18,6 +18,7 @@
 #define __addr_range_nowrap(addr, size) \
 	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
 
+#ifdef CONFIG_MMU
 extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n);
 extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n);
 extern unsigned long __clear_user(void __user *mem, unsigned long len);
@@ -29,8 +30,6 @@ static inline int __access_ok(const void __user *ptr, unsigned long size);
 
 #define INLINE_COPY_USER
 
-#include <asm-generic/uaccess.h>
-
 static inline int __access_ok(const void __user *ptr, unsigned long size)
 {
 	unsigned long addr = (unsigned long)ptr;
@@ -62,5 +61,8 @@ do {									\
 	barrier();							\
 	current->thread.segv_continue = NULL;				\
 } while (0)
+#endif
+
+#include <asm-generic/uaccess.h>
 
 #endif
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 4b84760b5e55..bc03bf3d114d 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -64,7 +64,8 @@ void __init arch_mm_preinit(void)
 	 * to be turned on.
 	 */
 	brk_end = PAGE_ALIGN((unsigned long) sbrk(0));
-	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
+	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1,
+		   !IS_ENABLED(CONFIG_MMU));
 	memblock_free((void *)brk_end, uml_reserved - brk_end);
 	uml_reserved = brk_end;
 	min_low_pfn = PFN_UP(__pa(uml_reserved));
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 04/10] um: change machine name for uname output
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (2 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 03/10] um: nommu: memory handling Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 05/10] x86/um/vdso: nommu: vdso memory update Johannes Berg
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

From: Hajime Tazaki <thehajime@gmail.com>

This commit tries to display MMU/!MMU mode from the output of uname(2)
so that users can distinguish which mode of UML is running right now.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
[remove / to fix regression with systemd userspace]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: regression fix

---
 arch/um/Makefile | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/um/Makefile b/arch/um/Makefile
index 937639edc295..1f85b73d4abb 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -148,6 +148,12 @@ export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE) $(CC_FLAGS_
 CLEAN_FILES += linux x.i gmon.out
 MRPROPER_FILES += $(HOST_DIR)/include/generated
 
+ifeq ($(CONFIG_MMU),y)
+UTS_MACHINE := "um"
+else
+UTS_MACHINE := "um\(nommu\)"
+endif
+
 archclean:
 	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
 		-o -name '*.gcov' \) -type f -print | xargs rm -f
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 05/10] x86/um/vdso: nommu: vdso memory update
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (3 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 04/10] um: change machine name for uname output Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 06/10] um: further decouple MMU related code Johannes Berg
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

From: Hajime Tazaki <thehajime@gmail.com>

On !MMU mode, the address of vdso is accessible from userspace.  This
commit implements the entry point by pointing a block of page address.

This commit also add memory permission configuration of vdso page to be
executable.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Ricardo Koller <ricarkol@google.com>
[remove print, add comment on #endif]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/x86/um/vdso/vma.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/x86/um/vdso/vma.c b/arch/x86/um/vdso/vma.c
index 51a2b9f2eca9..8e1f5ee44f4e 100644
--- a/arch/x86/um/vdso/vma.c
+++ b/arch/x86/um/vdso/vma.c
@@ -9,6 +9,7 @@
 #include <asm/page.h>
 #include <asm/elf.h>
 #include <linux/init.h>
+#include <os.h>
 
 unsigned long um_vdso_addr;
 static struct page *um_vdso;
@@ -20,18 +21,25 @@ static int __init init_vdso(void)
 {
 	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
 
-	um_vdso_addr = task_size - PAGE_SIZE;
-
 	um_vdso = alloc_page(GFP_KERNEL);
 	if (!um_vdso)
 		panic("Cannot allocate vdso\n");
 
 	copy_page(page_address(um_vdso), vdso_start);
 
+#ifdef CONFIG_MMU
+	um_vdso_addr = task_size - PAGE_SIZE;
+#else
+	/* this is fine with NOMMU as everything is accessible */
+	um_vdso_addr = (unsigned long)page_address(um_vdso);
+	os_protect_memory((void *)um_vdso_addr, vdso_end - vdso_start, 1, 0, 1);
+#endif
+
 	return 0;
 }
 subsys_initcall(init_vdso);
 
+#ifdef CONFIG_MMU
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct vm_area_struct *vma;
@@ -53,3 +61,4 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
 	return IS_ERR(vma) ? PTR_ERR(vma) : 0;
 }
+#endif /* CONFIG_MMU */
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 06/10] um: further decouple MMU related code
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (4 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 05/10] x86/um/vdso: nommu: vdso memory update Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 07/10] um: nommu: add SMP futex operations Johannes Berg
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Since this approach shares more code with the MMU version
in nommu, further move some code around to be able to use
it in nommu (report_enomem) or be able to replace it (this
applies to mm_id, stack, sync). Also add empty inlines for
the TLB flushing and decouple trap.c code.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/um/include/asm/tlbflush.h |  20 +++
 arch/um/kernel/Makefile        |   2 +-
 arch/um/kernel/physmem.c       |   7 +
 arch/um/kernel/skas/Makefile   |   3 +-
 arch/um/kernel/skas/mmu.c      |  25 ++++
 arch/um/kernel/skas/process.c  |  26 ----
 arch/um/kernel/tlb.c           |   7 -
 arch/um/kernel/trap-mmu.c      | 238 +++++++++++++++++++++++++++++++++
 arch/um/kernel/trap.c          | 219 ------------------------------
 9 files changed, 293 insertions(+), 254 deletions(-)
 create mode 100644 arch/um/kernel/trap-mmu.c

diff --git a/arch/um/include/asm/tlbflush.h b/arch/um/include/asm/tlbflush.h
index 13a3009942be..f73b568a0859 100644
--- a/arch/um/include/asm/tlbflush.h
+++ b/arch/um/include/asm/tlbflush.h
@@ -30,6 +30,8 @@
  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
  */
 
+#ifdef CONFIG_MMU
+
 extern int um_tlb_sync(struct mm_struct *mm);
 
 extern void flush_tlb_all(void);
@@ -56,4 +58,22 @@ static inline void flush_tlb_kernel_range(unsigned long start,
 	um_tlb_sync(&init_mm);
 }
 
+#else /* !CONFIG_MMU */
+
+/*
+ * With NOMMU the kernel and userspace share a single host address space,
+ * so there is nothing to synchronise and all TLB flushes are no-ops.
+ */
+static inline int um_tlb_sync(struct mm_struct *mm) { return 0; }
+static inline void flush_tlb_all(void) { }
+static inline void flush_tlb_mm(struct mm_struct *mm) { }
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long address) { }
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end) { }
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end) { }
+
+#endif /* CONFIG_MMU */
+
 #endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index d56fe6d829cc..5cd1bd4b23ac 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -19,7 +19,7 @@ obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
 	signal.o sysrq.o time.o trap.o \
 	um_arch.o umid.o kmsg_dump.o capflags.o skas/
 obj-y += load_file.o
-obj-$(CONFIG_MMU) += mem-pgtable.o tlb.o
+obj-$(CONFIG_MMU) += mem-pgtable.o tlb.o trap-mmu.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index ae6ca373c261..ae9b8f3144b8 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -110,6 +110,13 @@ int phys_mapping(unsigned long phys, unsigned long long *offset_out)
 }
 EXPORT_SYMBOL(phys_mapping);
 
+void report_enomem(void)
+{
+	printk(KERN_ERR "UML ran out of memory on the host side! "
+			"This can happen due to a memory limitation or "
+			"vm.max_map_count has been reached.\n");
+}
+
 static int __init uml_mem_setup(char *line, int *add)
 {
 	char *retptr;
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 3384be42691f..28dd33580abc 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,8 +3,9 @@
 # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 #
 
-obj-y := stub.o mmu.o process.o syscall.o uaccess.o \
+obj-y := stub.o process.o syscall.o \
 	 stub_exe_embed.o
+obj-$(CONFIG_MMU) += mmu.o uaccess.o
 
 # Stub executable
 
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index b5017096028b..facb88d1e393 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -12,6 +12,7 @@
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
 #include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
 #include <as-layout.h>
 #include <os.h>
 #include <skas.h>
@@ -40,6 +41,30 @@ void exit_turnstile(struct mm_id *mm_id)
 	mutex_unlock(__get_turnstile(mm_id));
 }
 
+unsigned long current_stub_stack(void)
+{
+	if (current->mm == NULL)
+		return 0;
+
+	return current->mm->context.id.stack;
+}
+
+struct mm_id *current_mm_id(void)
+{
+	if (current->mm == NULL)
+		return NULL;
+
+	return &current->mm->context.id;
+}
+
+void current_mm_sync(void)
+{
+	if (current->mm == NULL)
+		return;
+
+	um_tlb_sync(current->mm);
+}
+
 int init_new_context(struct task_struct *task, struct mm_struct *mm)
 {
 	struct mm_id *new_id = &mm->context.id;
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 4a7673b0261a..dcdce50b4595 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -9,8 +9,6 @@
 #include <linux/sched/task.h>
 #include <linux/smp-internal.h>
 
-#include <asm/tlbflush.h>
-
 #include <as-layout.h>
 #include <kern.h>
 #include <os.h>
@@ -42,30 +40,6 @@ int __init start_uml(void)
 				 &init_task.thread.switch_buf);
 }
 
-unsigned long current_stub_stack(void)
-{
-	if (current->mm == NULL)
-		return 0;
-
-	return current->mm->context.id.stack;
-}
-
-struct mm_id *current_mm_id(void)
-{
-	if (current->mm == NULL)
-		return NULL;
-
-	return &current->mm->context.id;
-}
-
-void current_mm_sync(void)
-{
-	if (current->mm == NULL)
-		return;
-
-	um_tlb_sync(current->mm);
-}
-
 static DEFINE_SPINLOCK(initial_jmpbuf_spinlock);
 
 void initial_jmpbuf_lock(void)
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 1f175716b474..012bcc76168d 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -40,13 +40,6 @@ static int kern_unmap(struct mm_id *mm_idp,
 	return os_unmap_memory((void *)virt, len);
 }
 
-void report_enomem(void)
-{
-	printk(KERN_ERR "UML ran out of memory on the host side! "
-			"This can happen due to a memory limitation or "
-			"vm.max_map_count has been reached.\n");
-}
-
 static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
 				   unsigned long end,
 				   struct vm_ops *ops)
diff --git a/arch/um/kernel/trap-mmu.c b/arch/um/kernel/trap-mmu.c
new file mode 100644
index 000000000000..a233a61e1801
--- /dev/null
+++ b/arch/um/kernel/trap-mmu.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ */
+
+#include <linux/mm.h>
+#include <linux/sched/signal.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/sched/debug.h>
+#include <asm/current.h>
+#include <asm/tlbflush.h>
+#include <arch.h>
+#include <as-layout.h>
+#include <kern_util.h>
+#include <os.h>
+#include <skas.h>
+
+/*
+ * NOTE: UML does not have exception tables. As such, this is almost a copy
+ * of the code in mm/memory.c, only adjusting the logic to simply check whether
+ * we are coming from the kernel instead of doing an additional lookup in the
+ * exception table.
+ * We can do this simplification because we never get here if the exception was
+ * fixable.
+ */
+static inline bool get_mmap_lock_carefully(struct mm_struct *mm, bool is_user)
+{
+	if (likely(mmap_read_trylock(mm)))
+		return true;
+
+	if (!is_user)
+		return false;
+
+	return !mmap_read_lock_killable(mm);
+}
+
+static inline bool mmap_upgrade_trylock(struct mm_struct *mm)
+{
+	/*
+	 * We don't have this operation yet.
+	 *
+	 * It should be easy enough to do: it's basically a
+	 *    atomic_long_try_cmpxchg_acquire()
+	 * from RWSEM_READER_BIAS -> RWSEM_WRITER_LOCKED, but
+	 * it also needs the proper lockdep magic etc.
+	 */
+	return false;
+}
+
+static inline bool upgrade_mmap_lock_carefully(struct mm_struct *mm, bool is_user)
+{
+	mmap_read_unlock(mm);
+	if (!is_user)
+		return false;
+
+	return !mmap_write_lock_killable(mm);
+}
+
+/*
+ * Helper for page fault handling.
+ *
+ * This is kind of equivalend to "mmap_read_lock()" followed
+ * by "find_extend_vma()", except it's a lot more careful about
+ * the locking (and will drop the lock on failure).
+ *
+ * For example, if we have a kernel bug that causes a page
+ * fault, we don't want to just use mmap_read_lock() to get
+ * the mm lock, because that would deadlock if the bug were
+ * to happen while we're holding the mm lock for writing.
+ *
+ * So this checks the exception tables on kernel faults in
+ * order to only do this all for instructions that are actually
+ * expected to fault.
+ *
+ * We can also actually take the mm lock for writing if we
+ * need to extend the vma, which helps the VM layer a lot.
+ */
+static struct vm_area_struct *
+um_lock_mm_and_find_vma(struct mm_struct *mm,
+			unsigned long addr, bool is_user)
+{
+	struct vm_area_struct *vma;
+
+	if (!get_mmap_lock_carefully(mm, is_user))
+		return NULL;
+
+	vma = find_vma(mm, addr);
+	if (likely(vma && (vma->vm_start <= addr)))
+		return vma;
+
+	/*
+	 * Well, dang. We might still be successful, but only
+	 * if we can extend a vma to do so.
+	 */
+	if (!vma || !(vma->vm_flags & VM_GROWSDOWN)) {
+		mmap_read_unlock(mm);
+		return NULL;
+	}
+
+	/*
+	 * We can try to upgrade the mmap lock atomically,
+	 * in which case we can continue to use the vma
+	 * we already looked up.
+	 *
+	 * Otherwise we'll have to drop the mmap lock and
+	 * re-take it, and also look up the vma again,
+	 * re-checking it.
+	 */
+	if (!mmap_upgrade_trylock(mm)) {
+		if (!upgrade_mmap_lock_carefully(mm, is_user))
+			return NULL;
+
+		vma = find_vma(mm, addr);
+		if (!vma)
+			goto fail;
+		if (vma->vm_start <= addr)
+			goto success;
+		if (!(vma->vm_flags & VM_GROWSDOWN))
+			goto fail;
+	}
+
+	if (expand_stack_locked(vma, addr))
+		goto fail;
+
+success:
+	mmap_write_downgrade(mm);
+	return vma;
+
+fail:
+	mmap_write_unlock(mm);
+	return NULL;
+}
+
+/*
+ * Note this is constrained to return 0, -EFAULT, -EACCES, -ENOMEM by
+ * segv().
+ */
+int handle_page_fault(unsigned long address, unsigned long ip,
+		      int is_write, int is_user, int *code_out)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	pmd_t *pmd;
+	pte_t *pte;
+	int err = -EFAULT;
+	unsigned int flags = FAULT_FLAG_DEFAULT;
+
+	*code_out = SEGV_MAPERR;
+
+	/*
+	 * If the fault was with pagefaults disabled, don't take the fault, just
+	 * fail.
+	 */
+	if (faulthandler_disabled())
+		goto out_nosemaphore;
+
+	if (is_user)
+		flags |= FAULT_FLAG_USER;
+retry:
+	vma = um_lock_mm_and_find_vma(mm, address, is_user);
+	if (!vma)
+		goto out_nosemaphore;
+
+	*code_out = SEGV_ACCERR;
+	if (is_write) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto out;
+		flags |= FAULT_FLAG_WRITE;
+	} else {
+		/* Don't require VM_READ|VM_EXEC for write faults! */
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto out;
+	}
+
+	do {
+		vm_fault_t fault;
+
+		fault = handle_mm_fault(vma, address, flags, NULL);
+
+		if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+			goto out_nosemaphore;
+
+		/* The fault is fully completed (including releasing mmap lock) */
+		if (fault & VM_FAULT_COMPLETED)
+			return 0;
+
+		if (unlikely(fault & VM_FAULT_ERROR)) {
+			if (fault & VM_FAULT_OOM) {
+				goto out_of_memory;
+			} else if (fault & VM_FAULT_SIGSEGV) {
+				goto out;
+			} else if (fault & VM_FAULT_SIGBUS) {
+				err = -EACCES;
+				goto out;
+			}
+			BUG();
+		}
+		if (fault & VM_FAULT_RETRY) {
+			flags |= FAULT_FLAG_TRIED;
+
+			goto retry;
+		}
+
+		pmd = pmd_off(mm, address);
+		pte = pte_offset_kernel(pmd, address);
+	} while (!pte_present(*pte));
+	err = 0;
+	/*
+	 * The below warning was added in place of
+	 *	pte_mkyoung(); if (is_write) pte_mkdirty();
+	 * If it's triggered, we'd see normally a hang here (a clean pte is
+	 * marked read-only to emulate the dirty bit).
+	 * However, the generic code can mark a PTE writable but clean on a
+	 * concurrent read fault, triggering this harmlessly. So comment it out.
+	 */
+#if 0
+	WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
+#endif
+
+out:
+	mmap_read_unlock(mm);
+out_nosemaphore:
+	return err;
+
+out_of_memory:
+	/*
+	 * We ran out of memory, call the OOM killer, and return the userspace
+	 * (which will retry the fault, or kill us if we got oom-killed).
+	 */
+	mmap_read_unlock(mm);
+	if (!is_user)
+		goto out_nosemaphore;
+	pagefault_out_of_memory();
+	return 0;
+}
+
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 177615820a4c..ab60bab8d987 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -17,225 +17,6 @@
 #include <os.h>
 #include <skas.h>
 
-/*
- * NOTE: UML does not have exception tables. As such, this is almost a copy
- * of the code in mm/memory.c, only adjusting the logic to simply check whether
- * we are coming from the kernel instead of doing an additional lookup in the
- * exception table.
- * We can do this simplification because we never get here if the exception was
- * fixable.
- */
-static inline bool get_mmap_lock_carefully(struct mm_struct *mm, bool is_user)
-{
-	if (likely(mmap_read_trylock(mm)))
-		return true;
-
-	if (!is_user)
-		return false;
-
-	return !mmap_read_lock_killable(mm);
-}
-
-static inline bool mmap_upgrade_trylock(struct mm_struct *mm)
-{
-	/*
-	 * We don't have this operation yet.
-	 *
-	 * It should be easy enough to do: it's basically a
-	 *    atomic_long_try_cmpxchg_acquire()
-	 * from RWSEM_READER_BIAS -> RWSEM_WRITER_LOCKED, but
-	 * it also needs the proper lockdep magic etc.
-	 */
-	return false;
-}
-
-static inline bool upgrade_mmap_lock_carefully(struct mm_struct *mm, bool is_user)
-{
-	mmap_read_unlock(mm);
-	if (!is_user)
-		return false;
-
-	return !mmap_write_lock_killable(mm);
-}
-
-/*
- * Helper for page fault handling.
- *
- * This is kind of equivalend to "mmap_read_lock()" followed
- * by "find_extend_vma()", except it's a lot more careful about
- * the locking (and will drop the lock on failure).
- *
- * For example, if we have a kernel bug that causes a page
- * fault, we don't want to just use mmap_read_lock() to get
- * the mm lock, because that would deadlock if the bug were
- * to happen while we're holding the mm lock for writing.
- *
- * So this checks the exception tables on kernel faults in
- * order to only do this all for instructions that are actually
- * expected to fault.
- *
- * We can also actually take the mm lock for writing if we
- * need to extend the vma, which helps the VM layer a lot.
- */
-static struct vm_area_struct *
-um_lock_mm_and_find_vma(struct mm_struct *mm,
-			unsigned long addr, bool is_user)
-{
-	struct vm_area_struct *vma;
-
-	if (!get_mmap_lock_carefully(mm, is_user))
-		return NULL;
-
-	vma = find_vma(mm, addr);
-	if (likely(vma && (vma->vm_start <= addr)))
-		return vma;
-
-	/*
-	 * Well, dang. We might still be successful, but only
-	 * if we can extend a vma to do so.
-	 */
-	if (!vma || !(vma->vm_flags & VM_GROWSDOWN)) {
-		mmap_read_unlock(mm);
-		return NULL;
-	}
-
-	/*
-	 * We can try to upgrade the mmap lock atomically,
-	 * in which case we can continue to use the vma
-	 * we already looked up.
-	 *
-	 * Otherwise we'll have to drop the mmap lock and
-	 * re-take it, and also look up the vma again,
-	 * re-checking it.
-	 */
-	if (!mmap_upgrade_trylock(mm)) {
-		if (!upgrade_mmap_lock_carefully(mm, is_user))
-			return NULL;
-
-		vma = find_vma(mm, addr);
-		if (!vma)
-			goto fail;
-		if (vma->vm_start <= addr)
-			goto success;
-		if (!(vma->vm_flags & VM_GROWSDOWN))
-			goto fail;
-	}
-
-	if (expand_stack_locked(vma, addr))
-		goto fail;
-
-success:
-	mmap_write_downgrade(mm);
-	return vma;
-
-fail:
-	mmap_write_unlock(mm);
-	return NULL;
-}
-
-/*
- * Note this is constrained to return 0, -EFAULT, -EACCES, -ENOMEM by
- * segv().
- */
-int handle_page_fault(unsigned long address, unsigned long ip,
-		      int is_write, int is_user, int *code_out)
-{
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
-	pmd_t *pmd;
-	pte_t *pte;
-	int err = -EFAULT;
-	unsigned int flags = FAULT_FLAG_DEFAULT;
-
-	*code_out = SEGV_MAPERR;
-
-	/*
-	 * If the fault was with pagefaults disabled, don't take the fault, just
-	 * fail.
-	 */
-	if (faulthandler_disabled())
-		goto out_nosemaphore;
-
-	if (is_user)
-		flags |= FAULT_FLAG_USER;
-retry:
-	vma = um_lock_mm_and_find_vma(mm, address, is_user);
-	if (!vma)
-		goto out_nosemaphore;
-
-	*code_out = SEGV_ACCERR;
-	if (is_write) {
-		if (!(vma->vm_flags & VM_WRITE))
-			goto out;
-		flags |= FAULT_FLAG_WRITE;
-	} else {
-		/* Don't require VM_READ|VM_EXEC for write faults! */
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
-			goto out;
-	}
-
-	do {
-		vm_fault_t fault;
-
-		fault = handle_mm_fault(vma, address, flags, NULL);
-
-		if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
-			goto out_nosemaphore;
-
-		/* The fault is fully completed (including releasing mmap lock) */
-		if (fault & VM_FAULT_COMPLETED)
-			return 0;
-
-		if (unlikely(fault & VM_FAULT_ERROR)) {
-			if (fault & VM_FAULT_OOM) {
-				goto out_of_memory;
-			} else if (fault & VM_FAULT_SIGSEGV) {
-				goto out;
-			} else if (fault & VM_FAULT_SIGBUS) {
-				err = -EACCES;
-				goto out;
-			}
-			BUG();
-		}
-		if (fault & VM_FAULT_RETRY) {
-			flags |= FAULT_FLAG_TRIED;
-
-			goto retry;
-		}
-
-		pmd = pmd_off(mm, address);
-		pte = pte_offset_kernel(pmd, address);
-	} while (!pte_present(*pte));
-	err = 0;
-	/*
-	 * The below warning was added in place of
-	 *	pte_mkyoung(); if (is_write) pte_mkdirty();
-	 * If it's triggered, we'd see normally a hang here (a clean pte is
-	 * marked read-only to emulate the dirty bit).
-	 * However, the generic code can mark a PTE writable but clean on a
-	 * concurrent read fault, triggering this harmlessly. So comment it out.
-	 */
-#if 0
-	WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
-#endif
-
-out:
-	mmap_read_unlock(mm);
-out_nosemaphore:
-	return err;
-
-out_of_memory:
-	/*
-	 * We ran out of memory, call the OOM killer, and return the userspace
-	 * (which will retry the fault, or kill us if we got oom-killed).
-	 */
-	mmap_read_unlock(mm);
-	if (!is_user)
-		goto out_nosemaphore;
-	pagefault_out_of_memory();
-	return 0;
-}
-
 static void show_segv_info(struct uml_pt_regs *regs)
 {
 	struct task_struct *tsk = current;
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 07/10] um: nommu: add SMP futex operations
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (5 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 06/10] um: further decouple MMU related code Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 08/10] um: nommu: add userspace runner processes Johannes Berg
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The asm-generic futex implementation only supports UP operations,
and the normal (MMU) implementation from uaccess.c isn't built
nor would it work.

Since NOMMU shares address space anyway, it's all trivial and we
can just make a trivial implementation.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: use cmpxchg() return value correctly
---
 arch/um/include/asm/futex.h | 51 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h
index 785fd6649aa2..07ab81f09281 100644
--- a/arch/um/include/asm/futex.h
+++ b/arch/um/include/asm/futex.h
@@ -12,7 +12,56 @@ int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
 int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 			      u32 oldval, u32 newval);
 #else
+#include <linux/atomic.h>
 #include <asm-generic/futex.h>
-#endif
+
+#ifdef CONFIG_SMP
+static inline int
+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
+{
+	u32 oldval, newval;
+	u32 *p = (u32 __force *)uaddr;
+
+	do {
+		oldval = READ_ONCE(*p);
+
+		switch (op) {
+		case FUTEX_OP_SET:
+			newval = oparg;
+			break;
+		case FUTEX_OP_ADD:
+			newval = oldval + oparg;
+			break;
+		case FUTEX_OP_OR:
+			newval = oldval | oparg;
+			break;
+		case FUTEX_OP_ANDN:
+			newval = oldval & ~oparg;
+			break;
+		case FUTEX_OP_XOR:
+			newval = oldval ^ oparg;
+			break;
+		default:
+			return -ENOSYS;
+		}
+	} while (!try_cmpxchg(p, &oldval, newval));
+
+	*oval = oldval;
+	return 0;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
+{
+	u32 *p = (u32 __force *)uaddr;
+
+	*uval = cmpxchg(p, oldval, newval);
+
+	return 0;
+}
+#endif /* CONFIG_SMP */
+
+#endif /* CONFIG_MMU */
 
 #endif
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 08/10] um: nommu: add userspace runner processes
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (6 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 07/10] um: nommu: add SMP futex operations Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23 13:59   ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 09/10] um: allow deselecting CONFIG_MMU Johannes Berg
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

For NOMMU there are not separate address spaces for
each userspace process group, which on the one hand
means we cannot start them on demand, but on the
other means we can just have one for each (virtual)
CPU, and map all of the memory into them.

Implement such processes, and the remaining bits
needed to compile the kernel without CONFIG_MMU.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/um/kernel/Makefile      |  3 ++
 arch/um/kernel/skas/Makefile |  3 ++
 arch/um/kernel/skas/nommu.c  | 91 ++++++++++++++++++++++++++++++++++++
 arch/um/kernel/smp.c         |  3 +-
 arch/um/kernel/time.c        |  3 +-
 arch/um/kernel/trap-nommu.c  | 13 ++++++
 6 files changed, 114 insertions(+), 2 deletions(-)
 create mode 100644 arch/um/kernel/skas/nommu.c
 create mode 100644 arch/um/kernel/trap-nommu.c

diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 5cd1bd4b23ac..b087b4278173 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -20,6 +20,9 @@ obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
 	um_arch.o umid.o kmsg_dump.o capflags.o skas/
 obj-y += load_file.o
 obj-$(CONFIG_MMU) += mem-pgtable.o tlb.o trap-mmu.o
+ifneq ($(CONFIG_MMU),y)
+obj-y += trap-nommu.o
+endif
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 28dd33580abc..c098d087c3f2 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -6,6 +6,9 @@
 obj-y := stub.o process.o syscall.o \
 	 stub_exe_embed.o
 obj-$(CONFIG_MMU) += mmu.o uaccess.o
+ifneq ($(CONFIG_MMU),y)
+obj-y += nommu.o
+endif
 
 # Stub executable
 
diff --git a/arch/um/kernel/skas/nommu.c b/arch/um/kernel/skas/nommu.c
new file mode 100644
index 000000000000..80d5c4eaa96b
--- /dev/null
+++ b/arch/um/kernel/skas/nommu.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/cpumask.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/mutex.h>
+#include <linux/panic.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <as-layout.h>
+#include <mem.h>
+#include <os.h>
+#include <skas.h>
+#include <mm_id.h>
+
+struct nommu_runner {
+	struct mm_id mm_id;
+	struct mutex turnstile;
+};
+
+static struct nommu_runner nommu_runners[NR_CPUS];
+
+static struct nommu_runner *this_runner(void)
+{
+	return &nommu_runners[raw_smp_processor_id()];
+}
+
+struct mutex *__get_turnstile(struct mm_id *mm_id)
+{
+	return &container_of(mm_id, struct nommu_runner, mm_id)->turnstile;
+}
+
+void enter_turnstile(struct mm_id *mm_id)
+{
+	mutex_lock(__get_turnstile(mm_id));
+}
+
+void exit_turnstile(struct mm_id *mm_id)
+{
+	mutex_unlock(__get_turnstile(mm_id));
+}
+
+unsigned long current_stub_stack(void)
+{
+	return this_runner()->mm_id.stack;
+}
+
+struct mm_id *current_mm_id(void)
+{
+	return &this_runner()->mm_id;
+}
+
+void current_mm_sync(void)
+{
+}
+
+static int __init nommu_start_runners(void)
+{
+	unsigned long long offset;
+	struct nommu_runner *r;
+	int cpu, err, fd;
+
+	fd = phys_mapping(uml_reserved - uml_physmem, &offset);
+
+	for_each_possible_cpu(cpu) {
+		r = &nommu_runners[cpu];
+		mutex_init(&r->turnstile);
+
+		r->mm_id.stack = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+						  ilog2(STUB_DATA_PAGES));
+		if (!r->mm_id.stack)
+			panic("OOM allocating userspace stack for CPU %d", cpu);
+
+		err = start_userspace(&r->mm_id);
+		if (err < 0)
+			panic("userspace startup for CPU %d failed: %d",
+			      cpu, err);
+
+		map(&r->mm_id, uml_reserved, high_physmem - uml_reserved,
+		    UM_PROT_READ | UM_PROT_WRITE | UM_PROT_EXEC, fd, offset);
+
+		err = syscall_stub_flush(&r->mm_id);
+		if (err < 0)
+			panic("physmem map/flush failed for CPU%d: %d",
+			      cpu, err);
+	}
+
+	return 0;
+}
+arch_initcall(nommu_start_runners);
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index f1e52b7348fb..92ea1beaed8b 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -20,6 +20,7 @@
 #include <init.h>
 #include <kern.h>
 #include <os.h>
+#include <skas.h>
 #include <smp.h>
 
 enum {
@@ -66,7 +67,7 @@ static void ipi_handler(int vector, struct uml_pt_regs *regs)
 	irq_enter();
 
 	if (current->mm)
-		os_alarm_process(current->mm->context.id.pid);
+		os_alarm_process(current_mm_id()->pid);
 
 	switch (vector) {
 	case UML_IPI_RES:
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index b344a36b44eb..d620b6d6310a 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -19,6 +19,7 @@
 #include <asm/param.h>
 #include <kern_util.h>
 #include <os.h>
+#include <skas.h>
 #include <linux/delay.h>
 #include <linux/time-internal.h>
 #include <linux/um_timetravel.h>
@@ -873,7 +874,7 @@ static irqreturn_t um_timer(int irq, void *dev)
 	if (time_travel_mode != TT_MODE_INFCPU &&
 	    time_travel_mode != TT_MODE_EXTERNAL &&
 	    get_current()->mm)
-		os_alarm_process(get_current()->mm->context.id.pid);
+		os_alarm_process(current_mm_id()->pid);
 
 	evt->event_handler(evt);
 
diff --git a/arch/um/kernel/trap-nommu.c b/arch/um/kernel/trap-nommu.c
new file mode 100644
index 000000000000..891a9cefa935
--- /dev/null
+++ b/arch/um/kernel/trap-nommu.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <shared/kern_util.h>
+
+int handle_page_fault(unsigned long address, unsigned long ip,
+		      int is_write, int is_user, int *code_out)
+{
+	/* everything that's valid is already mapped in NOMMU */
+	*code_out = SEGV_MAPERR;
+	return -EFAULT;
+}
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 09/10] um: allow deselecting CONFIG_MMU
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (7 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 08/10] um: nommu: add userspace runner processes Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23  9:35 ` [PATCH v2 10/10] Documentation: um: document nommu UML Johannes Berg
  2026-07-23 11:50 ` [PATCH v2 00/10] simplified UML/NOMMU approach Lorenzo Stoakes (ARM)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

From: Hajime Tazaki <thehajime@gmail.com>

Allow deselecting CONFIG_MMU to build a no-MMU
UML kernel.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Ricardo Koller <ricarkol@google.com>
[drop defconfig file, minor adjustments/fixes, rewrite message]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/um/Kconfig | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index d9541d13d9eb..d17bcdd200c4 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -17,9 +17,9 @@ config UML
 	select ARCH_HAS_KCOV
 	select ARCH_HAS_STRNCPY_FROM_USER
 	select ARCH_HAS_STRNLEN_USER
-	select ARCH_HAS_STRICT_KERNEL_RWX
+	select ARCH_HAS_STRICT_KERNEL_RWX if MMU
 	select HAVE_ARCH_AUDITSYSCALL
-	select HAVE_ARCH_KASAN if X86_64
+	select HAVE_ARCH_KASAN if X86_64 && MMU
 	select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ASM_MODVERSIONS
@@ -37,18 +37,23 @@ config UML
 	select ARCH_SUPPORTS_LTO_CLANG_THIN
 	select TRACE_IRQFLAGS_SUPPORT
 	select TTY # Needed for line.c
-	select HAVE_ARCH_VMAP_STACK
+	select HAVE_ARCH_VMAP_STACK if MMU
 	select HAVE_RUST
 	select ARCH_HAS_UBSAN
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_SYSCALL_TRACEPOINTS
 	select THREAD_INFO_IN_TASK
 	select SPARSE_IRQ
-	select MMU_GATHER_RCU_TABLE_FREE
+	select MMU_GATHER_RCU_TABLE_FREE if MMU
+	select UACCESS_MEMCPY if !MMU
+	select GENERIC_STRNLEN_USER if !MMU
+	select GENERIC_STRNCPY_FROM_USER if !MMU
 
 config MMU
-	bool
+	bool "MMU support"
 	default y
+	help
+	  Turning this off allows a nommu build, say Y.
 
 config UML_DMA_EMULATION
 	bool
@@ -229,8 +234,15 @@ config MAGIC_SYSRQ
 	  The keys are documented in <file:Documentation/admin-guide/sysrq.rst>. Don't say Y
 	  unless you really know what this hack does.
 
+config ARCH_FORCE_MAX_ORDER
+	int "Order of maximal physically contiguous allocations" if EXPERT
+	default "10" if MMU
+	default "16" if !MMU
+
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
+	default 3 if !MMU
+	range 3 10 if !MMU
 	default 2 if 64BIT
 	range 2 10 if 64BIT
 	default 1 if !64BIT
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 10/10] Documentation: um: document nommu UML
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (8 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 09/10] um: allow deselecting CONFIG_MMU Johannes Berg
@ 2026-07-23  9:35 ` Johannes Berg
  2026-07-23 11:50 ` [PATCH v2 00/10] simplified UML/NOMMU approach Lorenzo Stoakes (ARM)
  10 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23  9:35 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Add a description of nommu UML, a bit about how it works and some
notes on how to use it. Partially based on Hajime's documentation.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Documentation/virt/index.rst         |  1 +
 Documentation/virt/uml/nommu-uml.rst | 54 ++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)
 create mode 100644 Documentation/virt/uml/nommu-uml.rst

diff --git a/Documentation/virt/index.rst b/Documentation/virt/index.rst
index c1f0bbc37315..142134ed45c0 100644
--- a/Documentation/virt/index.rst
+++ b/Documentation/virt/index.rst
@@ -9,6 +9,7 @@ Virtualization Support
 
    kvm/index
    uml/user_mode_linux_howto_v2
+   uml/nommu-uml
    paravirt_ops
    guest-halt-polling
    ne_overview
diff --git a/Documentation/virt/uml/nommu-uml.rst b/Documentation/virt/uml/nommu-uml.rst
new file mode 100644
index 000000000000..105e596ae1cc
--- /dev/null
+++ b/Documentation/virt/uml/nommu-uml.rst
@@ -0,0 +1,54 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. contents:: :local:
+
+Execution model
+===============
+
+When emulating a system with an MMU, UML gives every ``mm_struct`` its own
+host process with its own host address space, and keeps that address space
+in sync with the kernel's page tables by issuing ``mmap()``/``munmap()``
+into it.
+
+NOMMU has no per-process address spaces: there is a single "physical" address
+space that the kernel and every userspace process share.  UML models this with
+a **userspace runner** - an ordinary uml-userspace stub host process, started
+exactly like an MMU userspace process, but with the whole of "physical" memory
+(the physmem file) mapped into it at the kernel's addresses:
+
+- The runner ``exec()``'s the stub just like the MMU case.  The only extra step
+  is that, once it is up, the kernel maps the entire physmem file into it in one
+  go, at the same addresses the kernel uses.
+- Because NOMMU never remaps, that single mapping is all a runner ever needs:
+  there is no per-mm host process, no TLB sync and no ``mmap()`` of individual
+  page-table entries into a child.  Userspace code and data - placed in memory
+  by the loader - are directly executable and accessible.
+- The runner processes hold no per-task state: the kernel loads a task's state
+  on every entry, so there's just one process per CPU.
+
+Running a task's userspace therefore only means pointing a runner at that
+task's code and letting it run until the next syscall or signal
+
+Building and running
+====================
+
+Configure and build the ARCH=um kernel normally, but deselect CONFIG_MMU.
+
+KUnit tests can be run in NOMMU mode with::
+
+   ./tools/testing/kunit/kunit.py run \
+       --kconfig_add CONFIG_MMU=n --kconfig_add CONFIG_KUNIT_UML_PCI=n
+
+Running a normal userspace requires NOMMU-aware binaries.  There is no stock
+x86_64 NOMMU distribution, but a prebuilt Alpine image with musl-libc and
+busybox built for NOMMU is available and can be turned into a root image::
+
+   cid=$(docker create ghcr.io/thehajime/alpine:3.20.3-um-nommu)
+   docker export "$cid" > alpine.tar
+   docker rm "$cid"
+   mkdir alpine-root && tar xf alpine.tar -C alpine-root
+   mke2fs -q -F -t ext4 -d alpine-root alpine.ext4 1200M
+
+Then boot it::
+
+   ./linux ubd0=./alpine.ext4 root=/dev/ubda rw mem=1024m init=/sbin/init
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 00/10] simplified UML/NOMMU approach
  2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
                   ` (9 preceding siblings ...)
  2026-07-23  9:35 ` [PATCH v2 10/10] Documentation: um: document nommu UML Johannes Berg
@ 2026-07-23 11:50 ` Lorenzo Stoakes (ARM)
  2026-07-23 12:22   ` Johannes Berg
  10 siblings, 1 reply; 15+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-07-23 11:50 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-um, Hajime Tazaki, liam, Ricardo Koller

On Thu, Jul 23, 2026 at 11:35:41AM +0200, Johannes Berg wrote:
> Prior RFC/v1 was here:
> https://lore.kernel.org/linux-um/20260720185103.530603-11-johannes@sipsolutions.net/

Thanks for this! I really really want a nommu UML mode for testing purposes so
I'm very happy you're doing this :)

One mildly annoying note though - it'd be good for the cover letter to summarise
what the series is about, what it achieves, how it compares for instance to
Hajime's original approach ([0]).

I guess how cover letters are used varies by subsystem somewhat but I find it
really actively useful to see a summary in the cover letter.

Anyway reading thorugh the RFC which already covers this seems that this
achieves nommu UML with less changes needed which sounds really interesting!

I may pull this series locally and have a play... :)

>
> I cleaned up and added the docs commit now, other changes:
>  - fixed futex implementation after discussions
>  - fixed regression in earlier uname change
>
> johannes
>

Cheers, Lorenzo

[0]:https://lore.kernel.org/all/m2framxerm.wl-thehajime@gmail.com/


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 00/10] simplified UML/NOMMU approach
  2026-07-23 11:50 ` [PATCH v2 00/10] simplified UML/NOMMU approach Lorenzo Stoakes (ARM)
@ 2026-07-23 12:22   ` Johannes Berg
  2026-07-23 15:11     ` Lorenzo Stoakes (ARM)
  0 siblings, 1 reply; 15+ messages in thread
From: Johannes Berg @ 2026-07-23 12:22 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM); +Cc: linux-um, Hajime Tazaki, liam, Ricardo Koller

On Thu, 2026-07-23 at 12:50 +0100, Lorenzo Stoakes (ARM) wrote:
> On Thu, Jul 23, 2026 at 11:35:41AM +0200, Johannes Berg wrote:
> > Prior RFC/v1 was here:
> > https://lore.kernel.org/linux-um/20260720185103.530603-11-johannes@sipsolutions.net/
> 
> Thanks for this! I really really want a nommu UML mode for testing purposes so
> I'm very happy you're doing this :)

:)

> One mildly annoying note though - it'd be good for the cover letter to summarise
> what the series is about, what it achieves, how it compares for instance to
> Hajime's original approach ([0]).
> 
> I guess how cover letters are used varies by subsystem somewhat but I find it
> really actively useful to see a summary in the cover letter.
> 
> Anyway reading thorugh the RFC which already covers this seems that this
> achieves nommu UML with less changes needed which sounds really interesting!

Right, sorry, I got lazy and didn't copy/paste the RFC cover letter but
only put the link to it instead. Is there something beyond what I wrote
there that you were looking for?


> I may pull this series locally and have a play... :)

If you do, let us know how it goes :)

johannes


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 08/10] um: nommu: add userspace runner processes
  2026-07-23  9:35 ` [PATCH v2 08/10] um: nommu: add userspace runner processes Johannes Berg
@ 2026-07-23 13:59   ` Johannes Berg
  0 siblings, 0 replies; 15+ messages in thread
From: Johannes Berg @ 2026-07-23 13:59 UTC (permalink / raw)
  To: linux-um; +Cc: Hajime Tazaki, liam, ljs, Ricardo Koller

On Thu, 2026-07-23 at 11:35 +0200, Johannes Berg wrote:
> 
> +struct mutex *__get_turnstile(struct mm_id *mm_id)
> +{
> +	return &container_of(mm_id, struct nommu_runner, mm_id)->turnstile;
> +}
> +
> +void enter_turnstile(struct mm_id *mm_id)
> +{
> +	mutex_lock(__get_turnstile(mm_id));
> +}
> +
> +void exit_turnstile(struct mm_id *mm_id)
> +{
> +	mutex_unlock(__get_turnstile(mm_id));
> +}

I should comment on this - it really shouldn't be necessary here, and
the mutex should never be contended. Also, __get_turnstile() is only
needed for context tracking, so I'm not even sure it matters what it
returns (I don't fully understand the clang context tracking).

I was tempted to make the mutex_lock() something like

	if (WARN_ON(!try_mutex_lock()))
		mutex_lock();

but eventually decided to just keep it. I think we'll probably want to
remove the whole turnstile business entirely anyway, and have real SMP
for userspace threads. In fact I started prototyping this as well, but
didn't have time to finish it yet.

So all this really is a bit of just fluff right now and hopefully will
eventually go away.

johannes


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 00/10] simplified UML/NOMMU approach
  2026-07-23 12:22   ` Johannes Berg
@ 2026-07-23 15:11     ` Lorenzo Stoakes (ARM)
  0 siblings, 0 replies; 15+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-07-23 15:11 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-um, Hajime Tazaki, liam, Ricardo Koller

On Thu, Jul 23, 2026 at 02:22:50PM +0200, Johannes Berg wrote:
> On Thu, 2026-07-23 at 12:50 +0100, Lorenzo Stoakes (ARM) wrote:
> > On Thu, Jul 23, 2026 at 11:35:41AM +0200, Johannes Berg wrote:
> > > Prior RFC/v1 was here:
> > > https://lore.kernel.org/linux-um/20260720185103.530603-11-johannes@sipsolutions.net/
> >
> > Thanks for this! I really really want a nommu UML mode for testing purposes so
> > I'm very happy you're doing this :)
>
> :)
>
> > One mildly annoying note though - it'd be good for the cover letter to summarise
> > what the series is about, what it achieves, how it compares for instance to
> > Hajime's original approach ([0]).
> >
> > I guess how cover letters are used varies by subsystem somewhat but I find it
> > really actively useful to see a summary in the cover letter.
> >
> > Anyway reading thorugh the RFC which already covers this seems that this
> > achieves nommu UML with less changes needed which sounds really interesting!
>
> Right, sorry, I got lazy and didn't copy/paste the RFC cover letter but
> only put the link to it instead. Is there something beyond what I wrote
> there that you were looking for?

No, I think the previous version covered it off well, just a nag (hence being
self aware about the mildly annoying nature of it :P)

UML isn't really my area so can't give in-depth review but I really want
this to be a thing so happy to be cc'd on this!

>
>
> > I may pull this series locally and have a play... :)
>
> If you do, let us know how it goes :)

Will do! :)

>
> johannes

Cheers, Lorenzo


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-07-23 15:11 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23  9:35 [PATCH v2 00/10] simplified UML/NOMMU approach Johannes Berg
2026-07-23  9:35 ` [PATCH v2 01/10] x86/um: nommu: elf loader for fdpic Johannes Berg
2026-07-23  9:35 ` [PATCH v2 02/10] um: decouple MMU specific code from the common part Johannes Berg
2026-07-23  9:35 ` [PATCH v2 03/10] um: nommu: memory handling Johannes Berg
2026-07-23  9:35 ` [PATCH v2 04/10] um: change machine name for uname output Johannes Berg
2026-07-23  9:35 ` [PATCH v2 05/10] x86/um/vdso: nommu: vdso memory update Johannes Berg
2026-07-23  9:35 ` [PATCH v2 06/10] um: further decouple MMU related code Johannes Berg
2026-07-23  9:35 ` [PATCH v2 07/10] um: nommu: add SMP futex operations Johannes Berg
2026-07-23  9:35 ` [PATCH v2 08/10] um: nommu: add userspace runner processes Johannes Berg
2026-07-23 13:59   ` Johannes Berg
2026-07-23  9:35 ` [PATCH v2 09/10] um: allow deselecting CONFIG_MMU Johannes Berg
2026-07-23  9:35 ` [PATCH v2 10/10] Documentation: um: document nommu UML Johannes Berg
2026-07-23 11:50 ` [PATCH v2 00/10] simplified UML/NOMMU approach Lorenzo Stoakes (ARM)
2026-07-23 12:22   ` Johannes Berg
2026-07-23 15:11     ` Lorenzo Stoakes (ARM)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.