From nobody Sun Feb 8 16:05:46 2026 Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C26DD2BF002 for ; Wed, 4 Feb 2026 02:28:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770172103; cv=none; b=pol4dPwdqhsHRfWEwPBM6QprBbYLJUtBsaAF35XOkdl7sgvM4YDkFKTMOW2M4hDBbvOsxAXiaMDW5Of3MDRDsYJUNdbive7upnnllKTrOc0OM5c2OWugoJWI4x/ZdOwS0x69Ttk8YZh0ufT8GXEdYCXWgVvMBR696SOTsHpxX4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770172103; c=relaxed/simple; bh=ZiBjYTpVGhtkj5Ak/GnH8XcMsvP0AYgN0WurqAcjoHI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ez5RMOxgLUP005v9YfOdwIjBIe2YBEcWM/5waHnDCBrsbO2pWqlxAeAz6cHTZonW0rURl8FCeFZmJh4/gJjwKNNASmRG4ZKL3Ve9807pPkMLpH4oGYnZsFE3Ue55ZP3wX4rl+VZRdnYEW6lwWJvldm7JZnF02QoOUGyeyYqjIJY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=A/HgOm0I; arc=none smtp.client-ip=209.85.210.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="A/HgOm0I" Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-82318b640beso3543781b3a.0 for ; Tue, 03 Feb 2026 18:28:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770172101; x=1770776901; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KNOvTdYobj6+1S0fsqiY4Qax5jbv4IaGWEMEORei1Pk=; b=A/HgOm0IdV3HYRkP+0eZnQHw9VGY61VyT6O2p0VadodfHhBNLWkcXXtULSOd0ZRPy5 /eQLPYGYjwdpcYBrmagLQ8jFiRws2HU/puDUkLJwMxtvMlb4Qjcv6IVDyZSeliFQdhvI Yeps8G4XHX8ikcdMgXDO+JHa8Bq12E6JN9gzYmmEwikvKWUi4bbjzkTYv1Z9bEHqEL0U Rrgnuwg6/Cmc9ppvyW4HqTsy36tRbxW++NxiBlzA3W9a6lxlAOvuBT6ZdsbiPp7CKdpr KJSXWA/CmOZ/Zul7XkT8urFpaJHl+dXQWRNB6JBphAZjs+WiwCvhkr8VgAoTfpW/2aVq O0jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770172101; x=1770776901; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=KNOvTdYobj6+1S0fsqiY4Qax5jbv4IaGWEMEORei1Pk=; b=E5hCyU47NORMKhlDbeRP0Bo4bHcYLStnBb5q46rqtbOCSaHgFGFt0pX2Y/aZ8BamhQ gYkXhKsO85Y5vVjc+ZqGw0dgrnrNQJUqrwIVHp4GMy8VYCNMb4Jw/Rv1PCO2tsBggGqP hdVj1E56DSNqZ0t/fH8E8wqoQ5B+ToR8AQ55G56pP7ycZ9XVSlKxwuyFxjaMYCeR2oxI Fn7tkZgT1qij5zr5FnlgXQpe1Rszj0FKfSNggTTss+CUNyi3CJ9IH2cM/mOq8RwH1K2+ 8FD7zrvl9qFQBnVg2fPlTTaDKFk6vLZMSKE96J5kMIqj4EocA/0qhyeohpJIUIXrHHr7 ecWw== X-Forwarded-Encrypted: i=1; AJvYcCU6GsqFVKr1SP/A9gv5qR2JwLBfeuJbtLlyE7wBfnjMx/YgAhQ4HMr+ZO6hS1ecCCee4i/yr6lgkgvB1To=@vger.kernel.org X-Gm-Message-State: AOJu0YwS1yDzkKlMoHOQif+QrhPS9FDoaaOd1jkF0Jyx+++KYSmdfXeI T7NPU88PCpNtAIyr969dTX7ye4EqDnIztMsspw8fl85unITlRvZP8gRv X-Gm-Gg: AZuq6aLIGTVuHQub6phfzkXf64oIv0eQ8im73tYwTCNe8oSSli5Yg2JZqdr+8rC6vwi ktZIgOaRKR2j12+6it8uvvXSpWhDn3Ihdn4SPZWLB+rSOjR63zGTar8qCbJiZAIUI+2gCxs4wYy UAqa/g5RdWTc0mwGp/FMYOzsbKACvVNmw0Z2hnIjBldM+FOJSOcJcG4H8qbbolEScTaXMsEOjMs B9I9m32NBHFxe5UhgpGyCfZKJ4s8cy0ZYVHMbdtry1zjGM9IKvgUaGMBaYDjn90vA3paaweacT6 YSstnp/yWKDtM5QsOcXUMwSbq/Zm9JxGcRrHe0nkKvo9hEejkexAESM3vbmRg8aUntOfEWS+RSH 1a5gYJkxGTR7r4ZRC2LEBJDRZYJony+HOYLRLOptbTE3W72JVRG3jPwkoMfGPl2uV8u80DBh7iM eImsCiKFP5knUqtM9sKgKa7fASXdpWMJ9vjPIbQU4PTycTXCtNFKu10TNoKT6VoX4Ys+qIMGOpS eMI5QGOgEkT6CC1v6oRpjTRpcI= X-Received: by 2002:a05:6a00:3c84:b0:81f:9bed:ae9d with SMTP id d2e1a72fcca58-8241c6e2f4fmr1458678b3a.46.1770172101033; Tue, 03 Feb 2026 18:28:21 -0800 (PST) Received: from ikb-h07-29-noble.in.iijlab.net ([202.214.97.5]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8241d47a418sm660116b3a.53.2026.02.03.18.28.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Feb 2026 18:28:19 -0800 (PST) Received: by ikb-h07-29-noble.in.iijlab.net (Postfix, from userid 1010) id 87CA61200C33; Wed, 4 Feb 2026 11:28:18 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Cc: thehajime@gmail.com, ricarkol@google.com, Liam.Howlett@oracle.com, linux-kernel@vger.kernel.org Subject: [PATCH v14 02/13] um: decouple MMU specific code from the common part Date: Wed, 4 Feb 2026 11:28:00 +0900 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- arch/um/kernel/Makefile | 5 +- arch/um/kernel/mem-pgtable.c | 55 ++++++++++++++ arch/um/kernel/mem.c | 35 --------- arch/um/kernel/process.c | 38 ++++++++++ arch/um/kernel/skas/process.c | 37 --------- arch/um/os-Linux/Makefile | 3 +- arch/um/os-Linux/process.c | 129 ++++++++++++++++++++++++++++++++ arch/um/os-Linux/skas/process.c | 128 +------------------------------ 8 files changed, 228 insertions(+), 202 deletions(-) create mode 100644 arch/um/kernel/mem-pgtable.c diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index be60bc451b3f..76d36751973e 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -16,9 +16,10 @@ always-$(KBUILD_BUILTIN) :=3D vmlinux.lds =20 obj-y =3D 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 \ - um_arch.o umid.o kmsg_dump.o capflags.o skas/ + signal.o sysrq.o time.o \ + um_arch.o umid.o kmsg_dump.o capflags.o obj-y +=3D load_file.o +obj-$(CONFIG_MMU) +=3D mem-pgtable.o tlb.o trap.o skas/ =20 obj-$(CONFIG_BLK_DEV_INITRD) +=3D initrd.o obj-$(CONFIG_GPROF) +=3D 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Allocate and free page tables. */ + +pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *pgd =3D (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] =3D { + [VM_NONE] =3D PAGE_NONE, + [VM_READ] =3D PAGE_READONLY, + [VM_WRITE] =3D PAGE_COPY, + [VM_WRITE | VM_READ] =3D PAGE_COPY, + [VM_EXEC] =3D PAGE_READONLY, + [VM_EXEC | VM_READ] =3D PAGE_READONLY, + [VM_EXEC | VM_WRITE] =3D PAGE_COPY, + [VM_EXEC | VM_WRITE | VM_READ] =3D PAGE_COPY, + [VM_SHARED] =3D PAGE_NONE, + [VM_SHARED | VM_READ] =3D PAGE_READONLY, + [VM_SHARED | VM_WRITE] =3D PAGE_SHARED, + [VM_SHARED | VM_WRITE | VM_READ] =3D PAGE_SHARED, + [VM_SHARED | VM_EXEC] =3D PAGE_READONLY, + [VM_SHARED | VM_EXEC | VM_READ] =3D PAGE_READONLY, + [VM_SHARED | VM_EXEC | VM_WRITE] =3D PAGE_SHARED, + [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] =3D PAGE_SHARED +}; +DECLARE_VM_GET_PAGE_PROT diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 39c4a7e21c6f..f3258680bfbe 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -107,45 +106,11 @@ void free_initmem(void) { } =20 -/* Allocate and free page tables. */ - -pgd_t *pgd_alloc(struct mm_struct *mm) -{ - pgd_t *pgd =3D __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); } =20 -static const pgprot_t protection_map[16] =3D { - [VM_NONE] =3D PAGE_NONE, - [VM_READ] =3D PAGE_READONLY, - [VM_WRITE] =3D PAGE_COPY, - [VM_WRITE | VM_READ] =3D PAGE_COPY, - [VM_EXEC] =3D PAGE_READONLY, - [VM_EXEC | VM_READ] =3D PAGE_READONLY, - [VM_EXEC | VM_WRITE] =3D PAGE_COPY, - [VM_EXEC | VM_WRITE | VM_READ] =3D PAGE_COPY, - [VM_SHARED] =3D PAGE_NONE, - [VM_SHARED | VM_READ] =3D PAGE_READONLY, - [VM_SHARED | VM_WRITE] =3D PAGE_SHARED, - [VM_SHARED | VM_WRITE | VM_READ] =3D PAGE_SHARED, - [VM_SHARED | VM_EXEC] =3D PAGE_READONLY, - [VM_SHARED | VM_EXEC | VM_READ] =3D PAGE_READONLY, - [VM_SHARED | VM_EXEC | VM_WRITE] =3D PAGE_SHARED, - [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] =3D PAGE_SHARED -}; -DECLARE_VM_GET_PAGE_PROT - void mark_rodata_ro(void) { unsigned long rodata_start =3D PFN_ALIGN(__start_rodata); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 63b38a3f73f7..b07c1f120910 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -307,3 +308,40 @@ unsigned long __get_wchan(struct task_struct *p) =20 return 0; } + +extern void start_kernel(void); + +static int __init start_kernel_proc(void *unused) +{ + block_signals_trace(); + + start_kernel(); + return 0; +} + +char cpu_irqstacks[NR_CPUS][THREAD_SIZE] __aligned(THREAD_SIZE); + +int __init start_uml(void) +{ + stack_protections((unsigned long) &cpu_irqstacks[0]); + set_sigstack(cpu_irqstacks[0], THREAD_SIZE); + + init_new_thread_signals(); + + init_task.thread.request.thread.proc =3D start_kernel_proc; + init_task.thread.request.thread.arg =3D NULL; + return start_idle_thread(task_stack_page(&init_task), + &init_task.thread.switch_buf); +} + +static DEFINE_SPINLOCK(initial_jmpbuf_spinlock); + +void initial_jmpbuf_lock(void) +{ + spin_lock_irq(&initial_jmpbuf_spinlock); +} + +void initial_jmpbuf_unlock(void) +{ + spin_unlock_irq(&initial_jmpbuf_spinlock); +} diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 4a7673b0261a..d643854942bc 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -17,31 +17,6 @@ #include #include =20 -extern void start_kernel(void); - -static int __init start_kernel_proc(void *unused) -{ - block_signals_trace(); - - start_kernel(); - return 0; -} - -char cpu_irqstacks[NR_CPUS][THREAD_SIZE] __aligned(THREAD_SIZE); - -int __init start_uml(void) -{ - stack_protections((unsigned long) &cpu_irqstacks[0]); - set_sigstack(cpu_irqstacks[0], THREAD_SIZE); - - init_new_thread_signals(); - - init_task.thread.request.thread.proc =3D start_kernel_proc; - init_task.thread.request.thread.arg =3D NULL; - return start_idle_thread(task_stack_page(&init_task), - &init_task.thread.switch_buf); -} - unsigned long current_stub_stack(void) { if (current->mm =3D=3D NULL) @@ -65,15 +40,3 @@ void current_mm_sync(void) =20 um_tlb_sync(current->mm); } - -static DEFINE_SPINLOCK(initial_jmpbuf_spinlock); - -void initial_jmpbuf_lock(void) -{ - spin_lock_irq(&initial_jmpbuf_spinlock); -} - -void initial_jmpbuf_unlock(void) -{ - spin_unlock_irq(&initial_jmpbuf_spinlock); -} diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index f8d672d570d9..40e3e0eab6a0 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -8,7 +8,8 @@ KCOV_INSTRUMENT :=3D n =20 obj-y =3D elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ registers.o sigio.o signal.o start_up.o time.o tty.o \ - umid.o user_syms.o util.o skas/ + umid.o user_syms.o util.o +obj-$(CONFIG_MMU) +=3D skas/ =20 CFLAGS_signal.o +=3D -Wframe-larger-than=3D4096 =20 diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 3a2a84ab9325..734d143417c8 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -6,6 +6,7 @@ =20 #include #include +#include #include #include #include @@ -17,10 +18,16 @@ #include #include #include +#include #include #include #include #include +#include +#include + +int using_seccomp; +int unscheduled_userspace_iterations; =20 void os_alarm_process(int pid) { @@ -209,3 +216,125 @@ int os_futex_wake(void *uaddr) NULL, NULL, 0)); return r < 0 ? -errno : r; } + +int is_skas_winch(int pid, int fd, void *data) +{ + return pid =3D=3D getpgrp(); +} + +void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) +{ + (*buf)[0].JB_IP =3D (unsigned long) handler; + (*buf)[0].JB_SP =3D (unsigned long) stack + UM_THREAD_SIZE - + sizeof(void *); +} + +#define INIT_JMP_NEW_THREAD 0 +#define INIT_JMP_CALLBACK 1 +#define INIT_JMP_HALT 2 +#define INIT_JMP_REBOOT 3 + +void switch_threads(jmp_buf *me, jmp_buf *you) +{ + unscheduled_userspace_iterations =3D 0; + + if (UML_SETJMP(me) =3D=3D 0) + UML_LONGJMP(you, 1); +} + +static jmp_buf initial_jmpbuf; + +static __thread void (*cb_proc)(void *arg); +static __thread void *cb_arg; +static __thread jmp_buf *cb_back; + +int start_idle_thread(void *stack, jmp_buf *switch_buf) +{ + int n; + + set_handler(SIGWINCH); + + /* + * Can't use UML_SETJMP or UML_LONGJMP here because they save + * and restore signals, with the possible side-effect of + * trying to handle any signals which came when they were + * blocked, which can't be done on this stack. + * Signals must be blocked when jumping back here and restored + * after returning to the jumper. + */ + n =3D setjmp(initial_jmpbuf); + switch (n) { + case INIT_JMP_NEW_THREAD: + (*switch_buf)[0].JB_IP =3D (unsigned long) uml_finishsetup; + (*switch_buf)[0].JB_SP =3D (unsigned long) stack + + UM_THREAD_SIZE - sizeof(void *); + break; + case INIT_JMP_CALLBACK: + (*cb_proc)(cb_arg); + longjmp(*cb_back, 1); + break; + case INIT_JMP_HALT: + kmalloc_ok =3D 0; + return 0; + case INIT_JMP_REBOOT: + kmalloc_ok =3D 0; + return 1; + default: + printk(UM_KERN_ERR "Bad sigsetjmp return in %s - %d\n", + __func__, n); + fatal_sigsegv(); + } + longjmp(*switch_buf, 1); + + /* unreachable */ + printk(UM_KERN_ERR "impossible long jump!"); + fatal_sigsegv(); + return 0; +} + +void initial_thread_cb_skas(void (*proc)(void *), void *arg) +{ + jmp_buf here; + + cb_proc =3D proc; + cb_arg =3D arg; + cb_back =3D &here; + + initial_jmpbuf_lock(); + if (UML_SETJMP(&here) =3D=3D 0) + UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); + initial_jmpbuf_unlock(); + + cb_proc =3D NULL; + cb_arg =3D NULL; + cb_back =3D NULL; +} + +void halt_skas(void) +{ + initial_jmpbuf_lock(); + UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); + /* unreachable */ +} + +static bool noreboot; + +static int __init noreboot_cmd_param(char *str, int *add) +{ + *add =3D 0; + noreboot =3D true; + return 0; +} + +__uml_setup("noreboot", noreboot_cmd_param, +"noreboot\n" +" Rather than rebooting, exit always, akin to QEMU's -no-reboot option.= \n" +" This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch= \n" +" crashes in CI\n\n"); + +void reboot_skas(void) +{ + initial_jmpbuf_lock(); + UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT); + /* unreachable */ +} diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/proces= s.c index d6c22f8aa06d..0ebde3d488d6 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -29,16 +28,10 @@ #include #include #include -#include #include #include #include "../internal.h" =20 -int is_skas_winch(int pid, int fd, void *data) -{ - return pid =3D=3D getpgrp(); -} - static const char *ptrace_reg_name(int idx) { #define R(n) case HOST_##n: return #n @@ -426,8 +419,6 @@ static int __init init_stub_exe_fd(void) } __initcall(init_stub_exe_fd); =20 -int using_seccomp; - /** * start_userspace() - prepare a new userspace process * @mm_id: The corresponding struct mm_id @@ -540,7 +531,7 @@ int start_userspace(struct mm_id *mm_id) return err; } =20 -static int unscheduled_userspace_iterations; +extern int unscheduled_userspace_iterations; extern unsigned long tt_extra_sched_jiffies; =20 void userspace(struct uml_pt_regs *regs) @@ -789,120 +780,3 @@ void userspace(struct uml_pt_regs *regs) } } } - -void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) -{ - (*buf)[0].JB_IP =3D (unsigned long) handler; - (*buf)[0].JB_SP =3D (unsigned long) stack + UM_THREAD_SIZE - - sizeof(void *); -} - -#define INIT_JMP_NEW_THREAD 0 -#define INIT_JMP_CALLBACK 1 -#define INIT_JMP_HALT 2 -#define INIT_JMP_REBOOT 3 - -void switch_threads(jmp_buf *me, jmp_buf *you) -{ - unscheduled_userspace_iterations =3D 0; - - if (UML_SETJMP(me) =3D=3D 0) - UML_LONGJMP(you, 1); -} - -static jmp_buf initial_jmpbuf; - -static __thread void (*cb_proc)(void *arg); -static __thread void *cb_arg; -static __thread jmp_buf *cb_back; - -int start_idle_thread(void *stack, jmp_buf *switch_buf) -{ - int n; - - set_handler(SIGWINCH); - - /* - * Can't use UML_SETJMP or UML_LONGJMP here because they save - * and restore signals, with the possible side-effect of - * trying to handle any signals which came when they were - * blocked, which can't be done on this stack. - * Signals must be blocked when jumping back here and restored - * after returning to the jumper. - */ - n =3D setjmp(initial_jmpbuf); - switch (n) { - case INIT_JMP_NEW_THREAD: - (*switch_buf)[0].JB_IP =3D (unsigned long) uml_finishsetup; - (*switch_buf)[0].JB_SP =3D (unsigned long) stack + - UM_THREAD_SIZE - sizeof(void *); - break; - case INIT_JMP_CALLBACK: - (*cb_proc)(cb_arg); - longjmp(*cb_back, 1); - break; - case INIT_JMP_HALT: - kmalloc_ok =3D 0; - return 0; - case INIT_JMP_REBOOT: - kmalloc_ok =3D 0; - return 1; - default: - printk(UM_KERN_ERR "Bad sigsetjmp return in %s - %d\n", - __func__, n); - fatal_sigsegv(); - } - longjmp(*switch_buf, 1); - - /* unreachable */ - printk(UM_KERN_ERR "impossible long jump!"); - fatal_sigsegv(); - return 0; -} - -void initial_thread_cb_skas(void (*proc)(void *), void *arg) -{ - jmp_buf here; - - cb_proc =3D proc; - cb_arg =3D arg; - cb_back =3D &here; - - initial_jmpbuf_lock(); - if (UML_SETJMP(&here) =3D=3D 0) - UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); - initial_jmpbuf_unlock(); - - cb_proc =3D NULL; - cb_arg =3D NULL; - cb_back =3D NULL; -} - -void halt_skas(void) -{ - initial_jmpbuf_lock(); - UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); - /* unreachable */ -} - -static bool noreboot; - -static int __init noreboot_cmd_param(char *str, int *add) -{ - *add =3D 0; - noreboot =3D true; - return 0; -} - -__uml_setup("noreboot", noreboot_cmd_param, -"noreboot\n" -" Rather than rebooting, exit always, akin to QEMU's -no-reboot option.= \n" -" This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch= \n" -" crashes in CI\n\n"); - -void reboot_skas(void) -{ - initial_jmpbuf_lock(); - UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT); - /* unreachable */ -} --=20 2.43.0