um: nommu: add userspace runner processes

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.

Link: https://patch.msgid.link/20260723113633.2184dce9413e.I9f810f3ed177d6dc980cad36c231f8c745dee48f@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-07-23 11:35:49 +02:00
parent 282d0be410
commit 3a080039a5
6 changed files with 114 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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;
}