kern
changeset 17:098b1cb5eeaa
forgot to add a shitload of files
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 26 Mar 2011 21:39:14 +0200 |
parents | 2cbc2b922e49 |
children | 096807345aa2 |
files | src/boot/mboot.h src/mem.c src/mem.h src/vm-asm.S src/vm.c src/vm.h |
diffstat | 6 files changed, 371 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/boot/mboot.h Sat Mar 26 21:39:14 2011 +0200 1.3 @@ -0,0 +1,103 @@ 1.4 +#ifndef MBOOT_H_ 1.5 +#define MBOOT_H_ 1.6 + 1.7 +#include <inttypes.h> 1.8 + 1.9 +#define MB_MEM (1 << 0) 1.10 +#define MB_BOOTDEV (1 << 1) 1.11 +#define MB_CMDLINE (1 << 2) 1.12 +#define MB_MODULES (1 << 3) 1.13 +#define MB_AOUT_SYM (1 << 4) 1.14 +#define MB_ELF_SHDR (1 << 5) 1.15 +#define MB_MMAP (1 << 6) 1.16 +#define MB_DRIVES (1 << 7) 1.17 +#define MB_CFGTAB (1 << 8) 1.18 +#define MB_LDRNAME (1 << 9) 1.19 +#define MB_APM (1 << 10) 1.20 +#define MB_GFX (1 << 11) 1.21 + 1.22 +#define MB_MEM_VALID 1 1.23 +#define MB_DRIVE_CHS 0 1.24 +#define MB_DRIVE_LBA 1 1.25 + 1.26 +struct mboot_module { 1.27 + uint32_t start_addr, end_addr; 1.28 + char *str; 1.29 + uint32_t reserved; 1.30 +}; 1.31 + 1.32 +struct mboot_elf_shdr_table { 1.33 + uint32_t num; 1.34 + uint32_t size; 1.35 + uint32_t addr; 1.36 + uint32_t shndx; 1.37 +}; 1.38 + 1.39 +struct mboot_mmap { 1.40 + uint32_t skip; 1.41 + uint32_t base_low, base_high; 1.42 + uint32_t length_low, length_high; 1.43 + uint32_t type; 1.44 +}; 1.45 + 1.46 +struct mboot_drive { 1.47 + uint32_t size; 1.48 + uint8_t id; 1.49 + uint8_t mode; 1.50 + uint16_t cyl; 1.51 + uint8_t heads, sect; 1.52 + uint16_t ports[1]; /* zero-terminated */ 1.53 +} __attribute__ ((packed)); 1.54 + 1.55 +struct mboot_apm { 1.56 + uint16_t ver; 1.57 + uint16_t cseg; 1.58 + uint32_t offs; 1.59 + uint16_t cseg16; 1.60 + uint16_t dseg; 1.61 + uint16_t flags; 1.62 + uint16_t cseg_len; 1.63 + uint16_t cseg16_len; 1.64 + uint16_t dseg_len; 1.65 +} __attribute__ ((packed)); 1.66 + 1.67 +struct mboot_vbe { 1.68 + uint32_t ctl_info; 1.69 + uint32_t mode_info; 1.70 + uint16_t mode; 1.71 + uint16_t ifseg, ifoffs, iflen; 1.72 +} __attribute__ ((packed)); 1.73 + 1.74 + 1.75 +/* multiboot information structure */ 1.76 +struct mboot_info { 1.77 + uint32_t flags; 1.78 + /* mem_lower: available low memory (up to 640kb) 1.79 + * mem_upper: available upper memory (from 1mb and upwards) 1.80 + */ 1.81 + uint32_t mem_lower, mem_upper; 1.82 + /* boot device fields: MSB -> [part3|part2|part1|drive] <- LSB */ 1.83 + uint32_t boot_dev; 1.84 + char *cmdline; 1.85 + /* loaded kernel modules */ 1.86 + uint32_t mods_count; 1.87 + struct mboot_module *mods; 1.88 + /* elf sections table */ 1.89 + struct mboot_elf_shdr_table elf; 1.90 + /* memory map */ 1.91 + uint32_t mmap_len; 1.92 + struct mboot_mmap *mmap; 1.93 + /* drives table */ 1.94 + uint32_t drives_len; 1.95 + struct mboot_drive *drives; 1.96 + /* address of BIOS ROM configuration table */ 1.97 + uint32_t cfgtable; 1.98 + char *boot_loader_name; 1.99 + /* advanced power management */ 1.100 + struct mboot_apm *apm; 1.101 + /* video bios extensions */ 1.102 + struct mboot_vbe vbe; 1.103 +}; 1.104 + 1.105 + 1.106 +#endif /* MBOOT_H_ */
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/mem.c Sat Mar 26 21:39:14 2011 +0200 2.3 @@ -0,0 +1,40 @@ 2.4 +#include <stdio.h> 2.5 +#include "mem.h" 2.6 +#include "panic.h" 2.7 +#include "vm.h" 2.8 + 2.9 +/* end of kernel image */ 2.10 +extern int _end; 2.11 + 2.12 +static uint32_t brk; 2.13 + 2.14 +void init_mem(struct mboot_info *mb) 2.15 +{ 2.16 + /* start the physical allocated break at the end of 2.17 + * the kernel image 2.18 + */ 2.19 + brk = (uint32_t)&_end; 2.20 +} 2.21 + 2.22 +uint32_t alloc_phys_page(void) 2.23 +{ 2.24 + uint32_t addr, dbg_prev_brk; 2.25 + 2.26 + if(ADDR_TO_PGOFFS(brk)) { 2.27 + /* brk is not aligned, find the next page-aligned address */ 2.28 + addr = (brk + PGSIZE) & ~PGOFFS_MASK; 2.29 + } else { 2.30 + /* brk is aligned, so we can use that address directly */ 2.31 + addr = brk; 2.32 + } 2.33 + 2.34 + if(addr >= MAX_BRK) { 2.35 + panic("alloc_phys_page() out of early alloc space"); 2.36 + } 2.37 + 2.38 + dbg_prev_brk = brk; 2.39 + brk = addr + PGSIZE; /* move the break to the end of the page */ 2.40 + 2.41 + printf("DBG: alloc_phys_page(): %x (brk %x -> %x)\n", addr, dbg_prev_brk, brk); 2.42 + return addr; 2.43 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/mem.h Sat Mar 26 21:39:14 2011 +0200 3.3 @@ -0,0 +1,12 @@ 3.4 +#ifndef MEM_H_ 3.5 +#define MEM_H_ 3.6 + 3.7 +#include "mboot.h" 3.8 + 3.9 +/* maximum break for the early allocator */ 3.10 +#define MAX_BRK 0x400000 3.11 + 3.12 +void init_mem(struct mboot_info *mb); 3.13 +uint32_t alloc_phys_page(void); 3.14 + 3.15 +#endif /* MEM_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/vm-asm.S Sat Mar 26 21:39:14 2011 +0200 4.3 @@ -0,0 +1,27 @@ 4.4 + .text 4.5 +/* enable_paging(void) 4.6 + * sets the cr0 bit 31 which enables page translation */ 4.7 + .globl enable_paging 4.8 +enable_paging: 4.9 + movl %cr0, %eax 4.10 + orl $0x80000000, %eax 4.11 + movl %eax, %cr0 4.12 + ret 4.13 + 4.14 +/* set_pgdir_addr(uint32_t addr) 4.15 + * sets the address of the page directory by writing to cr3, which 4.16 + * also results in a TLB flush. */ 4.17 + .globl set_pgdir_addr 4.18 +set_pgdir_addr: 4.19 + movl 4(%esp), %eax 4.20 + movl %eax, %cr3 4.21 + ret 4.22 + 4.23 +/* get_fault_addr(void) 4.24 + * returns the contents of control register 2, which provides 4.25 + * the faulting address during a page fault exception 4.26 + */ 4.27 + .globl get_fault_addr 4.28 +get_fault_addr: 4.29 + movl %cr2, %eax 4.30 + ret
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/vm.c Sat Mar 26 21:39:14 2011 +0200 5.3 @@ -0,0 +1,147 @@ 5.4 +#include <stdio.h> 5.5 +#include <string.h> 5.6 +#include <inttypes.h> 5.7 +#include "vm.h" 5.8 +#include <stdio.h> 5.9 +#include "intr.h" 5.10 +#include "mem.h" 5.11 +#include "panic.h" 5.12 + 5.13 + 5.14 +/* defined in vm-asm.S */ 5.15 +void enable_paging(void); 5.16 +void set_pgdir_addr(uint32_t addr); 5.17 +uint32_t get_fault_addr(void); 5.18 + 5.19 +static void pgfault(int inum, uint32_t err); 5.20 + 5.21 +/* page directory */ 5.22 +static uint32_t pgdir[1024]; 5.23 + 5.24 +#define KMEM_START 0xc0000000 5.25 +#define IDMAP_START 0xa0000 5.26 + 5.27 +#define ATTR_PGDIR_MASK 0x3f 5.28 +#define ATTR_PGTBL_MASK 0x1ff 5.29 +#define ADDR_PGENT_MASK 0xfffff000 5.30 + 5.31 +#define PAGEFAULT 14 5.32 + 5.33 +void init_vm(struct mboot_info *mb) 5.34 +{ 5.35 + init_mem(mb); 5.36 + 5.37 + memset(pgdir, 0, sizeof pgdir); 5.38 + 5.39 + /* map the video memory and kernel code 1-1 */ 5.40 + map_mem_range(IDMAP_START, MAX_BRK - IDMAP_START, IDMAP_START, 0); 5.41 + 5.42 + interrupt(PAGEFAULT, pgfault); 5.43 + 5.44 + set_pgdir_addr((int32_t)pgdir); 5.45 + enable_paging(); 5.46 +} 5.47 + 5.48 +void map_page(int vpage, int ppage, unsigned int attr) 5.49 +{ 5.50 + uint32_t *pgtbl; 5.51 + int diridx = PAGE_TO_PGTBL(vpage); 5.52 + int pgidx = PAGE_TO_PGTBL_PG(vpage); 5.53 + 5.54 + if(!(pgdir[diridx] & PG_PRESENT)) { 5.55 + uint32_t addr = alloc_phys_page(); 5.56 + pgtbl = (uint32_t*)addr; 5.57 + pgdir[diridx] = addr | (attr & ATTR_PGDIR_MASK) | PG_PRESENT; 5.58 + } else { 5.59 + pgtbl = (uint32_t*)(pgdir[diridx] & ADDR_PGENT_MASK); 5.60 + } 5.61 + 5.62 + pgtbl[pgidx] = PAGE_TO_ADDR(ppage) | (attr & ATTR_PGTBL_MASK) | PG_PRESENT; 5.63 +} 5.64 + 5.65 +void unmap_page(int vpage) 5.66 +{ 5.67 + uint32_t *pgtbl; 5.68 + int diridx = PAGE_TO_PGTBL(vpage); 5.69 + int pgidx = PAGE_TO_PGTBL_PG(vpage); 5.70 + 5.71 + if(!(pgdir[diridx] & PG_PRESENT)) { 5.72 + goto err; 5.73 + } 5.74 + pgtbl = (uint32_t*)(pgdir[diridx] & ADDR_PGENT_MASK); 5.75 + 5.76 + if(!(pgtbl[pgidx] & PG_PRESENT)) { 5.77 + goto err; 5.78 + } 5.79 + pgtbl[pgidx] = 0; 5.80 + 5.81 + return; 5.82 +err: 5.83 + printf("unmap_page(%d): page already not mapped\n", vpage); 5.84 +} 5.85 + 5.86 +void map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr) 5.87 +{ 5.88 + int i; 5.89 + 5.90 + for(i=0; i<pgcount; i++) { 5.91 + map_page(vpg_start + i, ppg_start + i, attr); 5.92 + } 5.93 +} 5.94 + 5.95 +void map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr) 5.96 +{ 5.97 + int vpg_start, ppg_start, num_pages; 5.98 + 5.99 + if(!sz) return; 5.100 + 5.101 + if(ADDR_TO_PGOFFS(paddr)) { 5.102 + panic("map_mem_range called with unaligned physical address: %x\n", paddr); 5.103 + } 5.104 + 5.105 + vpg_start = ADDR_TO_PAGE(vaddr); 5.106 + ppg_start = ADDR_TO_PAGE(paddr); 5.107 + num_pages = ADDR_TO_PAGE(sz) + 1; 5.108 + 5.109 + map_page_range(vpg_start, num_pages, ppg_start, attr); 5.110 +} 5.111 + 5.112 + 5.113 +/* if(mb->flags & MB_MMAP) { 5.114 + struct mboot_mmap *mem, *mmap_end; 5.115 + 5.116 + mem = mb->mmap; 5.117 + mmap_end = (struct mboot_mmap*)((char*)mb->mmap + mb->mmap_len); 5.118 + 5.119 + printf("memory map:\n"); 5.120 + while(mem < mmap_end) { 5.121 + unsigned int end = mem->base_low + mem->length_low; 5.122 + char *type = mem->type == MB_MEM_VALID ? "free:" : "hole:"; 5.123 + 5.124 + printf(" %s %x - %x (%u bytes)\n", type, mem->base_low, end, mem->length_low); 5.125 + mem = (struct mboot_mmap*)((char*)mem + mem->skip + sizeof mem->skip); 5.126 + } 5.127 + } 5.128 + 5.129 + if(mb->flags & MB_MEM) { 5.130 + printf("lower memory: %ukb, upper mem: %ukb\n", mb->mem_lower, mb->mem_upper); 5.131 + } 5.132 +*/ 5.133 + 5.134 +static void pgfault(int inum, uint32_t err) 5.135 +{ 5.136 + printf("~~~~ PAGE FAULT ~~~~\n"); 5.137 + 5.138 + printf("fault address: %x\n", get_fault_addr()); 5.139 + 5.140 + if(err & PG_PRESENT) { 5.141 + if(err & 8) { 5.142 + printf("reserved bit set in some paging structure\n"); 5.143 + } else { 5.144 + printf("%s protection violation ", (err & PG_WRITABLE) ? "write" : "read"); 5.145 + printf("in %s mode\n", err & PG_USER ? "user" : "kernel"); 5.146 + } 5.147 + } else { 5.148 + printf("page not present\n"); 5.149 + } 5.150 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/vm.h Sat Mar 26 21:39:14 2011 +0200 6.3 @@ -0,0 +1,42 @@ 6.4 +#ifndef VM_H_ 6.5 +#define VM_H_ 6.6 + 6.7 +#include <stdlib.h> 6.8 +#include "mboot.h" 6.9 + 6.10 +/* page mapping flags */ 6.11 +#define PG_PRESENT (1 << 0) 6.12 +#define PG_WRITABLE (1 << 1) 6.13 +#define PG_USER (1 << 2) 6.14 +#define PG_WRITE_THROUGH (1 << 3) 6.15 +#define PG_NOCACHE (1 << 4) 6.16 +#define PG_ACCESSED (1 << 5) 6.17 +#define PG_DIRTY (1 << 6) 6.18 +#define PG_TYPE (1 << 7) 6.19 +/* PG_GLOBAL mappings won't flush from TLB */ 6.20 +#define PG_GLOBAL (1 << 8) 6.21 + 6.22 + 6.23 +#define PGSIZE 4096 6.24 +#define PGOFFS_MASK 0xfff 6.25 +#define PGNUM_MASK 0xfffff000 6.26 + 6.27 +#define ADDR_TO_PAGE(x) ((uint32_t)(x) >> 12) 6.28 +#define PAGE_TO_ADDR(x) ((uint32_t)(x) << 12) 6.29 + 6.30 +#define ADDR_TO_PGTBL(x) ((uint32_t)(x) >> 22) 6.31 +#define ADDR_TO_PGTBL_PG(x) (((uint32_t)(x) >> 12) & 0x3ff) 6.32 +#define ADDR_TO_PGOFFS(x) ((uint32_t)(x) & PGOFFS_MASK) 6.33 + 6.34 +#define PAGE_TO_PGTBL(x) ((uint32_t)(x) >> 10) 6.35 +#define PAGE_TO_PGTBL_PG(x) ((uint32_t)(x) & 0x3ff) 6.36 + 6.37 + 6.38 +void init_vm(struct mboot_info *mb); 6.39 + 6.40 +void map_page(int vpage, int ppage, unsigned int attr); 6.41 +void map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr); 6.42 + 6.43 +void map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr); 6.44 + 6.45 +#endif /* VM_H_ */