From 2307bc6058c5468bc98b82c72448cb68a2fa6e47 Mon Sep 17 00:00:00 2001 From: jonay2000 Date: Sun, 8 Mar 2020 16:52:47 +0100 Subject: [PATCH] enabled high interrupt vectors to enable higher-half interrupts Co-authored-by: Victor Roest --- .github/workflows/os_test.yml | 2 +- kernel/src/common/interrupt.c | 52 +++++++++++----------- kernel/src/common/startup.s | 6 +++ kernel/src/drivers/chipset/bcm2836/timer.c | 8 ++-- kernel/src/ds/u8_array_list.c | 6 ++- kernel/src/fs/path.c | 2 + kernel/src/fs/test/test_path.c | 1 + kernel/src/klibc/alloc.c | 8 +++- kernel/src/vm/README.md | 19 ++++---- kernel/src/vm/include/vm2.h | 6 ++- kernel/src/vm/vm2.c | 2 +- 11 files changed, 65 insertions(+), 47 deletions(-) diff --git a/.github/workflows/os_test.yml b/.github/workflows/os_test.yml index f38de978..4f0ed217 100644 --- a/.github/workflows/os_test.yml +++ b/.github/workflows/os_test.yml @@ -21,7 +21,7 @@ jobs: sudo apt-get install build-essential qemu-system-arm python3 wget texinfo zlib1g-dev -y - name: Install Toolchain - #if: steps.cache-toolchain.outputs.cache-hit != 'true' + if: steps.cache-toolchain.outputs.cache-hit != 'true' run: rm -rf toolchain/arm-none-eabi/ && make toolchain - name: Compile diff --git a/kernel/src/common/interrupt.c b/kernel/src/common/interrupt.c index dc92c7f2..dd5ce9b8 100644 --- a/kernel/src/common/interrupt.c +++ b/kernel/src/common/interrupt.c @@ -6,36 +6,36 @@ /* copy vector table from wherever QEMU loads the kernel to 0x00 */ void init_vector_table() { - /* This doesn't seem to work well with virtual memory; reverting - * to old method. - extern uint32_t vector_table_start, vector_table_end; - uint32_t *src = &vector_table_start; - uint32_t *dst = (uint32_t *) HIVECTABLE; - - while(src < &vector_table_end) - *dst++ = *src++; - */ + // allocate space for the IVR at the high vector location. + vm2_allocate_kernel_page(kernell1PageTable, HIGH_VECTOR_LOCATION, true); /* Primary Vector Table */ - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x0, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x04, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x08, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x0C, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x10, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x14, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x18, BRANCH_INSTRUCTION); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x1C, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x00, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x04, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x08, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x0C, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x10, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x14, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x18, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x1C, BRANCH_INSTRUCTION); /* Secondary Vector Table */ - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x20, &reset_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x24, &undef_instruction_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x28, &software_interrupt_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x2C, &prefetch_abort_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x30, &data_abort_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x34, &reserved_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x38, &irq_handler); - mmio_write(KERNEL_VIRTUAL_OFFSET + 0x3C, &fiq_handler); - + mmio_write(HIGH_VECTOR_LOCATION + 0x20, &reset_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x24, &undef_instruction_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x28, &software_interrupt_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x2C, &prefetch_abort_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x30, &data_abort_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x34, &reserved_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x38, &irq_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x3C, &fiq_handler); + + /// Enable high vectors (Vectors located at HIGH_VECTOR_LOCATION). + asm volatile ( + "mrc p15, 0, r1, c1, c0, 0 \n" // Read p15 + "orr r1, %0\n" // Enable High Vector bit + "mcr p15, 0, r1, c1, c0, 0\n" // Set p15 + :: "r" (1u << 13u) + ); } /* handlers */ diff --git a/kernel/src/common/startup.s b/kernel/src/common/startup.s index 88b2311a..59758767 100644 --- a/kernel/src/common/startup.s +++ b/kernel/src/common/startup.s @@ -8,6 +8,12 @@ _Reset: cmp r1, #0 bne loop + // Move the interrupt vector tables to 0x80000000 + ldr r0, =0xE000ED08 + ldr r1, =0x80000000 + str r1, [r0] + + ldr sp, =EARLY_KERNEL_STACK_TOP // Set the kernel/SVC stack push {r0-r11} diff --git a/kernel/src/drivers/chipset/bcm2836/timer.c b/kernel/src/drivers/chipset/bcm2836/timer.c index 633231b8..3b216929 100644 --- a/kernel/src/drivers/chipset/bcm2836/timer.c +++ b/kernel/src/drivers/chipset/bcm2836/timer.c @@ -41,14 +41,12 @@ void bcm2836_timer_init() { uint32_t freq = get_frequency(); - kprintf("control frequency: %i\n", freq); + TRACE("control frequency: %i", freq); // 1 (milli)second timer - write_interrupt_count_value(freq); - - kprintf("value: %i\n", read_interrupt_count_value()); - kprintf("value: %i\n", read_interrupt_count_value()); + write_interrupt_count_value(freq * 100); // when the register reaches the count value set above, interrupt. + // TODO: Enable timer // mmio_write(&bcm2836_registers_base->Core0TimersInterruptControl, VIRTUAL_NONSECURE_TIMER); // Enable timer interrupts. diff --git a/kernel/src/ds/u8_array_list.c b/kernel/src/ds/u8_array_list.c index b24f9b60..55bdc6e2 100644 --- a/kernel/src/ds/u8_array_list.c +++ b/kernel/src/ds/u8_array_list.c @@ -6,6 +6,7 @@ #include #include #include +#include U8ArrayList * u8a_create(uint32_t initial_cap) { U8ArrayList * list = kmalloc(sizeof(U8ArrayList)); @@ -39,7 +40,7 @@ void u8a_set(U8ArrayList * list, uint32_t index, uint8_t data) { uint32_t u8a_push(U8ArrayList * list, uint8_t data) { if(list->capacity == 0 || list->length >= list->capacity - 1) { - uint32_t new_size = max((list->capacity + (list->capacity >> 2)), list->capacity + 2); + uint32_t new_size = max((list->capacity + (list->capacity >> 2u)), list->capacity + 2); assert(new_size > list->capacity) @@ -47,6 +48,7 @@ uint32_t u8a_push(U8ArrayList * list, uint8_t data) { list->array = krealloc(list->array, list->capacity * sizeof(uint8_t)); } + list->array[list->length++] = data; return list->length; @@ -97,4 +99,4 @@ U8ArrayList * u8a_clone(U8ArrayList * arr) { } return newarr; -} \ No newline at end of file +} diff --git a/kernel/src/fs/path.c b/kernel/src/fs/path.c index 00b4cb2a..c7ad6739 100644 --- a/kernel/src/fs/path.c +++ b/kernel/src/fs/path.c @@ -5,6 +5,8 @@ #include #include +#include + const Path root = { .length = 1, diff --git a/kernel/src/fs/test/test_path.c b/kernel/src/fs/test/test_path.c index 23ea9128..1e52324c 100644 --- a/kernel/src/fs/test/test_path.c +++ b/kernel/src/fs/test/test_path.c @@ -71,6 +71,7 @@ TEST_CREATE(path_parent_test_4, { ASSERT(path_contents_equal(p1, p2)); path_free(p1); path_free(p2); + }) TEST_CREATE(path_parent_test_5, { diff --git a/kernel/src/klibc/alloc.c b/kernel/src/klibc/alloc.c index a9426e6a..00c7b9cc 100644 --- a/kernel/src/klibc/alloc.c +++ b/kernel/src/klibc/alloc.c @@ -33,13 +33,17 @@ uint32_t kmalloc_size(void* ptr) { // TODO: Implement in-place realloc if the next block is free. // Resize memory pointed to by ptr to new size void * krealloc(void *ptr, uint32_t newsize) { + if (ptr == NULL) { + TRACE("[MEM DEBUG] Realloc with nullptr"); + return kmalloc(newsize); + } + uint32_t oldsize = kmalloc_size(ptr); + if (newsize == 0) { kfree(ptr); return NULL; - } else if (ptr == NULL) { - return kmalloc(newsize); } else if (newsize <= oldsize) { return ptr; } else { diff --git a/kernel/src/vm/README.md b/kernel/src/vm/README.md index 7d0d0b31..50f1efe3 100644 --- a/kernel/src/vm/README.md +++ b/kernel/src/vm/README.md @@ -9,9 +9,9 @@ | Address | Description | | ---------- | ---------------------------------------------------------------------- | -| 0x0000000 | Interrupt Vector Table | -| 0x0004000 | Kernel L1 page table | -| 0x0008000 | Kernel start | +| 0x00000000 | Interrupt Vector Table | +| 0x00004000 | Kernel L1 page table | +| 0x00080000 | Kernel start | | ... | *Kernel* | | ... | *Kernel* | | KERNEL END | Physical Memory Manager starting point | @@ -22,16 +22,17 @@ | Address | Description | | ---------- | ---------------------------------------------------------------------- | -| 0x0000000 | Virtual Process Address Space | -| 0x8000000 | Interrupt Vector Table (remap of the first gigabyte of phys --> virt) | -| 0x8004000 | Kernel page table | -| 0x8008000 | Kernel start | +| 0x00000000 | Virtual Process Address Space | +| 0x80000000 | (start of) remap of physical 0x00000000-0x40000000 | +| 0x80004000 | Kernel page table | +| 0x80008000 | Kernel start | | ... | *Kernel* | | ... | *Kernel* | | KERNEL END | Location of the PMM in virtual address space | | ... | (Virtual) Physical Memory Manager | -| 0xC000000 | Kernel heap start (growing up) | -| 0xFFFFFFF | MMIO mappings (growing down) | +| 0xC0000000 | Kernel heap start (growing up) | +| 0xFFF00000 | MMIO mappings (growing down) | +| 0xFFFF0000 | High location of the vector table | ***Note:*** Both the MMIO mapping and kernel heap occupy the same gigabyte. The sum of the two can't exceed 1 gigabyte and when the kernel heap grows to touch the MMIO top, the heap is full. diff --git a/kernel/src/vm/include/vm2.h b/kernel/src/vm/include/vm2.h index 5e1bb231..296c66e0 100644 --- a/kernel/src/vm/include/vm2.h +++ b/kernel/src/vm/include/vm2.h @@ -310,8 +310,12 @@ extern const size_t __KERNEL_VIRTUAL_OFFSET[]; /// Location of the Kernel's Physical Memory Manager's Info structs. Can grow to a max of 16MiB when using 4GiB RAM. #define KERNEL_PMM_BASE KERNEL_VIRTUAL_END +// Location of the vector table in memory table. +// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABIFJFG.html +#define HIGH_VECTOR_LOCATION 0xFFFF0000 + /// From this address down, mmio devices are mapped in the kernel's virtual address space. -#define KERNEL_MMIO_BASE (4 * Gibibyte) +#define KERNEL_MMIO_BASE ((4 * Gibibyte) - (1 * Mebibyte)) /// Address space for the kernel heap, grows towards the mmio #define KERNEL_HEAP_BASE (3 * Gibibyte) diff --git a/kernel/src/vm/vm2.c b/kernel/src/vm/vm2.c index f5d95aff..5bbc5e46 100644 --- a/kernel/src/vm/vm2.c +++ b/kernel/src/vm/vm2.c @@ -91,7 +91,7 @@ void vm2_start() { /// Unmap the 1:1 mapped first megabyte which startup.s created to boot to a higher half kernel. /// We don't need it anymore! -// kernell1PageTable->entries[0] = (L1PagetableEntry){0}; + kernell1PageTable->entries[0] = (L1PagetableEntry){0}; /// Map the entire gigabyte (or less on some boards, but never more) physical ram to virtual 2GB-3GB. /// this includes the kernel, kernel stack, kernel pagetables, process pagetables, pmm etc.