diff --git a/kernel/Makefile b/kernel/Makefile index 9408c144..5cdacf31 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -9,7 +9,7 @@ CFLAGS += -pipe -std=gnu99 -ffreestanding -Wall -Werror -g -O0 -mcpu=arm1176jzf- # variables to define in the preprocessor. MEMORY = 1G -DEFINITIONS = MEM_DEBUG ENABLE_TESTS +DEFINITIONS = MEM_DEBUG #DEFINITIONS = MEM_DEBUG test: DEFINITIONS += ENABLE_TESTS # if we execute the test: rule, enable tests before recompiling KERNEL_PARAMS = root=/dev/ram mem=$(MEMORY) diff --git a/kernel/src/memory/allocator.c b/kernel/src/allocator/allocator.c similarity index 100% rename from kernel/src/memory/allocator.c rename to kernel/src/allocator/allocator.c diff --git a/kernel/src/memory/include/allocator.h b/kernel/src/allocator/include/allocator.h similarity index 100% rename from kernel/src/memory/include/allocator.h rename to kernel/src/allocator/include/allocator.h diff --git a/kernel/src/memory/include/mem_alloc.h b/kernel/src/allocator/include/mem_alloc.h similarity index 100% rename from kernel/src/memory/include/mem_alloc.h rename to kernel/src/allocator/include/mem_alloc.h diff --git a/kernel/src/memory/llist.c b/kernel/src/allocator/llist.c similarity index 100% rename from kernel/src/memory/llist.c rename to kernel/src/allocator/llist.c diff --git a/kernel/src/memory/mem_alloc.c b/kernel/src/allocator/mem_alloc.c similarity index 99% rename from kernel/src/memory/mem_alloc.c rename to kernel/src/allocator/mem_alloc.c index b5cb941f..614d7aa5 100644 --- a/kernel/src/memory/mem_alloc.c +++ b/kernel/src/allocator/mem_alloc.c @@ -1,7 +1,6 @@ #include "klibc.h" #include #include -#include #include #include #include diff --git a/kernel/src/memory/test/test_allocator.c b/kernel/src/allocator/test/test_allocator.c similarity index 100% rename from kernel/src/memory/test/test_allocator.c rename to kernel/src/allocator/test/test_allocator.c diff --git a/kernel/src/common/include/argparse.h b/kernel/src/common/include/argparse.h deleted file mode 100644 index 7225ebae..00000000 --- a/kernel/src/common/include/argparse.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __ARGPARSE_H__ -#define __ARGPARSE_H__ - - - -#define ATAG_NONE 0x00000000 -#define ATAG_CORE 0x54410001 - -struct atag_core { - uint32_t flags; - uint32_t pagesize; - uint32_t rootdev; -}; - -#define ATAG_MEM 0x54410002 - -struct atag_mem { - uint32_t size; - uint32_t start; -}; - -#define ATAG_VIDEOTEXT 0x54410003 -#define ATAG_RAMDISK 0x54410004 -#define ATAG_INITRD2 0x54420005 -#define ATAG_SERIAL 0x54410006 -#define ATAG_REVISION 0x54410007 -#define ATAG_VIDEOLFB 0x54410008 -#define ATAG_CMDLINE 0x54410009 - -struct atag_cmdline { - char cmdline[1]; -}; - -struct atag_header { - uint32_t size; - uint32_t tag; -}; - -struct atag { - struct atag_header header; - union { - struct atag_core core; - struct atag_mem mem; - struct atag_cmdline cmdline; - } content; -}; - -static inline struct atag *atag_next_header(struct atag *t) -{ - return (struct atag*) ((uint32_t*)(t) + t->header.size); -} - -#define atag_iterator(tag, addr) struct atag* tag = (struct atag*) addr; tag->header.tag != ATAG_NONE; tag = atag_next_header(tag) - -void atag_print(struct atag *t); - -void argparse_process(uint32_t *p_bootargs); -void parse_arguments(int argc, char **argv); -int analyze_arguments(char **argv); -char* read_cmdline_tag(uint32_t *tag_base); -char** split_string(char *line, char **list); -int number_of_words(char *line); -int string_to_unsigned_int(char *input, int base); -int hex_value_of_character(char c); - -#endif diff --git a/kernel/src/common/include/interrupt.h b/kernel/src/common/include/interrupt.h index 21f024ad..b65b5f01 100644 --- a/kernel/src/common/include/interrupt.h +++ b/kernel/src/common/include/interrupt.h @@ -35,6 +35,7 @@ #define BRANCH_INSTRUCTION 0xe59ff018 // ldr pc, pc+offset (where offset is 0x20 bytes) // System Call Types +// TODO: maybe make enum? #define SYSCALL_CREATE 0 #define SYSCALL_SWITCH 1 #define SYSCALL_DELETE 2 diff --git a/kernel/src/common/interrupt.c b/kernel/src/common/interrupt.c index f1596936..dc92c7f2 100644 --- a/kernel/src/common/interrupt.c +++ b/kernel/src/common/interrupt.c @@ -1,11 +1,8 @@ #include -#include -#include -#include #include -#include #include #include +#include /* copy vector table from wherever QEMU loads the kernel to 0x00 */ void init_vector_table() { @@ -42,52 +39,44 @@ void init_vector_table() { } /* handlers */ -void reset_handler(void) -{ - kprintf("RESET HANDLER\n"); +void reset_handler(void) { + INFO("RESET HANDLER\n"); _Reset(); } -void __attribute__((interrupt("UNDEF"))) undef_instruction_handler(void) -{ - int spsr, lr; +void __attribute__((interrupt("UNDEF"))) undef_instruction_handler() { + size_t spsr, lr; asm volatile("mrs %0, spsr" : "=r"(spsr)); asm volatile("mov %0, lr" : "=r" (lr)); - int thumb = spsr & 0x20; - int pc = thumb ? lr - 0x2 : lr - 0x4; + size_t thumb = spsr & 0x20u; + size_t pc = thumb ? lr - 0x2u : lr - 0x4u; - if ((*(size_t *) pc) == UNDEFINED_INSTRUCTION_BYTES){ - kprintf("FATAL ERROR\n"); - panic(); - } - kprintf("UNDEFINED INSTRUCTION HANDLER\n"); + WARN("UNDEFINED INSTRUCTION HANDLER"); - int copro = (*(int*)pc & 0xf00000) >> 24; + size_t copro = (*(size_t *)pc & 0xf00000u) >> 24u; - if (spsr & 0x20) { - kprintf("THUMB mode\n"); + if (spsr & 0x20u) { + WARN("THUMB mode"); } else { - kprintf("ARM mode\n"); + WARN("ARM mode"); } - if (spsr & 0x1000000) { - kprintf("JAZELLE enabled\n"); + if (spsr & 0x1000000u) { + WARN("JAZELLE enabled"); } - kprintf("COPRO: %x\n", copro); - kprintf("violating instruction (at %x): %x\n", pc, *((int *) pc)); - if (pc >= V_KERNBASE && pc < V_KERNTOP) - { - kprintf("(instruction is in kernel address range)\n"); + WARN("COPRO: 0x%x", copro); + WARN("violating instruction (at 0x%x): 0x%x", pc, *((size_t *) pc)); + if (pc >= KERNEL_VIRTUAL_START && pc < KERNEL_VIRTUAL_END) { + WARN("(instruction is in kernel address range)"); } - panic(); + FATAL("UNDEFINED INSTRUCTION HANDLER"); } -long __attribute__((interrupt("SWI"))) software_interrupt_handler(void) -{ +long __attribute__((interrupt("SWI"))) software_interrupt_handler(void) { int callNumber = 0, r0 = 0, r1 = 0, r2 = 0, r3 = 0; asm volatile ("MOV %0, r7":"=r"(callNumber)::); @@ -188,15 +177,11 @@ long __attribute__((interrupt("SWI"))) software_interrupt_handler(void) } } -void __attribute__((interrupt("ABORT"))) prefetch_abort_handler(void) -{ - int lr; - +void __attribute__((interrupt("ABORT"))) prefetch_abort_handler(void) { + size_t lr; asm volatile("mov %0, lr" : "=r" (lr)); - kprintf("PREFETCH ABORT HANDLER, violating address: %x\n", (lr - 4)); - - panic(); + FATAL("PREFETCH ABORT HANDLER, violating address: 0x%x", (lr - 4u)); } void __attribute__((interrupt("ABORT"))) data_abort_handler(void) { @@ -207,20 +192,20 @@ void __attribute__((interrupt("ABORT"))) data_abort_handler(void) { asm volatile("mov %0, lr" : "=r" (lr)); int pc = lr - 8; - int far; + uint32_t far; asm volatile("mrc p15, 0, %0, c6, c0, 0" : "=r" (far)); - DEBUG("DATA ABORT HANDLER (Page Fault)"); - DEBUG("faulting address: 0x%x", far); + WARN("DATA ABORT HANDLER (Page Fault)"); + WARN("faulting address: 0x%x", far); if (far >= KERNEL_VIRTUAL_OFFSET) { - DEBUG("(address is in kernel address range)\n"); + DEBUG("(address is in kernel address range)"); } - DEBUG("violating instruction (at 0x%x): %x", pc, *((int *) pc)); + WARN("violating instruction (at 0x%x): 0x%x", pc, *((int *) pc)); // Get the Data Fault Status Register int dfsr; asm volatile("MRC p15, 0, %0, c5, c0, 0" : "=r" (dfsr)); - DEBUG("DFSR: 0x%x", dfsr); + WARN("DFSR: 0x%x", dfsr); #ifdef ENABLE_TESTS @@ -234,8 +219,9 @@ void reserved_handler(void) } // the attribute automatically saves and restores state +// TODO: We might not want that! (context switches etc) void __attribute__((interrupt("IRQ"))) irq_handler(void) { - kprintf("IRQ HANDLER\n"); + DEBUG("IRQ HANDLER"); return chipset.handle_irq(); // int * pendingregister = (int *) 0x40000060; @@ -260,7 +246,7 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void) { } void __attribute__((interrupt("FIQ"))) fiq_handler(void) { - kprintf("FIQ HANDLER\n"); + DEBUG("FIQ HANDLER\n"); return chipset.handle_fiq(); // handle_irq_interrupt(interrupt_registers->fiq_control & 0x7f); @@ -283,7 +269,7 @@ void __attribute__((always_inline)) inline SemihostingCall(enum SemihostingSWI m /* enable IRQ and/or FIQ */ void enable_interrupt(InterruptType mask) { - kprintf("Enabling interrupts with mask %i\n", mask); + INFO("Enabling interrupts with mask %i", mask); // enable interrupt on the core switch (mask) { @@ -296,12 +282,15 @@ void enable_interrupt(InterruptType mask) { case BOTH: asm volatile("cpsie if"); break; + default: + /** should never happen **/ + return; } } /* disable IRQ and/or FIQ */ void disable_interrupt(InterruptType mask) { - kprintf("Disabling interrupts with mask %i\n", mask); + INFO("Disabling interrupts with mask %i", mask); // disable interrupts on the core switch (mask) { @@ -314,13 +303,16 @@ void disable_interrupt(InterruptType mask) { case BOTH: asm volatile("cpsid if"); break; + default: + /** should never happen **/ + return; } } /* disable IRQ and/or FIQ, but also return a copy of the CPSR */ int disable_interrupt_save(InterruptType mask) { - kprintf("Disabling interrupts (save) with mask %i\n", mask); + INFO("Disabling interrupts (save) with mask %i", mask); /* get a copy of the current process status register */ int cpsr; @@ -336,13 +328,16 @@ int disable_interrupt_save(InterruptType mask) { case BOTH: asm volatile("cpsid if"); break; + default: + /** should never happen **/ + return -1; } return cpsr; } /* return a full 32-bit copy of the current process status register */ -int get_proc_status() { - int cpsr; +size_t get_proc_status() { + size_t cpsr; asm volatile("mrs %0, cpsr" : "=r"(cpsr)); return cpsr; } @@ -350,6 +345,6 @@ int get_proc_status() { /* restore control status (interrupt, mode bits) of the cpsr */ /* (e.g. when we return from a handler, restore value from disable_interrupt_save */ -void restore_proc_status(int cpsr) { +void restore_proc_status(size_t cpsr) { asm volatile("msr cpsr_c, %0" : : "r"(cpsr)); } diff --git a/kernel/src/common/start.c b/kernel/src/common/start.c index edda33d2..4d1ae2f7 100644 --- a/kernel/src/common/start.c +++ b/kernel/src/common/start.c @@ -78,18 +78,7 @@ void start(uint32_t *p_bootargs) { // If we return, the tests failed. SemihostingCall(OSSpecific); #endif - kprintf("done parsing atag list\n"); - //init_kheap(31 * 0x100000); - //init_uheap(0x100000); - - //initialize pcb table and PID - /* init_all_processes(); */ - //print_process_state(0); - //run_process_tests(); - //print_PID(); - // init_q(); - //common(); // TODO: // * Mount vfs @@ -98,6 +87,6 @@ void start(uint32_t *p_bootargs) { asm volatile("cpsie i"); - kprintf("End of start method.\n"); + INFO("End of boot sequence.\n"); SLEEP; } diff --git a/kernel/src/drivers/chipset/bcm2836/bcm2836.c b/kernel/src/drivers/chipset/bcm2836/bcm2836.c index 93b3281b..91c000c1 100644 --- a/kernel/src/drivers/chipset/bcm2836/bcm2836.c +++ b/kernel/src/drivers/chipset/bcm2836/bcm2836.c @@ -1,7 +1,7 @@ // https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf #include #include -#include +#include #include #include #include diff --git a/kernel/src/drivers/chipset/bcm2836/timer.c b/kernel/src/drivers/chipset/bcm2836/timer.c index 06af7c4e..633231b8 100644 --- a/kernel/src/drivers/chipset/bcm2836/timer.c +++ b/kernel/src/drivers/chipset/bcm2836/timer.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include inline static uint32_t get_frequency() { diff --git a/kernel/src/klibc/include/klibc.h b/kernel/src/klibc/include/klibc.h index 4ae87d88..77bf1e9d 100644 --- a/kernel/src/klibc/include/klibc.h +++ b/kernel/src/klibc/include/klibc.h @@ -85,12 +85,9 @@ unsigned int rand(); #else #define INFO(...) #endif -//#define WARN(format, ...) kprintf("\e[38;5;208m[WARN] " format "\e[0m\n", ##__VA_ARGS__) +#define WARN(format, ...) kprintf("\e[38;5;208m[WARN] " format "\e[0m\n", ##__VA_ARGS__) + -// Defines an instruction that will raise an undefined instruction code on both ARM (and hopefully THUMB2) -#define UNDEFINED_INSTRUCTION_BYTES 0xF7F1A2F3 -#define STRINGIFY2(X) #X -#define STRINGIFY(X) STRINGIFY2(X) #define FATAL(format, ...) kprintf("\e[38;5;160m[FATAL] \e[38;5;208m%s:%i\e[38;5;160m " format "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__); panic() //4-17-15: Initial panic * assert_fail functions added diff --git a/kernel/src/klibc/klibc.c b/kernel/src/klibc/klibc.c index 72a38bcd..d1ef3e75 100644 --- a/kernel/src/klibc/klibc.c +++ b/kernel/src/klibc/klibc.c @@ -71,7 +71,7 @@ void splash() { kprintf("\t██╔════╝██║ ██║██╔══██╗██╔════╝██╔════╝██╔═══██╗ ██╔═══██╗██╔════╝\n"); kprintf("\t██║ ██║ ██║██████╔╝███████╗█████╗ ██║ ██║ ██║ ██║███████╗\n"); kprintf("\t██║ ██║ ██║██╔══██╗╚════██║██╔══╝ ██║ ██║ ██║ ██║╚════██║\n"); - kprintf("\t╚██████╗╚██████╔╝██║ ██║███████║███████╗██████╔╝ ╚██████╔╝██████║\n\n"); + kprintf("\t╚██████╗╚██████╔╝██║ ██║███████║███████╗██████╔╝ ╚██████╔╝██████║\n\n\n"); } /*4-17-15: - Prakash diff --git a/kernel/src/memory/include/memory.h b/kernel/src/memory/include/memory.h deleted file mode 100644 index 35c191a3..00000000 --- a/kernel/src/memory/include/memory.h +++ /dev/null @@ -1,43 +0,0 @@ - -#include - - - -#define P_KERNBASE 0x00008000 -#define P_KERNTOP 0x00200000 -//Physical location of kernel. Defined in the linker script. -//const uint32_t P_KERNBASE; -//const uint32_t P_KERNTOP; - -//Virtual location of kernel -#define V_KERNBASE 0xf0000000 -#define V_KERNTOP 0xf0200000 - -//All static kernel data structures -//Total space=1MB, currently used=44kB -#define P_KDSBASE 0x07f00000 -#define P_L1PTBASE P_KERNTOP - -#define V_KDSBASE 0xfff00000 -#define V_L1PTBASE V_KERNTOP - -//#define PERIPHBASE 0x10000000 -#define PERIPHBASE 0x3F000000 -#define PERIPHTOP 0x20000000 - -#define PCIBASE 0x41000000 -#define PCITOP 0x70000000 - -//remapped physical memory for direct access -#define PMAPBASE 0xf0200000 -#define PMAPTOP 0xf7f00000 - -#define BCM2836BASE 0x40000000 -#define TIMERBASE BCM2836BASE + 0x40 - -// Region where we use 4K pages. -#define P_4K_BASE (P_L1PTBASE+0x200000) -#define P_4K_TOP (PMAPTOP - 0xf0000000) - -//High vectors are enabled by setting V bit in the control register -#define HIVECTABLE 0xffff0000 diff --git a/kernel/src/memory/include/mmap.h b/kernel/src/memory/include/mmap.h deleted file mode 100644 index 104c2890..00000000 --- a/kernel/src/memory/include/mmap.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Memory Mapped I/O addresses - */ - -#ifndef MMAP_H -#define MMAP_H - -#include - -#define mmio_read(address) (*((volatile uint32_t *)(address))) -#define mmio_write(address, value) mmio_write_internal((volatile uint32_t *)(address), (volatile uint32_t)(value)) - -// Do the mmio write in assembly to remove any chance of gcc optimizing the call away. *yes* even if it was marked volatile already. -// Hence the 4 hours it took us to make timer.c work...... -static inline void mmio_write_internal(volatile uint32_t * address, volatile uint32_t value ) { - asm volatile ( - "ldr r1, %1\n" - "str r1, %0\n" - :: - "m" (*address), - "m" (value) - ); -} - -void prepare_pagetable(); -void mmap(void *p_bootargs); -void request_identity_mapped_section(size_t start_address, size_t megabytes); - -#define CLOCK_ADDRESS (volatile uint32_t *const) 0x101e8000 /* RTC base address */ - -/* Physical Hardware Addresses */ -#define PERIPHERAL_BASE_PI (volatile uint32_t *const) 0x20000000 -#define PIC_ADDRESS_PI (volatile uint32_t *const) 0x2000B000 /* interrupt controller peripheral */ -//#define UART0_ADDRESS_PI (volatile uint32_t *const) 0x20201000 /* UART 0 base address */ -#define CLOCK_ADDRESS_PI (volatile uint32_t *const) 0x20003000 /* RTC base address */ -#define GPIO_ADDRESS_PI (volatile uint32_t *const) 0x20200000 - -#endif // MMAP_H diff --git a/kernel/src/memory/mmap.c b/kernel/src/memory/mmap.c deleted file mode 100644 index a0bab95b..00000000 --- a/kernel/src/memory/mmap.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* - * APX AP Privileged Unprivileged - * 1 11 (0x8c00) = read-only read-only - * 1 01 (0x8400) = read-only no access - * 0 10 (0x0800) = read-write read-only - * 0 01 (0x0400) = read-write no-access - * See http://infocenter.arm.com/help/topic/com.arm.doc.ddi0333h/Caceaije.html - - * Bits 0 and 1 identify the table entry type - * 0 = translation fault - * 1 = course page table - * 2 = section or supersection - */ - -int vm_build_free_frame_list(void *start, void *end); - -volatile unsigned int * first_level_pt __attribute__((deprecated)) = (unsigned int *) (P_L1PTBASE + PAGE_TABLE_SIZE) ; -//extern struct vm_free_list *vm_vas_free_list; -//extern struct vm_free_list *vm_l1pt_free_list; -//extern struct vm_free_list *vm_l2pt_free_list; - -bool mmapped = false; - - -// Must be called before mmap and after vm.c -//void request_identity_mapped_section(size_t start_address, size_t megabytes) { -// -// if (mmapped) { -// // TODO: Technically possible if we were to flush the cache -// kprintf("Can only request identity mapping before mmap is called."); -// panic(); -// } -// kprintf("Identity mapping %i megabyte(s) at 0x%x\n", megabytes, start_address); -// -// for (unsigned int i = 0; i < megabytes; i++) { -//// first_level_pt[(start_address + (i * 0x100000)) >> 20] = ((start_address + (i *0x100000)) & 0xFFF00000) | 0x0400 | 2; -// } -//} - - -// 0x00000000 -// --- --- -// L1 off -void mmap(void *p_bootargs) { - - disable_interrupt(BOTH); - //stash register state on the stack - asm volatile("push {r0-r11}"); - - kprintf("Boot arguments location: %X\n", p_bootargs); - -// kprintf("first_level_pt=%X\n", first_level_pt); - -// for (int i = 0; i < PAGE_TABLE_SIZE >> 2; i++) { -// first_level_pt[i] = 0; -// } - - //temporarily map where it is until we copy it in VAS -// first_level_pt[P_KDSBASE >> 20] = P_KDSBASE | 0x0400 | 2; - //first_level_pt[0x07f00000>>20] = first_level_pt[7F] = 0x07ffirst_level_pt=400000000 = 0x07f04010 - // 0x00004000 - // 0x00000010 - - //1MB for static kernel data structures (stacks and l1 pt) -// first_level_pt[V_KDSBASE >> 20] = P_KDSBASE | 0x0400 | 2; - //first_level_pt[0xfff00000>>20] = first_level_pt[0xfff] = 0x0x7f04010 - - //map the kernel where its currently loaded in the same location temporarily - //should be less than a MB -// first_level_pt[P_KERNBASE >> 20] = 0 << 20 | 0x0400 | 2; - - //also map it to high memory at 0xf0000000 (vpn = 3840) -// first_level_pt[V_KERNBASE >> 20] = 0 << 20 | 0x0400 | 2; -// first_level_pt[(V_KERNBASE + 0x100000) >> 20] = 0x100000 | 0x0400 | 2; // 0xf...; - - //map ~2MB of peripheral registers one-to-one -// first_level_pt[PERIPHBASE >> 20] = PERIPHBASE | 0x0400 | 2; // PERIPHBASE + 1 MiB -// first_level_pt[(PERIPHBASE + 0x100000) >> 20] = (PERIPHBASE + 0x100000) | 0x0400 | 2; -// first_level_pt[(PERIPHBASE + 0x200000) >> 20] = (PERIPHBASE + 0x200000) | 0x0400 | 2; -// first_level_pt[(0x20000000) >> 20] = (0x20000000) | 0x0400 | 2; -// -// first_level_pt[BCM2836BASE >> 20] = (BCM2836BASE & 0xFFF00000) | 0x0400 | 2; // TIMERBASE + 1 MiB -// first_level_pt[(PERIPHBASE) >> 20] = (PERIPHBASE + 0x300000) | 0x0400 | 2; - - - // TODO: re enable when we actually need it. 700mb seems a bit excessive though. - //map 752MB of PCI interface one-to-one -// unsigned int pci_bus_addr = PCIBASE; -// for (int i = (PCIBASE >> 20); i < (PCITOP >> 20); i++) { -// first_level_pt[i] = pci_bus_addr | 0x0400 | 2; -// pci_bus_addr += 0x100000; -// } -// request_identity_mapped_section(Gibibyte - 25 * Mebibyte, 20); - - // Quick coarse page table address - //unsigned int coarse_page_table_address = P_L1PTBASE + 2*PAGE_TABLE_SIZE; - //os_printf("coarse pt: 0x%X\n", coarse_page_table_address); - - //remap 62MB of physical memory after the kernel - // (KERNTOP to end of physical RAM (PMAPTOP)) - // This is where we allocate frames from. Except for the first one. -// unsigned int phys_addr = P_KERNTOP; - // +1 to skip L1PTBASE -// for (int i = (PMAPBASE >> 20); i < (PMAPTOP >> 20); i++) { -// first_level_pt[i] = phys_addr | 0x0400 | 2; -// phys_addr += 0x100000; -// } - - - // Fill in the coarse page table - // (TODO: How do we handle 64kB pages? Do they take up 16 entries?) - //os_memset((void*)coarse_page_table_address, 0, L2_PAGE_TABLE_SIZE); - // Set the first page to phys_addr - //*(unsigned int*)coarse_page_table_address = phys_addr | 0x20 | 2; - //os_printf("0x%X\n", *(unsigned int*)coarse_page_table_address); - -// first_level_pt[V_L1PTBASE >> 20] = P_L1PTBASE | 0x0400 | 2; - - // We have to empty out the first MB of that, so we can use it as an array of VASs - // The first slot is actually the kernel's VAS -// ((struct vas*) P_L1PTBASE)->l1_pagetable = (unsigned int*) (V_L1PTBASE + PAGE_TABLE_SIZE); //first_level_pt; -// ((struct vas*) P_L1PTBASE)->l1_pagetable_phys = first_level_pt; -// ((struct vas*) P_L1PTBASE)->next = 0x0; -// vm_vas_free_list = (struct vm_free_list*) ((void*) vm_vas_free_list + sizeof(struct vas)); -// vm_l1pt_free_list = (struct vm_free_list*) ((void*) vm_l1pt_free_list + PAGE_TABLE_SIZE); - -// unsigned int pt_addr = (unsigned int) first_level_pt; - - /*CONTROL REGISTER - * Enable MMU by setting 0 - * Alignment bit 1 - * D-cache bit 2 - * I-cache bit 12 - * V bit 13 (1=high vectors 0xffff0000) - * We disable high vectors, since low vectors work just fine. - */ - -// asm volatile ( -// // invalidate caches -// "mcr p15, 0, %[r], c7, c7, 0\n" -// // invalidate tlb -// "mcr p15, 0, %[r], c8, c7, 0\n" -// // data sync barrier -// "mcr p15, 0, %[r], c7,c10, 4\n" -// -// // set domains -// "mov r2, #0x01\n" -//// "ldr r2, =0x55555555\n" // [added] full r/w to everyone -// "mcr p15, 0, r2, c3, c0, 0\n" -// -// "mcr p15, 0, %[addr], c2, c0, 0\n" // Give the pagetable addr to the MMU -// "mcr p15, 0, %[addr], c2, c0, 1\n" -// -// "mrc p15, 0, r3, c1, c0, 0\n" // Read p15 -//// "mov r4, #0x1000 \n" -//// "add r4, #0x7 \n" -//// "orr r3, r4 \n" -// "orr r3, #0x800000\n" // Enable Armv6 bit -//// "orr r3, #0x1000\n" -// "orr r3, r3, #0x1\n" // Enable MMU bit -// "mcr p15, 0, r3, c1, c0, 0 \n" // Set p15 -// : -// : [addr] "r" (pt_addr), -// [r] "r" (0x0) -// ); - -// mmapped = true; - -// SemihostingCall(OSSpecific); - - // Build the free frame list -// vm_build_free_frame_list((void*) PMAPBASE + 0x100000, (void*) PMAPTOP); //(void*)PMAPBASE+(unsigned int)((PMAPTOP)-(PMAPBASE))); - - //restore register state - asm volatile("pop {r0-r11}"); - - // Except for r0, which is p_bootargs. stacks.s needs to know it. - asm volatile("mov r0, %[args]" : : [args] "r" (p_bootargs)); - - // asm volatile("cpsie if"); - asm volatile (".include \"src/memory/stacks.s\""); - -// void start2(uint32_t *p_bootargs); -// kprintf("Location of start2: 0x%x\n", &start2); -// //branch to proper kernel at start -//// asm volatile("bl start2"); -// -// void * oldstart2 = start2; -// void (*newstart2)(uint32_t *) = oldstart2 + V_KERNBASE; -// -// newstart2(p_bootargs); -} diff --git a/kernel/src/memory/stacks.s b/kernel/src/memory/stacks.s deleted file mode 100644 index 4bc9e933..00000000 --- a/kernel/src/memory/stacks.s +++ /dev/null @@ -1,52 +0,0 @@ -.equ stack_size, 0x1000 -.equ stack_base, 0xfffff000 - -.equ Mode_USR, 0x10 -.equ Mode_FIQ, 0x11 -.equ Mode_IRQ, 0x12 -.equ Mode_SVC, 0x13 -.equ Mode_MON, 0x16 -.equ Mode_ABT, 0x17 -.equ Mode_UND, 0x1B -.equ Mode_SYS, 0x1F - - MOV R1, R0 // R0 has p_bootargs, which we need to hang onto - LDR R0, =stack_base - MSR CPSR_c, #Mode_FIQ - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_IRQ - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_SVC - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_MON - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_ABT - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_UND - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_SYS - MOV sp, R0 - - MSR CPSR_c, #Mode_SVC - ADD fp, sp, #0 - - EOR R0, R0 - ADD R0, pc, #0xf0000000 - MOV pc, R0 - - EOR R0, R0 - ADD R0, lr, #0xf0000000 - MOV lr, R0 - MOV R0, R1 diff --git a/kernel/src/memory/vm/include/frame.h b/kernel/src/memory/vm/include/frame.h deleted file mode 100644 index 87f00fa5..00000000 --- a/kernel/src/memory/vm/include/frame.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __VM_FRAME_H -#define __VM_FRAME_H - -int vm_build_free_frame_list(void *start, void *end); -void *vm_get_free_frame(); -void vm_release_frame(void *p); -int vm_count_free_frames(); - -#endif diff --git a/kernel/src/memory/vm/include/swap_framework.h b/kernel/src/memory/vm/include/swap_framework.h deleted file mode 100644 index d8a6380b..00000000 --- a/kernel/src/memory/vm/include/swap_framework.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef __VM_SWAP_FRAMEWORK_H -#define __VM_SWAP_FRAMEWORK_H - -#include "../../../../old/include/klibc.h" -#include "stdint.h" - -// NOTE: SWAPPING CANNOT WORK UNTIL FILESYSTEMS CAN ALLOCATE MORE THAN 16 PAGES AT A TIME -/* Contributors: Noel Negusse and Jesse Thaden - * Last Update: 05/10/15 - */ - -/* Function: swap_framework - * Purpose: To present an API for swapping pages to various swap spaces - * so that pages may be stored independently of other related operations - * - * EXAMPLE OF VIRTUAL MEMORY ID/ADDRESS FROM SWAP SPACE - * _____________________________________________________________ - * || [24 bit] SWAP SPACE OFFSET |[8 bit] SWAP SPACE # || - * ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - * * Total: 32 Bit Address - * therefore, there are 256 possible swap spaces possible - * w/ 2^12 page entries each (Assuming 4kB pages) - */ - -#define SWAP_SPACES (1<<8) -#define PAGE_ENTRIES (1<<12) // Assuming 4kB Pages right now -#define PAGE_SIZE (1<<12) // May carry an if statement later to account for different page sis -#define COMPRESSED_SIZE 10 // The size of compressing 16MiB of data - -typedef uint32_t *(*func)(void*, uint32_t*); - -struct swap_space { - struct swap_entry *e_head; // currently only used for LZ swap -// uint16_t pages_free; - uint8_t lower_bits; // swap space ID [8-bits] -// uint16_t flags; // swp_used (1000 or 1), swp_writeok (0010 or 2) or both (0011 or 3) - uint8_t priority; // lower is better - func store_func; - func retrieve_func; -}; // Total: 14 bytes - -struct swap_entry { - uint16_t e_flags; // PRIVILEGED_RO = 1, USER_RO = 2, PRIVILEGED_RW = 4, USER_RW = - uint16_t cmp_size; // size of compressed page - void *cmp_page; // virtual address pointer used for resolving page faults; NULL = unusedi -}; // Total: 8 bytes - -static struct swap_space *holder; -static os_size_t memory_count; - - -// Swap_init initializes swap framework -void swap_init(); -//void swap_init(os_size_t); To be implemented... [specifies global page size] - - -/* store_page will store a page to media - not main memory - storage, e.g. HDD - * from the page*. ID parameter passed will change to appropriate index (i.e. return value) - * void* page -> data to be paged - * os_size_t pagesize: The size of a page in bytes, i.e. 4096 b - * uint32_t* ID -> The page ID or address - * - * Returns: A pointer to a index value (from a bit vector) in memory - * OR returns a NULL/0 on failure - */ -uint32_t store_page(void*, uint32_t*); -uint32_t store_page_LZ(void*, uint32_t*); // All LZ functions not yet working... -// uint32_t *store_page(void*, os_size_t, uint32_t*); To be implemented... (will replace) -// uint32_t *store_pageLZ(void*, os_size_t, uint32_t*); diddo - - -/* retrieve_page will retrieve the page identified the ID pointer and - * will store it back into main memory (specified by the void *page pointer) - * - * Returns: NULL on failure or simply passes back ID on success - * NOTE: Page size was set by store_page - */ -uint32_t retrieve_page(void*, uint32_t*); -uint32_t retrieve_page_LZ(void*, uint32_t*); - - -/* Returns: The total stored memory in bytes by function store_page(void*, uint32_t*) */ -os_size_t sum_stored(); - - -/* vm_swap_page will store a page from main memory (specified by void *page) - * to a swap space either on disk or a compressed block in memory - * - * Returns: The ID pointer - bit vector index - of where the swap_space was stored and - * changes the ID pointer that value as well. Returns NULL on failure - */ -uint32_t vm_swapout_page(void*, uint32_t*); // store the page -uint32_t vm_swapin_page(void*, uint32_t*); // retrieve the page - - -/* vm_register/vm_deregister will activate/deactivate a swap space and set a priority - * accordingly to it. This allows the swap spaces use as well as increasing it's efficiency - * NOTE: deregister_swap_space will always deregister the lowest priority swap space first - * - * Returns: -1 or 1 whether the swap space registeration was a failure or success, respectively - */ -int vm_register_swap_space(func, func, int, int16_t); -void vm_deregister_swap_space(uint8_t); - - -/* Resolves the page fault and updates the corresponding page table - * - * Returns: 0 if the page_fault could not be resolved - * returns the new physical address of the loaded memory - */ -uint32_t vm_page_fault_handler(void*); - - -/* vm_scan_pages will scan through all pages for the corresponding page - * to the given page - * - * Returns: The address of matching swapped page - */ -//uint32_t* vm_scan_pages(void*); - -#endif diff --git a/kernel/src/memory/vm/include/swap_fs.h b/kernel/src/memory/vm/include/swap_fs.h deleted file mode 100644 index ddd64701..00000000 --- a/kernel/src/memory/vm/include/swap_fs.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __VM_SWAP_FS_H -#define __VM_SWAP_FS_H - -#include "bitvector.h" -#include "swap_framework.h" - - -/* Last Update: 05/11/15 */ - - -bit_vector *bv_arr[SWAP_SPACES]; -// bit_vector *free_bitvector; - - -//helper function -char *generate_filename(uint8_t); - - -/* swapfs_init initializes swap file system framework for 'npages' number of pages - * - * Returns: -1 if failure, number of bytes written on success - */ -int32_t swapfs_init(int, uint8_t); - - -/* swapfs_store will store a page to media - not main memory - storage, e.g. HDD - * from the page* - * void* page -> data to be paged - * os_size_t pagesize: The size of a page in bytes, i.e. 4096 b - * uint32_t* ID -> The page ID or address - * - * Returns: The stored page's swap space ID, index OR -1 on failure - * NOTE: Relying on the changed id pointer is safer than using the output (unless - * for error checking) due to the int64_t type output - */ -int64_t swapfs_store(void*, uint32_t*, uint8_t); - - -/* swapfs_retrieve will retrieve the page identified by the ID pointer and - * will store it back into main memory (specified by the void *page pointer) - * - * Returns: -1 on failure and 1 on success - */ -int64_t swapfs_retrieve(void*, uint32_t*, uint8_t); - - -/* Returns: -1 if failure, 1 if success */ -int32_t swapfs_disable(uint8_t); - - -#endif diff --git a/kernel/src/memory/vm/include/swap_pqueue.h b/kernel/src/memory/vm/include/swap_pqueue.h deleted file mode 100644 index 3945070e..00000000 --- a/kernel/src/memory/vm/include/swap_pqueue.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __VM_SWAP_PQUEUE_H -#define __VM_SWAP_PQUEUE_H - -#include "stdint.h" -#include "swap_framework.h" - - -/* Last Update: 05/10/15 */ - - -struct node{ - struct node *next; - struct swap_entry *e_head; - uint8_t lower_bits; // swap space ID [8-bits] -// uint16_t flags; // SWP_USED (1000 or 1), SWP_WRITEOK (0010 or 2) - uint8_t priority; // lower is better - func store_func; - func retrieve_func; -}; // Total: 16 bytes - -static struct node *head; -static struct node *path; //tail -static uint8_t s; - - -/* pqueue_init initializes the priority queue with a given - * swap_space type struct - */ -void pqueue_init(struct swap_space*); - - -/* pqueue_set does a deep copy of the value of the second - * struct to the front struct - */ -void pqueue_set(struct node*, struct swap_space*); - - -/* pqueue_push pushes the swap_space struct onto the proper - * index based on the priority found in the struct - */ -void pqueue_push(struct swap_space*); - - -/* pqueue_pop_front & pqueue_pop_back pops a node from the head/back of the - * pqueue_pop_front priority queue as well as freeing the given memory of the - * head/back - */ -void pqueue_pop_front(); -void pqueue_pop_back(); -void pqueue_pop_at(uint8_t); // Note: 'at' ssid not index - -/* pqueue_size returns the current size of the priority queue */ -uint8_t pqueue_size(); - - -/* pqueue_index finds the given index of the priority queue - * - * Returns: The struct of the given index in pqueue - * NOTE: THIS IS NOT THE SAME AS THE SWAP_SPACE STRUCT - */ -struct node *pqueue_index(int); - - -/* It 'peeks' at the head of the list for a specified value - * - * Returns: The specified value from the head of the list - * 0 - lower_bits - * 1 - priority - * 2 - e_head - */ -void *pqueue_peek(int); - - -/* pqueue_find finds the actual index of the swap space ID (lower_bit value) - * - * Returns: The found node specified or NULL if not found - * NOTE: THIS IS NOT THE SAME AS THE SWAP_SPACE STRUCT - */ -struct node *pqueue_find(uint8_t); - - -#endif diff --git a/kernel/src/memory/vm/include/vm.h b/kernel/src/memory/vm/include/vm.h deleted file mode 100644 index e3111c97..00000000 --- a/kernel/src/memory/vm/include/vm.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef __VM_H -#define __VM_H - -#include -#include -#include -#include - -//#define BLOCK_SIZE (1<<20) -#define BLOCK_SIZE ((uint32_t)(1<<12)) - -#define PAGE_TABLE_SIZE (1<<14) -#define L2_PAGE_TABLE_SIZE (1<<12) - -struct vas { - // A pointer to the first level of the pagetable. - volatile unsigned int *l1_pagetable; - volatile unsigned int *l1_pagetable_phys; // The physical address to it - - // A pointer to the next VAS (it's a linked list) - struct vas *next; -}; - -#define VM_ERR_BADV -1 -#define VM_ERR_BADP -2 -#define VM_ERR_MAPPED -3 -#define VM_ERR_BADPERM -4 -#define VM_ERR_UNKNOWN -5 -#define VM_ERR_NOT_MAPPED -6 - -#define KERNEL_VAS ((struct vas*)V_L1PTBASE) - - -#define VM_L1_GET_ENTRY(table,vptr) table[((unsigned int)vptr)>>20] -#define VM_L1_SET_ENTRY(table,vptr,ent) (table[((unsigned int)vptr)>>20]=ent) -#define VM_ENTRY_GET_FRAME(x) ((x)&~((PAGE_TABLE_SIZE<<1) - 1)) -#define VM_ENTRY_GET_L2(x) ((x)&~0x1FF) -#define VM_L2_ENTRY(l2pt,vptr) ((uint32_t*)l2pt)[((unsigned int)vptr&0x000FF000)>>12] -#define VM_L2ENTRY_GET_FRAME(x) ((x)&0xFFFFF000) - -/** - * These permissions dictate who can access what pages. Note that you - * cannot combine these arbitrarily. For example: - * VM_PERM_PRIVILEGED_RO|VM_PERM_PRIVILEGED_RW - * makes no sense. If the user mode is granted a given permission, then the - * privileged mode is granted that permission as well, unless there is a - * confliction. Some examples: - * VM_PERM_USER_RO - * grants RO status to both user and privileged modes. - * - * VM_PERM_USER_RO|VM_PERM_PRIVILEGED_RW - * grants RO to the user, and RW to privileged modes. - * - * VM_PERM_USER_RW|VM_PERM_PRIVILEGED_RO - * doesn't make sense. USER_RW grants RW to both user and privileged, but - * PRIVILEGED_RO contradicts the USER_RW's implied grant. - * - * VM_ERR_BADPERM is returned if a bad permission is passed. Note that 0 - * is a valid permission, indicating that nobody may have access. - * - * (RO stands for Read-Only, RW for Read-Write) - */ -#define VM_PERM_PRIVILEGED_RO 1 -#define VM_PERM_USER_RO 2 -#define VM_PERM_PRIVILEGED_RW 4 -#define VM_PERM_USER_RW 8 - -void vm_init(); - -/** - * vm_allocate_page and vm_free_page allocate and free pages, and allow the - * VAS to access them at the given virtual address (vptr). - * Note that you cannot call free_page on a virtual address that was - * mapped using set_mapping. - * Return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_MAPPED - vptr is already mapped in this VAS. - * VM_ERR_BADPERM - permission is not valid (see above). - * - * free_page return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_MAPPED - vptr was mapped using set_mapping, not allocate_page. - * VM_ERR_NOT_MAPPED - vptr is not mapped in this VAS. - */ -int vm_allocate_page(struct vas *vas, void *vptr, int permission); -void *vm_allocate_pages(struct vas *vas, void *vptr, uint32_t nbytes, int permission); -int vm_free_page(struct vas *vas, void *vptr); - -/** - * vm_pin and vm_unpin currently do nothing. However, in the future, they will - * prevent pages from being swapped out of physical memory. - * Return values: - * 0 - Success. - */ -int vm_pin(struct vas *vas, void *vptr); -int vm_unpin(struct vas *vas, void *vptr); - -/** - * vm_set_mapping maps the given vptr to the given pptr. - * Return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_BADP - pptr was not a multiple of BLOCK_SIZE. - * VM_ERR_MAPPED - vptr is already mapped in this VAS. - * VM_ERR_BADPERM - permission is not valid. - * - * vm_free_mapping unmaps the vptr. Note that you may not call free_mapping - * on a virtual address that was allocated using allocate_page. - * Return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_NOT_MAPPED - vptr was not mapped using set_mapping. - */ -int vm_set_mapping(struct vas *vas, void *vptr, void *pptr, int permission); -int vm_free_mapping(struct vas *vas, void *vptr); - - -/* vm_swap_free_mapping is the spapping frameworks flavor on vm's vm_free_mapping - * It takes in an extra paramter that will be set to the L2 page entry (instead of 0) - * - Noel Negusse - * - * Returns: Same as vm_free_mapping - */ -int vm_swap_free_mapping(struct vas*, void*, uint32_t*); - - -/** - * Will make the memory that accessible to other_vas at other_ptr - * accessible to vas at this_ptr. - * It can then be unmapped from either using a typical vm_free_mapping - * or vm_free_page. The behavior of vm_free_mapping and vm_free_page - * will be made equivalent. - * For both, the behavior will be to free the frame if a frame was - * allocated (via vm_allocate_page) and the page is not shared. If the - * page is shared, then both will behave like vm_free_mapping. - * - * It is an error for other_ptr to point to an area not mapped in other_vas. - * - * For example, given vas1 and vas2: - * - * vm_allocate_page(vas2,0x10) - * vm_map_shared_memory(vas1, 0x20, vas2, 0x10) - * // Now vas1's 0x20 points to the same memory as vas2's 0x10 - * vm_free_page(vas2, 0x10) - * // Now vas1 is the sole owner of the memory at vas1's 0x20 - * vm_free_mapping(vas1, 0x20) - * // Now that frame has been freed - * - * All the pointers have to be a multiple of BLOCK_SIZE. - * - * Return values: - * 0 - success - * VM_ERR_BADV - this_ptr was not a multiple of BLOCK_SIZE. - * VM_ERR_BADP - other_ptr was not a multiple of BLOCK_SIZE. - * VM_ERR_NOT_MAPPED - other_ptr is not mapped in other_vas. - * VM_ERR_MAPPED - this_ptr is already mapped in vas. - * VM_ERR_BADPERM - permission is bad. - */ -int vm_map_shared_memory(struct vas *vas, void *this_ptr, struct vas *other_vas, void *other_ptr, int permission); - -/** - * This enabled the given VAS. - */ -void vm_enable_vas(struct vas *vas); - -/** - * Allocates a new VAS. - * - * Note that there is a limit of 4096 VASs in the system, including the - * kernel's VAS. - */ -struct vas *vm_new_vas(); -int vm_free_vas(struct vas *vas); - -/** - * Retrieves a reference to the currently running VAS. - */ -struct vas *vm_get_current_vas(); - -/** - * Switches to the kernel's VAS. - */ -void vm_use_kernel_vas(); - -static inline void ensure_kernel_vas() -{ - assert (vm_get_current_vas() == KERNEL_VAS && "Must run in kernel VAS!"); -} - -void vm_test(); - -static inline void vm_invalidate_tlb(void) -{ - // Invalidate the TLB - asm volatile("mcr p15, 0, %[r], c8, c5, 0" : : [r] "r" (0x0)); - asm volatile("mcr p15, 0, %[r], c8, c6, 0" : : [r] "r" (0x0)); - asm volatile("mcr p15, 0, %[r], c8, c7, 0" : : [r] "r" (0x0)); -} - -uint32_t *vm_vtop(struct vas *vas, uint32_t *vptr); -uint32_t *vm_ptov(struct vas *vas, uint32_t *vptr); - -#endif diff --git a/kernel/src/memory/vm/test/test_vm.c b/kernel/src/memory/vm/test/test_vm.c deleted file mode 100644 index 2a0f8bbd..00000000 --- a/kernel/src/memory/vm/test/test_vm.c +++ /dev/null @@ -1,105 +0,0 @@ -//#include -//#include "klibc.h" -//#include "memory.h" -//#include "vm.h" -// -//// TODO: This test has many LOG calls, we should try and looking at improving the logging capabilities -//TEST_CREATE(test_vm_1, { -// struct vas *vas1 = vm_new_vas(); -// LOG("Got new vas at 0x%X\n", vas1); -// -// // We're part of the kernel, which is already mapped into vas1. -// // But our stack isn't, so let's add that mapping. -// unsigned int mystack = (unsigned int) &vas1; -// mystack &= 0xFFF00000; // Round down to nearest MB -// LOG("Stack addr: 0x%X\n", mystack); -// LOG("Created page table w/ 0xFFF00000's entry = 0x%X\n", -// vas1->l1_pagetable[V_KDSBASE>>20]); -// -// vm_enable_vas(vas1); -// -// // Do we still have the stack? -// // FIXME Update constant as necessary -// #define STACK_ADDR 0xF020000C -// // Invalid stack -// ASSERT_EQ((unsigned int) vas1, STACK_ADDR); -// -// struct vas *vas2 = (struct vas*) V_L1PTBASE; -// INFO("%X (%X)\n", vas2, &vas2); -// INFO("%X\n", *((unsigned int* ) vas2)); -// INFO("%X\n", vas2->l1_pagetable); -// INFO("Entry: %x\n", -// vas1->l1_pagetable[(unsigned int ) vas2->l1_pagetable >> 20]); -// INFO("%X\n", vas2->l1_pagetable[0]); -// INFO("(deref: entry at 0x200000: 0x%X)\n", -// vas2->l1_pagetable[0x200000 >> 20]); -// -// // Test making a thing in this thing -// struct vas *vas3 = vm_new_vas(); -// vm_enable_vas(vas3); -// INFO("%X and %X and %X\n", vas1, vas2, vas3); -// -// // Test allocating frames... -// #define P3_BASE 0x24000000 -// int retval = vm_allocate_page(vas3, (void*) P3_BASE, VM_PERM_PRIVILEGED_RW); -// -// // vm_allocate_page fails -// ASSERT(!retval); -// -// int *p = (int*) 0xFFFFFFF0; -// p[0] = 1; -// -// ASSERT_EQ(p[0], 1); -// -// // Oh man! We should be able to write to there! -// p = (int*) P3_BASE; -// p[0] = 1; -// -// LOG("%x %x\n", &p, p); -// -// ASSERT_EQ(p[0], 1); -// -// // Test shared memory... -// LOG("Testing shared memory...\n"); -// int *p_3 = (int*) P3_BASE;//0x24000000; -// int *p_1 = (int*) 0x31000000; -// retval = vm_map_shared_memory(vas1, p_1, vas3, p_3, VM_PERM_PRIVILEGED_RW); -// LOG("map_shared_memory returned %d\n", retval); -// -// p_3[0] = 321; -// vm_enable_vas(vas1); -// ASSERT_EQ(p_1[0], 321); -// p_1[1] = 456; -// -// vm_enable_vas(vas3); -// ASSERT_EQ(p_3[1], 456); -// -// // Test allocating many frames... (this was commented but seems to work just fine) -// *p += BLOCK_SIZE; -// while (!vm_allocate_page(vas3, (void*) p, 0)) { -// //LOG("Allocated memory...\n"); -// p += BLOCK_SIZE; -// } -// -// p -= BLOCK_SIZE; -// kprintf("Highest frame allocated: 0x%X\n", p); -// -// while ((unsigned int) p > P3_BASE) { -// //LOG("Freed memory...\n"); -// vm_free_page(vas3, p); -// p -= BLOCK_SIZE; -// } -// -// // FIXME: This part of the test crashes the os, we should catch that in some way. -// // Test the data abort... -//// WARN("You should see a data abort...\n"); -//// int i = p[-1]; -//// LOG("%d\n", i); -// -// // Free the page! -// LOG("Freeing page at %X\n", p); -// vm_free_page(vas3, p); -// -// // Clean up & switch back to the kernel's VAS before we return. -// vm_enable_vas((struct vas*) KERNEL_VAS); -//}) diff --git a/kernel/src/vm/README.md b/kernel/src/vm/README.md new file mode 100644 index 00000000..7d0d0b31 --- /dev/null +++ b/kernel/src/vm/README.md @@ -0,0 +1,37 @@ + +# Virtual Memory + +## Description + +## Memory map + +### Physical + +| Address | Description | +| ---------- | ---------------------------------------------------------------------- | +| 0x0000000 | Interrupt Vector Table | +| 0x0004000 | Kernel L1 page table | +| 0x0008000 | Kernel start | +| ... | *Kernel* | +| ... | *Kernel* | +| KERNEL END | Physical Memory Manager starting point | +| ... | Physical Memory Manager | +| 0xXXXXXXXX | End of Physical memory (Device dependent, max 1GB) | + +### Virtual + +| 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 | +| ... | *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) | + +***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/mmio.h b/kernel/src/vm/include/mmio.h new file mode 100644 index 00000000..3d446ac6 --- /dev/null +++ b/kernel/src/vm/include/mmio.h @@ -0,0 +1,21 @@ +#ifndef MMIO_H +#define MMIO_H + + +#define mmio_read(address) (*((volatile uint32_t *)(address))) +#define mmio_write(address, value) mmio_write_internal((volatile uint32_t *)(address), (volatile uint32_t)(value)) + +// Do the mmio write in assembly to remove any chance of gcc optimizing the call away. *yes* even if it was marked volatile already. +// Hence the 4 hours it took us to make timer.c work...... +static inline void mmio_write_internal(volatile uint32_t * address, volatile uint32_t value ) { + asm volatile ( + "ldr r1, %1\n" + "str r1, %0\n" + :: + "m" (*address), + "m" (value) + ); +} + +#endif + diff --git a/kernel/src/memory/vm/include/pmm.h b/kernel/src/vm/include/pmm.h similarity index 100% rename from kernel/src/memory/vm/include/pmm.h rename to kernel/src/vm/include/pmm.h diff --git a/kernel/src/memory/vm/include/tlb_cache_id_allocator.h b/kernel/src/vm/include/tlb_cache_id_allocator.h similarity index 100% rename from kernel/src/memory/vm/include/tlb_cache_id_allocator.h rename to kernel/src/vm/include/tlb_cache_id_allocator.h diff --git a/kernel/src/memory/vm/include/vas2.h b/kernel/src/vm/include/vas2.h similarity index 80% rename from kernel/src/memory/vm/include/vas2.h rename to kernel/src/vm/include/vas2.h index 7982774d..2356602d 100644 --- a/kernel/src/memory/vm/include/vas2.h +++ b/kernel/src/vm/include/vas2.h @@ -1,8 +1,8 @@ #ifndef VAS_2_H #define VAS_2_H -#include -#include +#include "vm2.h" +#include "tlb_cache_id_allocator.h" struct vas2 { diff --git a/kernel/src/memory/vm/include/vm2.h b/kernel/src/vm/include/vm2.h similarity index 99% rename from kernel/src/memory/vm/include/vm2.h rename to kernel/src/vm/include/vm2.h index 1333bd86..5e1bb231 100644 --- a/kernel/src/memory/vm/include/vm2.h +++ b/kernel/src/vm/include/vm2.h @@ -326,4 +326,7 @@ extern const size_t __KERNEL_VIRTUAL_OFFSET[]; #define PAGE_SIZE (4 * Kibibyte) + + + #endif diff --git a/kernel/src/memory/vm/memory-layout.svg b/kernel/src/vm/memory-layout.svg similarity index 100% rename from kernel/src/memory/vm/memory-layout.svg rename to kernel/src/vm/memory-layout.svg diff --git a/kernel/src/memory/vm/pmm.c b/kernel/src/vm/pmm.c similarity index 100% rename from kernel/src/memory/vm/pmm.c rename to kernel/src/vm/pmm.c diff --git a/kernel/src/memory/vm/test/test_pagealloc2.c b/kernel/src/vm/test/test_pagealloc2.c similarity index 100% rename from kernel/src/memory/vm/test/test_pagealloc2.c rename to kernel/src/vm/test/test_pagealloc2.c diff --git a/kernel/src/memory/vm/test/test_vm2.c b/kernel/src/vm/test/test_vm2.c similarity index 100% rename from kernel/src/memory/vm/test/test_vm2.c rename to kernel/src/vm/test/test_vm2.c diff --git a/kernel/src/memory/vm/tlb_cache_id_allocator.c b/kernel/src/vm/tlb_cache_id_allocator.c similarity index 100% rename from kernel/src/memory/vm/tlb_cache_id_allocator.c rename to kernel/src/vm/tlb_cache_id_allocator.c diff --git a/kernel/src/memory/vm/vas2.c b/kernel/src/vm/vas2.c similarity index 100% rename from kernel/src/memory/vm/vas2.c rename to kernel/src/vm/vas2.c diff --git a/kernel/src/memory/vm/vm2.c b/kernel/src/vm/vm2.c similarity index 100% rename from kernel/src/memory/vm/vm2.c rename to kernel/src/vm/vm2.c