feat: add fadt based lapic timer calibration
This commit is contained in:
parent
54d48e7d91
commit
61dfda6a70
7 changed files with 257 additions and 28 deletions
98
kernel/include/acpi/fadt.h
Normal file
98
kernel/include/acpi/fadt.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#pragma once
|
||||
|
||||
#include "acpi/acpi.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "util/number.h"
|
||||
|
||||
namespace acpi {
|
||||
|
||||
struct fadt_flags_t {
|
||||
uint32_t wbinvd : 1;
|
||||
uint32_t wbinvd_flush : 1;
|
||||
uint32_t processor_c1 : 1;
|
||||
uint32_t p_level2_up : 1;
|
||||
uint32_t power_button : 1;
|
||||
uint32_t sleep_button : 1;
|
||||
uint32_t fixed_rtc : 1;
|
||||
uint32_t rtc_s4 : 1;
|
||||
uint32_t timer_value_extended : 1;
|
||||
uint32_t reserved : 23;
|
||||
};
|
||||
static_assert(sizeof(fadt_flags_t) == 4);
|
||||
|
||||
// Prefix of the FADT through the flags field; real tables continue past this,
|
||||
// so no field after flags may be added without also handling table revisions.
|
||||
struct fadt_t {
|
||||
sdt_header_t header;
|
||||
uint32_t firmware_control;
|
||||
uint32_t dsdt_address;
|
||||
uint8_t reserved;
|
||||
uint8_t preferred_pm_profile;
|
||||
uint16_t sci_interrupt;
|
||||
uint32_t smi_command_port;
|
||||
uint8_t acpi_enable;
|
||||
uint8_t acpi_disable;
|
||||
uint8_t s4bios_request;
|
||||
uint8_t pstate_control;
|
||||
uint32_t pm1a_event_block;
|
||||
uint32_t pm1b_event_block;
|
||||
uint32_t pm1a_control_block;
|
||||
uint32_t pm1b_control_block;
|
||||
uint32_t pm2_control_block;
|
||||
uint32_t pm_timer_block;
|
||||
uint32_t gpe0_block;
|
||||
uint32_t gpe1_block;
|
||||
uint8_t pm1_event_length;
|
||||
uint8_t pm1_control_length;
|
||||
uint8_t pm2_control_length;
|
||||
uint8_t pm_timer_length;
|
||||
uint8_t gpe0_block_length;
|
||||
uint8_t gpe1_block_length;
|
||||
uint8_t gpe1_base;
|
||||
uint8_t cstate_control;
|
||||
uint16_t p_level2_latency;
|
||||
uint16_t p_level3_latency;
|
||||
uint16_t flush_size;
|
||||
uint16_t flush_stride;
|
||||
uint8_t duty_offset;
|
||||
uint8_t duty_width;
|
||||
uint8_t day_alarm;
|
||||
uint8_t month_alarm;
|
||||
uint8_t century;
|
||||
uint16_t iapc_boot_architecture;
|
||||
uint8_t reserved2;
|
||||
fadt_flags_t flags;
|
||||
} __attribute__((packed));
|
||||
static_assert(sizeof(fadt_t) == 116);
|
||||
|
||||
constexpr uint64_t pm_timer_frequency_hz = 3'579'545;
|
||||
|
||||
struct pm_timer_duration_t {
|
||||
uint64_t pm_ticks;
|
||||
};
|
||||
|
||||
constexpr pm_timer_duration_t pm_timer_milliseconds(uint64_t count) {
|
||||
return pm_timer_duration_t{count * pm_timer_frequency_hz / 1'000};
|
||||
}
|
||||
|
||||
struct Fadt {
|
||||
explicit Fadt(paddr_t fadt_physical) : table(fadt_physical.access<fadt_t>()) {}
|
||||
explicit Fadt(const fadt_t* fadt_table) : table(fadt_table) {}
|
||||
|
||||
bool has_pm_timer() const {
|
||||
return table->pm_timer_block != 0 && table->pm_timer_length == 4;
|
||||
}
|
||||
|
||||
uint16_t pm_timer_port() const {
|
||||
return static_cast<uint16_t>(table->pm_timer_block);
|
||||
}
|
||||
|
||||
bool pm_timer_is_32bit() const {
|
||||
return table->flags.timer_value_extended != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const fadt_t* table;
|
||||
};
|
||||
|
||||
} // namespace acpi
|
||||
Loading…
Add table
Add a link
Reference in a new issue