Skip to content

Commit

Permalink
goodbye smp again
Browse files Browse the repository at this point in the history
  • Loading branch information
tombl committed Feb 28, 2024
1 parent 8ae8223 commit 5f8d223
Show file tree
Hide file tree
Showing 26 changed files with 124 additions and 199 deletions.
2 changes: 1 addition & 1 deletion arch/wasm/Kbuild
Original file line number Diff line number Diff line change
@@ -1 +1 @@
obj-y += kernel/ mm/
obj-y += kernel/ mm/
19 changes: 5 additions & 14 deletions arch/wasm/Kconfig
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
config WASM
def_bool y
depends on !BINFMT_ELF && !MMU && !MODULES && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT
depends on !SMP && !BINFMT_ELF && !MMU && !MODULES && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT
select ARCH_HAS_BINFMT_WASM
select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_NO_SWAP
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select BUG
select FLATMEM
select FORCE_NR_CPUS
select FORCE_NR_CPUS if SMP
select GENERIC_ATOMIC64
select GENERIC_CSUM
select GENERIC_HWEIGHT
select OF
select OF_EARLY_FLATTREE
select PAGE_SIZE_64KB
select SMP
# select SMP
select THREAD_INFO_IN_TASK
select UACCESS_MEMCPY if !MMU
select USE_PER_CPU_TLS

config ARCH_HAS_BINFMT_WASM
bool

menu "Executable file formats"
config BINFMT_WASM
bool "Kernel support for WASM binaries"
depends on ARCH_HAS_BINFMT_WASM
endmenu

config CMDLINE
string "Kernel command string to append"
default ""
Expand All @@ -40,12 +31,12 @@ config EARLY_PRINTK
def_bool y

config SMP
def_bool y
def_bool n

config NR_CPUS
int
default 1 if !SMP
default 8 if SMP
default 16 if SMP

config HZ
int
Expand Down
2 changes: 1 addition & 1 deletion arch/wasm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ LD = wasm-ld
WASM_FEATURES = -matomics -mbulk-memory -mexception-handling -mextended-const -mmultivalue -mmutable-globals -mnontrapping-fptoint -mreference-types -mrelaxed-simd -msign-ext -msimd128

cflags-y += -Wno-incompatible-library-redeclaration '-D__builtin_return_address=wasm_return_address' $(WASM_FEATURES)
ldflags-y += --import-memory --shared-memory --max-memory=4294967296 --no-gc-sections
ldflags-y += --import-memory --max-memory=4294967296 --shared-memory

KBUILD_CFLAGS += $(cflags-y)
KBUILD_AFLAGS += $(aflags-y)
Expand Down
4 changes: 3 additions & 1 deletion arch/wasm/include/asm/current.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#ifndef _WASM_CURRENT_H
#define _WASM_CURRENT_H

#include <asm/percpu.h>

struct task_struct;

extern _Thread_local struct task_struct * current;
DECLARE_PER_CPU(struct task_struct*, current);

#endif
5 changes: 1 addition & 4 deletions arch/wasm/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@

struct task_struct;

static inline void cpu_relax(void)
{
wasm_relax();
}
void cpu_relax(void);

#define current_text_addr() wasm_return_address(-1)

Expand Down
6 changes: 5 additions & 1 deletion arch/wasm/include/asm/sigcontext.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#ifndef _WASM_SIGCONTEXT_H
#define _WASM_SIGCONTEXT_H

struct pt_regs {};
struct pt_regs {
void* current_stack;
int (*fn)(void*);
void* fn_arg;
};

struct sigcontext {
struct pt_regs regs;
Expand Down
4 changes: 4 additions & 0 deletions arch/wasm/include/asm/smp.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#ifndef _WASM_SMP_H
#define _WASM_SMP_H

#ifdef CONFIG_SMP

#define raw_smp_processor_id() (current_thread_info()->cpu)

struct cpumask;
void arch_send_call_function_ipi_mask(const struct cpumask *mask);
void arch_send_call_function_single_ipi(int cpu);

#endif

#endif
4 changes: 1 addition & 3 deletions arch/wasm/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ struct thread_info {
struct task_struct *task;
unsigned long flags;
int preempt_count;
struct task_struct *from_sched;
#ifdef CONFIG_SMP
// struct task_struct *from_sched;
unsigned int cpu;
#endif
};

#define INIT_THREAD_INFO(tsk) \
Expand Down
4 changes: 0 additions & 4 deletions arch/wasm/include/asm/wasm_imports.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#define import(name) __attribute__((import_module("kernel"), import_name(name)))

import("breakpoint") void wasm_breakpoint(void);
import("relax") void wasm_relax(void);
import("idle") void wasm_idle(void);
import("halt") void wasm_halt(void);
import("restart") void wasm_restart(void);

Expand All @@ -27,8 +25,6 @@ import("get_now_nsec") unsigned long long wasm_get_now_nsec(void);

import("get_stacktrace") void wasm_get_stacktrace(char *buf, size_t size);

import("new_worker") void wasm_new_worker(void* arg, char name[16]);

#undef import

#endif
3 changes: 2 additions & 1 deletion arch/wasm/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ obj-y += \
process.o \
ptrace.o \
setup.o \
smp.o \
stacktrace.o \
time.o

obj-$(CONFIG_SMP) += smp.o
89 changes: 27 additions & 62 deletions arch/wasm/kernel/process.c
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
#include "linux/thread_info.h"
#include <asm/sysmem.h>
#include <asm/wasm_imports.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/sched/task.h>

void arch_cpu_idle(void)
{
wasm_idle();
}

__asm__(".globaltype __stack_pointer, i32\n");

static void *get_stack_pointer(void)
Expand All @@ -31,75 +24,47 @@ static void __always_inline set_stack_pointer(void *ptr)
struct task_struct *__switch_to(struct task_struct *from,
struct task_struct *to)
{
// struct thread_info *from_info = task_thread_info(from);
struct thread_info *to_info = task_thread_info(to);

to_info->from_sched = from;

pr_info("context switch CPU: %i PID: %u -> %u STACK: %p -> %p\n",
smp_processor_id(), from->pid, to->pid, get_stack_pointer(),
to->stack);
struct pt_regs *from_regs = task_pt_regs(from);
struct pt_regs *to_regs = task_pt_regs(to);

set_stack_pointer(to->stack);
current = to;
from_regs->current_stack = get_stack_pointer();

return from;
}
pr_info("context switch PID: %u STACK: %p\n"
"-> %u %p\n",
from->pid, from_regs->current_stack, to->pid,
to_regs->current_stack);

struct entry_arg {
int cpu;
struct thread_info *thread_info;
int (*fn)(void *);
void *fn_arg;
};
void show_stack(struct task_struct *task, unsigned long *sp,
const char *loglvl);
set_stack_pointer(to_regs->current_stack);

int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
{
struct entry_arg *entry;

if (!args->fn) panic("can't copy userspace thread"); // yet
current = to;

entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
schedule_tail(from);

entry->fn = args->fn;
entry->fn_arg = args->fn_arg;
entry->thread_info = task_thread_info(p);
pr_info("regs: %p\n", to_regs);
BUG_ON(!to_regs->fn);

wasm_new_worker(entry, p->comm);
pr_info("about to call %p %p\n", to_regs->fn, to_regs->fn_arg);
to_regs->fn(to_regs->fn_arg);
to_regs->fn = NULL;

return 0;
return from;
}

static atomic_t next_cpu_nr = ATOMIC_INIT(1);
void noinline_for_stack task_entry_inner(struct entry_arg *entry)
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
{
int (*fn)(void *) = entry->fn;
void *fn_arg = entry->fn_arg;
struct thread_info *thread_info = entry->thread_info;
int cpu;
kfree(entry);
struct pt_regs *childregs = task_pt_regs(p);

cpu = atomic_inc_return(&next_cpu_nr);
smp_tls_init(cpu);
current = thread_info->from_sched;
current_thread_info()->cpu = cpu;
pr_info("== THREAD ENTRY! CPU: %i ==", cpu);
memset(childregs, 0, sizeof(struct pt_regs));

if (thread_info->from_sched)
schedule_tail(thread_info->from_sched);
childregs->current_stack = childregs;

fn(fn_arg);
if (!args->fn)
panic("can't copy userspace thread"); // yet

do_exit(0);
}
pr_info("copying thread %i %p\n", p->pid, childregs);

__attribute__((export_name("task_entry"))) void
task_entry(struct entry_arg *entry)
{
set_stack_pointer(entry->thread_info->task->stack);
task_entry_inner(entry);
childregs->fn = args->fn;
childregs->fn_arg = args->fn_arg;

return 0;
}
2 changes: 2 additions & 0 deletions arch/wasm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ __attribute__((export_name("start"))) void __init _start(void)
{
static char wasm_dt[1024];

#ifdef CONFIG_SMP
early_tls_init();
#endif
__wasm_call_ctors();

setup_early_printk(NULL);
Expand Down
2 changes: 1 addition & 1 deletion arch/wasm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,4 @@ void handle_ipi(struct pt_regs *regs)

mb(); /* Order data access and bit testing. */
}
}
}
16 changes: 12 additions & 4 deletions arch/wasm/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ void calibrate_delay(void)

void __delay(unsigned long cycles)
{
cycles_t start = wasm_get_now_nsec();
static int zero = 0;
int ret = __builtin_wasm_memory_atomic_wait32(&zero, 0, cycles);
BUG_ON(ret != 2); // 2 means timeout
}

while ((wasm_get_now_nsec() - start) < cycles)
cpu_relax();
void cpu_relax(void)
{
__delay(100);
}

void __udelay(unsigned long usecs)
Expand All @@ -33,6 +37,10 @@ void __const_udelay(unsigned long xloops)
__delay(xloops / 0x10c7ul); /* 2**32 / 1000000 (rounded up) */
}

unsigned long long sched_clock(void) {
return wasm_get_now_nsec();
}

static u64 clock_read(struct clocksource *cs)
{
return wasm_get_now_nsec();
Expand All @@ -50,4 +58,4 @@ void __init time_init(void)
{
if (clocksource_register_khz(&clocksource, 1000000))
panic("unable to register clocksource\n");
}
}
3 changes: 2 additions & 1 deletion arch/wasm/mm/Makefile
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
obj-y := init.o page.o tls.o
obj-y := init.o page.o
obj-$(CONFIG_SMP) := tls.o
2 changes: 1 addition & 1 deletion arch/wasm/mm/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ void smp_tls_init(int cpu)
{
BUG_ON(__per_cpu_offset[cpu] == (void *)-1);
__wasm_init_tls((void *)__per_cpu_offset[cpu]);
}
}
10 changes: 6 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
packages = nixpkgs.lib.genAttrs
[ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]
(system:
let pkgs = nixpkgs.legacyPackages.${system}; in {
default = pkgs.clangStdenv.mkDerivation {
let pkgs = nixpkgs.legacyPackages.${system};
llvm = pkgs.llvmPackages_17;
in {
default = llvm.stdenv.mkDerivation {
pname = "linux";
version = "6.1.69-wasm";
src = ./.;
Expand Down Expand Up @@ -35,8 +37,8 @@
pkg-config
ncurses

lld
libllvm
llvm.lld
llvm.libllvm
wabt
esbuild
];
Expand Down
7 changes: 7 additions & 0 deletions fs/Kconfig.binfmt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ config BINFMT_MISC
you have use for it; the module is called binfmt_misc. If you
don't know what to answer at this point, say Y.

config ARCH_HAS_BINFMT_WASM
bool

config BINFMT_WASM
bool "Kernel support for WASM binaries"
depends on ARCH_HAS_BINFMT_WASM

config COREDUMP
bool "Enable core dump support" if EXPERT
default y
Expand Down
2 changes: 1 addition & 1 deletion include/linux/percpu-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ do { \
(void)__vpp_verify; \
} while (0)

#ifdef CONFIG_SMP
#if defined(CONFIG_SMP) || defined(CONFIG_USE_PER_CPU_TLS)

/*
* Add an offset to a pointer but keep the pointer as-is. Use RELOC_HIDE()
Expand Down
Loading

0 comments on commit 5f8d223

Please sign in to comment.