diff --git a/base/usr/include/kernel/mmu.h b/base/usr/include/kernel/mmu.h index 48df93a5..7e04e6e5 100644 --- a/base/usr/include/kernel/mmu.h +++ b/base/usr/include/kernel/mmu.h @@ -34,7 +34,6 @@ union PML * mmu_get_page(uintptr_t virtAddr, int flags); void mmu_set_directory(union PML * new_pml); void mmu_free(union PML * from); union PML * mmu_clone(union PML * from); -void mmu_init(size_t memsize, uintptr_t firstFreePage); void mmu_invalidate(uintptr_t addr); uintptr_t mmu_allocate_a_frame(void); uintptr_t mmu_allocate_n_frames(int n); diff --git a/kernel/arch/aarch64/mmu.c b/kernel/arch/aarch64/mmu.c index 4cd7902e..da5f12db 100644 --- a/kernel/arch/aarch64/mmu.c +++ b/kernel/arch/aarch64/mmu.c @@ -671,12 +671,12 @@ static uintptr_t k2p(void * x) { return ((uintptr_t)x - MODULE_BASE_START) + QEMU_VIRT_KERNEL_BASE; } -void mmu_init(uintptr_t memsize, uintptr_t firstFreePage) { +void mmu_init(uintptr_t memsize, size_t physsize, uintptr_t firstFreePage, uintptr_t endOfRamDisk) { this_core->current_pml = (union PML *)&init_page_region; /* On this machine, there's 1GiB of unavailable memory. */ unavailable_memory = 1048576; - total_memory = 4194304; + total_memory = memsize / 1024; /* MAIR setup? */ uint64_t mair; @@ -727,9 +727,12 @@ void mmu_init(uintptr_t memsize, uintptr_t firstFreePage) { /* Set up some space to map us */ + /* How many 2MiB spans do we need to cover to endOfRamDisk? */ + size_t twoms = (endOfRamDisk + (LARGE_PAGE_SIZE - 1)) / LARGE_PAGE_SIZE; + /* init_page_region[511] -> high_base_pml[510] -> kbase_pmls[0] -> kbase_pmls[1+n] */ high_base_pml[510].raw = k2p(&kbase_pmls[0]) | PTE_VALID | PTE_TABLE | PTE_AF; - for (size_t j = 0; j < 64; ++j) { + for (size_t j = 0; j < twoms; ++j) { kbase_pmls[0][j].raw = k2p(&kbase_pmls[1+j]) | PTE_VALID | PTE_TABLE | PTE_AF; for (int i = 0; i < 512; ++i) { kbase_pmls[1+j][i].raw = (uintptr_t)(QEMU_VIRT_KERNEL_BASE + LARGE_PAGE_SIZE * j + PAGE_SIZE * i) | @@ -750,7 +753,7 @@ void mmu_init(uintptr_t memsize, uintptr_t firstFreePage) { /* Physical frame allocator. We're gonna do this the same as the one we have x86-64, because * I can't be bothered to think of anything better right now... */ - nframes = (memsize) >> 12; + nframes = (physsize) >> 12; size_t bytesOfFrames = INDEX_FROM_BIT(nframes * 8); bytesOfFrames = (bytesOfFrames + PAGE_LOW_MASK) & PAGE_SIZE_MASK; @@ -775,7 +778,7 @@ void mmu_init(uintptr_t memsize, uintptr_t firstFreePage) { } /* Set kernel space as in use */ - for (uintptr_t i = 0; i < 64 * LARGE_PAGE_SIZE; i += PAGE_SIZE) { + for (uintptr_t i = 0; i < twoms * LARGE_PAGE_SIZE; i += PAGE_SIZE) { mmu_frame_set(QEMU_VIRT_KERNEL_BASE + i); } diff --git a/kernel/arch/aarch64/user.c b/kernel/arch/aarch64/user.c index 73696d5f..654af2f6 100644 --- a/kernel/arch/aarch64/user.c +++ b/kernel/arch/aarch64/user.c @@ -20,11 +20,13 @@ #include #include #include +#include #include extern void framebuffer_initialize(void); extern void fbterm_initialize(void); +extern void mmu_init(size_t memsize, size_t phys, uintptr_t firstFreePage, uintptr_t endOfInitrd); static uint32_t swizzle(uint32_t from) { uint8_t a = from >> 24; @@ -735,6 +737,7 @@ static void exception_handlers(void) { asm volatile("msr VBAR_EL1, %0" :: "r"(&_exception_vector)); } +static void update_clock(void); void aarch64_sync_enter(struct regs * r) { uint64_t esr, far, elr, spsr; asm volatile ("mrs %0, ESR_EL1" : "=r"(esr)); @@ -742,6 +745,10 @@ void aarch64_sync_enter(struct regs * r) { asm volatile ("mrs %0, ELR_EL1" : "=r"(elr)); asm volatile ("mrs %0, SPSR_EL1" : "=r"(spsr)); + if (this_core->current_process) { + this_core->current_process->time_switch = arch_perf_timer(); + } + if (elr == 0xFFFFB00F && far == 0xFFFFB00F) { task_exit(0); __builtin_unreachable(); @@ -760,6 +767,8 @@ void aarch64_sync_enter(struct regs * r) { printf(" x5: %#zx\n", r->x5); #endif + update_clock(); + extern void syscall_handler(struct regs *); syscall_handler(r); @@ -777,6 +786,7 @@ void aarch64_sync_enter(struct regs * r) { if (far == 0x1de7ec7edbadc0de) { /* KVM is mad at us */ + printf("kvm: blip (esr=%#zx, elr=%#zx; pid=%d [%s])\n", esr, elr, this_core->current_process->id, this_core->current_process->name); return; } @@ -820,12 +830,19 @@ static void fpu_enable(void) { } static void timer_start(void) { + volatile uint32_t * clock_addr = mmu_map_from_physical(0x09010000); + + clock_addr[4] = 0; + clock_addr[7] = 1; + + #if 0 asm volatile ("msr CNTKCTL_EL1, %0" :: "r"( (1 << 17) /* lower rate */ | (23 << 4) /* uh lowest bit? */ | (1 << 1) /* enable event stream */ )); + #endif } static uint64_t time_slice_basis = 0; /**< When the last clock update happened */ @@ -862,6 +879,19 @@ void arch_pause(void) { switch_next(); } +static fs_node_t * mouse_pipe; +static fs_node_t * keyboard_pipe; + +static void fake_input(void) { + mouse_pipe = make_pipe(128); + mouse_pipe->flags = FS_CHARDEVICE; + vfs_mount("/dev/mouse", mouse_pipe); + + keyboard_pipe = make_pipe(128); + keyboard_pipe->flags = FS_CHARDEVICE; + vfs_mount("/dev/kbd", keyboard_pipe); +} + void arch_clear_icache(uintptr_t start, uintptr_t end) { for (uintptr_t x = start; x < end; x += 64) { if (!mmu_validate_user_pointer((void*)x, 64, MMU_PTR_WRITE)) continue; @@ -873,6 +903,33 @@ void arch_clear_icache(uintptr_t start, uintptr_t end) { } } +/** + * Figure out 1) how much actual memory we have and 2) what the last + * address of physical memory is. + */ +static void dtb_memory_size(size_t * memsize, size_t * physsize) { + uint32_t * memory = find_node_prefix("memory"); + if (!memory) { + printf("dtb: Could not find memory node.\n"); + arch_fatal(); + } + + uint32_t * regs = node_find_property(memory, "reg"); + if (!regs) { + printf("dtb: memory node has no regs\n"); + arch_fatal(); + } + + /* Eventually, same with fw-cfg, we'll need to actually figure out + * the size of the 'reg' cells, but at least right now it's been + * 2 address, 2 size. */ + uint64_t mem_addr = (uint64_t)swizzle(regs[3]) | ((uint64_t)swizzle(regs[2]) << 32UL); + uint64_t mem_size = (uint64_t)swizzle(regs[5]) | ((uint64_t)swizzle(regs[4]) << 32UL); + + *memsize = mem_size; + *physsize = mem_addr + mem_size; +} + /** * Main kernel C entrypoint for qemu's -machine virt @@ -912,7 +969,13 @@ int kmain(void) { /* TODO get initial memory map data? * Eh, we can probably just probe the existing tables... maybe... */ - mmu_init(8UL * 1024 * 1024 * 1024 /* Should be maximum valid physical address */, 0x40100000 /* Should be end of DTB */); + extern char end[]; + size_t memsize, physsize; + dtb_memory_size(&memsize, &physsize); + mmu_init( + memsize, physsize, + 0x40100000 /* Should be end of DTB, but we're really just guessing */, + (uintptr_t)&end + ramdisk_size - 0xffffffff80000000UL); /* Find the cmdline */ dtb_locate_cmdline(); @@ -935,6 +998,7 @@ int kmain(void) { timer_start(); /* TODO Install drivers that may need to sleep here */ + fake_input(); generic_main(); diff --git a/kernel/arch/x86_64/main.c b/kernel/arch/x86_64/main.c index 5b455005..ecb8a3bd 100644 --- a/kernel/arch/x86_64/main.c +++ b/kernel/arch/x86_64/main.c @@ -45,6 +45,7 @@ extern void ps2hid_install(void); extern void serial_initialize(void); extern void fbterm_initialize(void); extern void pci_remap(void); +extern void mmu_init(size_t memsize, uintptr_t firstFreePage); struct multiboot * mboot_struct = NULL; int mboot_is_2 = 0; diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index ba2c9d31..1a464239 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -872,7 +872,6 @@ long sys_fork(void) { } long sys_clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) { - printf("sys_clone() from pid=%d\n", this_core->current_process->id); if (!new_stack || !PTR_INRANGE(new_stack)) return -EINVAL; if (!thread_func || !PTR_INRANGE(thread_func)) return -EINVAL; return (int)clone(new_stack, thread_func, arg);