fix: flush the screen when fault occurs.
chore: update the memory map accordingly.
#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();
// 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"
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
#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);
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
#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();
* 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 */
#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
console_view_down();
void
-console_flush(void* arg);
+console_flush();
void
console_start_flushing();
--- /dev/null
+#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 */
/* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */
#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)
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 */
void
intr_routine_divide_zero(const isr_param* param)
{
+ console_flush();
__print_panic_msg("Divide by zero!", param);
spin();
}
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();
}
void
intr_routine_sys_panic(const isr_param* param)
{
+ console_flush();
__print_panic_msg((char*)(param->registers.edi), param);
spin();
}
void
intr_routine_fallback(const isr_param* param)
{
+ console_flush();
__print_panic_msg("Unknown Interrupt", param);
spin();
}
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();
}
}
void
-console_flush(void* arg)
+console_flush()
{
if (mutex_on_hold(&lx_console.buffer.lock)) {
return;
--- /dev/null
+#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
--- /dev/null
+#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
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);
syscall_install();
console_start_flushing();
+ console_flush();
unlock_reserved_memory();