From 6c541a2654040e37aaef6ee4380ec8057b122364 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Mon, 25 Jun 2018 20:44:10 +0200 Subject: kern/percpu: introduce per-CPU operations --- arch/x86/machine/boot.c | 2 ++ kern/percpu.c | 30 ++++++++++++++++++++++++++++++ kern/percpu.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/arch/x86/machine/boot.c b/arch/x86/machine/boot.c index 6934896e..6a26a90d 100644 --- a/arch/x86/machine/boot.c +++ b/arch/x86/machine/boot.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -504,6 +505,7 @@ boot_ap_main(void) cpu_ap_setup(); thread_ap_setup(); pmap_ap_setup(); + percpu_ap_setup(); kernel_ap_main(); /* Never reached */ diff --git a/kern/percpu.c b/kern/percpu.c index 53861a30..f344bd70 100644 --- a/kern/percpu.c +++ b/kern/percpu.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,14 @@ static void *percpu_area_content __initdata; static size_t percpu_area_size __initdata; static int percpu_skip_warning __initdata; +static struct slist percpu_ops __initdata; + +static void __init +percpu_op_run(const struct percpu_op *op) +{ + op->fn(); +} + static int __init percpu_bootstrap(void) { @@ -51,6 +60,8 @@ percpu_setup(void) struct vm_page *page; unsigned int order; + slist_init(&percpu_ops); + percpu_area_size = &_percpu_end - &_percpu; log_info("percpu: max_cpus: %u, section size: %zuk", CONFIG_MAX_CPUS, percpu_area_size >> 10); @@ -76,6 +87,15 @@ INIT_OP_DEFINE(percpu_setup, INIT_OP_DEP(percpu_bootstrap, true), INIT_OP_DEP(vm_page_setup, true)); +void __init +percpu_register_op(struct percpu_op *op) +{ + slist_insert_tail(&percpu_ops, &op->node); + + /* Run on BSP */ + percpu_op_run(op); +} + int __init percpu_add(unsigned int cpu) { @@ -116,6 +136,16 @@ out: return 0; } +void __init +percpu_ap_setup(void) +{ + struct percpu_op *op; + + slist_for_each_entry(&percpu_ops, op, node) { + percpu_op_run(op); + } +} + static int __init percpu_cleanup(void) { diff --git a/kern/percpu.h b/kern/percpu.h index 96f706ea..f77e7fd8 100644 --- a/kern/percpu.h +++ b/kern/percpu.h @@ -59,10 +59,26 @@ #include #include +#include #define PERCPU_SECTION .percpu #define __percpu __section(QUOTE(PERCPU_SECTION)) +typedef void (*percpu_op_fn_t)(void); + +/* + * Per-CPU operation. + * + * These operations allow initialization code to register functions to be run + * on APs when they're started. + */ +struct percpu_op { + struct slist_node node; + percpu_op_fn_t fn; +}; + +#define PERCPU_OP_INITIALIZER(op_fn) { .fn = op_fn } + /* * Boundaries of the percpu section. * @@ -95,6 +111,15 @@ percpu_area(unsigned int cpu) return area; } +/* + * Register a percpu operation to be run on all processors when + * they're started. + * + * The operation is run on the BSP when it's registered. It's run as late as + * possible on APs, normally right before scheduling is enabled. + */ +void percpu_register_op(struct percpu_op *op); + /* * Register a processor. * @@ -104,6 +129,11 @@ percpu_area(unsigned int cpu) */ int percpu_add(unsigned int cpu); +/* + * Run registered percpu operations on an AP. + */ +void percpu_ap_setup(void); + /* * This init operation provides : * - access to percpu variables on processor 0 @@ -112,6 +142,7 @@ INIT_OP_DECLARE(percpu_bootstrap); /* * This init operation provides : + * - percpu operations can be registered * - new percpu areas can be created * * The dependency that provides access to percpu variables on all processors -- cgit v1.2.3