diff --git a/.vscode/settings.json b/.vscode/settings.json index 34a995ee..365483c5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,14 @@ "cmake.configureOnOpen": false, "makefile.configureOnOpen": false, "files.associations": { - "*.h": "c" + "*.h": "c", + "array": "c", + "deque": "c", + "string": "c", + "unordered_map": "c", + "vector": "c", + "string_view": "c", + "initializer_list": "c" }, "C_Cpp.default.intelliSenseMode": "linux-gcc-x86" } diff --git a/devel/virtualbox/grub.cfg b/devel/virtualbox/grub.cfg index a5ab4137..9af1634d 100644 --- a/devel/virtualbox/grub.cfg +++ b/devel/virtualbox/grub.cfg @@ -32,8 +32,6 @@ linux16 /boot/jinue \ DEBUG_DUMP_MEMORY_MAP=1 \ DEBUG_DUMP_SYSCALL_IMPLEMENTATION=1 \ DEBUG_DUMP_RAMDISK=1 \ - RUN_TEST_ACPI=1 \ RUN_TEST_IPC=1 - initrd16 /boot/jinue-testapp-initrd.tar.gz boot diff --git a/doc/syscalls/README.md b/doc/syscalls/README.md index 68b62e5e..7ef69bdb 100644 --- a/doc/syscalls/README.md +++ b/doc/syscalls/README.md @@ -29,9 +29,8 @@ | 20 | [START_THREAD](start-thread.md) | Start a thread | | 21 | [AWAIT_THREAD](await-thread.md) | Wait for a thread to exit | | 22 | [REPLY_ERROR](reply-error.md) | Reply to message with an error | -| 23 | [SET_ACPI](set-acpi.md) | Provide mapped ACPI tables | -| 24-4095 | - | Reserved | -| 4096+ | [SEND](send.md) | Send a message | +| 23-4095 | - | Reserved | +| 4096+ | [SEND](send.md) | Send a message | #### Reserved Function Numbers diff --git a/doc/syscalls/set-acpi.md b/doc/syscalls/set-acpi.md deleted file mode 100644 index cb2bec6e..00000000 --- a/doc/syscalls/set-acpi.md +++ /dev/null @@ -1,59 +0,0 @@ -# SET_ACPI - Provide Mapped ACPI Tables - -## Description - -Provide the mapped ACPI tables to the kernel. - -This system call is reserved for use by the user space loader. It fails if -called by another process. - -The user space loader must make a best effort to map the relevant ACPI tables -and must call this system call with the result, unless the `JINUE_AT_ACPI_RSDP` -auxiliary vector has been set to zero or omitted. - -## Arguments - -Function number (`arg0`) is 23. - -A pointer to a [jinue_acpi_tables_t structure](../../include/jinue/shared/types.h) -(i.e. the ACPI tables structure) that contains pointers to mapped ACPI tables -is set in `arg1`. - -If the user space loader could not map certain ACPI tables, it should set the -relevant pointers to zero (C language `NULL` value) and still call this -function. - -``` - +----------------------------------------------------------------+ - | function = 23 | arg0 - +----------------------------------------------------------------+ - 31 0 - - +----------------------------------------------------------------+ - | pointer to ACPI tables structure | arg1 - +----------------------------------------------------------------+ - 31 0 - - +----------------------------------------------------------------+ - | reserved (0) | arg2 - +----------------------------------------------------------------+ - 31 0 - - +----------------------------------------------------------------+ - | reserved (0) | arg3 - +----------------------------------------------------------------+ - 31 0 -``` - -## Return Value - -On success, this function returns 0 (in `arg0`). On failure, this function -returns -1 and an error number is set (in `arg1`). - -## Errors - -* JINUE_EINVAL if any part of the ACPI tables structure as specified by `arg1` -belongs to the kernel. -* JINUE_ENOSYS if this function does not exist on this CPU architecture. -* JINUE_ENOSYS if this function is called by a process other than the user -space loader. diff --git a/include/jinue/jinue.h b/include/jinue/jinue.h index 60393765..da98a711 100644 --- a/include/jinue/jinue.h +++ b/include/jinue/jinue.h @@ -119,6 +119,4 @@ int jinue_await_thread(int fd, int *perrno); int jinue_reply_error(uintptr_t errcode, int *perrno); -int jinue_set_acpi(jinue_acpi_tables_t *tables, int *perrno); - #endif diff --git a/include/jinue/shared/asm/syscalls.h b/include/jinue/shared/asm/syscalls.h index bb9d2930..87601269 100644 --- a/include/jinue/shared/asm/syscalls.h +++ b/include/jinue/shared/asm/syscalls.h @@ -92,9 +92,6 @@ /** reply to current message with an error code */ #define JINUE_SYS_REPLY_ERROR 22 -/** provide the mapped ACPI tables */ -#define JINUE_SYS_SET_ACPI 23 - /** start of function numbers for user space messages */ #define JINUE_SYS_USER_BASE 4096 diff --git a/include/jinue/shared/types.h b/include/jinue/shared/types.h index 5396f852..88c352d4 100644 --- a/include/jinue/shared/types.h +++ b/include/jinue/shared/types.h @@ -113,10 +113,4 @@ typedef struct { uintptr_t cookie; } jinue_mint_args_t; -typedef struct { - const void *rsdt; - const void *fadt; - const void *madt; -} jinue_acpi_tables_t; - #endif diff --git a/include/kernel/application/syscalls.h b/include/kernel/application/syscalls.h index d538ae5c..2c62d899 100644 --- a/include/kernel/application/syscalls.h +++ b/include/kernel/application/syscalls.h @@ -72,8 +72,6 @@ int reply_error(uintptr_t errcode); int send(uintptr_t *errcode, int fd, int function, const jinue_message_t *message); -int set_acpi(const jinue_acpi_tables_t *tables); - void set_thread_local(void *addr, size_t size); int start_thread(int fd, const thread_params_t *params); diff --git a/include/kernel/domain/services/mman.h b/include/kernel/domain/services/mman.h index 42254501..5a931cf6 100644 --- a/include/kernel/domain/services/mman.h +++ b/include/kernel/domain/services/mman.h @@ -37,4 +37,8 @@ void *map_in_kernel(kern_paddr_t paddr, size_t size, int prot); +void resize_map_in_kernel(size_t size); + +void undo_map_in_kernel(void); + #endif diff --git a/include/kernel/machine/acpi.h b/include/kernel/infrastructure/acpi/acpi.h similarity index 77% rename from include/kernel/machine/acpi.h rename to include/kernel/infrastructure/acpi/acpi.h index c3a4affd..3a836af9 100644 --- a/include/kernel/machine/acpi.h +++ b/include/kernel/infrastructure/acpi/acpi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Philippe Aubertin. + * Copyright (C) 2025 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -29,12 +29,17 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JINUE_KERNEL_MACHINE_ACPI_H -#define JINUE_KERNEL_MACHINE_ACPI_H +#ifndef JINUE_KERNEL_INFRASTRUCTURE_ACPI_ACPI_H +#define JINUE_KERNEL_INFRASTRUCTURE_ACPI_ACPI_H -#include -#include +#include +#include +#include +#include +#include -void machine_set_acpi_tables(const jinue_acpi_tables_t *tables); +bool verify_acpi_rsdp(const acpi_rsdp_t *rsdp); + +void map_acpi_tables(kern_paddr_t rsdp_paddr, const acpi_table_def_t *table_defs); #endif diff --git a/include/kernel/infrastructure/i686/drivers/asm/acpi.h b/include/kernel/infrastructure/acpi/asm/acpi.h similarity index 81% rename from include/kernel/infrastructure/i686/drivers/asm/acpi.h rename to include/kernel/infrastructure/acpi/asm/acpi.h index caf1a150..dc3dda6e 100644 --- a/include/kernel/infrastructure/i686/drivers/asm/acpi.h +++ b/include/kernel/infrastructure/acpi/asm/acpi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Philippe Aubertin. + * Copyright (C) 202-2025 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -29,10 +29,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_ACPI_H -#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_ACPI_H - -#define ACPI_BDA_EBDA 0x40e +#ifndef JINUE_KERNEL_INFRASTRUCTURE_ACPI_ASM_ACPI_H +#define JINUE_KERNEL_INFRASTRUCTURE_ACPI_ASM_ACPI_H #define ACPI_V1_REVISION 0 @@ -40,4 +38,9 @@ #define ACPI_V1_RSDP_SIZE 20 +/* Arbitrary value expected to be large enough to accomodate any real table + * while ensuring we don't create arbitrary large mappings because of garbage + * data in length members. */ +#define ACPI_TABLE_MAX_SIZE (128 * 1024) + #endif diff --git a/include/kernel/infrastructure/acpi/asm/tables.h b/include/kernel/infrastructure/acpi/asm/tables.h new file mode 100644 index 00000000..75ab1bfc --- /dev/null +++ b/include/kernel/infrastructure/acpi/asm/tables.h @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2025 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_INFRASTRUCTURE_ACPI_ASM_TABLES_H +#define JINUE_KERNEL_INFRASTRUCTURE_ACPI_ASM_TABLES_H + + +#define ACPI_FADT_SIGNATURE "FACP" + +#define ACPI_HPET_SIGNATURE "HPET" + +#define ACPI_MADT_SIGNATURE "APIC" + +#define ACPI_RSDP_SIGNATURE "RSD PTR " + +#define ACPI_RSDT_SIGNATURE "RSDT" + +#define ACPI_XSDT_SIGNATURE "XSDT" + +/* ACPI 6.4 section 5.2.3.2 Generic Address Structure (GAS) address space ID */ + +#define ACPI_GAS_ADDR_SPACE_SYSTEM_MEMORY 0x00 + +#define ACPI_GAS_ADDR_SPACE_SYSTEM_IO_SPACE 0x01 + +#define ACPI_GAS_ADDR_SPACE_PCI_CONFIG 0x02 + +#define ACPI_GAS_ADDR_SPACE_EMBEDDED_CONTROLLER 0x03 + +#define ACPI_GAS_ADDR_SPACE_SMBUS 0x04 + +#define ACPI_GAS_ADDR_SPACE_SYSTEM_CMOS 0x05 + +#define ACPI_GAS_ADDR_SPACE_PCI_BAR_TARGET 0x06 + +#define ACPI_GAS_ADDR_SPACE_IPMI 0x07 + +#define ACPI_GAS_ADDR_SPACE_GPIO 0x08 + +#define ACPI_GAS_ADDR_SPACE_GENERAL_SERIAL_BUS 0x09 + +#define ACPI_GAS_ADDR_SPACE_PCC 0x0a + +#define ACPI_GAS_ADDR_SPACE_FUNCTIONAL_FIXED_HARDWARE 0x7f + +/* ACPI 6.4 section 5.2.3.2 GAS access size */ + +#define ACPI_GAS_ACCESS_SIZE_UNDEFINED 0 + +#define ACPI_GAS_ACCESS_SIZE_BYTE_8 1 + +#define ACPI_GAS_ACCESS_SIZE_WORD_16 2 + +#define ACPI_GAS_ACCESS_SIZE_DWORD_32 3 + +#define ACPI_GAS_ACCESS_SIZE_QWORD_64 4 + +/* ACPI 6.4 section 5.2.9 values for Preferred_PM_Profile field of FADT */ + +#define ACPI_PM_PROFILE_UNSPECIFIED 0 + +#define ACPI_PM_PROFILE_DESKTOP 1 + +#define ACPI_PM_PROFILE_MOBILE 2 + +#define ACPI_PM_PROFILE_WORKSTATION 3 + +#define ACPI_PM_PROFILE_ENTERPRISE_SERVER 4 + +#define ACPI_PM_PROFILE_SOHO_SERVER 5 + +#define ACPI_PM_PROFILE_APPLIANCE_PC 6 + +#define ACPI_PM_PROFILE_PERFORMANCE_SERVER 7 + +#define ACPI_PM_PROFILE_TABLET 8 + +/* ACPI 6.4 section 5.2.9 + * Table 5.10 Fixed ACPI Description Table Fixed Feature Flags */ + +#define ACPI_FADT_FLAG_WBINVD (1 << 0) + +#define ACPI_FADT_FLAG_WBINVD_FLUSH (1 << 1) + +#define ACPI_FADT_FLAG_PROC_C1 (1 << 2) + +#define ACPI_FADT_FLAG_P_LVL2_UP (1 << 3) + +#define ACPI_FADT_FLAG_PWR_BUTTON (1 << 4) + +#define ACPI_FADT_FLAG_SLP_BUTTON (1 << 5) + +#define ACPI_FADT_FLAG_FIX_RTC (1 << 6) + +#define ACPI_FADT_FLAG_FIX_S4 (1 << 7) + +#define ACPI_FADT_FLAG_TMR_VAL_EXT (1 << 8) + +#define ACPI_FADT_FLAG_DCK_CAP (1 << 9) + +#define ACPI_FADT_FLAG_RESET_REG_SUP (1 << 10) + +#define ACPI_FADT_FLAG_SEALED_CASE (1 << 11) + +#define ACPI_FADT_FLAG_HEADLESS (1 << 12) + +#define ACPI_FADT_FLAG_CPU_SW_SLP (1 << 13) + +#define ACPI_FADT_FLAG_PCI_EXP_WAK (1 << 14) + +#define ACPI_FADT_FLAG_USE_PLATFORM_CLOCK (1 << 15) + +#define ACPI_FADT_FLAG_S4_RTC_STS_VALID (1 << 16) + +#define ACPI_FADT_FLAG_REMOTE_POWER_ON_CAPABLE (1 << 17) + +#define ACPI_FADT_FLAG_FORCE_APIC_CLUSTER_MODEL (1 << 18) + +#define ACPI_FADT_FLAG_FORCE_APIC_PHYS_DEST_MODE (1 << 19) + +#define ACPI_FADT_FLAG_HW_REDUCED_ACPI (1 << 20) + +#define ACPI_FADT_FLAG_LOW_POWER_S0_IDLE_CAPABLE (1 << 21) + +/* ACPI 6.4 section 5.2.9.3 IA-PC Boot Architecture Flags */ + +#define ACPI_IAPC_BOOT_ARCH_LEGACY_DEVICES (1 << 0) + +#define ACPI_IAPC_BOOT_ARCH_8042 (1 << 1) + +#define ACPI_IAPC_BOOT_ARCH_VGA_NOT_PRESENT (1 << 2) + +#define ACPI_IAPC_BOOT_ARCH_MSI_NOT_SUPPORTED (1 << 3) + +#define ACPI_IAPC_BOOT_ARCH_PCIE_ASPM_CONTROLS (1 << 4) + +#define ACPI_IAPC_BOOT_ARCH_CMOS_RTC_NOT_PRESENT (1 << 5) + +/* ACPI 6.4 section 5.2.9.4 ARM Architecture Boot Flags */ + +#define ACPI_ARM_BOOT_ARCH_PSCI_COMPLIANT (1 << 0) + +#define ACPI_ARM_BOOT_ARCH_PSCI_USE_HVC (1 << 1) + +/* ACPI 6.4 section 5.2.12 MADT flags */ + +#define ACPI_MADT_FLAG_PCAT_COMPAT (1 << 0) + +/* ACPI 6.4 section 5.2.12 MADT interrupt controller structure types */ + +#define ACPI_MADT_ENTRY_LOCAL_APIC 0 + +#define ACPI_MADT_ENTRY_IO_APIC 1 + +#define ACPI_MADT_ENTRY_SOURCE_OVERRIDE 2 + +#define ACPI_MADT_ENTRY_NMI_SOURCE 3 + +#define ACPI_MADT_ENTRY_LOCAL_APIC_NMI 4 + +#define ACPI_MADT_ENTRY_LOCAL_APIC_ADDR_OVERRIDE 5 + +#define ACPI_MADT_ENTRY_IO_SAPIC 6 + +#define ACPI_MADT_ENTRY_LOCAL_SAPIC 7 + +#define ACPI_MADT_ENTRY_PLATFORM_INTR_SOURCES 8 + +#define ACPI_MADT_ENTRY_LOCAL_X2APIC 9 + +#define ACPI_MADT_ENTRY_LOCAL_X2APIC_NMI 0xa + +#define ACPI_MADT_ENTRY_GIC_CPU_INTERFACE_GICC 0xb + +#define ACPI_MADT_ENTRY_GIC_DISTRIBUTOR_GICD 0xc + +#define ACPI_MADT_ENTRY_GIC_MSI_FRAME 0xd + +#define ACPI_MADT_ENTRY_GIC_REDISTRIBUTOR_GICR 0xe + +#define ACPI_MADT_ENTRY_GIC_INTR_TRANSLATION_ITS 0xf + +#define ACPI_MADT_ENTRY_MULTIPROCESSOR_WAKEUP 0x10 + +/* ACPI 6.4 section 5.2.12.2 MADT local APIC flags */ + +#define ACPI_MADT_LOCAL_APIC_FLAG_ENABLED (1 << 0) + +#define ACPI_MADT_LOCAL_APIC_FLAG_ONLINE_CAPABLE (1 << 1) + +/* ACPI 6.4 section 5.2.12.5 interrupt source override flags + * + * These flags are identical to the equivalent ones from version 1.4 of Intel's + * MultiProcessor Specification. + * + * These flags are described in table 5.26 of the ACPI specification. They are + * set in the flags field of the following structures in the MADT: + * - Interrupt Source Override Structure (type 2) + * - Non-Maskable Interrupt (NMI) Source Structure (type 3) + * - Local APIC NMI Structure (type 6) + * - Platform Interrupt Source Structure (type 8) + * - Local x2APIC NMI Structure (type 10/0xa) */ + +#define ACPI_MADT_MPS_INTI_FLAG_POLARITY (1 << 0) + +#define ACPI_MADT_MPS_INTI_TRIGGER_MODE_BUS (0 << 1) + +#define ACPI_MADT_MPS_INTI_TRIGGER_EDGE (1 << 1) + +#define ACPI_MADT_MPS_INTI_TRIGGER_LEVEL (3 << 1) + +#endif diff --git a/include/kernel/infrastructure/acpi/tables.h b/include/kernel/infrastructure/acpi/tables.h new file mode 100644 index 00000000..f614b33b --- /dev/null +++ b/include/kernel/infrastructure/acpi/tables.h @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2025 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_INFRASTRUCTURE_ACPI_TABLES_H +#define JINUE_KERNEL_INFRASTRUCTURE_ACPI_TABLES_H + +#include +#include +#include +#include + +/* ACPI 6.4 section 5.2.5.3 Root System Description Pointer (RSDP) Structure */ + +typedef PACKED_STRUCT { + char signature[8]; + uint8_t checksum; + char oemid[6]; + uint8_t revision; + uint32_t rsdt_address; + uint32_t length; + uint64_t xsdt_address; + uint8_t extended_checksum; + uint8_t reserved[3]; +} acpi_rsdp_t; + +/* ACPI 6.4 section 5.2.6 System Description Table Header */ + +typedef struct { + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oemid[6]; + char oem_table_id[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +} acpi_table_header_t; + +/* ACPI 6.4 section 5.2.3.2 Generic Address Structure (GAS) */ + +typedef PACKED_STRUCT { + uint8_t addr_space_id; + uint8_t reg_width; + uint8_t reg_offset; + uint8_t access_size; + uint64_t address; +} acpi_gas_t; + +/* ACPI 6.4 section 5.2.7 Root System Description Table (RSDT) and 5.2.8 + * Extended System Description Table (XSDT) */ + +typedef PACKED_STRUCT { + acpi_table_header_t header; + uint32_t entries[]; +} acpi_rsdt_t; + +/* ACPI 6.4 section 5.2.9 Fixed ACPI Description Table (FADT) */ + +typedef PACKED_STRUCT { + acpi_table_header_t header; + uint32_t firmware_ctrl; + uint32_t dsdt; + uint8_t reserved1; + uint8_t preferred_pm_profile; + uint16_t sci_int; + uint32_t sci_cmd; + uint8_t acpi_enable; + uint8_t acpi_disable; + uint8_t s4bios_req; + uint8_t pstate_cnt; + uint32_t pm1a_evt_blk; + uint32_t pm1b_evt_blk; + uint32_t pm1a_cnt_blk; + uint32_t pm1b_cnt_blk; + uint32_t pm2_cnt_blk; + uint32_t pm_tmr_blk; + uint32_t gpe0_blk; + uint32_t gpe1_blk; + uint8_t pm1_evt_len; + uint8_t pm1_cnt_len; + uint8_t pm2_cnt_len; + uint8_t pm_tmr_len; + uint8_t gpe0_blk_len; + uint8_t gpe1_blk_len; + uint8_t gpe1_base; + uint8_t cst_cnt; + uint16_t p_lvl2_lat; + uint16_t p_lvl3_lat; + uint16_t flush_size; + uint16_t flush_stride; + uint8_t duty_offset; + uint8_t duty_width; + uint8_t day_alrm; + uint8_t mon_alrm; + uint8_t century; + uint16_t iapc_boot_arch; + uint8_t reserved2; + uint32_t flags; + acpi_gas_t reset_reg; + uint8_t reset_value; + uint16_t arm_boot_arch; + uint8_t fadt_minor_version; + uint64_t x_firmware_ctrl; + uint64_t x_dsdt; + acpi_gas_t x_pm1a_evt_blk; + acpi_gas_t x_pm1b_evt_blk; + acpi_gas_t x_pm1a_cnt_blk; + acpi_gas_t x_pm1b_cnt_blk; + acpi_gas_t x_pm2_cnt_blk; + acpi_gas_t x_pm_tmr_blk; + acpi_gas_t x_gpe0_blk; + acpi_gas_t x_gpe1_blk; + acpi_gas_t sleep_control_reg; + acpi_gas_t sleep_status_reg; + uint64_t hypervisor_vendor_identity; +} acpi_fadt_t; + +/* ACPI 6.4 section 5.2.12 Multiple APIC Description Table (MADT) */ + +typedef PACKED_STRUCT { + acpi_table_header_t header; + uint32_t local_intr_controller_addr; + uint32_t flags; + char entries[]; +} acpi_madt_t; + +typedef PACKED_STRUCT { + uint8_t type; + uint8_t length; +} madt_entry_header_t; + +/* ACPI 6.4 section 5.2.12.2 Processor Local APIC Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint8_t processor_uid; + uint8_t apic_id; + uint32_t flags; +} acpi_madt_lapic_t; + +/* ACPI 6.4 section 5.2.12.3 I/O APIC Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint8_t apic_id; + uint8_t reserved; + uint32_t addr; + uint32_t intr_base; +} acpi_madt_ioapic_t; + +/* ACPI 6.4 section 5.2.12.5 Interrupt Source Override Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint8_t bus; + uint8_t source; + uint32_t global_sys_interrupt; + uint16_t flags; +} acpi_madt_src_override_t; + +/* ACPI 6.4 section 5.2.12.6 Non-Maskable Interrupt (NMI) Source Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint16_t flags; + uint32_t global_sys_interrupt; +} acpi_madt_nmi_source_t; + +/* ACPI 6.4 section 5.2.12.7 Local APIC NMI Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint8_t processor_uid; + uint16_t flags; + uint8_t lint_num; +} acpi_madt_lapic_nmi_t; + +/* ACPI 6.4 section 5.2.12.8 Local APIC Address Override Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint16_t reserved; + uint64_t lapic_addr; +} acpi_madt_lapic_addr_t; + +/* ACPI 6.4 section 5.2.12.12 Processor Local x2APIC Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint16_t reserved; + uint32_t apic_id; + uint32_t flags; + uint32_t processor_uid; +} acpi_madt_x2apic_t; + +/* ACPI 6.4 section 5.2.12.13. Local x2APIC NMI Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint16_t flags; + uint32_t processor_uid; + uint8_t lint_num; + uint8_t reserved[3]; +} acpi_madt_x2apic_nmi_t; + +/* ACPI 6.4 section 5.2.12.19 Multiprocessor Wakeup Structure */ + +typedef PACKED_STRUCT { + madt_entry_header_t header; + uint16_t mailbox_version; + uint32_t reserved; + uint64_t mailbox_addr; +} acpi_madt_wakeup_t; + +/* IA-PC HPET (High Precision Event Timers) Specification + * Section 3.2.4 "The ACPI 2.0 HPET Description Table (HPET)" + * + * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf + */ + +typedef PACKED_STRUCT { + acpi_table_header_t header; + uint32_t event_timer_block_id; + acpi_gas_t base_address; + uint8_t hpet_number; + uint16_t periodic_min_tick; + uint8_t prot_and_oem; +} acpi_hpet_t; + +#endif diff --git a/include/kernel/infrastructure/acpi/types.h b/include/kernel/infrastructure/acpi/types.h index 6ab908ca..ef2218bc 100644 --- a/include/kernel/infrastructure/acpi/types.h +++ b/include/kernel/infrastructure/acpi/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Philippe Aubertin. + * Copyright (C) 2024-2025 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,8 @@ #include +/* ACPI 6.4 section 15.1 INT 15H, E820H - Query System Address Map */ + typedef struct { uint64_t addr; uint64_t size; @@ -41,15 +43,8 @@ typedef struct { } acpi_addr_range_t; typedef struct { - char signature[8]; - uint8_t checksum; - char oemid[6]; - uint8_t revision; - uint32_t rsdt_address; - uint32_t length; - uint64_t xsdt_address; - uint8_t extended_checksum; - uint8_t reserved[3]; -} acpi_rsdp_t; + const char *signature; + const void **ptr; +} acpi_table_def_t; #endif diff --git a/include/kernel/infrastructure/compiler.h b/include/kernel/infrastructure/compiler.h index d71263c0..abca7519 100644 --- a/include/kernel/infrastructure/compiler.h +++ b/include/kernel/infrastructure/compiler.h @@ -38,4 +38,6 @@ #define NORETURN #endif +#define PACKED_STRUCT struct __attribute__((__packed__)) + #endif diff --git a/include/kernel/infrastructure/i686/drivers/acpi.h b/include/kernel/infrastructure/i686/drivers/acpi.h index 216ea95c..54c88fc3 100644 --- a/include/kernel/infrastructure/i686/drivers/acpi.h +++ b/include/kernel/infrastructure/i686/drivers/acpi.h @@ -32,11 +32,13 @@ #ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ACPI_H #define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ACPI_H -#include +#include #include -void acpi_init(void); +void find_acpi_rsdp(void); -uint32_t acpi_get_rsdp_paddr(void); +void init_acpi(void); + +kern_paddr_t acpi_get_rsdp_paddr(void); #endif diff --git a/userspace/testapp/tests/acpi.h b/include/kernel/infrastructure/i686/drivers/asm/bios.h similarity index 87% rename from userspace/testapp/tests/acpi.h rename to include/kernel/infrastructure/i686/drivers/asm/bios.h index bf7c69a0..5e83a241 100644 --- a/userspace/testapp/tests/acpi.h +++ b/include/kernel/infrastructure/i686/drivers/asm/bios.h @@ -1,22 +1,22 @@ /* - * Copyright (C) 2024 Philippe Aubertin. + * Copyright (C) 2024-2025 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * 3. Neither the name of the author nor the names of other contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -29,9 +29,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TESTAPP_TEST_ACPI_H_ -#define TESTAPP_TEST_ACPI_H_ +#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_BIOS_H +#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_BIOS_H -void run_acpi_test(void); +#define BIOS_BDA_EBDA_SEGMENT 0x40e #endif diff --git a/include/kernel/infrastructure/i686/pmap/nopae.h b/include/kernel/infrastructure/i686/pmap/nopae.h index 7e0e0a12..876b927b 100644 --- a/include/kernel/infrastructure/i686/pmap/nopae.h +++ b/include/kernel/infrastructure/i686/pmap/nopae.h @@ -44,9 +44,9 @@ void nopae_create_addr_space(addr_space_t *addr_space, pte_t *page_directory); void nopae_destroy_addr_space(addr_space_t *addr_space); -unsigned int nopae_page_table_offset_of(void *addr); +unsigned int nopae_page_table_offset_of(const void *addr); -unsigned int nopae_page_directory_offset_of(void *addr); +unsigned int nopae_page_directory_offset_of(const void *addr); pte_t *nopae_lookup_page_directory(addr_space_t *addr_space); diff --git a/include/kernel/infrastructure/i686/pmap/pae.h b/include/kernel/infrastructure/i686/pmap/pae.h index eb9a7d5f..6ae5180e 100644 --- a/include/kernel/infrastructure/i686/pmap/pae.h +++ b/include/kernel/infrastructure/i686/pmap/pae.h @@ -52,13 +52,13 @@ void pae_destroy_addr_space(addr_space_t *addr_space); pte_t *pae_lookup_page_directory( addr_space_t *addr_space, - void *addr, + const void *addr, bool create_as_needed, bool *reload_cr3); -unsigned int pae_page_table_offset_of(void *addr); +unsigned int pae_page_table_offset_of(const void *addr); -unsigned int pae_page_directory_offset_of(void *addr); +unsigned int pae_page_directory_offset_of(const void *addr); pte_t *pae_get_pte_with_offset(pte_t *pte, unsigned int offset); diff --git a/include/kernel/machine/pmap.h b/include/kernel/machine/pmap.h index d95bcbd4..4f39e94e 100644 --- a/include/kernel/machine/pmap.h +++ b/include/kernel/machine/pmap.h @@ -53,6 +53,6 @@ bool machine_clone_userspace_mapping( size_t length, int prot) ; -kern_paddr_t machine_lookup_kernel_paddr(void *addr); +kern_paddr_t machine_lookup_kernel_paddr(const void *addr); #endif diff --git a/include/kernel/types.h b/include/kernel/types.h index 19293f2c..14071b39 100644 --- a/include/kernel/types.h +++ b/include/kernel/types.h @@ -87,17 +87,10 @@ struct descriptor_t { uintptr_t cookie; }; -typedef enum { - PROCESS_ID_KERNEL, - PROCESS_ID_LOADER, - PROCESS_ID_USER -} process_id; - typedef struct { object_header_t header; addr_space_t addr_space; int running_threads_count; - process_id id; spinlock_t descriptors_lock; descriptor_t descriptors[JINUE_DESC_NUM]; } process_t; diff --git a/kernel/Makefile b/kernel/Makefile index 7f072c2c..e374f65e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -63,7 +63,6 @@ sources.kernel.c = \ application/interrupts/hardware.c \ application/interrupts/spurious.c \ application/interrupts/tick.c \ - application/syscalls/acpi.c \ application/syscalls/close.c \ application/syscalls/create_endpoint.c \ application/syscalls/create_process.c \ @@ -102,6 +101,7 @@ sources.kernel.c = \ domain/services/panic.c \ domain/services/scheduler.c \ domain/config.c \ + infrastructure/acpi/acpi.c \ infrastructure/i686/drivers/acpi.c \ infrastructure/i686/drivers/pic8259.c \ infrastructure/i686/drivers/pit8253.c \ diff --git a/kernel/application/kmain.c b/kernel/application/kmain.c index 7e93b575..673f7c44 100644 --- a/kernel/application/kmain.c +++ b/kernel/application/kmain.c @@ -91,7 +91,6 @@ void kmain(const char *cmdline) { panic("Could not create initial process."); } - process->id = PROCESS_ID_LOADER; process_switch_to(process); /* create user space loader main thread */ diff --git a/kernel/application/syscalls/acpi.c b/kernel/application/syscalls/acpi.c deleted file mode 100644 index 8660bd12..00000000 --- a/kernel/application/syscalls/acpi.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2024 Philippe Aubertin. - * All rights reserved. - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -int set_acpi(const jinue_acpi_tables_t *tables) { - process_t *process = get_current_process(); - - if(process->id != PROCESS_ID_LOADER) { - return -JINUE_ENOSYS; - } - - machine_set_acpi_tables(tables); - - return 0; -} diff --git a/kernel/domain/entities/process.c b/kernel/domain/entities/process.c index b4a11173..bde886b5 100644 --- a/kernel/domain/entities/process.c +++ b/kernel/domain/entities/process.c @@ -123,8 +123,7 @@ process_t *process_new(void) { process_t *process = slab_cache_alloc(&process_cache); if(process != NULL) { - process->running_threads_count = 0; - process->id = PROCESS_ID_USER; + process->running_threads_count = 0; initialize_descriptors(process); if(!machine_init_process(process)) { diff --git a/kernel/domain/services/mman.c b/kernel/domain/services/mman.c index edc2b596..ac826e3c 100644 --- a/kernel/domain/services/mman.c +++ b/kernel/domain/services/mman.c @@ -29,6 +29,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -37,11 +38,13 @@ #include static struct { - addr_t addr; - spinlock_t lock; + addr_t addr; + const void *latest_addr; + int latest_prot; } alloc_state = { - .addr = (addr_t)MAPPING_AREA_ADDR, - .lock = SPINLOCK_INITIALIZER + .addr = (addr_t)MAPPING_AREA_ADDR, + .latest_addr = NULL, + .latest_prot = JINUE_PROT_NONE, }; /** @@ -63,17 +66,14 @@ void *map_in_kernel(kern_paddr_t paddr, size_t size, int prot) { size += offset; - spin_lock(&alloc_state.lock); - if((addr_t)MAPPING_AREA_END - alloc_state.addr < size) { - spin_unlock(&alloc_state.lock); panic("No more space to map memory in kernel"); } addr_t start = alloc_state.addr; - alloc_state.addr = ALIGN_END_PTR(start + size, PAGE_SIZE); - - spin_unlock(&alloc_state.lock); + alloc_state.addr = ALIGN_END_PTR(start + size, PAGE_SIZE); + alloc_state.latest_addr = start + offset; + alloc_state.latest_prot = prot; addr_t map_addr = start; kern_paddr_t map_paddr = paddr - offset; @@ -92,3 +92,54 @@ void *map_in_kernel(kern_paddr_t paddr, size_t size, int prot) { return start + offset; } + +/** + * Expand the latest mapping established by map_in_kernel() + * + * @param size size of memory to map + */ +void resize_map_in_kernel(size_t size) { + const void *addr = alloc_state.latest_addr; + int prot = alloc_state.latest_prot; + + void *start = ALIGN_START_PTR(addr, PAGE_SIZE); + addr_t old_end = alloc_state.addr; + addr_t new_end = ALIGN_END_PTR((addr_t)addr + size, PAGE_SIZE); + + /* Unmap additional pages if the mapping is shrunk. */ + + for(addr_t page_addr = new_end; page_addr < (addr_t)old_end; page_addr += PAGE_SIZE) { + machine_unmap_kernel_page(page_addr); + } + + /* Map additional pages if the mapping is grown. */ + + kern_paddr_t paddr = machine_lookup_kernel_paddr(start) + (new_end - old_end); + + for(addr_t page_addr = old_end; page_addr < (addr_t)new_end; page_addr += PAGE_SIZE) { + machine_map_kernel_page(page_addr, paddr, prot); + ++paddr; + } + + alloc_state.addr = new_end; +} + +/** + * Undo (unmap) the latest mapping established by map_in_kernel() + * + * @param addr address returned by map_in_kernel() for the mapping being undone + */ +void undo_map_in_kernel(void) { + const void *addr = alloc_state.latest_addr; + + void *start = ALIGN_START_PTR(addr, PAGE_SIZE); + void *end = alloc_state.addr; + + for(addr_t page_addr = start; page_addr < (addr_t)end; page_addr += PAGE_SIZE) { + machine_unmap_kernel_page(page_addr); + } + + alloc_state.addr = start; + alloc_state.latest_addr = NULL; + alloc_state.latest_prot = JINUE_PROT_NONE; +} diff --git a/kernel/infrastructure/acpi/acpi.c b/kernel/infrastructure/acpi/acpi.c new file mode 100644 index 00000000..756ee8e4 --- /dev/null +++ b/kernel/infrastructure/acpi/acpi.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2025 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/** + * Verify the checksum of an ACPI data structure + * + * @param buffer pointer to ACPI data structure + * @param buflen size of ACPI data structure + * @return true for correct checksum, false for checksum mismatch + */ +static bool verify_checksum(const void *buffer, size_t buflen) { + uint8_t sum = 0; + + for(int idx = 0; idx < buflen; ++idx) { + sum += ((const uint8_t *)buffer)[idx]; + } + + return sum == 0; +} + +/** + * Validate the ACPI RSDP + * + * @param rsdp pointer to ACPI RSDP + * @return true is RSDP is valid, false otherwise + */ +bool verify_acpi_rsdp(const acpi_rsdp_t *rsdp) { + if(strncmp(rsdp->signature, ACPI_RSDP_SIGNATURE, sizeof(rsdp->signature)) != 0) { + return false; + } + + if(!verify_checksum(rsdp, ACPI_V1_RSDP_SIZE)) { + return false; + } + + if(rsdp->revision == ACPI_V1_REVISION) { + return true; + } + + if(rsdp->revision != ACPI_V2_REVISION) { + return false; + } + + return verify_checksum(rsdp, sizeof(acpi_rsdp_t)); +} + +/** + * Verify the checksum of an ACPI table header + * + * @param header mapped ACPI table header + * @param signature expected signature + * @return true if the signature matches, false otherwise + * + * */ +static bool verify_table_signature(const acpi_table_header_t *header, const char *signature) { + return strncmp(header->signature, signature, sizeof(header->signature)) == 0; +} + +/** + * Map ACPI RSDP + * + * We don't validate the contents (checksum, revision) because this has already + * been done by find_acpi_rsdp(). + * + * @param paddr physical memory address of ACPI RSDP + * @return pointer to mapped RSDP on success, NULL on error + * + * */ +static const acpi_rsdp_t *map_rsdp(uint64_t paddr) { + return map_in_kernel(paddr, sizeof(acpi_rsdp_t), JINUE_PROT_READ); +} + +/** + * Extend the existing mapping of a table header to the full table + * + * @param header mapped ACPI table header + * @return pointer to mapped table on success, NULL on error + * + * */ +static const void *map_table(const acpi_table_header_t *header) { + if(header->length < sizeof(acpi_table_header_t)) { + return NULL; + } + + if(header->length > ACPI_TABLE_MAX_SIZE) { + return NULL; + } + + resize_map_in_kernel(header->length); + + if(! verify_checksum(header, header->length)) { + return NULL; + } + + return header; +} + +/** + * Map ACPI table header + * + * @param paddr physical memory address of ACPI table header + * @return pointer to mapped header on success, NULL on error + * + * */ +static const acpi_table_header_t *map_header(kern_paddr_t paddr) { + return map_in_kernel(paddr, sizeof(acpi_table_header_t), JINUE_PROT_READ); +} + +/** Size of the fixed part of the RSDT, excluding the entries. */ +#define RSDT_BASE_SIZE ((size_t)(const char *)&(((const acpi_rsdt_t *)0)->entries)) + +/** + * Map the RSDT/XSDT + * + * @param rsdt_paddr physical memory address of RSDT/XSDT + * @param is_xsdt whether the table is a XSDT (true) or a RSDT (false) + * @return mapped RSDT/XSDT on success, NULL on error + * + * */ +static const acpi_rsdt_t *map_rsdt(uint64_t rsdt_paddr, bool is_xsdt) { + const acpi_table_header_t *header = map_header(rsdt_paddr); + + if(header == NULL) { + return NULL; + } + + const char *const signature = is_xsdt ? ACPI_XSDT_SIGNATURE : ACPI_RSDT_SIGNATURE; + + if(! verify_table_signature(header, signature)) { + undo_map_in_kernel(); + return NULL; + } + + if(header->length < RSDT_BASE_SIZE) { + undo_map_in_kernel(); + return NULL; + } + + const acpi_rsdt_t *rsdt = map_table(header); + + if(rsdt == NULL) { + undo_map_in_kernel(); + return NULL; + } + + return rsdt; +} + +/** + * Match a table to a table definition + * + * If there is a match, map the table and assign it. Otherwise, unmap the + * header. + * + * @param header table header + * @param table_defs table definitions array terminated by a NULL signature + */ +static void match_table(const acpi_table_header_t *header, const acpi_table_def_t *table_defs) { + for(int idx = 0; table_defs[idx].signature != NULL; ++idx) { + const acpi_table_def_t *def = &table_defs[idx]; + + if(*def->ptr == NULL && verify_table_signature(header, def->signature)) { + *def->ptr = map_table(header); + return; + } + } + + undo_map_in_kernel(); +} + +/** + * Process the entries of the mapped RSDT/XSDT to find relevant tables + * + * @param rsdt mapped RSDT/XSDT + * @param is_xsdt whether the table is a XSDT (true) or RSDT (false) + * @param table_defs table definitions array terminated by a NULL signature + * + * */ +static void process_rsdt(const acpi_rsdt_t *rsdt, bool is_xsdt, const acpi_table_def_t *table_defs) { + size_t entries = (rsdt->header.length - RSDT_BASE_SIZE) / sizeof(uint32_t); + + if(is_xsdt && entries % 2 != 0) { + --entries; + } + + for(int idx = 0; idx < entries; ++idx) { + /* x86 is little endian */ + uint64_t paddr = rsdt->entries[idx]; + + if(is_xsdt) { + paddr |= ((uint64_t)rsdt->entries[++idx]) << 32; + } + + const acpi_table_header_t *header = map_header(paddr); + + if(header == NULL) { + continue; + } + + match_table(header, table_defs); + } +} + +/** + * Map the ACPI tables in the kernel's mapping area + * + * @param rsdp_paddr physical memory address of the RSDP + * @param table_defs table definitions array terminated by a NULL signature + */ +void map_acpi_tables(kern_paddr_t rsdp_paddr, const acpi_table_def_t *table_defs) { + const acpi_rsdp_t *rsdp = map_rsdp(rsdp_paddr); + + uint64_t rsdt_paddr; + bool is_xsdt; + + if(rsdp->revision == ACPI_V1_REVISION) { + rsdt_paddr = rsdp->rsdt_address; + is_xsdt = false; + } else { + /* TODO handle the case where the address > 4GB and PAE is disabled. */ + rsdt_paddr = rsdp->xsdt_address; + is_xsdt = true; + } + + const acpi_rsdt_t *rsdt = map_rsdt(rsdt_paddr, is_xsdt); + + if(rsdt == NULL) { + return; + } + + process_rsdt(rsdt, is_xsdt, table_defs); +} diff --git a/kernel/infrastructure/i686/drivers/acpi.c b/kernel/infrastructure/i686/drivers/acpi.c index 9e069d2f..ae4364e9 100644 --- a/kernel/infrastructure/i686/drivers/acpi.c +++ b/kernel/infrastructure/i686/drivers/acpi.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Philippe Aubertin. + * Copyright (C) 2024-2025 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -29,65 +29,30 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include +#include #include -#include +#include +#include +#include #include #include -#include #include -static uint32_t rsdp_paddr = 0; - -/** - * Verify the checksum of an ACPI data structure - * - * @param buffer pointer to ACPI data structure - * @param buflen size of ACPI data structure - * @return true for correct checksum, false for checksum mismatch - */ -static bool verify_checksum(const void *buffer, size_t buflen) { - uint8_t sum = 0; - - for(int idx = 0; idx < buflen; ++idx) { - sum += ((const uint8_t *)buffer)[idx]; - } - - return sum == 0; -} - -/** - * Validate the ACPI RSDP - * - * At the stage of the boot process where this function is called, the memory - * where the RSDP is located is mapped 1:1 so a pointer to the RSDP has the - * same value as its physical address. - * - * @param rsdp pointer to ACPI RSDP - * @return true is RSDP is valid, false otherwise - */ -static bool check_rsdp(const acpi_rsdp_t *rsdp) { - const char *const signature = "RSD PTR "; - - if(strncmp(rsdp->signature, signature, strlen(signature)) != 0) { - return false; - } - - if(!verify_checksum(rsdp, ACPI_V1_RSDP_SIZE)) { - return false; - } - - if(rsdp->revision == ACPI_V1_REVISION) { - return true; - } +static kern_paddr_t rsdp_paddr = 0; - if(rsdp->revision != ACPI_V2_REVISION) { - return false; - } +static struct { + const acpi_fadt_t *fadt; + const acpi_madt_t *madt; + const acpi_hpet_t *hpet; +} acpi_tables; - return verify_checksum(rsdp, sizeof(acpi_rsdp_t)); -} +static const acpi_table_def_t table_defs[] = { + { .signature = ACPI_FADT_SIGNATURE, .ptr = (const void **)&acpi_tables.fadt }, + { .signature = ACPI_MADT_SIGNATURE, .ptr = (const void **)&acpi_tables.madt }, + { .signature = ACPI_HPET_SIGNATURE, .ptr = (const void **)&acpi_tables.hpet }, + { .signature = NULL, .ptr = NULL }, +}; /** * Find the RSDP in memory @@ -103,16 +68,19 @@ static const acpi_rsdp_t *find_rsdp(void) { const char *const end = (const char *)0x100000; for(const char *addr = start; addr < end; addr += 16) { + /* At the stage of the boot process where this function is called, the + * memory where the RSDP is located is mapped 1:1 so a pointer to the + * RSDP has the same value as its physical address. */ const acpi_rsdp_t *rsdp = (const acpi_rsdp_t *)addr; - if(check_rsdp(rsdp)) { + if(verify_acpi_rsdp(rsdp)) { return rsdp; } } const char *bottom = (const char *)0x10000; const char *top = (const char *)(0xa0000 - 1024); - const char *ebda = (const char *)(16 * (*(uint16_t *)ACPI_BDA_EBDA)); + const char *ebda = (const char *)(16 * (*(uint16_t *)BIOS_BDA_EBDA_SEGMENT)); if(ebda < bottom || ebda > top) { return NULL; @@ -121,7 +89,7 @@ static const acpi_rsdp_t *find_rsdp(void) { for(const char *addr = ebda; addr < ebda + 1024; addr += 16) { const acpi_rsdp_t *rsdp = (const acpi_rsdp_t *)addr; - if(check_rsdp(rsdp)) { + if(verify_acpi_rsdp(rsdp)) { return rsdp; } } @@ -130,29 +98,33 @@ static const acpi_rsdp_t *find_rsdp(void) { } /** - * Initialize ACPI + * Locate the ACPI RSDP in memory */ -void acpi_init(void) { +void find_acpi_rsdp(void) { /* At the stage of the boot process where this function is called, the memory * where the RSDP is located is mapped 1:1 so a pointer to the RSDP has the * same value as its physical address. */ - rsdp_paddr = (uint32_t)find_rsdp(); + rsdp_paddr = (kern_paddr_t)find_rsdp(); } /** - * Get the physical address of the ACPI RSDP - * - * @return physical address of RSDP if found, zero otherwise + * Initialize ACPI */ -uint32_t acpi_get_rsdp_paddr(void) { - return rsdp_paddr; +void init_acpi(void) { + memset(&acpi_tables, 0, sizeof(acpi_tables)); + + if(rsdp_paddr == 0) { + return; + } + + map_acpi_tables(rsdp_paddr, table_defs); } /** - * Process the ACPI tables mapped by user space + * Get the physical address of the ACPI RSDP * - * @param tables structure with pointers to ACPI tables + * @return physical address of RSDP if found, zero otherwise */ -void machine_set_acpi_tables(const jinue_acpi_tables_t *tables) { - /* TODO implement this */ +kern_paddr_t acpi_get_rsdp_paddr(void) { + return rsdp_paddr; } diff --git a/kernel/infrastructure/i686/init.c b/kernel/infrastructure/i686/init.c index 76548cd6..6cae2c83 100644 --- a/kernel/infrastructure/i686/init.c +++ b/kernel/infrastructure/i686/init.c @@ -332,7 +332,7 @@ void machine_init(const config_t *config) { /* We must look for the ACPI RDSP while the relevant memory is still * identity mapped before we swith to the initial address space. */ - acpi_init(); + find_acpi_rsdp(); /* This must be done before we switch to the new address space because only * the boot allocator can allocate multiple consecutive pages. */ @@ -358,6 +358,8 @@ void machine_init(const config_t *config) { boot_alloc_reinit_at_klimit(&boot_alloc); initialize_page_allocator(&boot_alloc); + init_acpi(); + /* create slab cache to allocate PDPTs * * This must be done after the global page allocator has been initialized diff --git a/kernel/infrastructure/i686/pmap/nopae.c b/kernel/infrastructure/i686/pmap/nopae.c index a49227fb..8ee2fb29 100644 --- a/kernel/infrastructure/i686/pmap/nopae.c +++ b/kernel/infrastructure/i686/pmap/nopae.c @@ -69,7 +69,7 @@ void nopae_destroy_addr_space(addr_space_t *addr_space) { * @param addr virtual address * @return entry offset of address within page table */ -unsigned int nopae_page_table_offset_of(void *addr) { +unsigned int nopae_page_table_offset_of(const void *addr) { return PAGE_TABLE_OFFSET_OF(addr); } @@ -79,7 +79,7 @@ unsigned int nopae_page_table_offset_of(void *addr) { * @param addr virtual address * @return entry offset of address within page directory */ -unsigned int nopae_page_directory_offset_of(void *addr) { +unsigned int nopae_page_directory_offset_of(const void *addr) { return PAGE_DIRECTORY_OFFSET_OF(addr); } diff --git a/kernel/infrastructure/i686/pmap/pae.c b/kernel/infrastructure/i686/pmap/pae.c index 1be008da..3e136754 100644 --- a/kernel/infrastructure/i686/pmap/pae.c +++ b/kernel/infrastructure/i686/pmap/pae.c @@ -78,7 +78,7 @@ static uint64_t page_frame_number_mask; /** Get the Page Directory Pointer Table (PDPT) index of a virtual address * @param addr virtual address * */ -static inline unsigned int pdpt_offset_of(void *addr) { +static inline unsigned int pdpt_offset_of(const void *addr) { return (uintptr_t)addr >> (32 - PDPT_BITS); } @@ -438,7 +438,7 @@ void pae_destroy_addr_space(addr_space_t *addr_space) { */ pte_t *pae_lookup_page_directory( addr_space_t *addr_space, - void *addr, + const void *addr, bool create_as_needed, bool *reload_cr3) { @@ -484,7 +484,7 @@ pte_t *pae_lookup_page_directory( * @param addr virtual address * @return entry offset of address within page table */ -unsigned int pae_page_table_offset_of(void *addr) { +unsigned int pae_page_table_offset_of(const void *addr) { return PAGE_TABLE_OFFSET_OF(addr); } @@ -494,7 +494,7 @@ unsigned int pae_page_table_offset_of(void *addr) { * @param addr virtual address * @return entry offset of address within page directory */ -unsigned int pae_page_directory_offset_of(void *addr) { +unsigned int pae_page_directory_offset_of(const void *addr) { return PAGE_DIRECTORY_OFFSET_OF(addr); } diff --git a/kernel/infrastructure/i686/pmap/pmap.c b/kernel/infrastructure/i686/pmap/pmap.c index aa94b96b..74eed7b0 100644 --- a/kernel/infrastructure/i686/pmap/pmap.c +++ b/kernel/infrastructure/i686/pmap/pmap.c @@ -125,7 +125,7 @@ static inline const pte_t *get_pte_with_offset_const( * @param addr virtual address * @return entry offset of address within page table */ -static unsigned int page_table_offset_of(void *addr) { +static unsigned int page_table_offset_of(const void *addr) { if(pgtable_format_pae) { return pae_page_table_offset_of(addr); } @@ -140,7 +140,7 @@ static unsigned int page_table_offset_of(void *addr) { * @param addr virtual address * @return entry offset of address within page directory */ -static unsigned int page_directory_offset_of(void *addr) { +static unsigned int page_directory_offset_of(const void *addr) { if(pgtable_format_pae) { return pae_page_directory_offset_of(addr); } @@ -537,7 +537,7 @@ void pmap_switch_addr_space(addr_space_t *addr_space) { static pte_t *pmap_lookup_page_table( addr_space_t *addr_space, - void *addr, + const void *addr, bool create_as_needed, bool *reload_cr3) { @@ -617,7 +617,7 @@ static pte_t *pmap_lookup_page_table( * */ static pte_t *lookup_page_table_entry( addr_space_t *addr_space, - void *addr, + const void *addr, bool create_as_needed, bool *reload_cr3) { @@ -779,6 +779,7 @@ static bool map_page( * @param prot protections flags */ void machine_map_kernel_page(void *vaddr, kern_paddr_t paddr, int prot) { + /* TODO the kern_paddr_t type prevents this function from supporting addresses above 4GB. */ assert(is_kernel_pointer(vaddr)); map_page(NULL, vaddr, paddr, map_page_access_flags(prot) | X86_PTE_GLOBAL); } @@ -936,7 +937,7 @@ bool machine_clone_userspace_mapping( * @param addr virtual address of kernel page * @return physical address of page frame */ -kern_paddr_t machine_lookup_kernel_paddr(void *addr) { +kern_paddr_t machine_lookup_kernel_paddr(const void *addr) { assert( is_kernel_pointer(addr) ); pte_t *pte = lookup_page_table_entry(NULL, addr, false, NULL); diff --git a/kernel/interface/syscalls.c b/kernel/interface/syscalls.c index 35b0ea6d..2148bf4e 100644 --- a/kernel/interface/syscalls.c +++ b/kernel/interface/syscalls.c @@ -554,20 +554,6 @@ static void sys_reply_error(jinue_syscall_args_t *args) { set_return_value_or_error(args, retval); } -static void sys_acpi(jinue_syscall_args_t *args) { - const jinue_acpi_tables_t *userspace_tables = (const void *)args->arg1; - - if(! check_userspace_buffer(userspace_tables, sizeof(jinue_acpi_tables_t))) { - set_error(args, JINUE_EINVAL); - return; - } - - const jinue_acpi_tables_t tables = *userspace_tables; - - int retval = set_acpi(&tables); - set_return_value_or_error(args, retval); -} - /** * System call dispatching function * @@ -645,9 +631,6 @@ void handle_syscall(jinue_syscall_args_t *args) { case JINUE_SYS_REPLY_ERROR: sys_reply_error(args); break; - case JINUE_SYS_SET_ACPI: - sys_acpi(args); - break; default: sys_nosys(args); } diff --git a/tests/Makefile b/tests/Makefile index 130a33ae..c3ae361f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -37,7 +37,6 @@ run_log = run-test.log deps = $(kernel_img) $(testapp_initrd) tests = \ - test_acpi \ test_detect_qemu \ test_boot_nopae \ test_boot_pae \ diff --git a/tests/test_acpi.sh b/tests/test_acpi.sh deleted file mode 100755 index d57aa9c0..00000000 --- a/tests/test_acpi.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -# Copyright (C) 2024 Philippe Aubertin. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the author nor the names of other contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -CMDLINE="RUN_TEST_ACPI=1" - -run - -echo "* Check the ACPI test ran" -grep -F "Running ACPI test" $LOG || fail - -check_no_error - -check_no_warning - -# Only the user space loader is allowed to call this system call -echo "* Check the SET_ACPI system call fails with JINUE_ENOSYS" -grep -F "expected: jinue_set_acpi() set errno to: function not supported" $LOG || fail - -check_reboot diff --git a/userspace/lib/jinue/syscalls.c b/userspace/lib/jinue/syscalls.c index 2c96328f..c9e6c9dd 100644 --- a/userspace/lib/jinue/syscalls.c +++ b/userspace/lib/jinue/syscalls.c @@ -336,14 +336,3 @@ int jinue_reply_error(uintptr_t errcode, int *perrno) { return call_with_usual_convention(&args, perrno); } - -int jinue_set_acpi(jinue_acpi_tables_t *tables, int *perrno) { - jinue_syscall_args_t args; - - args.arg0 = JINUE_SYS_SET_ACPI; - args.arg1 = (uintptr_t)tables; - args.arg2 = 0; - args.arg3 = 0; - - return call_with_usual_convention(&args, perrno); -} diff --git a/userspace/loader/Makefile b/userspace/loader/Makefile index ff112b62..ef48d1f7 100644 --- a/userspace/loader/Makefile +++ b/userspace/loader/Makefile @@ -31,7 +31,6 @@ jinue_root = ../.. include $(jinue_root)/header.mk sources.c = \ - acpi/acpi.c \ archives/alloc.c \ archives/tar.c \ binfmt/elf.c \ diff --git a/userspace/loader/acpi/acpi.c b/userspace/loader/acpi/acpi.c deleted file mode 100644 index a3ad98c9..00000000 --- a/userspace/loader/acpi/acpi.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2024 Philippe Aubertin. - * All rights reserved. - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../debug.h" -#include "acpi.h" - -/** - * Verify the checksum of an ACPI data structure - * - * @param buffer pointer to ACPI data structure - * @param buflen size of ACPI data structure - * @return true for correct checksum, false for checksum mismatch - * - * */ -static bool verify_checksum(const void *buffer, size_t buflen) { - uint8_t sum = 0; - - for(int idx = 0; idx < buflen; ++idx) { - sum += ((const uint8_t *)buffer)[idx]; - } - - return sum == 0; -} - -/** - * Verify the checksum of an ACPI table header - * - * @param header mapped ACPI table header - * @param signature expected signature - * @return true if the signature matches, false otherwise - * - * */ -static bool verify_signature(const acpi_header_t *header, const char *signature) { - return strncmp(header->signature, signature, sizeof(header->signature)) == 0; -} - -/** - * Map an ACPI data structure - * - * @param paddr physical memory address of data structure - * @param size size of data structure - * @return pointer to mapped data on success, NULL on error - * - * */ -static const void *map_size(uint64_t paddr, size_t size) { - size_t offset = paddr % JINUE_PAGE_SIZE; - - size += offset; - paddr -= offset; - - void *mapped = mmap(NULL, size, PROT_READ, MAP_SHARED, 0, paddr); - - if(mapped == MAP_FAILED) { - return NULL; - } - - return (const char *)mapped + offset; -} - -/** - * Map ACPI RSDP - * - * We don't validate the contents (checksum, revision) because we assume the - * kernel has done so before setting the address in the auxiliary vector. - * - * @param paddr physical memory address of ACPI RSDP - * @return pointer to mapped RSDP on success, NULL on error - * - * */ -static const acpi_rsdp_t *map_rsdp(uint64_t paddr) { - const acpi_rsdp_t *rsdp = map_size(paddr, ACPI_V1_RSDP_SIZE); - - if(rsdp == NULL || rsdp->revision == ACPI_V1_REVISION) { - return rsdp; - } - - size_t offset = paddr % JINUE_PAGE_SIZE; - - if(JINUE_PAGE_SIZE - offset >= sizeof(acpi_rsdp_t)) { - return rsdp; - } - - /* Here, we rely on the fact that our implementation of mmap() allocates - * virtual memory sequentially to simply extend the existing mapping. */ - size_t extsize = sizeof(acpi_rsdp_t) - (JINUE_PAGE_SIZE - offset); - const void *extension = map_size(paddr - offset + JINUE_PAGE_SIZE, extsize); - - if(extension == NULL) { - return NULL; - } - - return rsdp; -} - -/** - * Map ACPI table header - * - * @param paddr physical memory address of ACPI table header - * @return pointer to mapped header on success, NULL on error - * - * */ -static const acpi_header_t *map_header(uint64_t paddr) { - return map_size(paddr, sizeof(acpi_header_t)); -} - -/** - * Extend the existing mapping of a table header to the full table - * - * This function relies on the fact that our implementation of mmap() allocates - * virtual memory sequentially to extend an existing mapping. It assumes that - * mmap() wasn't called since the call to map_header() that mapped the table - * header passed as agument. - * - * @param paddr physical memory address of the ACPI table - * @param header mapped ACPI table header - * @param name table name, for log messages - * @return pointer to mapped table on success, NULL on error - * - * */ -static const void *map_table(uint64_t paddr, const acpi_header_t *header, const char *name) { - if(header->length < sizeof(acpi_header_t)) { - jinue_warning("warning: value of ACPI table length member is too small (%" PRIu32 ", %s)", name); - return NULL; - } - - if(header->length > ACPI_TABLE_MAX_SIZE) { - jinue_warning("warning: value of ACPI table length member is too large (%" PRIu32 ", %s)", name); - return NULL; - } - - size_t offset = paddr % JINUE_PAGE_SIZE; - size_t allocated = JINUE_PAGE_SIZE - offset; - - if(allocated < sizeof(acpi_header_t)) { - allocated += JINUE_PAGE_SIZE; - } - - if(header->length > allocated) { - /* Here, we rely on the fact that our implementation of mmap() allocates - * virtual memory sequentially to simply extend the existing mapping. */ - size_t extsize = header->length - allocated; - const void *extension = map_size(paddr + allocated, extsize); - - if(extension == NULL) { - jinue_warning("warning: failed mapping ACPI table (%s)", name); - return NULL; - } - } - - if(! verify_checksum(header, header->length)) { - jinue_warning("warning: ACPI table checksum mismatch (%s)", name); - return NULL; - } - - return header; -} - -/* Size of the fixed part of the RSDT, excluding hte entries. */ -#define RSDT_BASE_SIZE ((size_t)(const char *)&(((const acpi_rsdt_t *)0)->entries)) - -/** - * Map the RSDT/XSDT - * - * @param paddr physical memory address of RSDT/XSDT - * @param is_xsdt whether the table is a XSDT (true) or a RSDT (false) - * @return mapped RSDT/XSDT on success, NULL on error - * - * */ -static const acpi_rsdt_t *map_rsdt(uint64_t paddr, bool is_xsdt) { - const acpi_header_t *header = map_header(paddr); - - if(header == NULL) { - return NULL; - } - - const char *const signature = is_xsdt ? "XSDT" : "RSDT"; - - if(! verify_signature(header, signature)) { - jinue_warning("warning: signature mismatch for ACPI %s", signature); - return NULL; - } - - if(header->length < RSDT_BASE_SIZE) { - jinue_warning("warning: ACPI %s table is too small", signature); - return NULL; - } - - return map_table(paddr, header, signature); -} - -/** - * Process the entries of the mapped RSDT/XSDT to find relevant tables - * - * @param tables tables structure (output) - * @param rsdt mapped RSDT/XSDT - * @param is_xsdt whether the table is a XSDT (true) or RSDT (false) - * - * */ -void process_rsdt(jinue_acpi_tables_t *tables, const acpi_rsdt_t *rsdt, bool is_xsdt) { - size_t entries = (rsdt->length - RSDT_BASE_SIZE) / sizeof(uint32_t); - - if(is_xsdt && entries % 2 != 0) { - --entries; - } - - for(int idx = 0; idx < entries; ++idx) { - /* x86 is little endian */ - uint64_t paddr = rsdt->entries[idx]; - - if(is_xsdt) { - paddr |= ((uint64_t)rsdt->entries[++idx]) << 32; - } - - const acpi_header_t *header = map_header(paddr); - - if(header == NULL) { - continue; - } - - const char *signature = "FACP"; - - if(verify_signature(header, signature) && tables->fadt == NULL) { - tables->fadt = map_table(paddr, header, "FADT"); - } - - signature = "APIC"; - - if(verify_signature(header, signature) && tables->madt == NULL) { - tables->madt = map_table(paddr, header, "MADT"); - } - } -} - -/** - * Map the RSDT/XSDT and then iterate over its entries to find relevant tables - * - * @param tables tables structure (output) - * @param paddr physical memory address of RSDT/XSDT - * @param is_xsdt whether the table is a XSDT (true) or RSDT (false) - * - * */ -static void load_rsdt(jinue_acpi_tables_t *tables, uint64_t paddr, bool is_xsdt) { - const acpi_rsdt_t *rsdt = map_rsdt(paddr, is_xsdt); - - if(rsdt == NULL) { - return; - } - - tables->rsdt = rsdt; - process_rsdt(tables, rsdt, is_xsdt); -} - -/** - * Map the RSDP/XSDT and then call load_rsdt() with the RSDT/XSDT address - * - * @param tables tables structure (output) - * @param rsdp_paddr physical memory address of the RSDP - * - * */ -static void load_rsdp(jinue_acpi_tables_t *tables, uint32_t rsdp_paddr) { - const acpi_rsdp_t *rsdp = map_rsdp(rsdp_paddr); - - if(rsdp == NULL) { - return; - } - - uint64_t rsdt_paddr; - bool is_xsdt; - - if(rsdp->revision == ACPI_V1_REVISION) { - rsdt_paddr = rsdp->rsdt_address; - is_xsdt = false; - } else { - /* TODO handle the case where the address > 4GB and PAE is disabled. */ - rsdt_paddr = rsdp->xsdt_address; - is_xsdt = true; - } - - load_rsdt(tables, rsdt_paddr, is_xsdt); -} - -/** - * Map relevant ACPI tables and report to kernel - * - * Map the ACPI tables needed by the kernel in memory, set the pointers to them - * in a tables structure (jinue_acpi_tables_t) and call the kernel with this - * information. - * - * @return EXIT_SUCCESS on success, EXIT_FAILURE on error - * - * */ -int load_acpi_tables(void) { - jinue_acpi_tables_t tables; - tables.rsdt = NULL; - tables.fadt = NULL; - tables.madt = NULL; - - uint32_t rsdp_paddr = getauxval(JINUE_AT_ACPI_RSDP); - - /* If the kernel set this auxiliary vector to zero, it knows the RSDP is - * nowhere to be found and doesn't expect to be called. Since this is - * expected, it is not a failure (i.e. we return EXIT_SUCCESS). - * - * In any other situation, the kernel does expect to be called with our - * best effort to map the tables so it can complete its initialization and - * it will deal with NULL entries in the tables structure if need be. */ - if(rsdp_paddr == 0) { - return EXIT_SUCCESS; - } - - load_rsdp(&tables, rsdp_paddr); - - dump_acpi_tables(&tables); - - int status = jinue_set_acpi(&tables, &errno); - - if(status != 0) { - jinue_error("error: ACPI call failed: %s", strerror(errno)); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/userspace/loader/acpi/acpi.h b/userspace/loader/acpi/acpi.h deleted file mode 100644 index b820b9ef..00000000 --- a/userspace/loader/acpi/acpi.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2024 Philippe Aubertin. - * All rights reserved. - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LOADER_ACPI_ACPI_H_ -#define LOADER_ACPI_ACPI_H_ - -#include - -#define ACPI_V1_REVISION 0 - -#define ACPI_V1_RSDP_SIZE 20 - -/* Arbitrary value expected to be large enough to accomodate any real table - * while ensuring we don't create arbitrary large mappings because of garbage - * data in length members. */ -#define ACPI_TABLE_MAX_SIZE (32 * 1024) - -typedef struct { - char signature[8]; - uint8_t checksum; - char oemid[6]; - uint8_t revision; - uint32_t rsdt_address; - uint32_t length; - uint64_t xsdt_address; - uint8_t extended_checksum; - uint8_t reserved[3]; -} acpi_rsdp_t; - -typedef struct { - char signature[4]; - uint32_t length; - uint8_t revision; - uint8_t checksum; - /* There are more fields but we are not interested in them. */ -} acpi_header_t; - -typedef struct { - char signature[4]; - uint32_t length; - uint8_t revision; - uint8_t checksum; - char oemid[6]; - char oem_table_id[8]; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; - uint32_t entries[]; -} acpi_rsdt_t; - -int load_acpi_tables(void); - -#endif diff --git a/userspace/loader/debug.c b/userspace/loader/debug.c index 08fa7efc..10e3f418 100644 --- a/userspace/loader/debug.c +++ b/userspace/loader/debug.c @@ -29,9 +29,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include -#include "acpi/acpi.h" #include "debug.h" #include "utils.h" @@ -115,27 +115,3 @@ void dump_ramdisk(const jinue_dirent_t *root) { dirent = jinue_dirent_get_next(dirent); } } - -static void dump_table(const acpi_header_t *table, const char *name) { - jinue_info(" %s:", name); - jinue_info(" address: %#p", table); - - if(table != NULL) { - jinue_info(" revision: %" PRIu8, table->revision); - jinue_info(" length: %" PRIu32, table->length); - } -} - -void dump_acpi_tables(const jinue_acpi_tables_t *tables) { - if(! bool_getenv("DEBUG_DUMP_ACPI_TABLES")) { - return; - } - - const acpi_header_t *rsdt = tables->rsdt; - const char *rsdt_name = (rsdt != NULL && rsdt->signature[0] == 'X') ? "XSDT" : "RSDT"; - - jinue_info("ACPI tables:"); - dump_table(rsdt, rsdt_name); - dump_table(tables->fadt, "FADT"); - dump_table(tables->madt, "MADT"); -} diff --git a/userspace/loader/debug.h b/userspace/loader/debug.h index 49f74887..a871bb4b 100644 --- a/userspace/loader/debug.h +++ b/userspace/loader/debug.h @@ -32,11 +32,8 @@ #ifndef LOADER_DEBUG_H_ #define LOADER_DEBUG_H_ -#include #include void dump_ramdisk(const jinue_dirent_t *root); -void dump_acpi_tables(const jinue_acpi_tables_t *tables); - #endif diff --git a/userspace/loader/loader.c b/userspace/loader/loader.c index a1f4df13..833bc7e2 100644 --- a/userspace/loader/loader.c +++ b/userspace/loader/loader.c @@ -35,7 +35,6 @@ #include #include #include -#include "acpi/acpi.h" #include "binfmt/elf.h" #include "core/meminfo.h" #include "core/server.h" @@ -199,12 +198,6 @@ static int start_initial_thread(thread_params_t *thread_params) { int main(int argc, char *argv[]) { jinue_info("Jinue user space loader (%s) started.", argv[0]); - int status = load_acpi_tables(); - - if(status != EXIT_SUCCESS) { - return status; - } - initialize_meminfo(); char map_buffer[MAP_BUFFER_SIZE]; @@ -216,7 +209,7 @@ int main(int argc, char *argv[]) { ramdisk_t ramdisk; - status = map_ramdisk(&ramdisk, map); + int status = map_ramdisk(&ramdisk, map); if(status != EXIT_SUCCESS) { return status; diff --git a/userspace/testapp/Makefile b/userspace/testapp/Makefile index 873dde6c..af073dd4 100644 --- a/userspace/testapp/Makefile +++ b/userspace/testapp/Makefile @@ -30,7 +30,7 @@ jinue_root = ../.. include $(jinue_root)/header.mk -sources.c = tests/acpi.c tests/ipc.c debug.c testapp.c utils.c +sources.c = tests/ipc.c debug.c testapp.c utils.c testapp = testapp stripped = $(testapp)-stripped temp_ramdisk_fs = ramdisk-tmp diff --git a/userspace/testapp/testapp.c b/userspace/testapp/testapp.c index 458b1c33..3c0e284a 100644 --- a/userspace/testapp/testapp.c +++ b/userspace/testapp/testapp.c @@ -37,7 +37,6 @@ #include #include #include -#include "tests/acpi.h" #include "tests/ipc.h" #include "debug.h" #include "utils.h" @@ -62,7 +61,6 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - run_acpi_test(); run_ipc_test(); if(bool_getenv("DEBUG_DO_REBOOT")) { diff --git a/userspace/testapp/tests/acpi.c b/userspace/testapp/tests/acpi.c deleted file mode 100644 index d1219d83..00000000 --- a/userspace/testapp/tests/acpi.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2024 Philippe Aubertin. - * All rights reserved. - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include "../utils.h" -#include "acpi.h" - -void run_acpi_test(void) { - if(! bool_getenv("RUN_TEST_ACPI")) { - return; - } - - jinue_info("Running ACPI test..."); - - jinue_acpi_tables_t tables; - tables.rsdt = NULL; - tables.fadt = NULL; - tables.madt = NULL; - - int status = jinue_set_acpi(&tables, &errno); - - if(status >= 0) { - jinue_error("error: jinue_set_acpi() unexpectedly succeeded"); - return; - } - - if(errno != JINUE_ENOSYS) { - jinue_error("error: jinue_set_acpi() failed: %s.", strerror(errno)); - return; - } - - jinue_info("expected: jinue_set_acpi() set errno to: %s.", strerror(errno)); -}