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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 #include #include +#include #include 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 #include #include +#include #include #include #include @@ -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 +#include +#include +#include + +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; +}