From c5f9f0c3074a43222044535c5de9e134f353e1db Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 18 Sep 2023 21:48:37 +0300 Subject: [PATCH] Kernel: Add LAI as a dependency I did not feel like implementing AML interpreter now, and wanted everything AML has to offer. I will be writing my own AML interperter at some point. --- .gitmodules | 4 + CMakeLists.txt | 3 + kernel/CMakeLists.txt | 17 +++- kernel/include/kernel/ACPI.h | 19 ++++- kernel/include/kernel/Arch.h | 4 + kernel/kernel/ACPI.cpp | 106 ++++++++++++++++--------- kernel/kernel/lai_host.cpp | 150 +++++++++++++++++++++++++++++++++++ kernel/lai | 1 + 8 files changed, 258 insertions(+), 46 deletions(-) create mode 100644 .gitmodules create mode 100644 kernel/kernel/lai_host.cpp create mode 160000 kernel/lai diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..30d88028 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "kernel/lai"] + path = kernel/lai + url = https://github.com/managarm/lai.git + ignore = untracked diff --git a/CMakeLists.txt b/CMakeLists.txt index 5526a851..27b9ae21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++) set(CMAKE_CXX_COMPILER_WORKS True) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-gcc) +set(CMAKE_C_COMPILER_WORKS True) + if(NOT EXISTS ${CMAKE_CXX_COMPILER}) set(CMAKE_CXX_COMPILER g++) endif() diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 02706efe..3801e43b 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.26) -project(kernel CXX ASM) +project(kernel CXX C ASM) if("${BANAN_ARCH}" STREQUAL "x86_64") set(ELF_FORMAT elf64-x86-64) @@ -98,6 +98,14 @@ else() message(FATAL_ERROR "unsupported architecure ${BANAN_ARCH}") endif() +file(GLOB_RECURSE LAI_SOURCES + lai/*.c +) +set(LAI_SOURCES + ${LAI_SOURCES} + kernel/lai_host.cpp +) + set(BAN_SOURCES ../BAN/BAN/New.cpp ../BAN/BAN/String.cpp @@ -116,6 +124,7 @@ set(LIBELF_SOURCES set(KERNEL_SOURCES ${KERNEL_SOURCES} + ${LAI_SOURCES} ${BAN_SOURCES} ${LIBC_SOURCES} ${LIBELF_SOURCES} @@ -128,10 +137,9 @@ target_compile_definitions(kernel PUBLIC __is_kernel) target_compile_definitions(kernel PUBLIC __arch=${BANAN_ARCH}) target_compile_options(kernel PUBLIC -O2 -g) -target_compile_options(kernel PUBLIC -Wno-literal-suffix) -target_compile_options(kernel PUBLIC -fno-rtti -fno-exceptions) +target_compile_options(kernel PUBLIC $<$:-Wno-literal-suffix -fno-rtti -fno-exceptions>) target_compile_options(kernel PUBLIC -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.) -target_compile_options(kernel PUBLIC -fstack-protector -ffreestanding -Wall -Wextra -Werror=return-type -Wstack-usage=1024 -fno-omit-frame-pointer -mgeneral-regs-only) +target_compile_options(kernel PUBLIC -fstack-protector -ffreestanding -Wall -Werror=return-type -Wstack-usage=1024 -fno-omit-frame-pointer -mgeneral-regs-only) if(ENABLE_KERNEL_UBSAN) target_compile_options(kernel PUBLIC -fsanitize=undefined) @@ -160,6 +168,7 @@ add_custom_command( add_custom_target(kernel-headers COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/ + COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/lai/include/ ${BANAN_INCLUDE}/ DEPENDS sysroot USES_TERMINAL ) diff --git a/kernel/include/kernel/ACPI.h b/kernel/include/kernel/ACPI.h index 2af66f29..4937a6af 100644 --- a/kernel/include/kernel/ACPI.h +++ b/kernel/include/kernel/ACPI.h @@ -114,20 +114,31 @@ namespace Kernel ACPI() = default; BAN::ErrorOr initialize_impl(); - const SDTHeader* get_header_from_index(size_t); - private: paddr_t m_header_table_paddr = 0; vaddr_t m_header_table_vaddr = 0; uint32_t m_entry_size = 0; - uint32_t m_entry_count = 0; struct MappedPage { Kernel::paddr_t paddr; Kernel::vaddr_t vaddr; + + SDTHeader* as_header() { return (SDTHeader*)vaddr; } }; BAN::Vector m_mapped_headers; }; -} \ No newline at end of file +} + +namespace BAN::Formatter +{ + template + void print_argument(F putc, const Kernel::ACPI::SDTHeader& header, const ValueFormat& format) + { + putc(header.signature[0]); + putc(header.signature[1]); + putc(header.signature[2]); + putc(header.signature[3]); + } +} diff --git a/kernel/include/kernel/Arch.h b/kernel/include/kernel/Arch.h index 0a31be74..068ebdd5 100644 --- a/kernel/include/kernel/Arch.h +++ b/kernel/include/kernel/Arch.h @@ -21,4 +21,8 @@ #include +#ifdef __cplusplus extern "C" uintptr_t read_rip(); +#else +extern uintptr_t read_rip(); +#endif diff --git a/kernel/kernel/ACPI.cpp b/kernel/kernel/ACPI.cpp index ecb443eb..ae447ce3 100644 --- a/kernel/kernel/ACPI.cpp +++ b/kernel/kernel/ACPI.cpp @@ -3,6 +3,8 @@ #include #include +#include + #define RSPD_SIZE 20 #define RSPDv2_SIZE 36 @@ -43,6 +45,7 @@ namespace Kernel if (s_instance == nullptr) return BAN::Error::from_errno(ENOMEM); TRY(s_instance->initialize_impl()); + lai_create_namespace(); return {}; } @@ -101,6 +104,9 @@ namespace Kernel const RSDP* rsdp = locate_rsdp(); if (rsdp == nullptr) return BAN::Error::from_error_code(ErrorCode::ACPI_NoRootSDT); + lai_set_acpi_revision(rsdp->revision); + + uint32_t root_entry_count = 0; if (rsdp->revision >= 2) { @@ -115,7 +121,7 @@ namespace Kernel m_header_table_paddr = (paddr_t)xsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK); m_entry_size = 8; - m_entry_count = (xsdt->length - sizeof(SDTHeader)) / 8; + root_entry_count = (xsdt->length - sizeof(SDTHeader)) / 8; } else { @@ -130,10 +136,10 @@ namespace Kernel m_header_table_paddr = (paddr_t)rsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK); m_entry_size = 4; - m_entry_count = (rsdt->length - sizeof(SDTHeader)) / 4; + root_entry_count = (rsdt->length - sizeof(SDTHeader)) / 4; } - size_t needed_pages = range_page_count(m_header_table_paddr, m_entry_count * m_entry_size); + size_t needed_pages = range_page_count(m_header_table_paddr, root_entry_count * m_entry_size); m_header_table_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); ASSERT(m_header_table_vaddr); @@ -146,61 +152,85 @@ namespace Kernel PageTable::Flags::Present ); - for (uint32_t i = 0; i < m_entry_count; i++) + auto map_header = + [](paddr_t header_paddr) -> vaddr_t + { + PageTable::kernel().map_page_at(header_paddr & PAGE_ADDR_MASK, 0, PageTable::Flags::Present); + size_t header_length = ((SDTHeader*)(header_paddr % PAGE_SIZE))->length; + PageTable::kernel().unmap_page(0); + + size_t needed_pages = range_page_count(header_paddr, header_length); + vaddr_t page_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); + ASSERT(page_vaddr); + + PageTable::kernel().map_range_at( + header_paddr & PAGE_ADDR_MASK, + page_vaddr, + needed_pages * PAGE_SIZE, + PageTable::Flags::Present + ); + + auto* header = (SDTHeader*)(page_vaddr + (header_paddr % PAGE_SIZE)); + if (!is_valid_std_header(header)) + { + PageTable::kernel().unmap_range(page_vaddr, needed_pages * PAGE_SIZE); + return 0; + } + + return page_vaddr + (header_paddr % PAGE_SIZE); + }; + + for (uint32_t i = 0; i < root_entry_count; i++) { paddr_t header_paddr = (m_entry_size == 4) ? ((uint32_t*)m_header_table_vaddr)[i] : ((uint64_t*)m_header_table_vaddr)[i]; - PageTable::kernel().map_page_at(header_paddr & PAGE_ADDR_MASK, 0, PageTable::Flags::Present); - size_t header_length = ((SDTHeader*)(header_paddr % PAGE_SIZE))->length; - PageTable::kernel().unmap_page(0); - - size_t needed_pages = range_page_count(header_paddr, header_length); - vaddr_t page_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); - ASSERT(page_vaddr); - - PageTable::kernel().map_range_at( - header_paddr & PAGE_ADDR_MASK, - page_vaddr, - needed_pages * PAGE_SIZE, - PageTable::Flags::Present - ); + vaddr_t header_vaddr = map_header(header_paddr); + if (header_vaddr == 0) + continue; MUST(m_mapped_headers.push_back({ .paddr = header_paddr, - .vaddr = page_vaddr + (header_paddr % PAGE_SIZE) + .vaddr = header_vaddr })); } + for (size_t i = 0; i < m_mapped_headers.size(); i++) + { + auto* header = m_mapped_headers[i].as_header(); + dprintln("found header {}", *header); + + if (memcmp(header->signature, "FACP", 4) == 0) + { + auto* fadt = (FADT*)header; + paddr_t dsdt_paddr = fadt->x_dsdt; + if (dsdt_paddr == 0 || !PageTable::is_valid_pointer(dsdt_paddr)) + dsdt_paddr = fadt->dsdt; + + vaddr_t dsdt_vaddr = map_header(dsdt_paddr); + if (dsdt_vaddr == 0) + continue; + + MUST(m_mapped_headers.push_back({ + .paddr = dsdt_paddr, + .vaddr = dsdt_vaddr + })); + } + } + return {}; } const ACPI::SDTHeader* ACPI::get_header(const char signature[4]) { - for (uint32_t i = 0; i < m_entry_count; i++) + for (auto& mapped_header : m_mapped_headers) { - const SDTHeader* header = get_header_from_index(i); - if (is_valid_std_header(header) && memcmp(header->signature, signature, 4) == 0) + auto* header = mapped_header.as_header(); + if (memcmp(header->signature, signature, 4) == 0) return header; } return nullptr; } - const ACPI::SDTHeader* ACPI::get_header_from_index(size_t index) - { - ASSERT(index < m_entry_count); - ASSERT(m_entry_size == 4 || m_entry_size == 8); - - paddr_t header_paddr = (m_entry_size == 4) ? - ((uint32_t*)m_header_table_vaddr)[index] : - ((uint64_t*)m_header_table_vaddr)[index]; - - for (const auto& page : m_mapped_headers) - if (page.paddr == header_paddr) - return (SDTHeader*)page.vaddr; - - ASSERT_NOT_REACHED(); - } - } \ No newline at end of file diff --git a/kernel/kernel/lai_host.cpp b/kernel/kernel/lai_host.cpp new file mode 100644 index 00000000..3b3eba9d --- /dev/null +++ b/kernel/kernel/lai_host.cpp @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include + +#include + +using namespace Kernel; + +void* laihost_malloc(size_t size) +{ + return kmalloc(size); +} + +void* laihost_realloc(void* ptr, size_t newsize, size_t oldsize) +{ + if (ptr == nullptr) + return laihost_malloc(newsize); + + void* new_ptr = laihost_malloc(newsize); + if (new_ptr == nullptr) + return nullptr; + + memcpy(new_ptr, ptr, BAN::Math::min(newsize, oldsize)); + kfree(ptr); + + return new_ptr; +} + +void laihost_free(void* ptr, size_t) +{ + kfree(ptr); +} + +void laihost_log(int level, const char* msg) +{ + if (level == LAI_DEBUG_LOG) + dprintln(msg); + else if (level == LAI_WARN_LOG) + dwarnln(msg); + else + ASSERT_NOT_REACHED(); +} + +void laihost_panic(const char* msg) +{ + Kernel::panic(msg); +} + +void* laihost_scan(const char* sig, size_t index) +{ + ASSERT(index == 0); + return (void*)ACPI::get().get_header(sig); +} + +void* laihost_map(size_t address, size_t count) +{ + size_t needed_pages = range_page_count(address, count); + vaddr_t vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); + ASSERT(vaddr); + + PageTable::kernel().map_range_at(address & PAGE_ADDR_MASK, vaddr, needed_pages * PAGE_SIZE, PageTable::Flags::ReadWrite | PageTable::Flags::Present); + + return (void*)(vaddr + (address % PAGE_SIZE)); +} + +void laihost_unmap(void* ptr, size_t count) +{ + PageTable::kernel().unmap_range((vaddr_t)ptr, count); +} + +void laihost_outb(uint16_t port, uint8_t val) +{ + IO::outb(port, val); +} + +void laihost_outw(uint16_t port, uint16_t val) +{ + IO::outw(port, val); +} + +void laihost_outd(uint16_t port, uint32_t val) +{ + IO::outl(port, val); +} + +uint8_t laihost_inb(uint16_t port) +{ + return IO::inb(port); +} + +uint16_t laihost_inw(uint16_t port) +{ + return IO::inw(port); +} + +uint32_t laihost_ind(uint16_t port) +{ + return IO::inl(port); +} + +void laihost_pci_writeb(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t fun, uint16_t offset, uint8_t val) +{ + ASSERT(seg == 0); + PCI::PCIManager::write_config_byte(bus, slot, fun, offset, val); +} + +void laihost_pci_writew(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t fun, uint16_t offset, uint16_t val) +{ + ASSERT(seg == 0); + PCI::PCIManager::write_config_word(bus, slot, fun, offset, val); +} + +void laihost_pci_writed(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t fun, uint16_t offset, uint32_t val) +{ + ASSERT(seg == 0); + PCI::PCIManager::write_config_dword(bus, slot, fun, offset, val); +} + +uint8_t laihost_pci_readb(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t fun, uint16_t offset) +{ + ASSERT(seg == 0); + return PCI::PCIManager::read_config_byte(bus, slot, fun, offset); +} + +uint16_t laihost_pci_readw(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t fun, uint16_t offset) +{ + ASSERT(seg == 0); + return PCI::PCIManager::read_config_word(bus, slot, fun, offset); + +} + +uint32_t laihost_pci_readd(uint16_t seg, uint8_t bus, uint8_t slot, uint8_t fun, uint16_t offset) +{ + ASSERT(seg == 0); + return PCI::PCIManager::read_config_dword(bus, slot, fun, offset); +} + +void laihost_sleep(uint64_t ms) +{ + SystemTimer::get().sleep(ms); +} + +uint64_t laihost_timer(void) +{ + auto time = SystemTimer::get().time_since_boot(); + return (1'000'000'000ull * time.tv_sec + time.tv_nsec) / 100; +} diff --git a/kernel/lai b/kernel/lai new file mode 160000 index 00000000..a2284653 --- /dev/null +++ b/kernel/lai @@ -0,0 +1 @@ +Subproject commit a228465314ee3a542f62d4bdefeb8fbe2b48da41