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.
This commit is contained in:
		
							parent
							
								
									8136248a67
								
							
						
					
					
						commit
						c9e09b840e
					
				|  | @ -0,0 +1,4 @@ | |||
| [submodule "kernel/lai"] | ||||
| 	path = kernel/lai | ||||
| 	url = https://github.com/managarm/lai.git | ||||
| 	ignore = untracked | ||||
|  | @ -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() | ||||
|  |  | |||
|  | @ -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 $<$<COMPILE_LANGUAGE:CXX>:-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 | ||||
| ) | ||||
|  |  | |||
|  | @ -114,20 +114,31 @@ namespace Kernel | |||
| 		ACPI() = default; | ||||
| 		BAN::ErrorOr<void> 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<MappedPage> m_mapped_headers;		 | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| namespace BAN::Formatter | ||||
| { | ||||
| 	template<typename F> | ||||
| 	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]); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -21,4 +21,8 @@ | |||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" uintptr_t read_rip(); | ||||
| #else | ||||
| extern uintptr_t read_rip(); | ||||
| #endif | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| #include <kernel/ACPI.h> | ||||
| #include <kernel/Memory/PageTable.h> | ||||
| 
 | ||||
| #include <lai/core.h> | ||||
| 
 | ||||
| #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(); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,150 @@ | |||
| #include <kernel/ACPI.h> | ||||
| #include <kernel/IO.h> | ||||
| #include <kernel/Memory/kmalloc.h> | ||||
| #include <kernel/Memory/PageTable.h> | ||||
| #include <kernel/PCI.h> | ||||
| #include <kernel/Timer/Timer.h> | ||||
| 
 | ||||
| #include <lai/host.h> | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
|  | @ -0,0 +1 @@ | |||
| Subproject commit a228465314ee3a542f62d4bdefeb8fbe2b48da41 | ||||
		Loading…
	
		Reference in New Issue