From 97512624bb0d747b5f8ac82952d06070eb98cb87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCegge?= Date: Tue, 11 Nov 2025 16:02:03 +0100 Subject: [PATCH 1/3] drivers: ACPI fixed power button driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver for ACPI fixed power buttons. It allows overwriting the default handler so the button can be used for custom purposes. One such purpose might be to trigger an experiment to run. Signed-off-by: Sandro Rüegge --- drivers/power_button.c | 57 ++++++++++++++++++++++++++++++++++ include/drivers/power_button.h | 20 ++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 drivers/power_button.c create mode 100644 include/drivers/power_button.h diff --git a/drivers/power_button.c b/drivers/power_button.c new file mode 100644 index 00000000..9002caee --- /dev/null +++ b/drivers/power_button.c @@ -0,0 +1,57 @@ +#include +#include +#include + +static void default_handler(void *); + +spinlock_t pb_handler_lock = SPINLOCK_INIT; +/** power button press handler */ +static pb_handler_t pb_handler = default_handler; +/** context passed to the power button press handler */ +static void *pb_context = NULL; + +static UINT32 button_handler(void *Context) { + AcpiClearEvent(ACPI_EVENT_POWER_BUTTON); + + if (pb_handler) + pb_handler(pb_context); + + return ACPI_INTERRUPT_HANDLED; +} + +static void default_handler(void *notused) { + acpi_power_off(); +} + +void pb_set_handler(pb_handler_t handler, void *context) { + unsigned long flags = interrupts_disable_save(); + pb_handler = handler; + pb_context = context; + interrupts_restore(flags); +} + +bool init_power_button() { +#ifdef KTF_ACPICA + ACPI_TABLE_FADT *fadt = acpi_find_table(ACPI_SIG_FADT); + + if (!(fadt->Flags & ACPI_FADT_POWER_BUTTON)) { + printk("PWRB: Configuring ACPI 'fixed' power button handling\n"); + + if (ACPI_FAILURE(AcpiClearEvent(ACPI_EVENT_POWER_BUTTON))) + panic("PWRB: Failed to clear power button event"); + + if (ACPI_FAILURE(AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON, + button_handler, NULL))) + panic("PWRB: Failed to install power button handler"); + } + else { + panic("PWRB: Non-fixed power button not implemented\n"); + } + + dprintk("PWRB: Initialized Power Button\n"); +#else + panic("PWRB: Power button without ACPICA not implemented\n"); +#endif + + return true; +} diff --git a/include/drivers/power_button.h b/include/drivers/power_button.h new file mode 100644 index 00000000..8d764b9f --- /dev/null +++ b/include/drivers/power_button.h @@ -0,0 +1,20 @@ +#ifndef KTF_POWER_BUTTON_H +#define KTF_POWER_BUTTON_H + +#include + +typedef void (*pb_handler_t)(void *); + +/** + * Set a handler for the power button. Useful to control experiments. + * + * Note: This function MUST be called from the bsp to ensure consistency! + */ +void pb_set_handler(pb_handler_t handler, void *context); + +/** + * Initialize power button handling. Requires ACPICA library. + */ +extern bool init_power_button(); + +#endif /* KTF_POWER_BUTTON_H */ From ebb8451436a428588a5fb2a4d76d8f7aeb87e05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCegge?= Date: Fri, 14 Nov 2025 13:30:01 +0100 Subject: [PATCH 2/3] percpu,drivers: Add cpu self reference to percpu Adding a self reference to the percpu allows checking what CPU some code is currently running on. We use this in pb_set_handler to ensure it runs on the bsp. --- common/cpu.c | 1 + drivers/power_button.c | 3 +++ include/cpu.h | 4 ++++ include/percpu.h | 2 ++ 4 files changed, 10 insertions(+) diff --git a/common/cpu.c b/common/cpu.c index 1bd0dc85..8094ab4a 100644 --- a/common/cpu.c +++ b/common/cpu.c @@ -49,6 +49,7 @@ static void init_cpu(cpu_t *cpu, unsigned int id, bool is_bsp, bool enabled) { cpu->percpu = get_percpu_page(id); BUG_ON(!cpu->percpu); + cpu->percpu->cpu = cpu; cpu->lock = SPINLOCK_INIT; list_init(&cpu->task_queue); diff --git a/drivers/power_button.c b/drivers/power_button.c index 9002caee..ef02a428 100644 --- a/drivers/power_button.c +++ b/drivers/power_button.c @@ -24,6 +24,9 @@ static void default_handler(void *notused) { } void pb_set_handler(pb_handler_t handler, void *context) { + // check that we are on the bsp. Assumes that there is no task migration + ASSERT(is_cpu_bsp(get_this_cpu())); + unsigned long flags = interrupts_disable_save(); pb_handler = handler; pb_context = context; diff --git a/include/cpu.h b/include/cpu.h index 31b39d2f..f7c7eeb6 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -67,6 +67,10 @@ extern void wait_for_all_cpus(void); /* Static declarations */ +static inline cpu_t *get_this_cpu() { + return PERCPU_GET(cpu); +} + static inline bool is_cpu_bsp(cpu_t *cpu) { return cpu->flags.bsp; } diff --git a/include/percpu.h b/include/percpu.h index f6029ec5..7563e38a 100644 --- a/include/percpu.h +++ b/include/percpu.h @@ -31,6 +31,7 @@ #include #include +struct cpu; struct percpu { list_head_t list; @@ -60,6 +61,7 @@ struct percpu { unsigned long usermode_private; volatile unsigned long apic_ticks; bool apic_timer_enabled; + struct cpu *cpu; } __aligned(PAGE_SIZE); typedef struct percpu percpu_t; From 9b2fae1ff78c0fa858ce67449e0348395c5d44b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCegge?= Date: Tue, 11 Nov 2025 16:02:33 +0100 Subject: [PATCH 3/3] cmdline: add option to enable power button handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sandro Rüegge --- common/cmdline.c | 3 +++ common/setup.c | 4 ++++ include/cmdline.h | 1 + 3 files changed, 8 insertions(+) diff --git a/common/cmdline.c b/common/cmdline.c index bbc48692..d5e50e86 100644 --- a/common/cmdline.c +++ b/common/cmdline.c @@ -58,6 +58,9 @@ bool_cmd("qemu_console", opt_qemu_console); bool opt_poweroff = true; bool_cmd("poweroff", opt_poweroff); +bool opt_power_button = false; +bool_cmd("power_button", opt_power_button); + static char opt_com1[20]; string_cmd("com1", opt_com1); diff --git a/common/setup.c b/common/setup.c index cae1a7b9..1185c12e 100644 --- a/common/setup.c +++ b/common/setup.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -283,6 +284,9 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, unsigned long enable_fpu(); } + if (opt_power_button) + init_power_button(); + #ifdef KTF_PMU printk("Initializing PFM library\n"); diff --git a/include/cmdline.h b/include/cmdline.h index 9b1fba1e..9fba50c2 100644 --- a/include/cmdline.h +++ b/include/cmdline.h @@ -67,6 +67,7 @@ extern bool opt_hpet; extern bool opt_fpu; extern bool opt_qemu_console; extern bool opt_poweroff; +extern bool opt_power_button; extern bool opt_fb_scroll; extern unsigned long opt_reboot_timeout; extern bool opt_tlb_global;