Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions common/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions common/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions common/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include <drivers/hpet.h>
#include <drivers/pic.h>
#include <drivers/pit.h>
#include <drivers/power_button.h>
#include <drivers/serial.h>
#include <drivers/vga.h>

Expand Down Expand Up @@ -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");

Expand Down
60 changes: 60 additions & 0 deletions drivers/power_button.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <acpi_ktf.h>
#include <drivers/power_button.h>
#include <spinlock.h>

static void default_handler(void *);

spinlock_t pb_handler_lock = SPINLOCK_INIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pb_handler_lock isn't used any more, can remove its definition as well.

/** 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) {
// 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;
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;
}
1 change: 1 addition & 0 deletions include/cmdline.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions include/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
20 changes: 20 additions & 0 deletions include/drivers/power_button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef KTF_POWER_BUTTON_H
#define KTF_POWER_BUTTON_H

#include <cpu.h>

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 */
2 changes: 2 additions & 0 deletions include/percpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <list.h>
#include <page.h>

struct cpu;
struct percpu {
list_head_t list;

Expand Down Expand Up @@ -60,6 +61,7 @@ struct percpu {
unsigned long usermode_private;
volatile unsigned long apic_ticks;
bool apic_timer_enabled;
struct cpu *cpu;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, using the proper typedef'd type cpu_t would cause a cyclic header include dependency?

} __aligned(PAGE_SIZE);
typedef struct percpu percpu_t;

Expand Down