From: Minep Date: Tue, 28 Jun 2022 17:51:27 +0000 (+0100) Subject: feat: vmm_vmap/ioremap/iounmap to make MMIO more flexible and easy X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/03944e7734220bf7e7aa7b7113bcbdf9c22808a5?hp=38965e3e83ba1b03c9c9a0f14cce85c1d0cd8fd8 feat: vmm_vmap/ioremap/iounmap to make MMIO more flexible and easy fix: flush the screen when fault occurs. chore: update the memory map accordingly. --- diff --git a/docs/img/lunaix-os-mem.png b/docs/img/lunaix-os-mem.png index 3301d80..75c82a4 100644 Binary files a/docs/img/lunaix-os-mem.png and b/docs/img/lunaix-os-mem.png differ diff --git a/lunaix-os/hal/apic.c b/lunaix-os/hal/apic.c index 289dd56..0099525 100644 --- a/lunaix-os/hal/apic.c +++ b/lunaix-os/hal/apic.c @@ -15,11 +15,14 @@ #include +#include #include #include LOG_MODULE("APIC") +static volatile uintptr_t _apic_base; + void apic_setup_lvts(); @@ -36,10 +39,12 @@ apic_init() // As we are going to use APIC, disable the old 8259 PIC pic_disable(); + _apic_base = ioremap(__APIC_BASE_PADDR, 4096); + // Hardware enable the APIC // By setting bit 11 of IA32_APIC_BASE register - // Note: After this point, you can't disable then re-enable it until a reset - // (i.e., reboot) + // Note: After this point, you can't disable then re-enable it until a + // reset (i.e., reboot) asm volatile("movl %0, %%ecx\n" "rdmsr\n" "orl %1, %%eax\n" @@ -91,3 +96,21 @@ apic_setup_lvts() apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1); apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV)); } + +void +apic_done_servicing() +{ + *(unsigned int*)(_apic_base + APIC_EOI) = 0; +} + +unsigned int +apic_read_reg(unsigned int reg) +{ + return *(unsigned int*)(_apic_base + (reg)); +} + +void +apic_write_reg(unsigned int reg, unsigned int val) +{ + *(unsigned int*)(_apic_base + reg) = val; +} \ No newline at end of file diff --git a/lunaix-os/hal/ioapic.c b/lunaix-os/hal/ioapic.c index dbe9106..5a03eff 100644 --- a/lunaix-os/hal/ioapic.c +++ b/lunaix-os/hal/ioapic.c @@ -2,9 +2,12 @@ #include #include #include +#include -#define IOAPIC_REG_SEL *((volatile uint32_t*)(MMIO_IOAPIC + IOAPIC_IOREGSEL)) -#define IOAPIC_REG_WIN *((volatile uint32_t*)(MMIO_IOAPIC + IOAPIC_IOWIN)) +#define IOAPIC_REG_SEL *((volatile uint32_t*)(_ioapic_base + IOAPIC_IOREGSEL)) +#define IOAPIC_REG_WIN *((volatile uint32_t*)(_ioapic_base + IOAPIC_IOWIN)) + +static volatile uintptr_t _ioapic_base; uint8_t ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq); @@ -16,6 +19,8 @@ ioapic_init() acpi_context* acpi_ctx = acpi_get_context(); + _ioapic_base = ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096); + // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic // (Remarks IRQ 8 is pin INTIN8) // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ diff --git a/lunaix-os/includes/hal/apic.h b/lunaix-os/includes/hal/apic.h index f96799c..a4ac95f 100644 --- a/lunaix-os/includes/hal/apic.h +++ b/lunaix-os/includes/hal/apic.h @@ -66,8 +66,11 @@ #define APIC_PRIORITY(cls, subcls) (((cls) << 4) | (subcls)) -#define apic_read_reg(reg) (*(uint32_t*)(MMIO_APIC + (reg))) -#define apic_write_reg(reg, val) (*(uint32_t*)(MMIO_APIC + (reg)) = (val)) +unsigned int +apic_read_reg(unsigned int reg); + +void +apic_write_reg(unsigned int reg, unsigned int val); void apic_init(); @@ -77,10 +80,7 @@ apic_init(); * This will issue a write action to EOI register. * */ -inline static void -apic_done_servicing() -{ - apic_write_reg(APIC_EOI, 0); -} +void +apic_done_servicing(); #endif /* __LUNAIX_APIC_H */ diff --git a/lunaix-os/includes/lunaix/common.h b/lunaix-os/includes/lunaix/common.h index fe0c0bc..7fdf0b3 100644 --- a/lunaix-os/includes/lunaix/common.h +++ b/lunaix-os/includes/lunaix/common.h @@ -20,10 +20,6 @@ #define VGA_BUFFER_PADDR 0xB8000 #define VGA_BUFFER_SIZE 4096 -#define MMIO_BASE (VGA_BUFFER_VADDR + MEM_4MB) -#define MMIO_APIC (MMIO_BASE) -#define MMIO_IOAPIC (MMIO_BASE + 4096) - #define KCODE_SEG 0x08 #define KDATA_SEG 0x10 #define UCODE_SEG 0x1B diff --git a/lunaix-os/includes/lunaix/lxconsole.h b/lunaix-os/includes/lunaix/lxconsole.h index ba8c907..02e2198 100644 --- a/lunaix-os/includes/lunaix/lxconsole.h +++ b/lunaix-os/includes/lunaix/lxconsole.h @@ -17,7 +17,7 @@ void console_view_down(); void -console_flush(void* arg); +console_flush(); void console_start_flushing(); diff --git a/lunaix-os/includes/lunaix/mm/mmio.h b/lunaix-os/includes/lunaix/mm/mmio.h new file mode 100644 index 0000000..c3f0d66 --- /dev/null +++ b/lunaix-os/includes/lunaix/mm/mmio.h @@ -0,0 +1,12 @@ +#ifndef __LUNAIX_MMIO_H +#define __LUNAIX_MMIO_H + +#include + +void* +ioremap(uintptr_t paddr, uint32_t size); + +void* +iounmap(uintptr_t vaddr, uint32_t size); + +#endif /* __LUNAIX_MMIO_H */ diff --git a/lunaix-os/includes/lunaix/mm/page.h b/lunaix-os/includes/lunaix/mm/page.h index 087e455..8883a6b 100644 --- a/lunaix-os/includes/lunaix/mm/page.h +++ b/lunaix-os/includes/lunaix/mm/page.h @@ -99,7 +99,7 @@ extern void __pg_mount_point; /* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */ #define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703) -#define PD_MOUNT_1 (MMIO_BASE + MEM_4MB) +#define PD_MOUNT_1 (VGA_BUFFER_VADDR + MEM_4MB) #define PG_MOUNT_BASE (PD_MOUNT_1 + MEM_4MB) #define PG_MOUNT_1 (PG_MOUNT_BASE) #define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000) diff --git a/lunaix-os/includes/lunaix/mm/vmm.h b/lunaix-os/includes/lunaix/mm/vmm.h index eab7315..db6e058 100644 --- a/lunaix-os/includes/lunaix/mm/vmm.h +++ b/lunaix-os/includes/lunaix/mm/vmm.h @@ -103,7 +103,20 @@ vmm_mount_pd(uintptr_t mnt, void* pde); void* vmm_unmount_pd(uintptr_t mnt); +void* +vmm_ioremap(uintptr_t paddr, size_t size); + void* vmm_next_free(uintptr_t start, int options); +/** + * @brief 将连续的物理地址空间映射到内核虚拟地址空间 + * + * @param paddr 物理地址空间的基地址 + * @param size 物理地址空间的大小 + * @return void* + */ +void* +vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr, uint32_t pattr); + #endif /* __LUNAIX_VMM_H */ diff --git a/lunaix-os/kernel/asm/x86/intr_routines.c b/lunaix-os/kernel/asm/x86/intr_routines.c index cf03b95..807dbe4 100644 --- a/lunaix-os/kernel/asm/x86/intr_routines.c +++ b/lunaix-os/kernel/asm/x86/intr_routines.c @@ -30,6 +30,7 @@ __print_panic_msg(const char* msg, const isr_param* param) void intr_routine_divide_zero(const isr_param* param) { + console_flush(); __print_panic_msg("Divide by zero!", param); spin(); } @@ -40,7 +41,7 @@ intr_routine_general_protection(const isr_param* param) kprintf(KERROR "Pid: %d\n", __current->pid); kprintf(KERROR "Addr: %p\n", (&debug_resv)[0]); kprintf(KERROR "Expected: %p\n", (&debug_resv)[1]); - console_flush(0); + console_flush(); __print_panic_msg("General Protection", param); spin(); } @@ -48,6 +49,7 @@ intr_routine_general_protection(const isr_param* param) void intr_routine_sys_panic(const isr_param* param) { + console_flush(); __print_panic_msg((char*)(param->registers.edi), param); spin(); } @@ -55,6 +57,7 @@ intr_routine_sys_panic(const isr_param* param) void intr_routine_fallback(const isr_param* param) { + console_flush(); __print_panic_msg("Unknown Interrupt", param); spin(); } @@ -76,6 +79,7 @@ intr_routine_apic_error(const isr_param* param) uint32_t error_reg = apic_read_reg(APIC_ESR); char buf[32]; sprintf(buf, "APIC error, ESR=0x%x", error_reg); + console_flush(); __print_panic_msg(buf, param); spin(); } diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/lxconsole.c index 0a2d449..d6b92f8 100644 --- a/lunaix-os/kernel/lxconsole.c +++ b/lunaix-os/kernel/lxconsole.c @@ -80,7 +80,7 @@ console_view_down() } void -console_flush(void* arg) +console_flush() { if (mutex_on_hold(&lx_console.buffer.lock)) { return; diff --git a/lunaix-os/kernel/mm/mmio.c b/lunaix-os/kernel/mm/mmio.c new file mode 100644 index 0000000..f6d5368 --- /dev/null +++ b/lunaix-os/kernel/mm/mmio.c @@ -0,0 +1,18 @@ +#include +#include +#include + +void* +ioremap(uintptr_t paddr, uint32_t size) +{ + return vmm_vmap(paddr, size, PG_PREM_RW, PP_FGPERSIST); +} + +void* +iounmap(uintptr_t vaddr, uint32_t size) +{ + for (size_t i = 0; i < size; i += PG_SIZE) { + uintptr_t paddr = vmm_del_mapping(PD_REFERENCED, vaddr + i); + pmm_free_page(KERNEL_PID, paddr); + } +} \ No newline at end of file diff --git a/lunaix-os/kernel/mm/vmap.c b/lunaix-os/kernel/mm/vmap.c new file mode 100644 index 0000000..0c10610 --- /dev/null +++ b/lunaix-os/kernel/mm/vmap.c @@ -0,0 +1,64 @@ +#include +#include +#include + +#define VMAP_START PG_MOUNT_BASE + MEM_4MB +#define VMAP_END PD_REFERENCED + +static uintptr_t start = VMAP_START; + +void* +vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr, pp_attr_t pattr) +{ + // next fit + assert_msg((paddr & 0xfff) == 0, "vmap: bad alignment"); + size = ROUNDUP(size, PG_SIZE); + + uintptr_t current_addr = start; + size_t examed_size = 0, wrapped = 0; + x86_page_table* pd = (x86_page_table*)L1_BASE_VADDR; + + while (!wrapped || current_addr >= start) { + size_t l1inx = L1_INDEX(current_addr); + if (!(pd->entry[l1inx])) { + // empty 4mb region + examed_size += MEM_4MB; + current_addr = (current_addr & 0xffc00000) + MEM_4MB; + } else { + x86_page_table* ptd = (x86_page_table*)(L2_VADDR(l1inx)); + size_t i = L2_INDEX(current_addr); + for (; i < 1024 && examed_size < size; i++) { + if (!ptd->entry[i]) { + examed_size += PG_SIZE; + } else if (examed_size) { + // found a discontinuity, start from beginning + examed_size = 0; + i++; + break; + } + } + current_addr += i << 12; + } + + if (examed_size >= size) { + goto done; + } + + if (current_addr >= VMAP_END) { + wrapped = 1; + current_addr = VMAP_START; + } + } + panick("vmm: out of memory"); + +done: + uintptr_t alloc_begin = current_addr - examed_size; + for (size_t i = 0; i < size; i += PG_SIZE) { + vmm_set_mapping( + PD_REFERENCED, alloc_begin + i, paddr + i, PG_PREM_RW, 0); + pmm_ref_page(KERNEL_PID, paddr + i); + } + start = alloc_begin + size; + + return (void*)alloc_begin; +} \ No newline at end of file diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 92d3fd3..582dfdd 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -115,16 +115,6 @@ init_platform() lock_reserved_memory(); acpi_init(_k_init_mb_info); - uintptr_t ioapic_addr = acpi_get_context()->madt.ioapic->ioapic_addr; - pmm_mark_page_occupied( - KERNEL_PID, FLOOR(__APIC_BASE_PADDR, PG_SIZE_BITS), 0); - pmm_mark_page_occupied(KERNEL_PID, FLOOR(ioapic_addr, PG_SIZE_BITS), 0); - - vmm_set_mapping( - PD_REFERENCED, MMIO_APIC, __APIC_BASE_PADDR, PG_PREM_RW, VMAP_NULL); - vmm_set_mapping( - PD_REFERENCED, MMIO_IOAPIC, ioapic_addr, PG_PREM_RW, VMAP_NULL); - apic_init(); ioapic_init(); timer_init(SYS_TIMER_FREQUENCY_HZ); @@ -136,6 +126,7 @@ init_platform() syscall_install(); console_start_flushing(); + console_flush(); unlock_reserved_memory();