Mercurial > hg > CbC > CbC_xv6
diff src/start.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/start.c Fri May 26 23:11:05 2017 +0900 @@ -0,0 +1,193 @@ +// initialize section +#include "types.h" +#include "param.h" +#include "arm.h" +#include "mmu.h" +#include "defs.h" +#include "memlayout.h" + +void _uart_putc(int c) +{ + volatile uint8 * uart0 = (uint8*)UART0; + *uart0 = c; +} + + +void _puts (char *s) +{ + while (*s != '\0') { + _uart_putc(*s); + s++; + } +} + +void _putint (char *prefix, uint val, char* suffix) +{ + char* arr = "0123456789ABCDEF"; + int idx; + + if (prefix) { + _puts(prefix); + } + + for (idx = sizeof(val) * 8 - 4; idx >= 0; idx -= 4) { + _uart_putc(arr[(val >> idx) & 0x0F]); + } + + if (suffix) { + _puts(suffix); + } +} + + +// kernel page table, reserved in the kernel.ld +extern uint32 _kernel_pgtbl; +extern uint32 _user_pgtbl; + +uint32 *kernel_pgtbl = &_kernel_pgtbl; +uint32 *user_pgtbl = &_user_pgtbl; + +#define PDE_SHIFT 20 + +uint32 get_pde (uint32 virt) +{ + virt >>= PDE_SHIFT; + return kernel_pgtbl[virt]; +} + +// setup the boot page table: dev_mem whether it is device memory +void set_bootpgtbl (uint32 virt, uint32 phy, uint len, int dev_mem ) +{ + uint32 pde; + int idx; + + // convert all the parameters to indexes + virt >>= PDE_SHIFT; + phy >>= PDE_SHIFT; + len >>= PDE_SHIFT; + + for (idx = 0; idx < len; idx++) { + pde = (phy << PDE_SHIFT); + + if (!dev_mem) { + // normal memory, make it kernel-only, cachable, bufferable + pde |= (AP_KO << 10) | PE_CACHE | PE_BUF | KPDE_TYPE; + } else { + // device memory, make it non-cachable and non-bufferable + pde |= (AP_KO << 10) | KPDE_TYPE; + } + + // use different page table for user/kernel space + if (virt < NUM_UPDE) { + user_pgtbl[virt] = pde; + } else { + kernel_pgtbl[virt] = pde; + } + + virt++; + phy++; + } +} + +static void _flush_all (void) +{ + uint val = 0; + + // flush all TLB + asm("MCR p15, 0, %[r], c8, c7, 0" : :[r]"r" (val):); + + // invalid entire data and instruction cache + // asm ("MCR p15,0,%[r],c7,c5,0": :[r]"r" (val):); + // asm ("MCR p15,0,%[r],c7,c6,0": :[r]"r" (val):); +} + +void load_pgtlb (uint32* kern_pgtbl, uint32* user_pgtbl) +{ + uint ret; + char arch; + uint val; + + // read the main id register to make sure we are running on ARMv6 + asm("MRC p15, 0, %[r], c0, c0, 0": [r]"=r" (ret)::); + + if (ret >> 24 == 0x41) { + //_puts ("ARM-based CPU\n"); + } + + arch = (ret >> 16) & 0x0F; + + if ((arch != 7) && (arch != 0xF)) { + _puts ("need AARM v6 or higher\n"); + } + + // we need to check the cache/tlb etc., but let's skip it for now + + // set domain access control: all domain will be checked for permission + val = 0x55555555; + asm("MCR p15, 0, %[v], c3, c0, 0": :[v]"r" (val):); + + // set the page table base registers. We use two page tables: TTBR0 + // for user space and TTBR1 for kernel space + val = 32 - UADDR_BITS; + asm("MCR p15, 0, %[v], c2, c0, 2": :[v]"r" (val):); + + // set the kernel page table + val = (uint)kernel_pgtbl | 0x00; + asm("MCR p15, 0, %[v], c2, c0, 1": :[v]"r" (val):); + + // set the user page table + val = (uint)user_pgtbl | 0x00; + asm("MCR p15, 0, %[v], c2, c0, 0": :[v]"r" (val):); + + // ok, enable paging using read/modify/write + asm("MRC p15, 0, %[r], c1, c0, 0": [r]"=r" (val)::); + + val |= 0x80300D; // enable MMU, cache, write buffer, high vector tbl, + // disable subpage + asm("MCR p15, 0, %[r], c1, c0, 0": :[r]"r" (val):); + + _flush_all(); +} + +extern void * edata_entry; +extern void * svc_stktop; +extern void kmain (void); +extern void jump_stack (void); + +extern void * edata; +extern void * end; + +// clear the BSS section for the main kernel, see kernel.ld +void clear_bss (void) +{ + memset(&edata, 0x00, (uint)&end-(uint)&edata); +} + +void start (void) +{ + uint32 vectbl; + _puts("starting xv6 for ARM...\n"); + + // double map the low memory, required to enable paging + // we do not map all the physical memory + set_bootpgtbl(0, 0, INIT_KERNMAP, 0); + set_bootpgtbl(KERNBASE, 0, INIT_KERNMAP, 0); + + // vector table is in the middle of first 1MB (0xF000) + vectbl = P2V_WO (VEC_TBL & PDE_MASK); + + if (vectbl <= (uint)&end) { + cprintf ("error: vector table overlaps kernel\n"); + } + + set_bootpgtbl(VEC_TBL, 0, 1 << PDE_SHIFT, 0); + set_bootpgtbl(KERNBASE+DEVBASE, DEVBASE, DEV_MEM_SZ, 1); + + load_pgtlb (kernel_pgtbl, user_pgtbl); + jump_stack (); + + // We can now call normal kernel functions at high memory + clear_bss (); + + kmain (); +}