feat: vmm_vmap/ioremap/iounmap to make MMIO more flexible and easy
authorMinep <zelong56@gmail.com>
Tue, 28 Jun 2022 17:51:27 +0000 (18:51 +0100)
committerMinep <zelong56@gmail.com>
Tue, 28 Jun 2022 17:51:27 +0000 (18:51 +0100)
fix: flush the screen when fault occurs.
chore: update the memory map accordingly.

14 files changed:
docs/img/lunaix-os-mem.png
lunaix-os/hal/apic.c
lunaix-os/hal/ioapic.c
lunaix-os/includes/hal/apic.h
lunaix-os/includes/lunaix/common.h
lunaix-os/includes/lunaix/lxconsole.h
lunaix-os/includes/lunaix/mm/mmio.h [new file with mode: 0644]
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/includes/lunaix/mm/vmm.h
lunaix-os/kernel/asm/x86/intr_routines.c
lunaix-os/kernel/lxconsole.c
lunaix-os/kernel/mm/mmio.c [new file with mode: 0644]
lunaix-os/kernel/mm/vmap.c [new file with mode: 0644]
lunaix-os/kernel/proc0.c

index 3301d80668f44d0cdc37f5ba7feac960882b5f3f..75c82a46b874ce7ae3e3fc17546b0979c03b4f3c 100644 (file)
Binary files a/docs/img/lunaix-os-mem.png and b/docs/img/lunaix-os-mem.png differ
index 289dd564b7fd9b3a0a340facdee7ed1b4d769e33..00995252120892cde34712677f641795ea390634 100644 (file)
 
 #include <arch/x86/interrupts.h>
 
+#include <lunaix/mm/mmio.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 
 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
index dbe910612aaf8718a6a0cc8bce72aa86cb0309cf..5a03eff11bd3809b6f752d733af7009700a1f12d 100644 (file)
@@ -2,9 +2,12 @@
 #include <hal/acpi/acpi.h>
 #include <hal/ioapic.h>
 #include <lunaix/common.h>
+#include <lunaix/mm/mmio.h>
 
-#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
index f96799cbb05ac2678b3966239b65abcf3f3c0a82..a4ac95fbaa382eebb636c435a9e8fae137ac1567 100644 (file)
 
 #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 */
index fe0c0bc31b34740563c32b5fce05f0266bb4ef58..7fdf0b30cbe88327a0cd111ff34f643a9f972dbc 100644 (file)
 #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
index ba8c907ae9c817ccefc83d04e8ab90417c782e07..02e21980db359d98b40b30806cb6a0ba93a463b6 100644 (file)
@@ -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 (file)
index 0000000..c3f0d66
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __LUNAIX_MMIO_H
+#define __LUNAIX_MMIO_H
+
+#include <stdint.h>
+
+void*
+ioremap(uintptr_t paddr, uint32_t size);
+
+void*
+iounmap(uintptr_t vaddr, uint32_t size);
+
+#endif /* __LUNAIX_MMIO_H */
index 087e4551bae7c91982cb8eb59233548a172245e3..8883a6b70eab665206c42d63f23678205cac1e7f 100644 (file)
@@ -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)
index eab731589745221569db2354440449e4727ab41d..db6e058fcb9941568feb55e06186d859dab65744 100644 (file)
@@ -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 */
index cf03b95db8e117e8d89b76ed78c0fa9faf2d805d..807dbe421e22ad2fe708e86ba40f69c776b82ef8 100644 (file)
@@ -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();
 }
index 0a2d449a1ad291df6a22fbeda1528a316ec1fa27..d6b92f8c719b425571ce7235580f9d23f36172b6 100644 (file)
@@ -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 (file)
index 0000000..f6d5368
--- /dev/null
@@ -0,0 +1,18 @@
+#include <lunaix/mm/mmio.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/vmm.h>
+
+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 (file)
index 0000000..0c10610
--- /dev/null
@@ -0,0 +1,64 @@
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
+
+#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
index 92d3fd3df34478c42da249d81649b43414902e0d..582dfdd41eeb3c9f4c907110238d113ee48347db 100644 (file)
@@ -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();