Kernel: Run clang-format on files

Let's rip off the band-aid
This commit is contained in:
Shannon Booth 2020-03-22 13:12:45 +13:00 committed by Andreas Kling
parent d0629d0a8c
commit 81adefef27
25 changed files with 2992 additions and 2995 deletions

View file

@ -29,70 +29,70 @@
namespace Kernel { namespace Kernel {
namespace ACPI { namespace ACPI {
void DynamicParser::initialize(PhysicalAddress rsdp) void DynamicParser::initialize(PhysicalAddress rsdp)
{ {
if (!StaticParser::is_initialized()) { if (!StaticParser::is_initialized()) {
new DynamicParser(rsdp); new DynamicParser(rsdp);
}
} }
void DynamicParser::initialize_without_rsdp() }
{ void DynamicParser::initialize_without_rsdp()
if (!StaticParser::is_initialized()) { {
new DynamicParser(); if (!StaticParser::is_initialized()) {
} new DynamicParser();
} }
}
DynamicParser::DynamicParser() DynamicParser::DynamicParser()
: IRQHandler(9) : IRQHandler(9)
, StaticParser() , StaticParser()
{ {
klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML"; klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML";
} }
DynamicParser::DynamicParser(PhysicalAddress rsdp) DynamicParser::DynamicParser(PhysicalAddress rsdp)
: IRQHandler(9) : IRQHandler(9)
, StaticParser(rsdp) , StaticParser(rsdp)
{ {
klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML"; klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML";
} }
void DynamicParser::handle_irq(const RegisterState&) void DynamicParser::handle_irq(const RegisterState&)
{ {
// FIXME: Implement IRQ handling of ACPI signals! // FIXME: Implement IRQ handling of ACPI signals!
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void DynamicParser::enable_aml_interpretation() void DynamicParser::enable_aml_interpretation()
{ {
// FIXME: Implement AML Interpretation // FIXME: Implement AML Interpretation
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void DynamicParser::enable_aml_interpretation(File&) void DynamicParser::enable_aml_interpretation(File&)
{ {
// FIXME: Implement AML Interpretation // FIXME: Implement AML Interpretation
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void DynamicParser::enable_aml_interpretation(u8*, u32) void DynamicParser::enable_aml_interpretation(u8*, u32)
{ {
// FIXME: Implement AML Interpretation // FIXME: Implement AML Interpretation
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void DynamicParser::disable_aml_interpretation() void DynamicParser::disable_aml_interpretation()
{ {
// FIXME: Implement AML Interpretation // FIXME: Implement AML Interpretation
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void DynamicParser::try_acpi_shutdown() void DynamicParser::try_acpi_shutdown()
{ {
// FIXME: Implement AML Interpretation to perform ACPI shutdown // FIXME: Implement AML Interpretation to perform ACPI shutdown
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void DynamicParser::build_namespace() void DynamicParser::build_namespace()
{ {
// FIXME: Implement AML Interpretation to build the ACPI namespace // FIXME: Implement AML Interpretation to build the ACPI namespace
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
} }
} }

View file

@ -35,30 +35,30 @@
namespace Kernel { namespace Kernel {
namespace ACPI { namespace ACPI {
class DynamicParser final : public IRQHandler class DynamicParser final : public IRQHandler
, StaticParser { , StaticParser {
public: public:
static void initialize(PhysicalAddress rsdp); static void initialize(PhysicalAddress rsdp);
static void initialize_without_rsdp(); static void initialize_without_rsdp();
virtual void enable_aml_interpretation() override; virtual void enable_aml_interpretation() override;
virtual void enable_aml_interpretation(File& dsdt_file) override; virtual void enable_aml_interpretation(File& dsdt_file) override;
virtual void enable_aml_interpretation(u8* physical_dsdt, u32 dsdt_payload_legnth) override; virtual void enable_aml_interpretation(u8* physical_dsdt, u32 dsdt_payload_legnth) override;
virtual void disable_aml_interpretation() override; virtual void disable_aml_interpretation() override;
virtual void try_acpi_shutdown() override; virtual void try_acpi_shutdown() override;
virtual bool can_shutdown() override { return true; } virtual bool can_shutdown() override { return true; }
virtual const char* purpose() const override { return "ACPI Parser"; } virtual const char* purpose() const override { return "ACPI Parser"; }
protected: protected:
DynamicParser(); DynamicParser();
explicit DynamicParser(PhysicalAddress); explicit DynamicParser(PhysicalAddress);
private: private:
void build_namespace(); void build_namespace();
// ^IRQHandler // ^IRQHandler
virtual void handle_irq(const RegisterState&) override; virtual void handle_irq(const RegisterState&) override;
OwnPtr<Region> m_acpi_namespace; OwnPtr<Region> m_acpi_namespace;
}; };
} }
} }

View file

@ -28,85 +28,85 @@
namespace Kernel { namespace Kernel {
namespace ACPI { namespace ACPI {
static Parser* s_acpi_parser; static Parser* s_acpi_parser;
Parser& Parser::the() Parser& Parser::the()
{ {
ASSERT(s_acpi_parser != nullptr); ASSERT(s_acpi_parser != nullptr);
return *s_acpi_parser; return *s_acpi_parser;
} }
void Parser::initialize_limited() void Parser::initialize_limited()
{ {
if (!Parser::is_initialized()) { if (!Parser::is_initialized()) {
s_acpi_parser = new Parser(false); s_acpi_parser = new Parser(false);
}
}
bool Parser::is_initialized()
{
return (s_acpi_parser != nullptr);
}
Parser::Parser(bool usable)
{
if (usable) {
klog() << "ACPI: Setting up a functional parser";
} else {
klog() << "ACPI: Limited Initialization. Vital functions are disabled by a request";
}
s_acpi_parser = this;
}
PhysicalAddress Parser::find_table(const char*)
{
klog() << "ACPI: Requested to search for a table, Abort!";
return {};
}
void Parser::try_acpi_reboot()
{
klog() << "ACPI: Cannot invoke reboot!";
}
void Parser::try_acpi_shutdown()
{
klog() << "ACPI: Cannot invoke shutdown!";
}
void Parser::enable_aml_interpretation()
{
klog() << "ACPI: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
void Parser::enable_aml_interpretation(File&)
{
klog() << "ACPI: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
void Parser::enable_aml_interpretation(u8*, u32)
{
klog() << "ACPI: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
void Parser::disable_aml_interpretation()
{
klog() << "ACPI Limited: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
const FADTFlags::HardwareFeatures& Parser::hardware_features() const
{
klog() << "ACPI Limited: Hardware features cannot be obtained";
ASSERT_NOT_REACHED();
}
const FADTFlags::x86_Specific_Flags& Parser::x86_specific_flags() const
{
klog() << "ACPI Limited: x86 specific features cannot be obtained";
ASSERT_NOT_REACHED();
}
bool Parser::is_operable()
{
return false;
} }
} }
bool Parser::is_initialized()
{
return (s_acpi_parser != nullptr);
}
Parser::Parser(bool usable)
{
if (usable) {
klog() << "ACPI: Setting up a functional parser";
} else {
klog() << "ACPI: Limited Initialization. Vital functions are disabled by a request";
}
s_acpi_parser = this;
}
PhysicalAddress Parser::find_table(const char*)
{
klog() << "ACPI: Requested to search for a table, Abort!";
return {};
}
void Parser::try_acpi_reboot()
{
klog() << "ACPI: Cannot invoke reboot!";
}
void Parser::try_acpi_shutdown()
{
klog() << "ACPI: Cannot invoke shutdown!";
}
void Parser::enable_aml_interpretation()
{
klog() << "ACPI: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
void Parser::enable_aml_interpretation(File&)
{
klog() << "ACPI: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
void Parser::enable_aml_interpretation(u8*, u32)
{
klog() << "ACPI: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
void Parser::disable_aml_interpretation()
{
klog() << "ACPI Limited: No AML Interpretation Allowed";
ASSERT_NOT_REACHED();
}
const FADTFlags::HardwareFeatures& Parser::hardware_features() const
{
klog() << "ACPI Limited: Hardware features cannot be obtained";
ASSERT_NOT_REACHED();
}
const FADTFlags::x86_Specific_Flags& Parser::x86_specific_flags() const
{
klog() << "ACPI Limited: x86 specific features cannot be obtained";
ASSERT_NOT_REACHED();
}
bool Parser::is_operable()
{
return false;
}
}
} }

View file

@ -35,448 +35,448 @@
namespace Kernel { namespace Kernel {
namespace ACPI { namespace ACPI {
void StaticParser::initialize(PhysicalAddress rsdp) void StaticParser::initialize(PhysicalAddress rsdp)
{ {
if (!Parser::is_initialized()) { if (!Parser::is_initialized()) {
new StaticParser(rsdp); new StaticParser(rsdp);
}
} }
void StaticParser::initialize_without_rsdp() }
{ void StaticParser::initialize_without_rsdp()
if (!Parser::is_initialized()) { {
new StaticParser(); if (!Parser::is_initialized()) {
} new StaticParser();
} }
}
bool StaticParser::is_initialized() bool StaticParser::is_initialized()
{ {
return Parser::is_initialized(); return Parser::is_initialized();
} }
void StaticParser::locate_static_data() void StaticParser::locate_static_data()
{ {
locate_main_system_description_table(); locate_main_system_description_table();
initialize_main_system_description_table(); initialize_main_system_description_table();
init_fadt(); init_fadt();
init_facs(); init_facs();
} }
PhysicalAddress StaticParser::find_table(const char* sig) PhysicalAddress StaticParser::find_table(const char* sig)
{ {
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
dbg() << "ACPI: Calling Find Table method!"; dbg() << "ACPI: Calling Find Table method!";
#endif #endif
for (auto p_sdt : m_sdt_pointers) { for (auto p_sdt : m_sdt_pointers) {
auto region = MM.allocate_kernel_region(p_sdt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Tables Finding", Region::Access::Read); auto region = MM.allocate_kernel_region(p_sdt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Tables Finding", Region::Access::Read);
auto* sdt = (const Structures::SDTHeader*)region->vaddr().offset(p_sdt.offset_in_page()).as_ptr(); auto* sdt = (const Structures::SDTHeader*)region->vaddr().offset(p_sdt.offset_in_page()).as_ptr();
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
dbg() << "ACPI: Examining Table @ P " << physical_sdt_ptr; dbg() << "ACPI: Examining Table @ P " << physical_sdt_ptr;
#endif #endif
if (!strncmp(sdt->sig, sig, 4)) { if (!strncmp(sdt->sig, sig, 4)) {
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
dbg() << "ACPI: Found Table @ P " << physical_sdt_ptr; dbg() << "ACPI: Found Table @ P " << physical_sdt_ptr;
#endif #endif
return p_sdt; return p_sdt;
}
} }
return {};
} }
return {};
}
void StaticParser::init_facs() void StaticParser::init_facs()
{ {
m_facs = find_table("FACS"); m_facs = find_table("FACS");
} }
const FADTFlags::HardwareFeatures& StaticParser::hardware_features() const const FADTFlags::HardwareFeatures& StaticParser::hardware_features() const
{ {
return m_hardware_flags; return m_hardware_flags;
} }
const FADTFlags::x86_Specific_Flags& StaticParser::x86_specific_flags() const const FADTFlags::x86_Specific_Flags& StaticParser::x86_specific_flags() const
{ {
return m_x86_specific_flags; return m_x86_specific_flags;
} }
void StaticParser::init_fadt() void StaticParser::init_fadt()
{ {
klog() << "ACPI: Initializing Fixed ACPI data"; klog() << "ACPI: Initializing Fixed ACPI data";
klog() << "ACPI: Searching for the Fixed ACPI Data Table"; klog() << "ACPI: Searching for the Fixed ACPI Data Table";
m_fadt = find_table("FACP"); m_fadt = find_table("FACP");
ASSERT(!m_fadt.is_null()); ASSERT(!m_fadt.is_null());
auto checkup_region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); auto checkup_region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
auto* sdt = (const Structures::FADT*)checkup_region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); auto* sdt = (const Structures::FADT*)checkup_region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
dbg() << "ACPI: FADT @ V " << sdt << ", P " << (void*)fadt.as_ptr(); dbg() << "ACPI: FADT @ V " << sdt << ", P " << (void*)fadt.as_ptr();
#endif #endif
klog() << "ACPI: Fixed ACPI data, Revision " << sdt->h.revision << ", Length " << sdt->h.length << " bytes"; klog() << "ACPI: Fixed ACPI data, Revision " << sdt->h.revision << ", Length " << sdt->h.length << " bytes";
klog() << "ACPI: DSDT " << PhysicalAddress(sdt->dsdt_ptr); klog() << "ACPI: DSDT " << PhysicalAddress(sdt->dsdt_ptr);
m_x86_specific_flags.cmos_rtc_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::CMOS_RTC_Not_Present); m_x86_specific_flags.cmos_rtc_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::CMOS_RTC_Not_Present);
m_x86_specific_flags.keyboard_8042 = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::PS2_8042); m_x86_specific_flags.keyboard_8042 = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::PS2_8042);
m_x86_specific_flags.legacy_devices = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::Legacy_Devices); m_x86_specific_flags.legacy_devices = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::Legacy_Devices);
m_x86_specific_flags.msi_not_supported = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::MSI_Not_Supported); m_x86_specific_flags.msi_not_supported = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::MSI_Not_Supported);
m_x86_specific_flags.vga_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::VGA_Not_Present); m_x86_specific_flags.vga_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::VGA_Not_Present);
m_hardware_flags.cpu_software_sleep = (sdt->flags & (u32)FADTFlags::FeatureFlags::CPU_SW_SLP); m_hardware_flags.cpu_software_sleep = (sdt->flags & (u32)FADTFlags::FeatureFlags::CPU_SW_SLP);
m_hardware_flags.docking_capability = (sdt->flags & (u32)FADTFlags::FeatureFlags::DCK_CAP); m_hardware_flags.docking_capability = (sdt->flags & (u32)FADTFlags::FeatureFlags::DCK_CAP);
m_hardware_flags.fix_rtc = (sdt->flags & (u32)FADTFlags::FeatureFlags::FIX_RTC); m_hardware_flags.fix_rtc = (sdt->flags & (u32)FADTFlags::FeatureFlags::FIX_RTC);
m_hardware_flags.force_apic_cluster_model = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_CLUSTER_MODEL); m_hardware_flags.force_apic_cluster_model = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_CLUSTER_MODEL);
m_hardware_flags.force_apic_physical_destination_mode = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_PHYSICAL_DESTINATION_MODE); m_hardware_flags.force_apic_physical_destination_mode = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_PHYSICAL_DESTINATION_MODE);
m_hardware_flags.hardware_reduced_acpi = (sdt->flags & (u32)FADTFlags::FeatureFlags::HW_REDUCED_ACPI); m_hardware_flags.hardware_reduced_acpi = (sdt->flags & (u32)FADTFlags::FeatureFlags::HW_REDUCED_ACPI);
m_hardware_flags.headless = (sdt->flags & (u32)FADTFlags::FeatureFlags::HEADLESS); m_hardware_flags.headless = (sdt->flags & (u32)FADTFlags::FeatureFlags::HEADLESS);
m_hardware_flags.low_power_s0_idle_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::LOW_POWER_S0_IDLE_CAPABLE); m_hardware_flags.low_power_s0_idle_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::LOW_POWER_S0_IDLE_CAPABLE);
m_hardware_flags.multiprocessor_c2 = (sdt->flags & (u32)FADTFlags::FeatureFlags::P_LVL2_UP); m_hardware_flags.multiprocessor_c2 = (sdt->flags & (u32)FADTFlags::FeatureFlags::P_LVL2_UP);
m_hardware_flags.pci_express_wake = (sdt->flags & (u32)FADTFlags::FeatureFlags::PCI_EXP_WAK); m_hardware_flags.pci_express_wake = (sdt->flags & (u32)FADTFlags::FeatureFlags::PCI_EXP_WAK);
m_hardware_flags.power_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::PWR_BUTTON); m_hardware_flags.power_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::PWR_BUTTON);
m_hardware_flags.processor_c1 = (sdt->flags & (u32)FADTFlags::FeatureFlags::PROC_C1); m_hardware_flags.processor_c1 = (sdt->flags & (u32)FADTFlags::FeatureFlags::PROC_C1);
m_hardware_flags.remote_power_on_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::REMOTE_POWER_ON_CAPABLE); m_hardware_flags.remote_power_on_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::REMOTE_POWER_ON_CAPABLE);
m_hardware_flags.reset_register_supported = (sdt->flags & (u32)FADTFlags::FeatureFlags::RESET_REG_SUPPORTED); m_hardware_flags.reset_register_supported = (sdt->flags & (u32)FADTFlags::FeatureFlags::RESET_REG_SUPPORTED);
m_hardware_flags.rtc_s4 = (sdt->flags & (u32)FADTFlags::FeatureFlags::RTC_s4); m_hardware_flags.rtc_s4 = (sdt->flags & (u32)FADTFlags::FeatureFlags::RTC_s4);
m_hardware_flags.s4_rtc_status_valid = (sdt->flags & (u32)FADTFlags::FeatureFlags::S4_RTC_STS_VALID); m_hardware_flags.s4_rtc_status_valid = (sdt->flags & (u32)FADTFlags::FeatureFlags::S4_RTC_STS_VALID);
m_hardware_flags.sealed_case = (sdt->flags & (u32)FADTFlags::FeatureFlags::SEALED_CASE); m_hardware_flags.sealed_case = (sdt->flags & (u32)FADTFlags::FeatureFlags::SEALED_CASE);
m_hardware_flags.sleep_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::SLP_BUTTON); m_hardware_flags.sleep_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::SLP_BUTTON);
m_hardware_flags.timer_value_extension = (sdt->flags & (u32)FADTFlags::FeatureFlags::TMR_VAL_EXT); m_hardware_flags.timer_value_extension = (sdt->flags & (u32)FADTFlags::FeatureFlags::TMR_VAL_EXT);
m_hardware_flags.use_platform_clock = (sdt->flags & (u32)FADTFlags::FeatureFlags::USE_PLATFORM_CLOCK); m_hardware_flags.use_platform_clock = (sdt->flags & (u32)FADTFlags::FeatureFlags::USE_PLATFORM_CLOCK);
m_hardware_flags.wbinvd = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD); m_hardware_flags.wbinvd = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD);
m_hardware_flags.wbinvd_flush = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD_FLUSH); m_hardware_flags.wbinvd_flush = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD_FLUSH);
} }
bool StaticParser::can_reboot() bool StaticParser::can_reboot()
{ {
auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
if (fadt->h.revision < 2) if (fadt->h.revision < 2)
return false; return false;
return m_hardware_flags.reset_register_supported; return m_hardware_flags.reset_register_supported;
} }
void StaticParser::access_generic_address(const Structures::GenericAddressStructure& structure, u32 value) void StaticParser::access_generic_address(const Structures::GenericAddressStructure& structure, u32 value)
{ {
switch (structure.address_space) { switch (structure.address_space) {
case (u8)GenericAddressStructure::AddressSpace::SystemIO: { case (u8)GenericAddressStructure::AddressSpace::SystemIO: {
IOAddress address(structure.address); IOAddress address(structure.address);
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << address; dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << address;
switch (structure.access_size) { switch (structure.access_size) {
case (u8)GenericAddressStructure::AccessSize::QWord: { case (u8)GenericAddressStructure::AccessSize::QWord: {
dbg() << "Trying to send QWord to IO port"; dbg() << "Trying to send QWord to IO port";
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
break; break;
}
case (u8)GenericAddressStructure::AccessSize::Undefined: {
dbg() << "ACPI Warning: Unknown access size " << structure.access_size;
ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::QWord);
ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::Undefined);
dbg() << "ACPI: Bit Width - " << structure.bit_width << " bits";
address.out(value, structure.bit_width);
break;
}
default:
address.out(value, (8 << (structure.access_size - 1)));
break;
}
return;
} }
case (u8)GenericAddressStructure::AddressSpace::SystemMemory: { case (u8)GenericAddressStructure::AccessSize::Undefined: {
auto p_reg = PhysicalAddress(structure.address); dbg() << "ACPI Warning: Unknown access size " << structure.access_size;
auto p_region = MM.allocate_kernel_region(p_reg.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::QWord);
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << p_reg; ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::Undefined);
switch (structure.access_size) { dbg() << "ACPI: Bit Width - " << structure.bit_width << " bits";
case (u8)GenericAddressStructure::AccessSize::Byte: { address.out(value, structure.bit_width);
auto* reg = (volatile u8*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr(); break;
(*reg) = value;
break;
}
case (u8)GenericAddressStructure::AccessSize::Word: {
auto* reg = (volatile u16*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
}
case (u8)GenericAddressStructure::AccessSize::DWord: {
auto* reg = (volatile u32*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
}
case (u8)GenericAddressStructure::AccessSize::QWord: {
auto* reg = (volatile u64*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
}
default:
ASSERT_NOT_REACHED();
}
return;
} }
case (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace: { default:
// According to the ACPI specification 6.2, page 168, PCI addresses must be confined to devices on Segment group 0, bus 0. address.out(value, (8 << (structure.access_size - 1)));
auto pci_address = PCI::Address(0, 0, ((structure.address >> 24) & 0xFF), ((structure.address >> 16) & 0xFF)); break;
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << pci_address; }
u32 offset_in_pci_address = structure.address & 0xFFFF; return;
if (structure.access_size == (u8)GenericAddressStructure::AccessSize::QWord) { }
dbg() << "Trying to send QWord to PCI configuration space"; case (u8)GenericAddressStructure::AddressSpace::SystemMemory: {
ASSERT_NOT_REACHED(); auto p_reg = PhysicalAddress(structure.address);
} auto p_region = MM.allocate_kernel_region(p_reg.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
ASSERT(structure.access_size != (u8)GenericAddressStructure::AccessSize::Undefined); dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << p_reg;
PCI::raw_access(pci_address, offset_in_pci_address, (1 << (structure.access_size - 1)), value); switch (structure.access_size) {
return; case (u8)GenericAddressStructure::AccessSize::Byte: {
auto* reg = (volatile u8*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
}
case (u8)GenericAddressStructure::AccessSize::Word: {
auto* reg = (volatile u16*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
}
case (u8)GenericAddressStructure::AccessSize::DWord: {
auto* reg = (volatile u32*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
}
case (u8)GenericAddressStructure::AccessSize::QWord: {
auto* reg = (volatile u64*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
(*reg) = value;
break;
} }
default: default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
return;
}
case (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace: {
// According to the ACPI specification 6.2, page 168, PCI addresses must be confined to devices on Segment group 0, bus 0.
auto pci_address = PCI::Address(0, 0, ((structure.address >> 24) & 0xFF), ((structure.address >> 16) & 0xFF));
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << pci_address;
u32 offset_in_pci_address = structure.address & 0xFFFF;
if (structure.access_size == (u8)GenericAddressStructure::AccessSize::QWord) {
dbg() << "Trying to send QWord to PCI configuration space";
ASSERT_NOT_REACHED();
}
ASSERT(structure.access_size != (u8)GenericAddressStructure::AccessSize::Undefined);
PCI::raw_access(pci_address, offset_in_pci_address, (1 << (structure.access_size - 1)), value);
return;
}
default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
ASSERT_NOT_REACHED();
}
bool StaticParser::validate_reset_register() bool StaticParser::validate_reset_register()
{ {
// According to the ACPI spec 6.2, page 152, The reset register can only be located in I/O bus, PCI bus or memory-mapped. // According to the ACPI spec 6.2, page 152, The reset register can only be located in I/O bus, PCI bus or memory-mapped.
auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
return (fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemMemory || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemIO); return (fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemMemory || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemIO);
}
void StaticParser::try_acpi_reboot()
{
InterruptDisabler disabler;
if (!can_reboot()) {
klog() << "ACPI: Reboot, Not supported!";
return;
} }
#ifdef ACPI_DEBUG
dbg() << "ACPI: Rebooting, Probing FADT (" << m_fadt << ")";
#endif
void StaticParser::try_acpi_reboot() auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
{ auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
InterruptDisabler disabler; ASSERT(validate_reset_register());
if (!can_reboot()) { access_generic_address(fadt->reset_reg, fadt->reset_value);
klog() << "ACPI: Reboot, Not supported!"; for (;;)
return; ;
}
void StaticParser::try_acpi_shutdown()
{
klog() << "ACPI: Shutdown is not supported with the current configuration, Abort!";
}
size_t StaticParser::get_table_size(PhysicalAddress table_header)
{
InterruptDisabler disabler;
#ifdef ACPI_DEBUG
dbg() << "ACPI: Checking SDT Length";
#endif
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_size()", Region::Access::Read);
auto* sdt = (volatile Structures::SDTHeader*)region->vaddr().offset(table_header.offset_in_page()).as_ptr();
return sdt->length;
}
u8 StaticParser::get_table_revision(PhysicalAddress table_header)
{
InterruptDisabler disabler;
#ifdef ACPI_DEBUG
dbg() << "ACPI: Checking SDT Revision";
#endif
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_revision()", Region::Access::Read);
auto* sdt = (volatile Structures::SDTHeader*)region->vaddr().offset(table_header.offset_in_page()).as_ptr();
return sdt->revision;
}
void StaticParser::initialize_main_system_description_table()
{
#ifdef ACPI_DEBUG
dbg() << "ACPI: Checking Main SDT Length to choose the correct mapping size";
#endif
ASSERT(!m_main_system_description_table.is_null());
auto length = get_table_size(m_main_system_description_table);
auto revision = get_table_revision(m_main_system_description_table);
auto main_sdt_region = MM.allocate_kernel_region(m_main_system_description_table.page_base(), PAGE_ROUND_UP(length) + PAGE_SIZE, "ACPI Static Parser Initialization", Region::Access::Read, false, true);
auto* sdt = (volatile Structures::SDTHeader*)main_sdt_region->vaddr().offset(m_main_system_description_table.offset_in_page()).as_ptr();
klog() << "ACPI: Main Description Table valid? " << StaticParsing::validate_table(const_cast<Structures::SDTHeader&>(*sdt), length);
if (m_xsdt_supported) {
volatile auto* xsdt = (volatile Structures::XSDT*)sdt;
klog() << "ACPI: Using XSDT, Enumerating tables @ " << m_main_system_description_table;
klog() << "ACPI: XSDT Revision " << revision << ", Total length - " << length;
#ifdef ACPI_DEBUG
dbg() << "ACPI: XSDT pointer @ V " << xsdt;
#endif
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &xsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", xsdt->table_ptrs[i]);
#endif
m_sdt_pointers.append(PhysicalAddress(xsdt->table_ptrs[i]));
} }
} else {
volatile auto* rsdt = (volatile Structures::RSDT*)sdt;
klog() << "ACPI: Using RSDT, Enumerating tables @ " << m_main_system_description_table;
klog() << "ACPI: RSDT Revision " << revision << ", Total length - " << length;
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
dbg() << "ACPI: Rebooting, Probing FADT (" << m_fadt << ")"; dbg() << "ACPI: RSDT pointer @ V " << rsdt;
#endif #endif
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); #ifdef ACPI_DEBUG
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &rsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", rsdt->table_ptrs[i]);
ASSERT(validate_reset_register()); #endif
access_generic_address(fadt->reset_reg, fadt->reset_value); m_sdt_pointers.append(PhysicalAddress(rsdt->table_ptrs[i]));
for (;;) }
;
} }
}
void StaticParser::try_acpi_shutdown() void StaticParser::locate_main_system_description_table()
{ {
klog() << "ACPI: Shutdown is not supported with the current configuration, Abort!"; auto rsdp_region = MM.allocate_kernel_region(m_rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Initialization", Region::Access::Read, false, true);
} volatile auto* rsdp = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(m_rsdp.offset_in_page()).as_ptr();
if (rsdp->base.revision == 0) {
size_t StaticParser::get_table_size(PhysicalAddress table_header) m_xsdt_supported = false;
{ } else if (rsdp->base.revision >= 2) {
InterruptDisabler disabler; if (rsdp->xsdt_ptr != (u64) nullptr) {
#ifdef ACPI_DEBUG m_xsdt_supported = true;
dbg() << "ACPI: Checking SDT Length";
#endif
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_size()", Region::Access::Read);
auto* sdt = (volatile Structures::SDTHeader*)region->vaddr().offset(table_header.offset_in_page()).as_ptr();
return sdt->length;
}
u8 StaticParser::get_table_revision(PhysicalAddress table_header)
{
InterruptDisabler disabler;
#ifdef ACPI_DEBUG
dbg() << "ACPI: Checking SDT Revision";
#endif
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_revision()", Region::Access::Read);
auto* sdt = (volatile Structures::SDTHeader*)region->vaddr().offset(table_header.offset_in_page()).as_ptr();
return sdt->revision;
}
void StaticParser::initialize_main_system_description_table()
{
#ifdef ACPI_DEBUG
dbg() << "ACPI: Checking Main SDT Length to choose the correct mapping size";
#endif
ASSERT(!m_main_system_description_table.is_null());
auto length = get_table_size(m_main_system_description_table);
auto revision = get_table_revision(m_main_system_description_table);
auto main_sdt_region = MM.allocate_kernel_region(m_main_system_description_table.page_base(), PAGE_ROUND_UP(length) + PAGE_SIZE, "ACPI Static Parser Initialization", Region::Access::Read, false, true);
auto* sdt = (volatile Structures::SDTHeader*)main_sdt_region->vaddr().offset(m_main_system_description_table.offset_in_page()).as_ptr();
klog() << "ACPI: Main Description Table valid? " << StaticParsing::validate_table(const_cast<Structures::SDTHeader&>(*sdt), length);
if (m_xsdt_supported) {
volatile auto* xsdt = (volatile Structures::XSDT*)sdt;
klog() << "ACPI: Using XSDT, Enumerating tables @ " << m_main_system_description_table;
klog() << "ACPI: XSDT Revision " << revision << ", Total length - " << length;
#ifdef ACPI_DEBUG
dbg() << "ACPI: XSDT pointer @ V " << xsdt;
#endif
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &xsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", xsdt->table_ptrs[i]);
#endif
m_sdt_pointers.append(PhysicalAddress(xsdt->table_ptrs[i]));
}
} else { } else {
volatile auto* rsdt = (volatile Structures::RSDT*)sdt;
klog() << "ACPI: Using RSDT, Enumerating tables @ " << m_main_system_description_table;
klog() << "ACPI: RSDT Revision " << revision << ", Total length - " << length;
#ifdef ACPI_DEBUG
dbg() << "ACPI: RSDT pointer @ V " << rsdt;
#endif
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &rsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", rsdt->table_ptrs[i]);
#endif
m_sdt_pointers.append(PhysicalAddress(rsdt->table_ptrs[i]));
}
}
}
void StaticParser::locate_main_system_description_table()
{
auto rsdp_region = MM.allocate_kernel_region(m_rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Initialization", Region::Access::Read, false, true);
volatile auto* rsdp = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(m_rsdp.offset_in_page()).as_ptr();
if (rsdp->base.revision == 0) {
m_xsdt_supported = false; m_xsdt_supported = false;
} else if (rsdp->base.revision >= 2) {
if (rsdp->xsdt_ptr != (u64) nullptr) {
m_xsdt_supported = true;
} else {
m_xsdt_supported = false;
}
}
if (!m_xsdt_supported) {
m_main_system_description_table = PhysicalAddress(rsdp->base.rsdt_ptr);
} else {
m_main_system_description_table = PhysicalAddress(rsdp->xsdt_ptr);
} }
} }
if (!m_xsdt_supported) {
StaticParser::StaticParser() m_main_system_description_table = PhysicalAddress(rsdp->base.rsdt_ptr);
: Parser(true) } else {
, m_rsdp(StaticParsing::search_rsdp()) m_main_system_description_table = PhysicalAddress(rsdp->xsdt_ptr);
{
if (!m_rsdp.is_null()) {
klog() << "ACPI: Using RSDP @ " << m_rsdp;
m_operable = true;
locate_static_data();
} else {
m_operable = false;
klog() << "ACPI: Disabled, due to RSDP being absent";
}
} }
}
StaticParser::StaticParser(PhysicalAddress rsdp) StaticParser::StaticParser()
: Parser(true) : Parser(true)
, m_rsdp(rsdp) , m_rsdp(StaticParsing::search_rsdp())
{ {
klog() << "ACPI: Using RSDP @ " << rsdp; if (!m_rsdp.is_null()) {
klog() << "ACPI: Using RSDP @ " << m_rsdp;
m_operable = true; m_operable = true;
locate_static_data(); locate_static_data();
} } else {
m_operable = false;
PhysicalAddress StaticParsing::search_rsdp_in_ebda(u16 ebda_segment) klog() << "ACPI: Disabled, due to RSDP being absent";
{
auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)(ebda_segment << 4))), PAGE_ROUND_UP(1024), "ACPI Static Parser RSDP Finding #1", Region::Access::Read, false, true);
char* p_rsdp_str = (char*)(PhysicalAddress(ebda_segment << 4).as_ptr());
for (char* rsdp_str = (char*)rsdp_region->vaddr().offset(offset_in_page((u32)(ebda_segment << 4))).as_ptr(); rsdp_str < (char*)(rsdp_region->vaddr().offset(offset_in_page((u32)(ebda_segment << 4))).get() + 1024); rsdp_str += 16) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Looking for RSDP in EBDA @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
#endif
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
return PhysicalAddress((FlatPtr)p_rsdp_str);
p_rsdp_str += 16;
}
return {};
}
PhysicalAddress StaticParsing::search_rsdp_in_bios_area()
{
auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(0xE0000), PAGE_ROUND_UP(0xFFFFF - 0xE0000), "ACPI Static Parser RSDP Finding #2", Region::Access::Read, false, true);
char* p_rsdp_str = (char*)(PhysicalAddress(0xE0000).as_ptr());
for (char* rsdp_str = (char*)rsdp_region->vaddr().offset(offset_in_page((u32)(0xE0000))).as_ptr(); rsdp_str < (char*)(rsdp_region->vaddr().offset(offset_in_page((u32)(0xE0000))).get() + (0xFFFFF - 0xE0000)); rsdp_str += 16) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Looking for RSDP in BIOS ROM area @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
#endif
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
return PhysicalAddress((FlatPtr)p_rsdp_str);
p_rsdp_str += 16;
}
return {};
}
inline bool StaticParsing::validate_table(Structures::SDTHeader& v_header, size_t length)
{
u8 checksum = 0;
auto* sdt = (u8*)&v_header;
for (size_t i = 0; i < length; i++)
checksum += sdt[i];
if (checksum == 0)
return true;
return false;
}
PhysicalAddress StaticParsing::search_rsdp()
{
PhysicalAddress rsdp;
auto region = MM.allocate_kernel_region(PhysicalAddress(0), PAGE_SIZE, "ACPI RSDP Searching", Region::Access::Read);
u16 ebda_seg = (u16) * ((uint16_t*)((region->vaddr().get() & PAGE_MASK) + 0x40e));
klog() << "ACPI: Probing EBDA, Segment 0x" << String::format("%x", ebda_seg);
rsdp = search_rsdp_in_ebda(ebda_seg);
if (!rsdp.is_null())
return rsdp;
return search_rsdp_in_bios_area();
}
PhysicalAddress StaticParsing::search_table(PhysicalAddress rsdp, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto rsdp_region = MM.allocate_kernel_region(rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parsing search_table()", Region::Access::Read, false, true);
volatile auto* rsdp_ptr = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(rsdp.offset_in_page()).as_ptr();
if (rsdp_ptr->base.revision == 0) {
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
}
if (rsdp_ptr->base.revision >= 2) {
if (rsdp_ptr->xsdt_ptr != (u64) nullptr)
return search_table_in_xsdt(PhysicalAddress(rsdp_ptr->xsdt_ptr), signature);
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
}
ASSERT_NOT_REACHED();
}
PhysicalAddress StaticParsing::search_table_in_xsdt(PhysicalAddress xsdt, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto main_sdt_region = MM.allocate_kernel_region(xsdt.page_base(), PAGE_SIZE, "ACPI Static Parsing search_table_in_xsdt()", Region::Access::Read, false, true);
auto* xsdt_ptr = (volatile Structures::XSDT*)main_sdt_region->vaddr().offset(xsdt.offset_in_page()).as_ptr();
for (u32 i = 0; i < ((xsdt_ptr->h.length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) {
if (match_table_signature(PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]), signature))
return PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]);
}
return {};
}
bool StaticParsing::match_table_signature(PhysicalAddress table_header, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto main_sdt_region = MM.allocate_kernel_region(table_header.page_base(), PAGE_SIZE, "ACPI Static Parsing match_table_signature()", Region::Access::Read, false, true);
auto* table_ptr = (volatile Structures::RSDT*)main_sdt_region->vaddr().offset(table_header.offset_in_page()).as_ptr();
return !strncmp(const_cast<const char*>(table_ptr->h.sig), signature, 4);
}
PhysicalAddress StaticParsing::search_table_in_rsdt(PhysicalAddress rsdt, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto main_sdt_region = MM.allocate_kernel_region(rsdt.page_base(), PAGE_SIZE, "ACPI Static Parsing search_table_in_rsdt()", Region::Access::Read, false, true);
auto* rsdt_ptr = (volatile Structures::RSDT*)main_sdt_region->vaddr().offset(rsdt.offset_in_page()).as_ptr();
for (u32 i = 0; i < ((rsdt_ptr->h.length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
if (match_table_signature(PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]), signature))
return PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]);
}
return {};
} }
} }
StaticParser::StaticParser(PhysicalAddress rsdp)
: Parser(true)
, m_rsdp(rsdp)
{
klog() << "ACPI: Using RSDP @ " << rsdp;
m_operable = true;
locate_static_data();
}
PhysicalAddress StaticParsing::search_rsdp_in_ebda(u16 ebda_segment)
{
auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)(ebda_segment << 4))), PAGE_ROUND_UP(1024), "ACPI Static Parser RSDP Finding #1", Region::Access::Read, false, true);
char* p_rsdp_str = (char*)(PhysicalAddress(ebda_segment << 4).as_ptr());
for (char* rsdp_str = (char*)rsdp_region->vaddr().offset(offset_in_page((u32)(ebda_segment << 4))).as_ptr(); rsdp_str < (char*)(rsdp_region->vaddr().offset(offset_in_page((u32)(ebda_segment << 4))).get() + 1024); rsdp_str += 16) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Looking for RSDP in EBDA @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
#endif
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
return PhysicalAddress((FlatPtr)p_rsdp_str);
p_rsdp_str += 16;
}
return {};
}
PhysicalAddress StaticParsing::search_rsdp_in_bios_area()
{
auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(0xE0000), PAGE_ROUND_UP(0xFFFFF - 0xE0000), "ACPI Static Parser RSDP Finding #2", Region::Access::Read, false, true);
char* p_rsdp_str = (char*)(PhysicalAddress(0xE0000).as_ptr());
for (char* rsdp_str = (char*)rsdp_region->vaddr().offset(offset_in_page((u32)(0xE0000))).as_ptr(); rsdp_str < (char*)(rsdp_region->vaddr().offset(offset_in_page((u32)(0xE0000))).get() + (0xFFFFF - 0xE0000)); rsdp_str += 16) {
#ifdef ACPI_DEBUG
dbg() << "ACPI: Looking for RSDP in BIOS ROM area @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
#endif
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
return PhysicalAddress((FlatPtr)p_rsdp_str);
p_rsdp_str += 16;
}
return {};
}
inline bool StaticParsing::validate_table(Structures::SDTHeader& v_header, size_t length)
{
u8 checksum = 0;
auto* sdt = (u8*)&v_header;
for (size_t i = 0; i < length; i++)
checksum += sdt[i];
if (checksum == 0)
return true;
return false;
}
PhysicalAddress StaticParsing::search_rsdp()
{
PhysicalAddress rsdp;
auto region = MM.allocate_kernel_region(PhysicalAddress(0), PAGE_SIZE, "ACPI RSDP Searching", Region::Access::Read);
u16 ebda_seg = (u16) * ((uint16_t*)((region->vaddr().get() & PAGE_MASK) + 0x40e));
klog() << "ACPI: Probing EBDA, Segment 0x" << String::format("%x", ebda_seg);
rsdp = search_rsdp_in_ebda(ebda_seg);
if (!rsdp.is_null())
return rsdp;
return search_rsdp_in_bios_area();
}
PhysicalAddress StaticParsing::search_table(PhysicalAddress rsdp, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto rsdp_region = MM.allocate_kernel_region(rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parsing search_table()", Region::Access::Read, false, true);
volatile auto* rsdp_ptr = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(rsdp.offset_in_page()).as_ptr();
if (rsdp_ptr->base.revision == 0) {
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
}
if (rsdp_ptr->base.revision >= 2) {
if (rsdp_ptr->xsdt_ptr != (u64) nullptr)
return search_table_in_xsdt(PhysicalAddress(rsdp_ptr->xsdt_ptr), signature);
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
}
ASSERT_NOT_REACHED();
}
PhysicalAddress StaticParsing::search_table_in_xsdt(PhysicalAddress xsdt, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto main_sdt_region = MM.allocate_kernel_region(xsdt.page_base(), PAGE_SIZE, "ACPI Static Parsing search_table_in_xsdt()", Region::Access::Read, false, true);
auto* xsdt_ptr = (volatile Structures::XSDT*)main_sdt_region->vaddr().offset(xsdt.offset_in_page()).as_ptr();
for (u32 i = 0; i < ((xsdt_ptr->h.length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) {
if (match_table_signature(PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]), signature))
return PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]);
}
return {};
}
bool StaticParsing::match_table_signature(PhysicalAddress table_header, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto main_sdt_region = MM.allocate_kernel_region(table_header.page_base(), PAGE_SIZE, "ACPI Static Parsing match_table_signature()", Region::Access::Read, false, true);
auto* table_ptr = (volatile Structures::RSDT*)main_sdt_region->vaddr().offset(table_header.offset_in_page()).as_ptr();
return !strncmp(const_cast<const char*>(table_ptr->h.sig), signature, 4);
}
PhysicalAddress StaticParsing::search_table_in_rsdt(PhysicalAddress rsdt, const char* signature)
{
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
// FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
ASSERT(strlen(signature) == 4);
auto main_sdt_region = MM.allocate_kernel_region(rsdt.page_base(), PAGE_SIZE, "ACPI Static Parsing search_table_in_rsdt()", Region::Access::Read, false, true);
auto* rsdt_ptr = (volatile Structures::RSDT*)main_sdt_region->vaddr().offset(rsdt.offset_in_page()).as_ptr();
for (u32 i = 0; i < ((rsdt_ptr->h.length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
if (match_table_signature(PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]), signature))
return PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]);
}
return {};
}
}
} }

View file

@ -32,48 +32,48 @@
namespace Kernel { namespace Kernel {
namespace ACPI { namespace ACPI {
class StaticParser : Parser { class StaticParser : Parser {
public: public:
static void initialize(PhysicalAddress rsdp); static void initialize(PhysicalAddress rsdp);
static void initialize_without_rsdp(); static void initialize_without_rsdp();
static bool is_initialized(); static bool is_initialized();
virtual PhysicalAddress find_table(const char* sig) override; virtual PhysicalAddress find_table(const char* sig) override;
virtual void try_acpi_reboot() override; virtual void try_acpi_reboot() override;
virtual bool can_reboot() override; virtual bool can_reboot() override;
virtual bool can_shutdown() override { return false; } virtual bool can_shutdown() override { return false; }
virtual void try_acpi_shutdown() override; virtual void try_acpi_shutdown() override;
virtual bool is_operable() override { return m_operable; } virtual bool is_operable() override { return m_operable; }
virtual const FADTFlags::HardwareFeatures& hardware_features() const override; virtual const FADTFlags::HardwareFeatures& hardware_features() const override;
virtual const FADTFlags::x86_Specific_Flags& x86_specific_flags() const override; virtual const FADTFlags::x86_Specific_Flags& x86_specific_flags() const override;
protected: protected:
StaticParser(); StaticParser();
explicit StaticParser(PhysicalAddress); explicit StaticParser(PhysicalAddress);
private: private:
void locate_static_data(); void locate_static_data();
void locate_main_system_description_table(); void locate_main_system_description_table();
void initialize_main_system_description_table(); void initialize_main_system_description_table();
size_t get_table_size(PhysicalAddress); size_t get_table_size(PhysicalAddress);
u8 get_table_revision(PhysicalAddress); u8 get_table_revision(PhysicalAddress);
void init_fadt(); void init_fadt();
void init_facs(); void init_facs();
bool validate_reset_register(); bool validate_reset_register();
void access_generic_address(const Structures::GenericAddressStructure&, u32 value); void access_generic_address(const Structures::GenericAddressStructure&, u32 value);
PhysicalAddress m_rsdp; PhysicalAddress m_rsdp;
PhysicalAddress m_main_system_description_table; PhysicalAddress m_main_system_description_table;
Vector<PhysicalAddress> m_sdt_pointers; Vector<PhysicalAddress> m_sdt_pointers;
PhysicalAddress m_fadt; PhysicalAddress m_fadt;
PhysicalAddress m_facs; PhysicalAddress m_facs;
bool m_xsdt_supported; bool m_xsdt_supported;
FADTFlags::HardwareFeatures m_hardware_flags; FADTFlags::HardwareFeatures m_hardware_flags;
FADTFlags::x86_Specific_Flags m_x86_specific_flags; FADTFlags::x86_Specific_Flags m_x86_specific_flags;
}; };
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -35,315 +35,315 @@ namespace Kernel {
namespace ACPI { namespace ACPI {
namespace FADTFlags { namespace FADTFlags {
enum class FeatureFlags : u32 { enum class FeatureFlags : u32 {
WBINVD = 1 << 0, WBINVD = 1 << 0,
WBINVD_FLUSH = 1 << 1, WBINVD_FLUSH = 1 << 1,
PROC_C1 = 1 << 2, PROC_C1 = 1 << 2,
P_LVL2_UP = 1 << 3, P_LVL2_UP = 1 << 3,
PWR_BUTTON = 1 << 4, PWR_BUTTON = 1 << 4,
SLP_BUTTON = 1 << 5, SLP_BUTTON = 1 << 5,
FIX_RTC = 1 << 6, FIX_RTC = 1 << 6,
RTC_s4 = 1 << 7, RTC_s4 = 1 << 7,
TMR_VAL_EXT = 1 << 8, TMR_VAL_EXT = 1 << 8,
DCK_CAP = 1 << 9, DCK_CAP = 1 << 9,
RESET_REG_SUPPORTED = 1 << 10, RESET_REG_SUPPORTED = 1 << 10,
SEALED_CASE = 1 << 11, SEALED_CASE = 1 << 11,
HEADLESS = 1 << 12, HEADLESS = 1 << 12,
CPU_SW_SLP = 1 << 13, CPU_SW_SLP = 1 << 13,
PCI_EXP_WAK = 1 << 14, PCI_EXP_WAK = 1 << 14,
USE_PLATFORM_CLOCK = 1 << 15, USE_PLATFORM_CLOCK = 1 << 15,
S4_RTC_STS_VALID = 1 << 16, S4_RTC_STS_VALID = 1 << 16,
REMOTE_POWER_ON_CAPABLE = 1 << 17, REMOTE_POWER_ON_CAPABLE = 1 << 17,
FORCE_APIC_CLUSTER_MODEL = 1 << 18, FORCE_APIC_CLUSTER_MODEL = 1 << 18,
FORCE_APIC_PHYSICAL_DESTINATION_MODE = 1 << 19, FORCE_APIC_PHYSICAL_DESTINATION_MODE = 1 << 19,
HW_REDUCED_ACPI = 1 << 20, HW_REDUCED_ACPI = 1 << 20,
LOW_POWER_S0_IDLE_CAPABLE = 1 << 21 LOW_POWER_S0_IDLE_CAPABLE = 1 << 21
}; };
enum class IA_PC_Flags : u8 { enum class IA_PC_Flags : u8 {
Legacy_Devices = 1 << 0, Legacy_Devices = 1 << 0,
PS2_8042 = 1 << 1, PS2_8042 = 1 << 1,
VGA_Not_Present = 1 << 2, VGA_Not_Present = 1 << 2,
MSI_Not_Supported = 1 << 3, MSI_Not_Supported = 1 << 3,
PCIe_ASPM_Controls = 1 << 4, PCIe_ASPM_Controls = 1 << 4,
CMOS_RTC_Not_Present = 1 << 5 CMOS_RTC_Not_Present = 1 << 5
}; };
struct [[gnu::packed]] HardwareFeatures struct [[gnu::packed]] HardwareFeatures
{ {
bool wbinvd : 1; bool wbinvd : 1;
bool wbinvd_flush : 1; bool wbinvd_flush : 1;
bool processor_c1 : 1; bool processor_c1 : 1;
bool multiprocessor_c2 : 1; bool multiprocessor_c2 : 1;
bool power_button : 1; bool power_button : 1;
bool sleep_button : 1; bool sleep_button : 1;
bool fix_rtc : 1; bool fix_rtc : 1;
bool rtc_s4 : 1; bool rtc_s4 : 1;
bool timer_value_extension : 1; bool timer_value_extension : 1;
bool docking_capability : 1; bool docking_capability : 1;
bool reset_register_supported : 1; bool reset_register_supported : 1;
bool sealed_case : 1; bool sealed_case : 1;
bool headless : 1; bool headless : 1;
bool cpu_software_sleep : 1; bool cpu_software_sleep : 1;
bool pci_express_wake : 1; bool pci_express_wake : 1;
bool use_platform_clock : 1; bool use_platform_clock : 1;
bool s4_rtc_status_valid : 1; bool s4_rtc_status_valid : 1;
bool remote_power_on_capable : 1; bool remote_power_on_capable : 1;
bool force_apic_cluster_model : 1; bool force_apic_cluster_model : 1;
bool force_apic_physical_destination_mode : 1; bool force_apic_physical_destination_mode : 1;
bool hardware_reduced_acpi : 1; bool hardware_reduced_acpi : 1;
bool low_power_s0_idle_capable : 1; bool low_power_s0_idle_capable : 1;
}; };
struct [[gnu::packed]] x86_Specific_Flags struct [[gnu::packed]] x86_Specific_Flags
{ {
bool legacy_devices : 1; bool legacy_devices : 1;
bool keyboard_8042 : 1; bool keyboard_8042 : 1;
bool vga_not_present : 1; bool vga_not_present : 1;
bool msi_not_supported : 1; bool msi_not_supported : 1;
bool cmos_rtc_not_present : 1; bool cmos_rtc_not_present : 1;
}; };
}; };
namespace GenericAddressStructure { namespace GenericAddressStructure {
enum class AddressSpace { enum class AddressSpace {
SystemMemory = 0, SystemMemory = 0,
SystemIO = 1, SystemIO = 1,
PCIConfigurationSpace = 2, PCIConfigurationSpace = 2,
EmbeddedController = 3, EmbeddedController = 3,
SMBus = 4, SMBus = 4,
PCC = 0xA, PCC = 0xA,
FunctionalFixedHardware = 0x7F FunctionalFixedHardware = 0x7F
}; };
enum class AccessSize { enum class AccessSize {
Undefined = 0, Undefined = 0,
Byte = 1, Byte = 1,
Word = 2, Word = 2,
DWord = 3, DWord = 3,
QWord = 4 QWord = 4
}; };
enum class BitWidth { enum class BitWidth {
Undefined = 0, Undefined = 0,
Byte = 8, Byte = 8,
Word = 16, Word = 16,
DWord = 32, DWord = 32,
QWord = 64 QWord = 64
}; };
} }
namespace Structures { namespace Structures {
struct [[gnu::packed]] RSDPDescriptor struct [[gnu::packed]] RSDPDescriptor
{ {
char sig[8]; char sig[8];
u8 checksum; u8 checksum;
char oem_id[6]; char oem_id[6];
u8 revision; u8 revision;
u32 rsdt_ptr; u32 rsdt_ptr;
}; };
struct [[gnu::packed]] RSDPDescriptor20 struct [[gnu::packed]] RSDPDescriptor20
{ {
RSDPDescriptor base; RSDPDescriptor base;
u32 length; u32 length;
u64 xsdt_ptr; u64 xsdt_ptr;
u8 ext_checksum; u8 ext_checksum;
u8 reserved[3]; u8 reserved[3];
}; };
struct [[gnu::packed]] SDTHeader struct [[gnu::packed]] SDTHeader
{ {
char sig[4]; char sig[4];
u32 length; u32 length;
u8 revision; u8 revision;
u8 checksum; u8 checksum;
char oem_id[6]; char oem_id[6];
char oem_table_id[8]; char oem_table_id[8];
u32 oem_revision; u32 oem_revision;
u32 creator_id; u32 creator_id;
u32 creator_revision; u32 creator_revision;
}; };
struct [[gnu::packed]] RSDT struct [[gnu::packed]] RSDT
{ {
SDTHeader h; SDTHeader h;
u32 table_ptrs[]; u32 table_ptrs[];
}; };
struct [[gnu::packed]] XSDT struct [[gnu::packed]] XSDT
{ {
SDTHeader h; SDTHeader h;
u64 table_ptrs[]; u64 table_ptrs[];
}; };
struct [[gnu::packed]] GenericAddressStructure struct [[gnu::packed]] GenericAddressStructure
{ {
u8 address_space; u8 address_space;
u8 bit_width; u8 bit_width;
u8 bit_offset; u8 bit_offset;
u8 access_size; u8 access_size;
u64 address; u64 address;
}; };
struct [[gnu::packed]] HPET struct [[gnu::packed]] HPET
{ {
SDTHeader h; SDTHeader h;
u8 hardware_revision_id; u8 hardware_revision_id;
u8 attributes; u8 attributes;
u16 pci_vendor_id; u16 pci_vendor_id;
GenericAddressStructure event_timer_block; GenericAddressStructure event_timer_block;
u8 hpet_number; u8 hpet_number;
u16 mininum_clock_tick; u16 mininum_clock_tick;
u8 page_protection; u8 page_protection;
}; };
struct [[gnu::packed]] FADT struct [[gnu::packed]] FADT
{ {
SDTHeader h; SDTHeader h;
u32 firmware_ctrl; u32 firmware_ctrl;
u32 dsdt_ptr; u32 dsdt_ptr;
u8 reserved; u8 reserved;
u8 preferred_pm_profile; u8 preferred_pm_profile;
u16 sci_int; u16 sci_int;
u32 smi_cmd; u32 smi_cmd;
u8 acpi_enable_value; u8 acpi_enable_value;
u8 acpi_disable_value; u8 acpi_disable_value;
u8 s4bios_req; u8 s4bios_req;
u8 pstate_cnt; u8 pstate_cnt;
u32 PM1a_EVT_BLK; u32 PM1a_EVT_BLK;
u32 PM1b_EVT_BLK; u32 PM1b_EVT_BLK;
u32 PM1a_CNT_BLK; u32 PM1a_CNT_BLK;
u32 PM1b_CNT_BLK; u32 PM1b_CNT_BLK;
u32 PM2_CNT_BLK; u32 PM2_CNT_BLK;
u32 PM_TMR_BLK; u32 PM_TMR_BLK;
u32 GPE0_BLK; u32 GPE0_BLK;
u32 GPE1_BLK; u32 GPE1_BLK;
u8 PM1_EVT_LEN; u8 PM1_EVT_LEN;
u8 PM1_CNT_LEN; u8 PM1_CNT_LEN;
u8 PM2_CNT_LEN; u8 PM2_CNT_LEN;
u8 PM_TMR_LEN; u8 PM_TMR_LEN;
u8 GPE0_BLK_LEN; u8 GPE0_BLK_LEN;
u8 GPE1_BLK_LEN; u8 GPE1_BLK_LEN;
u8 GPE1_BASE; u8 GPE1_BASE;
u8 cst_cnt; u8 cst_cnt;
u16 P_LVL2_LAT; u16 P_LVL2_LAT;
u16 P_LVL3_LAT; u16 P_LVL3_LAT;
u16 flush_size; u16 flush_size;
u16 flush_stride; u16 flush_stride;
u8 duty_offset; u8 duty_offset;
u8 duty_width; u8 duty_width;
u8 day_alrm; u8 day_alrm;
u8 mon_alrm; u8 mon_alrm;
u8 century; u8 century;
u16 ia_pc_boot_arch_flags; u16 ia_pc_boot_arch_flags;
u8 reserved2; u8 reserved2;
u32 flags; u32 flags;
GenericAddressStructure reset_reg; GenericAddressStructure reset_reg;
u8 reset_value; u8 reset_value;
u16 arm_boot_arch; u16 arm_boot_arch;
u8 fadt_minor_version; u8 fadt_minor_version;
u64 x_firmware_ctrl; u64 x_firmware_ctrl;
u64 x_dsdt; u64 x_dsdt;
GenericAddressStructure x_pm1a_evt_blk; GenericAddressStructure x_pm1a_evt_blk;
GenericAddressStructure x_pm1b_evt_blk; GenericAddressStructure x_pm1b_evt_blk;
GenericAddressStructure x_pm1a_cnt_blk; GenericAddressStructure x_pm1a_cnt_blk;
GenericAddressStructure x_pm1b_cnt_blk; GenericAddressStructure x_pm1b_cnt_blk;
GenericAddressStructure x_pm2_cnt_blk; GenericAddressStructure x_pm2_cnt_blk;
GenericAddressStructure x_pm_tmr_blk; GenericAddressStructure x_pm_tmr_blk;
GenericAddressStructure x_gpe0_blk; GenericAddressStructure x_gpe0_blk;
GenericAddressStructure x_gpe1_blk; GenericAddressStructure x_gpe1_blk;
GenericAddressStructure sleep_control; GenericAddressStructure sleep_control;
GenericAddressStructure sleep_status; GenericAddressStructure sleep_status;
u64 hypervisor_vendor_identity; u64 hypervisor_vendor_identity;
}; };
enum class MADTEntryType { enum class MADTEntryType {
LocalAPIC = 0x0, LocalAPIC = 0x0,
IOAPIC = 0x1, IOAPIC = 0x1,
InterruptSourceOverride = 0x2, InterruptSourceOverride = 0x2,
NMI_Source = 0x3, NMI_Source = 0x3,
LocalAPIC_NMI = 0x4, LocalAPIC_NMI = 0x4,
LocalAPIC_Address_Override = 0x5, LocalAPIC_Address_Override = 0x5,
IO_SAPIC = 0x6, IO_SAPIC = 0x6,
Local_SAPIC = 0x7, Local_SAPIC = 0x7,
Platform_interrupt_Sources = 0x8, Platform_interrupt_Sources = 0x8,
Local_x2APIC = 0x9, Local_x2APIC = 0x9,
Local_x2APIC_NMI = 0xA, Local_x2APIC_NMI = 0xA,
GIC_CPU = 0xB, GIC_CPU = 0xB,
GIC_Distributor = 0xC, GIC_Distributor = 0xC,
GIC_MSI = 0xD, GIC_MSI = 0xD,
GIC_Redistrbutor = 0xE, GIC_Redistrbutor = 0xE,
GIC_Interrupt_Translation = 0xF GIC_Interrupt_Translation = 0xF
}; };
struct [[gnu::packed]] MADTEntryHeader struct [[gnu::packed]] MADTEntryHeader
{ {
u8 type; u8 type;
u8 length; u8 length;
}; };
namespace MADTEntries { namespace MADTEntries {
struct [[gnu::packed]] IOAPIC struct [[gnu::packed]] IOAPIC
{ {
MADTEntryHeader h; MADTEntryHeader h;
u8 ioapic_id; u8 ioapic_id;
u8 reserved; u8 reserved;
u32 ioapic_address; u32 ioapic_address;
u32 gsi_base; u32 gsi_base;
}; };
struct [[gnu::packed]] InterruptSourceOverride struct [[gnu::packed]] InterruptSourceOverride
{ {
MADTEntryHeader h; MADTEntryHeader h;
u8 bus; u8 bus;
u8 source; u8 source;
u32 global_system_interrupt; u32 global_system_interrupt;
u16 flags; u16 flags;
}; };
} }
struct [[gnu::packed]] MADT struct [[gnu::packed]] MADT
{ {
SDTHeader h; SDTHeader h;
u32 lapic_address; u32 lapic_address;
u32 flags; u32 flags;
MADTEntryHeader entries[]; MADTEntryHeader entries[];
}; };
struct [[gnu::packed]] AMLTable struct [[gnu::packed]] AMLTable
{ {
SDTHeader h; SDTHeader h;
char aml_code[]; char aml_code[];
}; };
struct [[gnu::packed]] PCI_MMIO_Descriptor struct [[gnu::packed]] PCI_MMIO_Descriptor
{ {
u64 base_addr; u64 base_addr;
u16 seg_group_number; u16 seg_group_number;
u8 start_pci_bus; u8 start_pci_bus;
u8 end_pci_bus; u8 end_pci_bus;
u32 reserved; u32 reserved;
}; };
struct [[gnu::packed]] MCFG struct [[gnu::packed]] MCFG
{ {
SDTHeader header; SDTHeader header;
u64 reserved; u64 reserved;
PCI_MMIO_Descriptor descriptors[]; PCI_MMIO_Descriptor descriptors[];
}; };
} }
class StaticParser; class StaticParser;
class DynamicParser; class DynamicParser;
class Parser; class Parser;
namespace StaticParsing { namespace StaticParsing {
PhysicalAddress search_rsdp_in_ebda(u16 ebda_segment); PhysicalAddress search_rsdp_in_ebda(u16 ebda_segment);
PhysicalAddress search_rsdp_in_bios_area(); PhysicalAddress search_rsdp_in_bios_area();
PhysicalAddress search_rsdp(); PhysicalAddress search_rsdp();
bool match_table_signature(PhysicalAddress table_header, const char*); bool match_table_signature(PhysicalAddress table_header, const char*);
PhysicalAddress search_table(PhysicalAddress rsdp, const char*); PhysicalAddress search_table(PhysicalAddress rsdp, const char*);
PhysicalAddress search_table_in_xsdt(PhysicalAddress xsdt, const char*); PhysicalAddress search_table_in_xsdt(PhysicalAddress xsdt, const char*);
PhysicalAddress search_table_in_rsdt(PhysicalAddress rsdt, const char*); PhysicalAddress search_table_in_rsdt(PhysicalAddress rsdt, const char*);
inline bool validate_table(Structures::SDTHeader&, size_t length); inline bool validate_table(Structures::SDTHeader&, size_t length);
}; };
} }
} }

View file

@ -34,156 +34,156 @@
namespace Kernel { namespace Kernel {
namespace MultiProcessor { namespace MultiProcessor {
struct [[gnu::packed]] FloatingPointer struct [[gnu::packed]] FloatingPointer
{ {
char sig[4]; char sig[4];
u32 physical_address_ptr; u32 physical_address_ptr;
u8 length; u8 length;
u8 specification_revision; u8 specification_revision;
u8 checksum; u8 checksum;
u8 feature_info[5]; u8 feature_info[5];
}; };
struct [[gnu::packed]] EntryHeader struct [[gnu::packed]] EntryHeader
{ {
u8 entry_type; u8 entry_type;
}; };
struct [[gnu::packed]] ConfigurationTableHeader struct [[gnu::packed]] ConfigurationTableHeader
{ {
char sig[4]; char sig[4];
u16 length; u16 length;
u8 specification_revision; u8 specification_revision;
u8 checksum; u8 checksum;
char oem_id[8]; char oem_id[8];
char product_id[12]; char product_id[12];
u32 oem_table_ptr; u32 oem_table_ptr;
u16 oem_table_size; u16 oem_table_size;
u16 entry_count; u16 entry_count;
u32 local_apic_address; u32 local_apic_address;
u16 ext_table_length; u16 ext_table_length;
u8 ext_table_checksum; u8 ext_table_checksum;
u8 reserved; u8 reserved;
EntryHeader entries[]; EntryHeader entries[];
}; };
enum class ConfigurationTableEntryType { enum class ConfigurationTableEntryType {
Processor = 0, Processor = 0,
Bus = 1, Bus = 1,
IOAPIC = 2, IOAPIC = 2,
IO_Interrupt_Assignment = 3, IO_Interrupt_Assignment = 3,
Local_Interrupt_Assignment = 4, Local_Interrupt_Assignment = 4,
SystemAddressSpaceMapping = 128, SystemAddressSpaceMapping = 128,
BusHierarchyDescriptor = 129, BusHierarchyDescriptor = 129,
CompatibilityBusAddressSpaceModifier = 130 CompatibilityBusAddressSpaceModifier = 130
}; };
enum class ConfigurationTableEntryLength { enum class ConfigurationTableEntryLength {
Processor = 20, Processor = 20,
Bus = 8, Bus = 8,
IOAPIC = 8, IOAPIC = 8,
IO_Interrupt_Assignment = 8, IO_Interrupt_Assignment = 8,
Local_Interrupt_Assignment = 8, Local_Interrupt_Assignment = 8,
SystemAddressSpaceMapping = 20, SystemAddressSpaceMapping = 20,
BusHierarchyDescriptor = 8, BusHierarchyDescriptor = 8,
CompatibilityBusAddressSpaceModifier = 8 CompatibilityBusAddressSpaceModifier = 8
}; };
struct [[gnu::packed]] ExtEntryHeader struct [[gnu::packed]] ExtEntryHeader
{ {
u8 entry_type; u8 entry_type;
u8 entry_length; u8 entry_length;
}; };
struct [[gnu::packed]] ProcessorEntry struct [[gnu::packed]] ProcessorEntry
{ {
EntryHeader h; EntryHeader h;
u8 local_apic_id; u8 local_apic_id;
u8 local_apic_version; u8 local_apic_version;
u8 cpu_flags; u8 cpu_flags;
u32 cpu_signature; u32 cpu_signature;
u32 feature_flags; u32 feature_flags;
u8 reserved[8]; u8 reserved[8];
}; };
struct [[gnu::packed]] BusEntry struct [[gnu::packed]] BusEntry
{ {
EntryHeader h; EntryHeader h;
u8 bus_id; u8 bus_id;
char bus_type[6]; char bus_type[6];
}; };
struct [[gnu::packed]] IOAPICEntry struct [[gnu::packed]] IOAPICEntry
{ {
EntryHeader h; EntryHeader h;
u8 ioapic_id; u8 ioapic_id;
u8 ioapic_version; u8 ioapic_version;
u8 ioapic_flags; u8 ioapic_flags;
u32 ioapic_address; u32 ioapic_address;
}; };
enum class InterruptType { enum class InterruptType {
INT = 0, INT = 0,
NMI = 1, NMI = 1,
SMI = 2, SMI = 2,
ExtINT = 3, ExtINT = 3,
}; };
struct [[gnu::packed]] IOInterruptAssignmentEntry struct [[gnu::packed]] IOInterruptAssignmentEntry
{ {
EntryHeader h; EntryHeader h;
u8 interrupt_type; u8 interrupt_type;
u8 polarity; u8 polarity;
u8 trigger_mode; u8 trigger_mode;
u8 source_bus_id; u8 source_bus_id;
u8 source_bus_irq; u8 source_bus_irq;
u8 destination_ioapic_id; u8 destination_ioapic_id;
u8 destination_ioapic_intin_pin; u8 destination_ioapic_intin_pin;
}; };
struct [[gnu::packed]] LocalInterruptAssignmentEntry struct [[gnu::packed]] LocalInterruptAssignmentEntry
{ {
EntryHeader h; EntryHeader h;
u8 interrupt_type; u8 interrupt_type;
u8 polarity; u8 polarity;
u8 trigger_mode; u8 trigger_mode;
u8 source_bus_id; u8 source_bus_id;
u8 source_bus_irq; u8 source_bus_irq;
u8 destination_lapic_id; u8 destination_lapic_id;
u8 destination_lapic_lintin_pin; u8 destination_lapic_lintin_pin;
}; };
enum class SystemAddressType { enum class SystemAddressType {
IO = 0, IO = 0,
Memory = 1, Memory = 1,
Prefetch = 2, Prefetch = 2,
}; };
struct [[gnu::packed]] SystemAddressSpaceMappingEntry struct [[gnu::packed]] SystemAddressSpaceMappingEntry
{ {
ExtEntryHeader h; ExtEntryHeader h;
u8 bus_id; u8 bus_id;
u8 address_type; u8 address_type;
u64 address_base; u64 address_base;
u64 length; u64 length;
}; };
struct [[gnu::packed]] BusHierarchyDescriptorEntry struct [[gnu::packed]] BusHierarchyDescriptorEntry
{ {
ExtEntryHeader h; ExtEntryHeader h;
u8 bus_id; u8 bus_id;
u8 bus_info; u8 bus_info;
u8 parent_bus; u8 parent_bus;
u8 reserved[3]; u8 reserved[3];
}; };
struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry
{ {
ExtEntryHeader h; ExtEntryHeader h;
u8 bus_id; u8 bus_id;
u8 address_modifier; u8 address_modifier;
u32 predefined_range_list; u32 predefined_range_list;
}; };
} }

View file

@ -261,10 +261,10 @@ void page_fault_handler(RegisterState regs)
} }
dbg() << "Unrecoverable page fault, " dbg() << "Unrecoverable page fault, "
<< (regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "") << (regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "")
<< (regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "") << (regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "")
<< (regs.exception_code & PageFaultFlags::Write ? "write to" : "read from") << (regs.exception_code & PageFaultFlags::Write ? "write to" : "read from")
<< " address " << VirtualAddress(fault_address); << " address " << VirtualAddress(fault_address);
u32 malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE); u32 malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE);
u32 free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE); u32 free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE);
u32 kmalloc_scrub_pattern = explode_byte(KMALLOC_SCRUB_BYTE); u32 kmalloc_scrub_pattern = explode_byte(KMALLOC_SCRUB_BYTE);

View file

@ -329,7 +329,6 @@ Optional<KBuffer> procfs$pid_vm(InodeIdentifier identifier)
pagemap_builder.append('P'); pagemap_builder.append('P');
} }
region_object.add("pagemap", pagemap_builder.to_string()); region_object.add("pagemap", pagemap_builder.to_string());
} }
array.finish(); array.finish();
return builder.build(); return builder.build();

View file

@ -54,177 +54,177 @@ namespace Kernel {
namespace APIC { namespace APIC {
class ICRReg { class ICRReg {
u32 m_reg { 0 }; u32 m_reg { 0 };
public: public:
enum DeliveryMode { enum DeliveryMode {
Fixed = 0x0, Fixed = 0x0,
LowPriority = 0x1, LowPriority = 0x1,
SMI = 0x2, SMI = 0x2,
NMI = 0x4, NMI = 0x4,
INIT = 0x5, INIT = 0x5,
StartUp = 0x6, StartUp = 0x6,
}; };
enum DestinationMode { enum DestinationMode {
Physical = 0x0, Physical = 0x0,
Logical = 0x0, Logical = 0x0,
}; };
enum Level { enum Level {
DeAssert = 0x0, DeAssert = 0x0,
Assert = 0x1 Assert = 0x1
}; };
enum class TriggerMode { enum class TriggerMode {
Edge = 0x0, Edge = 0x0,
Level = 0x1, Level = 0x1,
}; };
enum DestinationShorthand { enum DestinationShorthand {
NoShorthand = 0x0, NoShorthand = 0x0,
Self = 0x1, Self = 0x1,
AllIncludingSelf = 0x2, AllIncludingSelf = 0x2,
AllExcludingSelf = 0x3, AllExcludingSelf = 0x3,
};
ICRReg(u8 vector, DeliveryMode delivery_mode, DestinationMode destination_mode, Level level, TriggerMode trigger_mode, DestinationShorthand destination)
: m_reg(vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination << 18))
{
}
u32 low() const { return m_reg; }
u32 high() const { return 0; }
}; };
static volatile u8* g_apic_base = nullptr; ICRReg(u8 vector, DeliveryMode delivery_mode, DestinationMode destination_mode, Level level, TriggerMode trigger_mode, DestinationShorthand destination)
: m_reg(vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination << 18))
static PhysicalAddress get_base()
{ {
u32 lo, hi;
MSR msr(APIC_BASE_MSR);
msr.get(lo, hi);
return PhysicalAddress(lo & 0xfffff000);
} }
static void set_base(const PhysicalAddress& base) u32 low() const { return m_reg; }
{ u32 high() const { return 0; }
u32 hi = 0; };
u32 lo = base.get() | 0x800;
MSR msr(APIC_BASE_MSR);
msr.set(lo, hi);
}
static void write_register(u32 offset, u32 value) static volatile u8* g_apic_base = nullptr;
{
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Write Access", Region::Access::Read | Region::Access::Write, false, true);
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
*lapic = value;
}
static u32 read_register(u32 offset) static PhysicalAddress get_base()
{ {
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Read Access", Region::Access::Read, false, true); u32 lo, hi;
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr(); MSR msr(APIC_BASE_MSR);
return *lapic; msr.get(lo, hi);
} return PhysicalAddress(lo & 0xfffff000);
}
static void write_icr(const ICRReg& icr) static void set_base(const PhysicalAddress& base)
{ {
write_register(APIC_REG_ICR_HIGH, icr.high()); u32 hi = 0;
write_register(APIC_REG_ICR_LOW, icr.low()); u32 lo = base.get() | 0x800;
} MSR msr(APIC_BASE_MSR);
msr.set(lo, hi);
}
static void write_register(u32 offset, u32 value)
{
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Write Access", Region::Access::Read | Region::Access::Write, false, true);
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
*lapic = value;
}
static u32 read_register(u32 offset)
{
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Read Access", Region::Access::Read, false, true);
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
return *lapic;
}
static void write_icr(const ICRReg& icr)
{
write_register(APIC_REG_ICR_HIGH, icr.high());
write_register(APIC_REG_ICR_LOW, icr.low());
}
#define APIC_LVT_MASKED (1 << 16) #define APIC_LVT_MASKED (1 << 16)
#define APIC_LVT_TRIGGER_LEVEL (1 << 14) #define APIC_LVT_TRIGGER_LEVEL (1 << 14)
#define APIC_LVT(iv, dm) ((iv & 0xff) | ((dm & 0x7) << 8)) #define APIC_LVT(iv, dm) ((iv & 0xff) | ((dm & 0x7) << 8))
asm( asm(
".globl apic_ap_start \n" ".globl apic_ap_start \n"
".type apic_ap_start, @function \n" ".type apic_ap_start, @function \n"
"apic_ap_start: \n" "apic_ap_start: \n"
".set begin_apic_ap_start, . \n" ".set begin_apic_ap_start, . \n"
" jmp apic_ap_start\n" // TODO: implement " jmp apic_ap_start\n" // TODO: implement
".set end_apic_ap_start, . \n" ".set end_apic_ap_start, . \n"
"\n" "\n"
".globl apic_ap_start_size \n" ".globl apic_ap_start_size \n"
"apic_ap_start_size: \n" "apic_ap_start_size: \n"
".word end_apic_ap_start - begin_apic_ap_start \n"); ".word end_apic_ap_start - begin_apic_ap_start \n");
extern "C" void apic_ap_start(void); extern "C" void apic_ap_start(void);
extern "C" u16 apic_ap_start_size; extern "C" u16 apic_ap_start_size;
void eoi() void eoi()
{ {
write_register(APIC_REG_EOI, 0x0); write_register(APIC_REG_EOI, 0x0);
} }
bool init() bool init()
{ {
if (!MSR::have()) if (!MSR::have())
return false; return false;
// check if we support local apic // check if we support local apic
CPUID id(1); CPUID id(1);
if ((id.edx() & (1 << 9)) == 0) if ((id.edx() & (1 << 9)) == 0)
return false; return false;
PhysicalAddress apic_base = get_base(); PhysicalAddress apic_base = get_base();
klog() << "Initializing APIC, base: " << apic_base; klog() << "Initializing APIC, base: " << apic_base;
set_base(apic_base); set_base(apic_base);
g_apic_base = apic_base.as_ptr(); g_apic_base = apic_base.as_ptr();
return true; return true;
} }
void enable_bsp() void enable_bsp()
{ {
// FIXME: Ensure this method can only be executed by the BSP. // FIXME: Ensure this method can only be executed by the BSP.
enable(0); enable(0);
} }
void enable(u32 cpu) void enable(u32 cpu)
{ {
klog() << "Enabling local APIC for cpu #" << cpu; klog() << "Enabling local APIC for cpu #" << cpu;
// dummy read, apparently to avoid a bug in old CPUs. // dummy read, apparently to avoid a bug in old CPUs.
read_register(APIC_REG_SIV); read_register(APIC_REG_SIV);
// set spurious interrupt vector // set spurious interrupt vector
write_register(APIC_REG_SIV, IRQ_APIC_SPURIOUS | 0x100); write_register(APIC_REG_SIV, IRQ_APIC_SPURIOUS | 0x100);
// local destination mode (flat mode) // local destination mode (flat mode)
write_register(APIC_REG_DF, 0xf0000000); write_register(APIC_REG_DF, 0xf0000000);
// set destination id (note that this limits it to 8 cpus) // set destination id (note that this limits it to 8 cpus)
write_register(APIC_REG_LD, 0); write_register(APIC_REG_LD, 0);
SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS); SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS);
write_register(APIC_REG_LVT_TIMER, APIC_LVT(0, 0) | APIC_LVT_MASKED); write_register(APIC_REG_LVT_TIMER, APIC_LVT(0, 0) | APIC_LVT_MASKED);
write_register(APIC_REG_LVT_THERMAL, APIC_LVT(0, 0) | APIC_LVT_MASKED); write_register(APIC_REG_LVT_THERMAL, APIC_LVT(0, 0) | APIC_LVT_MASKED);
write_register(APIC_REG_LVT_PERFORMANCE_COUNTER, APIC_LVT(0, 0) | APIC_LVT_MASKED); write_register(APIC_REG_LVT_PERFORMANCE_COUNTER, APIC_LVT(0, 0) | APIC_LVT_MASKED);
write_register(APIC_REG_LVT_LINT0, APIC_LVT(0, 7) | APIC_LVT_MASKED); write_register(APIC_REG_LVT_LINT0, APIC_LVT(0, 7) | APIC_LVT_MASKED);
write_register(APIC_REG_LVT_LINT1, APIC_LVT(0, 0) | APIC_LVT_TRIGGER_LEVEL); write_register(APIC_REG_LVT_LINT1, APIC_LVT(0, 0) | APIC_LVT_TRIGGER_LEVEL);
write_register(APIC_REG_LVT_ERR, APIC_LVT(0, 0) | APIC_LVT_MASKED); write_register(APIC_REG_LVT_ERR, APIC_LVT(0, 0) | APIC_LVT_MASKED);
write_register(APIC_REG_TPR, 0); write_register(APIC_REG_TPR, 0);
if (cpu != 0) { if (cpu != 0) {
static volatile u32 foo = 0; static volatile u32 foo = 0;
// INIT // INIT
write_icr(ICRReg(0, ICRReg::INIT, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf)); write_icr(ICRReg(0, ICRReg::INIT, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf));
for (foo = 0; foo < 0x800000; foo++) for (foo = 0; foo < 0x800000; foo++)
; // TODO: 10 millisecond delay ; // TODO: 10 millisecond delay
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
// SIPI // SIPI
write_icr(ICRReg(0x08, ICRReg::StartUp, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf)); // start execution at P8000 write_icr(ICRReg(0x08, ICRReg::StartUp, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf)); // start execution at P8000
for (foo = 0; foo < 0x80000; foo++) for (foo = 0; foo < 0x80000; foo++)
; // TODO: 200 microsecond delay ; // TODO: 200 microsecond delay
}
} }
} }
}
} }

View file

@ -32,10 +32,10 @@ namespace Kernel {
namespace APIC { namespace APIC {
void enable_bsp(); void enable_bsp();
void eoi(); void eoi();
bool init(); bool init();
void enable(u32 cpu); void enable(u32 cpu);
} }

View file

@ -30,8 +30,8 @@
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <Kernel/Arch/i386/CPU.h> #include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Interrupts/IRQController.h>
#include <Kernel/Interrupts/GenericInterruptHandler.h> #include <Kernel/Interrupts/GenericInterruptHandler.h>
#include <Kernel/Interrupts/IRQController.h>
namespace Kernel { namespace Kernel {

View file

@ -26,8 +26,8 @@
#pragma once #pragma once
#include <AK/String.h>
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/String.h>
class KParams { class KParams {
AK_MAKE_ETERNAL AK_MAKE_ETERNAL

View file

@ -29,9 +29,9 @@
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <Kernel/Interrupts/IRQHandler.h> #include <Kernel/Interrupts/IRQHandler.h>
#include <Kernel/Net/NetworkAdapter.h> #include <Kernel/Net/NetworkAdapter.h>
#include <LibBareMetal/IO.h>
#include <Kernel/PCI/Access.h> #include <Kernel/PCI/Access.h>
#include <Kernel/PCI/Device.h> #include <Kernel/PCI/Device.h>
#include <LibBareMetal/IO.h>
namespace Kernel { namespace Kernel {

View file

@ -26,10 +26,10 @@
#pragma once #pragma once
#include <AK/String.h>
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <AK/IPv4Address.h> #include <AK/IPv4Address.h>
#include <AK/NetworkOrdered.h> #include <AK/NetworkOrdered.h>
#include <AK/String.h>
#include <AK/Types.h> #include <AK/Types.h>
namespace Kernel { namespace Kernel {

View file

@ -30,8 +30,8 @@
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/SinglyLinkedList.h> #include <AK/SinglyLinkedList.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <AK/Weakable.h>
#include <AK/WeakPtr.h> #include <AK/WeakPtr.h>
#include <AK/Weakable.h>
#include <Kernel/KBuffer.h> #include <Kernel/KBuffer.h>
#include <Kernel/Net/ARP.h> #include <Kernel/Net/ARP.h>
#include <Kernel/Net/ICMP.h> #include <Kernel/Net/ICMP.h>

View file

@ -30,8 +30,7 @@
namespace Kernel { namespace Kernel {
struct RoutingDecision struct RoutingDecision {
{
RefPtr<NetworkAdapter> adapter; RefPtr<NetworkAdapter> adapter;
MACAddress next_hop; MACAddress next_hop;

View file

@ -126,7 +126,6 @@ public:
virtual ssize_t write(FileDescription&, const u8*, ssize_t) override final; virtual ssize_t write(FileDescription&, const u8*, ssize_t) override final;
virtual String absolute_path(const FileDescription&) const override = 0; virtual String absolute_path(const FileDescription&) const override = 0;
bool has_receive_timeout() const { return m_receive_timeout.tv_sec || m_receive_timeout.tv_usec; } bool has_receive_timeout() const { return m_receive_timeout.tv_sec || m_receive_timeout.tv_usec; }
const timeval& receive_timeout() const { return m_receive_timeout; } const timeval& receive_timeout() const { return m_receive_timeout; }

View file

@ -108,103 +108,103 @@ void PCI::Access::disable_bus_mastering(Address address)
namespace PCI { namespace PCI {
void enumerate_all(Function<void(Address, ID)> callback) void enumerate_all(Function<void(Address, ID)> callback)
{ {
PCI::Access::the().enumerate_all(callback); PCI::Access::the().enumerate_all(callback);
} }
void raw_access(Address address, u32 field, size_t access_size, u32 value) void raw_access(Address address, u32 field, size_t access_size, u32 value)
{ {
ASSERT(access_size != 0); ASSERT(access_size != 0);
if (access_size == 1) { if (access_size == 1) {
PCI::Access::the().write8_field(address, field, value); PCI::Access::the().write8_field(address, field, value);
return; return;
}
if (access_size == 2) {
PCI::Access::the().write16_field(address, field, value);
return;
}
if (access_size == 4) {
PCI::Access::the().write32_field(address, field, value);
return;
}
ASSERT_NOT_REACHED();
} }
if (access_size == 2) {
PCI::Access::the().write16_field(address, field, value);
return;
}
if (access_size == 4) {
PCI::Access::the().write32_field(address, field, value);
return;
}
ASSERT_NOT_REACHED();
}
ID get_id(Address address) ID get_id(Address address)
{ {
return PCI::Access::the().get_id(address); return PCI::Access::the().get_id(address);
} }
void enable_interrupt_line(Address address) void enable_interrupt_line(Address address)
{ {
PCI::Access::the().enable_interrupt_line(address); PCI::Access::the().enable_interrupt_line(address);
} }
void disable_interrupt_line(Address address) void disable_interrupt_line(Address address)
{ {
PCI::Access::the().disable_interrupt_line(address); PCI::Access::the().disable_interrupt_line(address);
} }
u8 get_interrupt_line(Address address) u8 get_interrupt_line(Address address)
{ {
return PCI::Access::the().get_interrupt_line(address); return PCI::Access::the().get_interrupt_line(address);
} }
u32 get_BAR0(Address address) u32 get_BAR0(Address address)
{ {
return PCI::Access::the().get_BAR0(address); return PCI::Access::the().get_BAR0(address);
} }
u32 get_BAR1(Address address) u32 get_BAR1(Address address)
{ {
return PCI::Access::the().get_BAR1(address); return PCI::Access::the().get_BAR1(address);
} }
u32 get_BAR2(Address address) u32 get_BAR2(Address address)
{ {
return PCI::Access::the().get_BAR2(address); return PCI::Access::the().get_BAR2(address);
} }
u32 get_BAR3(Address address) u32 get_BAR3(Address address)
{ {
return PCI::Access::the().get_BAR3(address); return PCI::Access::the().get_BAR3(address);
} }
u32 get_BAR4(Address address) u32 get_BAR4(Address address)
{ {
return PCI::Access::the().get_BAR4(address); return PCI::Access::the().get_BAR4(address);
} }
u32 get_BAR5(Address address) u32 get_BAR5(Address address)
{ {
return PCI::Access::the().get_BAR5(address); return PCI::Access::the().get_BAR5(address);
} }
u8 get_revision_id(Address address) u8 get_revision_id(Address address)
{ {
return PCI::Access::the().get_revision_id(address); return PCI::Access::the().get_revision_id(address);
} }
u8 get_subclass(Address address) u8 get_subclass(Address address)
{ {
return PCI::Access::the().get_subclass(address); return PCI::Access::the().get_subclass(address);
} }
u8 get_class(Address address) u8 get_class(Address address)
{ {
return PCI::Access::the().get_class(address); return PCI::Access::the().get_class(address);
} }
u16 get_subsystem_id(Address address) u16 get_subsystem_id(Address address)
{ {
return PCI::Access::the().get_subsystem_id(address); return PCI::Access::the().get_subsystem_id(address);
} }
u16 get_subsystem_vendor_id(Address address) u16 get_subsystem_vendor_id(Address address)
{ {
return PCI::Access::the().get_subsystem_vendor_id(address); return PCI::Access::the().get_subsystem_vendor_id(address);
} }
void enable_bus_mastering(Address address) void enable_bus_mastering(Address address)
{ {
PCI::Access::the().enable_bus_mastering(address); PCI::Access::the().enable_bus_mastering(address);
} }
void disable_bus_mastering(Address address) void disable_bus_mastering(Address address)
{ {
PCI::Access::the().disable_bus_mastering(address); PCI::Access::the().disable_bus_mastering(address);
} }
size_t get_BAR_Space_Size(Address address, u8 bar_number) size_t get_BAR_Space_Size(Address address, u8 bar_number)
{ {
return PCI::Access::the().get_BAR_Space_Size(address, bar_number); return PCI::Access::the().get_BAR_Space_Size(address, bar_number);
} }
} }
} }

View file

@ -68,134 +68,134 @@ namespace Kernel {
//#define PCI_DEBUG 1 //#define PCI_DEBUG 1
namespace PCI { namespace PCI {
struct ID { struct ID {
u16 vendor_id { 0 }; u16 vendor_id { 0 };
u16 device_id { 0 }; u16 device_id { 0 };
bool is_null() const { return !vendor_id && !device_id; } bool is_null() const { return !vendor_id && !device_id; }
bool operator==(const ID& other) const bool operator==(const ID& other) const
{ {
return vendor_id == other.vendor_id && device_id == other.device_id; return vendor_id == other.vendor_id && device_id == other.device_id;
} }
bool operator!=(const ID& other) const bool operator!=(const ID& other) const
{ {
return vendor_id != other.vendor_id || device_id != other.device_id; return vendor_id != other.vendor_id || device_id != other.device_id;
} }
}; };
struct Address { struct Address {
public: public:
Address() {} Address() {}
Address(u16 seg) Address(u16 seg)
: m_seg(seg) : m_seg(seg)
, m_bus(0) , m_bus(0)
, m_slot(0) , m_slot(0)
, m_function(0) , m_function(0)
{ {
} }
Address(u16 seg, u8 bus, u8 slot, u8 function) Address(u16 seg, u8 bus, u8 slot, u8 function)
: m_seg(seg) : m_seg(seg)
, m_bus(bus) , m_bus(bus)
, m_slot(slot) , m_slot(slot)
, m_function(function) , m_function(function)
{
}
Address(const Address& address)
: m_seg(address.seg())
, m_bus(address.bus())
, m_slot(address.slot())
, m_function(address.function())
{
}
bool is_null() const { return !m_bus && !m_slot && !m_function; }
operator bool() const { return !is_null(); }
u16 seg() const { return m_seg; }
u8 bus() const { return m_bus; }
u8 slot() const { return m_slot; }
u8 function() const { return m_function; }
u32 io_address_for_field(u8 field) const
{
return 0x80000000u | (m_bus << 16u) | (m_slot << 11u) | (m_function << 8u) | (field & 0xfc);
}
protected:
u32 m_seg { 0 };
u8 m_bus { 0 };
u8 m_slot { 0 };
u8 m_function { 0 };
};
inline const LogStream& operator<<(const LogStream& stream, const Address value)
{ {
return stream << "PCI [" << String::format("%w", value.seg()) << ":" << String::format("%b", value.bus()) << ":" << String::format("%b", value.slot()) << "." << String::format("%b", value.function()) << "]";
} }
struct ChangeableAddress : public Address { Address(const Address& address)
ChangeableAddress() : m_seg(address.seg())
: Address(0) , m_bus(address.bus())
{ , m_slot(address.slot())
} , m_function(address.function())
explicit ChangeableAddress(u16 seg) {
: Address(seg) }
{
}
ChangeableAddress(u16 seg, u8 bus, u8 slot, u8 function)
: Address(seg, bus, slot, function)
{
}
void set_seg(u16 seg) { m_seg = seg; }
void set_bus(u8 bus) { m_bus = bus; }
void set_slot(u8 slot) { m_slot = slot; }
void set_function(u8 function) { m_function = function; }
bool operator==(const Address& address)
{
if (m_seg == address.seg() && m_bus == address.bus() && m_slot == address.slot() && m_function == address.function())
return true;
else
return false;
}
const ChangeableAddress& operator=(const Address& address)
{
set_seg(address.seg());
set_bus(address.bus());
set_slot(address.slot());
set_function(address.function());
return *this;
}
};
ID get_id(PCI::Address); bool is_null() const { return !m_bus && !m_slot && !m_function; }
void enumerate_all(Function<void(Address, ID)> callback); operator bool() const { return !is_null(); }
void enable_interrupt_line(Address);
void disable_interrupt_line(Address);
u8 get_interrupt_line(Address);
void raw_access(Address, u32, size_t, u32);
u32 get_BAR0(Address);
u32 get_BAR1(Address);
u32 get_BAR2(Address);
u32 get_BAR3(Address);
u32 get_BAR4(Address);
u32 get_BAR5(Address);
u8 get_revision_id(Address);
u8 get_subclass(Address);
u8 get_class(Address);
u16 get_subsystem_id(Address);
u16 get_subsystem_vendor_id(Address);
size_t get_BAR_Space_Size(Address, u8);
void enable_bus_mastering(Address);
void disable_bus_mastering(Address);
class Initializer; u16 seg() const { return m_seg; }
class Access; u8 bus() const { return m_bus; }
class MMIOAccess; u8 slot() const { return m_slot; }
class IOAccess; u8 function() const { return m_function; }
class MMIOSegment;
class Device; u32 io_address_for_field(u8 field) const
{
return 0x80000000u | (m_bus << 16u) | (m_slot << 11u) | (m_function << 8u) | (field & 0xfc);
}
protected:
u32 m_seg { 0 };
u8 m_bus { 0 };
u8 m_slot { 0 };
u8 m_function { 0 };
};
inline const LogStream& operator<<(const LogStream& stream, const Address value)
{
return stream << "PCI [" << String::format("%w", value.seg()) << ":" << String::format("%b", value.bus()) << ":" << String::format("%b", value.slot()) << "." << String::format("%b", value.function()) << "]";
}
struct ChangeableAddress : public Address {
ChangeableAddress()
: Address(0)
{
}
explicit ChangeableAddress(u16 seg)
: Address(seg)
{
}
ChangeableAddress(u16 seg, u8 bus, u8 slot, u8 function)
: Address(seg, bus, slot, function)
{
}
void set_seg(u16 seg) { m_seg = seg; }
void set_bus(u8 bus) { m_bus = bus; }
void set_slot(u8 slot) { m_slot = slot; }
void set_function(u8 function) { m_function = function; }
bool operator==(const Address& address)
{
if (m_seg == address.seg() && m_bus == address.bus() && m_slot == address.slot() && m_function == address.function())
return true;
else
return false;
}
const ChangeableAddress& operator=(const Address& address)
{
set_seg(address.seg());
set_bus(address.bus());
set_slot(address.slot());
set_function(address.function());
return *this;
}
};
ID get_id(PCI::Address);
void enumerate_all(Function<void(Address, ID)> callback);
void enable_interrupt_line(Address);
void disable_interrupt_line(Address);
u8 get_interrupt_line(Address);
void raw_access(Address, u32, size_t, u32);
u32 get_BAR0(Address);
u32 get_BAR1(Address);
u32 get_BAR2(Address);
u32 get_BAR3(Address);
u32 get_BAR4(Address);
u32 get_BAR5(Address);
u8 get_revision_id(Address);
u8 get_subclass(Address);
u8 get_class(Address);
u16 get_subsystem_id(Address);
u16 get_subsystem_vendor_id(Address);
size_t get_BAR_Space_Size(Address, u8);
void enable_bus_mastering(Address);
void disable_bus_mastering(Address);
class Initializer;
class Access;
class MMIOAccess;
class IOAccess;
class MMIOSegment;
class Device;
} }

View file

@ -25,8 +25,8 @@
*/ */
#include <AK/JsonArraySerializer.h> #include <AK/JsonArraySerializer.h>
#include <AK/JsonObjectSerializer.h>
#include <AK/JsonObject.h> #include <AK/JsonObject.h>
#include <AK/JsonObjectSerializer.h>
#include <Kernel/KBufferBuilder.h> #include <Kernel/KBufferBuilder.h>
#include <Kernel/PerformanceEventBuffer.h> #include <Kernel/PerformanceEventBuffer.h>

View file

@ -65,61 +65,61 @@ asm(
namespace Syscall { namespace Syscall {
static int handle(RegisterState&, u32 function, u32 arg1, u32 arg2, u32 arg3); static int handle(RegisterState&, u32 function, u32 arg1, u32 arg2, u32 arg3);
void initialize() void initialize()
{ {
register_user_callable_interrupt_handler(0x82, syscall_asm_entry); register_user_callable_interrupt_handler(0x82, syscall_asm_entry);
klog() << "Syscall: int 0x82 handler installed"; klog() << "Syscall: int 0x82 handler installed";
} }
#pragma GCC diagnostic ignored "-Wcast-function-type" #pragma GCC diagnostic ignored "-Wcast-function-type"
typedef int (Process::*Handler)(u32, u32, u32); typedef int (Process::*Handler)(u32, u32, u32);
#define __ENUMERATE_REMOVED_SYSCALL(x) nullptr, #define __ENUMERATE_REMOVED_SYSCALL(x) nullptr,
#define __ENUMERATE_SYSCALL(x) reinterpret_cast<Handler>(&Process::sys$##x), #define __ENUMERATE_SYSCALL(x) reinterpret_cast<Handler>(&Process::sys$##x),
static Handler s_syscall_table[] = { static Handler s_syscall_table[] = {
ENUMERATE_SYSCALLS ENUMERATE_SYSCALLS
}; };
#undef __ENUMERATE_SYSCALL #undef __ENUMERATE_SYSCALL
#undef __ENUMERATE_REMOVED_SYSCALL #undef __ENUMERATE_REMOVED_SYSCALL
int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3) int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
{ {
ASSERT_INTERRUPTS_ENABLED(); ASSERT_INTERRUPTS_ENABLED();
auto& process = *Process::current; auto& process = *Process::current;
Thread::current->did_syscall(); Thread::current->did_syscall();
if (function == SC_exit || function == SC_exit_thread) { if (function == SC_exit || function == SC_exit_thread) {
// These syscalls need special handling since they never return to the caller. // These syscalls need special handling since they never return to the caller.
cli(); cli();
if (auto* tracer = process.tracer()) if (auto* tracer = process.tracer())
tracer->did_syscall(function, arg1, arg2, arg3, 0); tracer->did_syscall(function, arg1, arg2, arg3, 0);
if (function == SC_exit) if (function == SC_exit)
process.sys$exit((int)arg1); process.sys$exit((int)arg1);
else else
process.sys$exit_thread((void*)arg1); process.sys$exit_thread((void*)arg1);
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
return 0; return 0;
}
if (function == SC_fork)
return process.sys$fork(regs);
if (function == SC_sigreturn)
return process.sys$sigreturn(regs);
if (function >= Function::__Count) {
dbg() << process << ": Unknown syscall %u requested (" << arg1 << ", " << arg2 << ", " << arg3 << ")";
return -ENOSYS;
}
if (s_syscall_table[function] == nullptr) {
dbg() << process << ": Null syscall " << function << " requested: \"" << to_string((Function)function) << "\", you probably need to rebuild this program.";
return -ENOSYS;
}
return (process.*(s_syscall_table[function]))(arg1, arg2, arg3);
} }
if (function == SC_fork)
return process.sys$fork(regs);
if (function == SC_sigreturn)
return process.sys$sigreturn(regs);
if (function >= Function::__Count) {
dbg() << process << ": Unknown syscall %u requested (" << arg1 << ", " << arg2 << ", " << arg3 << ")";
return -ENOSYS;
}
if (s_syscall_table[function] == nullptr) {
dbg() << process << ": Null syscall " << function << " requested: \"" << to_string((Function)function) << "\", you probably need to rebuild this program.";
return -ENOSYS;
}
return (process.*(s_syscall_table[function]))(arg1, arg2, arg3);
}
} }
void syscall_handler(RegisterState& regs) void syscall_handler(RegisterState& regs)

View file

@ -184,20 +184,20 @@ namespace Kernel {
namespace Syscall { namespace Syscall {
enum Function { enum Function {
#undef __ENUMERATE_SYSCALL #undef __ENUMERATE_SYSCALL
#undef __ENUMERATE_REMOVED_SYSCALL #undef __ENUMERATE_REMOVED_SYSCALL
#define __ENUMERATE_REMOVED_SYSCALL(x) SC_##x, #define __ENUMERATE_REMOVED_SYSCALL(x) SC_##x,
#define __ENUMERATE_SYSCALL(x) SC_##x, #define __ENUMERATE_SYSCALL(x) SC_##x,
ENUMERATE_SYSCALLS ENUMERATE_SYSCALLS
#undef __ENUMERATE_SYSCALL #undef __ENUMERATE_SYSCALL
#undef __ENUMERATE_REMOVED_SYSCALL #undef __ENUMERATE_REMOVED_SYSCALL
__Count __Count
}; };
inline constexpr const char* to_string(Function function) inline constexpr const char* to_string(Function function)
{ {
switch (function) { switch (function) {
#undef __ENUMERATE_SYSCALL #undef __ENUMERATE_SYSCALL
#undef __ENUMERATE_REMOVED_SYSCALL #undef __ENUMERATE_REMOVED_SYSCALL
#define __ENUMERATE_REMOVED_SYSCALL(x) \ #define __ENUMERATE_REMOVED_SYSCALL(x) \
@ -206,267 +206,267 @@ namespace Syscall {
#define __ENUMERATE_SYSCALL(x) \ #define __ENUMERATE_SYSCALL(x) \
case SC_##x: \ case SC_##x: \
return #x; return #x;
ENUMERATE_SYSCALLS ENUMERATE_SYSCALLS
#undef __ENUMERATE_SYSCALL #undef __ENUMERATE_SYSCALL
#undef __ENUMERATE_REMOVED_SYSCALL #undef __ENUMERATE_REMOVED_SYSCALL
default: default:
break; break;
}
return "Unknown";
} }
return "Unknown";
}
#ifdef __serenity__ #ifdef __serenity__
struct StringArgument { struct StringArgument {
const char* characters { nullptr }; const char* characters { nullptr };
size_t length { 0 }; size_t length { 0 };
}; };
template<typename DataType, typename SizeType> template<typename DataType, typename SizeType>
struct MutableBufferArgument { struct MutableBufferArgument {
DataType* data { nullptr }; DataType* data { nullptr };
SizeType size { 0 }; SizeType size { 0 };
}; };
template<typename DataType, typename SizeType> template<typename DataType, typename SizeType>
struct ImmutableBufferArgument { struct ImmutableBufferArgument {
const DataType* data { nullptr }; const DataType* data { nullptr };
SizeType size { 0 }; SizeType size { 0 };
}; };
struct StringListArgument { struct StringListArgument {
StringArgument* strings { nullptr }; StringArgument* strings { nullptr };
size_t length { 0 }; size_t length { 0 };
}; };
struct SC_mmap_params { struct SC_mmap_params {
uint32_t addr; uint32_t addr;
uint32_t size; uint32_t size;
uint32_t alignment; uint32_t alignment;
int32_t prot; int32_t prot;
int32_t flags; int32_t flags;
int32_t fd; int32_t fd;
int32_t offset; // FIXME: 64-bit off_t? int32_t offset; // FIXME: 64-bit off_t?
StringArgument name; StringArgument name;
}; };
struct SC_open_params { struct SC_open_params {
int dirfd; int dirfd;
StringArgument path; StringArgument path;
int options; int options;
u16 mode; u16 mode;
}; };
struct SC_select_params { struct SC_select_params {
int nfds; int nfds;
fd_set* readfds; fd_set* readfds;
fd_set* writefds; fd_set* writefds;
fd_set* exceptfds; fd_set* exceptfds;
struct timeval* timeout; struct timeval* timeout;
}; };
struct SC_clock_nanosleep_params { struct SC_clock_nanosleep_params {
int clock_id; int clock_id;
int flags; int flags;
const struct timespec* requested_sleep; const struct timespec* requested_sleep;
struct timespec* remaining_sleep; struct timespec* remaining_sleep;
}; };
struct SC_sendto_params { struct SC_sendto_params {
int sockfd; int sockfd;
ImmutableBufferArgument<void, size_t> data; ImmutableBufferArgument<void, size_t> data;
int flags; int flags;
const sockaddr* addr; const sockaddr* addr;
socklen_t addr_length; socklen_t addr_length;
}; };
struct SC_recvfrom_params { struct SC_recvfrom_params {
int sockfd; int sockfd;
MutableBufferArgument<void, size_t> buffer; MutableBufferArgument<void, size_t> buffer;
int flags; int flags;
sockaddr* addr; sockaddr* addr;
socklen_t* addr_length; socklen_t* addr_length;
}; };
struct SC_getsockopt_params { struct SC_getsockopt_params {
int sockfd; int sockfd;
int level; int level;
int option; int option;
void* value; void* value;
socklen_t* value_size; socklen_t* value_size;
}; };
struct SC_setsockopt_params { struct SC_setsockopt_params {
int sockfd; int sockfd;
int level; int level;
int option; int option;
const void* value; const void* value;
socklen_t value_size; socklen_t value_size;
}; };
struct SC_getsockname_params { struct SC_getsockname_params {
int sockfd; int sockfd;
sockaddr* addr; sockaddr* addr;
socklen_t* addrlen; socklen_t* addrlen;
}; };
struct SC_getpeername_params { struct SC_getpeername_params {
int sockfd; int sockfd;
sockaddr* addr; sockaddr* addr;
socklen_t* addrlen; socklen_t* addrlen;
}; };
struct SC_futex_params { struct SC_futex_params {
i32* userspace_address; i32* userspace_address;
int futex_op; int futex_op;
i32 val; i32 val;
const timespec* timeout; const timespec* timeout;
}; };
struct SC_setkeymap_params { struct SC_setkeymap_params {
const char* map; const char* map;
const char* shift_map; const char* shift_map;
const char* alt_map; const char* alt_map;
const char* altgr_map; const char* altgr_map;
}; };
struct SC_create_thread_params { struct SC_create_thread_params {
unsigned int m_detach_state = 0; // JOINABLE or DETACHED unsigned int m_detach_state = 0; // JOINABLE or DETACHED
int m_schedule_priority = 30; // THREAD_PRIORITY_NORMAL int m_schedule_priority = 30; // THREAD_PRIORITY_NORMAL
// FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack) // FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack)
// "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE}, // "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE},
// a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize // a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize
// parameter the guard size specified by the previous pthread_attr_setguardsize() function call" // parameter the guard size specified by the previous pthread_attr_setguardsize() function call"
// ... ok, if you say so posix. Guess we get to lie to people about guard page size // ... ok, if you say so posix. Guess we get to lie to people about guard page size
unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE
unsigned int m_reported_guard_page_size = 0; // The lie we tell callers unsigned int m_reported_guard_page_size = 0; // The lie we tell callers
unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN
void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address
}; };
struct SC_realpath_params { struct SC_realpath_params {
StringArgument path; StringArgument path;
MutableBufferArgument<char, size_t> buffer; MutableBufferArgument<char, size_t> buffer;
}; };
struct SC_set_mmap_name_params { struct SC_set_mmap_name_params {
void* addr; void* addr;
size_t size; size_t size;
StringArgument name; StringArgument name;
}; };
struct SC_execve_params { struct SC_execve_params {
StringArgument path; StringArgument path;
StringListArgument arguments; StringListArgument arguments;
StringListArgument environment; StringListArgument environment;
}; };
struct SC_readlink_params { struct SC_readlink_params {
StringArgument path; StringArgument path;
MutableBufferArgument<char, size_t> buffer; MutableBufferArgument<char, size_t> buffer;
}; };
struct SC_link_params { struct SC_link_params {
StringArgument old_path; StringArgument old_path;
StringArgument new_path; StringArgument new_path;
}; };
struct SC_chown_params { struct SC_chown_params {
StringArgument path; StringArgument path;
u32 uid; u32 uid;
u32 gid; u32 gid;
}; };
struct SC_mknod_params { struct SC_mknod_params {
StringArgument path; StringArgument path;
u16 mode; u16 mode;
u32 dev; u32 dev;
}; };
struct SC_symlink_params { struct SC_symlink_params {
StringArgument target; StringArgument target;
StringArgument linkpath; StringArgument linkpath;
}; };
struct SC_rename_params { struct SC_rename_params {
StringArgument old_path; StringArgument old_path;
StringArgument new_path; StringArgument new_path;
}; };
struct SC_mount_params { struct SC_mount_params {
StringArgument source; StringArgument source;
StringArgument target; StringArgument target;
StringArgument fs_type; StringArgument fs_type;
int flags; int flags;
}; };
struct SC_pledge_params { struct SC_pledge_params {
StringArgument promises; StringArgument promises;
StringArgument execpromises; StringArgument execpromises;
}; };
struct SC_unveil_params { struct SC_unveil_params {
StringArgument path; StringArgument path;
StringArgument permissions; StringArgument permissions;
}; };
struct SC_waitid_params { struct SC_waitid_params {
int idtype; int idtype;
int id; int id;
struct siginfo* infop; struct siginfo* infop;
int options; int options;
}; };
struct SC_stat_params { struct SC_stat_params {
StringArgument path; StringArgument path;
struct stat* statbuf; struct stat* statbuf;
bool follow_symlinks; bool follow_symlinks;
}; };
void initialize(); void initialize();
int sync(); int sync();
inline u32 invoke(Function function) inline u32 invoke(Function function)
{ {
u32 result; u32 result;
asm volatile("int $0x82" asm volatile("int $0x82"
: "=a"(result) : "=a"(result)
: "a"(function) : "a"(function)
: "memory"); : "memory");
return result; return result;
} }
template<typename T1> template<typename T1>
inline u32 invoke(Function function, T1 arg1) inline u32 invoke(Function function, T1 arg1)
{ {
u32 result; u32 result;
asm volatile("int $0x82" asm volatile("int $0x82"
: "=a"(result) : "=a"(result)
: "a"(function), "d"((u32)arg1) : "a"(function), "d"((u32)arg1)
: "memory"); : "memory");
return result; return result;
} }
template<typename T1, typename T2> template<typename T1, typename T2>
inline u32 invoke(Function function, T1 arg1, T2 arg2) inline u32 invoke(Function function, T1 arg1, T2 arg2)
{ {
u32 result; u32 result;
asm volatile("int $0x82" asm volatile("int $0x82"
: "=a"(result) : "=a"(result)
: "a"(function), "d"((u32)arg1), "c"((u32)arg2) : "a"(function), "d"((u32)arg1), "c"((u32)arg2)
: "memory"); : "memory");
return result; return result;
} }
template<typename T1, typename T2, typename T3> template<typename T1, typename T2, typename T3>
inline u32 invoke(Function function, T1 arg1, T2 arg2, T3 arg3) inline u32 invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
{ {
u32 result; u32 result;
asm volatile("int $0x82" asm volatile("int $0x82"
: "=a"(result) : "=a"(result)
: "a"(function), "d"((u32)arg1), "c"((u32)arg2), "b"((u32)arg3) : "a"(function), "d"((u32)arg1), "c"((u32)arg2), "b"((u32)arg3)
: "memory"); : "memory");
return result; return result;
} }
#endif #endif
} }

View file

@ -24,9 +24,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <Kernel/Heap/kmalloc.h>
#include <Kernel/VM/MemoryManager.h> #include <Kernel/VM/MemoryManager.h>
#include <Kernel/VM/PhysicalPage.h> #include <Kernel/VM/PhysicalPage.h>
#include <Kernel/Heap/kmalloc.h>
namespace Kernel { namespace Kernel {