kern
changeset 47:f65b348780e3
continuing with the process implementation. not done yet, panics.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 28 Jul 2011 05:43:04 +0300 |
parents | b793b8fcba7d |
children | 4c9c16754b59 |
files | src/intr-asm.S src/intr.c src/intr.h src/main.c src/proc.c src/proc.h src/segm.c src/timer.c src/vm.c src/vm.h |
diffstat | 10 files changed, 133 insertions(+), 54 deletions(-) [+] |
line diff
1.1 --- a/src/intr-asm.S Thu Jul 28 05:33:59 2011 +0300 1.2 +++ b/src/intr-asm.S Thu Jul 28 05:43:04 2011 +0300 1.3 @@ -70,6 +70,9 @@ 1.4 intr_entry_common: 1.5 pusha 1.6 call dispatch_intr 1.7 + 1.8 + .globl intr_ret 1.9 +intr_ret: 1.10 popa 1.11 /* remove error code and intr num from stack */ 1.12 add $8, %esp
2.1 --- a/src/intr.c Thu Jul 28 05:33:59 2011 +0300 2.2 +++ b/src/intr.c Thu Jul 28 05:43:04 2011 +0300 2.3 @@ -35,21 +35,6 @@ 2.4 #define OCW2_EOI (1 << 5) 2.5 2.6 2.7 -/* structure used to pass the interrupt stack frame from the 2.8 - * entry points to the C dispatch function. 2.9 - */ 2.10 -struct intr_frame { 2.11 - /* registers pushed by pusha in intr_entry_* */ 2.12 - struct registers regs; 2.13 - /* interrupt number and error code pushed in intr_entry_* */ 2.14 - uint32_t inum, err; 2.15 - /* pushed by CPU during interrupt entry */ 2.16 - uint32_t eip, cs, eflags; 2.17 - /* pushed by CPU during interrupt entry from user space */ 2.18 - uint32_t esp, ss; 2.19 -}; 2.20 - 2.21 - 2.22 static void init_pic(int offset); 2.23 static void gate_desc(desc_t *desc, uint16_t sel, uint32_t addr, int dpl, int type); 2.24 static void set_intr_entry(int num, void (*handler)(void));
3.1 --- a/src/intr.h Thu Jul 28 05:33:59 2011 +0300 3.2 +++ b/src/intr.h Thu Jul 28 05:43:04 2011 +0300 3.3 @@ -12,6 +12,21 @@ 3.4 /* checks whether a particular interrupt is an remapped IRQ */ 3.5 #define IS_IRQ(n) ((n) >= IRQ_OFFSET && (n) < IRQ_OFFSET + 16) 3.6 3.7 +/* structure used to pass the interrupt stack frame from the 3.8 + * entry points to the C dispatch function. 3.9 + */ 3.10 +struct intr_frame { 3.11 + /* registers pushed by pusha in intr_entry_* */ 3.12 + struct registers regs; 3.13 + /* interrupt number and error code pushed in intr_entry_* */ 3.14 + uint32_t inum, err; 3.15 + /* pushed by CPU during interrupt entry */ 3.16 + uint32_t eip, cs, eflags; 3.17 + /* pushed by CPU during interrupt entry from user space */ 3.18 + uint32_t esp, ss; 3.19 +}; 3.20 + 3.21 + 3.22 3.23 typedef void (*intr_func_t)(int, uint32_t); 3.24 3.25 @@ -24,4 +39,6 @@ 3.26 int get_intr_state(void); 3.27 void set_intr_state(int s); 3.28 3.29 +void intr_ret(struct intr_frame ifrm); 3.30 + 3.31 #endif /* INTR_H_ */
4.1 --- a/src/main.c Thu Jul 28 05:33:59 2011 +0300 4.2 +++ b/src/main.c Thu Jul 28 05:43:04 2011 +0300 4.3 @@ -9,6 +9,7 @@ 4.4 #include "timer.h" 4.5 #include "mem.h" 4.6 #include "vm.h" 4.7 +#include "proc.h" 4.8 4.9 4.10 void kmain(struct mboot_info *mbinf) 4.11 @@ -41,6 +42,8 @@ 4.12 /* initialization complete, enable interrupts */ 4.13 enable_intr(); 4.14 4.15 + init_proc(); 4.16 + 4.17 4.18 for(;;) { 4.19 halt_cpu();
5.1 --- a/src/proc.c Thu Jul 28 05:33:59 2011 +0300 5.2 +++ b/src/proc.c Thu Jul 28 05:43:04 2011 +0300 5.3 @@ -1,13 +1,22 @@ 5.4 +#include <string.h> 5.5 #include "proc.h" 5.6 #include "tss.h" 5.7 #include "vm.h" 5.8 +#include "segm.h" 5.9 +#include "intr.h" 5.10 +#include "panic.h" 5.11 + 5.12 + 5.13 +/* defined in test_proc.S */ 5.14 +void test_proc(void); 5.15 +void test_proc_end(void); 5.16 5.17 static struct process proc[MAX_PROC]; 5.18 static int cur_pid; 5.19 5.20 void init_proc(void) 5.21 { 5.22 - int proc_size_pg, img_start_pg; 5.23 + int proc_size_pg, img_start_pg, stack_pg; 5.24 void *img_start; 5.25 cur_pid = -1; 5.26 5.27 @@ -24,30 +33,56 @@ 5.28 img_start = (void*)PAGE_TO_ADDR(img_start_pg); 5.29 memcpy(img_start, test_proc, proc_size_pg * PGSIZE); 5.30 5.31 + /* instruction pointer at the beginning of the process image */ 5.32 + proc[0].ctx.instr_ptr = (uint32_t)img_start; 5.33 + 5.34 + /* allocate the first page of the process stack */ 5.35 + stack_pg = ADDR_TO_PAGE(KMEM_START) - 1; 5.36 + if(pgalloc_vrange(stack_pg, 1) == -1) { 5.37 + panic("failed to allocate user stack page\n"); 5.38 + } 5.39 + proc[0].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE; 5.40 + 5.41 /* create the virtual address space for this process */ 5.42 - proc[0].ctx.pgtbl_paddr = clone_vmem(); 5.43 + proc[0].ctx.pgtbl_paddr = clone_vm(); 5.44 5.45 - /* we don't need the image in this address space */ 5.46 - unmap_pa 5.47 + /* we don't need the image and the stack in this address space */ 5.48 + unmap_page_range(img_start_pg, proc_size_pg); 5.49 pgfree(img_start_pg, proc_size_pg); 5.50 5.51 + unmap_page(stack_pg); 5.52 + pgfree(stack_pg, 1); 5.53 5.54 - /* fill in the proc[0].ctx with the appropriate process stack 5.55 - * and instruction pointers 5.56 - */ 5.57 5.58 /* switch to it by calling a function that takes the context 5.59 * of the current process, plugs the values into the interrupt 5.60 * stack, and calls iret. 5.61 * (should also set ss0/sp0 in TSS before returning) 5.62 */ 5.63 + context_switch(0); 5.64 + /* XXX this will never return */ 5.65 } 5.66 5.67 -/* 5.68 -void save_context(struct intr_frame *ifrm) 5.69 + 5.70 +void context_switch(int pid) 5.71 { 5.72 - proc[cur_pid].ctx->regs = ifrm->regs; 5.73 - proc[cur_pid].ctx->instr_ptr = ifrm->eip; 5.74 - proc[cur_pid].ctx->stack_ptr = ifrm->esp; 5.75 - proc[cur_pid].ctx->flags = ifrm->eflags; 5.76 -}*/ 5.77 + struct intr_frame ifrm; 5.78 + struct context *ctx = &proc[pid].ctx; 5.79 + 5.80 + cur_pid = pid; 5.81 + 5.82 + ifrm.inum = ifrm.err = 0; 5.83 + 5.84 + ifrm.regs = ctx->regs; 5.85 + ifrm.eflags = ctx->flags; 5.86 + 5.87 + ifrm.eip = ctx->instr_ptr; 5.88 + ifrm.cs = SEGM_KCODE; /* XXX change this when we setup the TSS */ 5.89 + ifrm.esp = ctx->stack_ptr; 5.90 + ifrm.ss = SEGM_KDATA; /* XXX */ 5.91 + 5.92 + /* switch to the vm of the process */ 5.93 + set_pgdir_addr(ctx->pgtbl_paddr); 5.94 + 5.95 + intr_ret(ifrm); 5.96 +}
6.1 --- a/src/proc.h Thu Jul 28 05:33:59 2011 +0300 6.2 +++ b/src/proc.h Thu Jul 28 05:43:04 2011 +0300 6.3 @@ -7,17 +7,22 @@ 6.4 #define MAX_PROC 128 6.5 6.6 struct context { 6.7 - struct registers regs; 6.8 - uint32_t instr_ptr; 6.9 - uint32_t stack_ptr; 6.10 - uint32_t flags; 6.11 - uint32_t pgtbl_paddr; 6.12 + struct registers regs; /* saved general purpose registers */ 6.13 + uint32_t instr_ptr; /* saved eip */ 6.14 + uint32_t stack_ptr; /* saved esp */ 6.15 + uint32_t flags; /* saved eflags */ 6.16 + uint32_t pgtbl_paddr; /* physical address of the page table */ 6.17 /* TODO add FPU state */ 6.18 }; 6.19 6.20 6.21 struct process { 6.22 + int parent; 6.23 struct context ctx; 6.24 }; 6.25 6.26 +void init_proc(void); 6.27 + 6.28 +void context_switch(int pid); 6.29 + 6.30 #endif /* PROC_H_ */
7.1 --- a/src/segm.c Thu Jul 28 05:33:59 2011 +0300 7.2 +++ b/src/segm.c Thu Jul 28 05:43:04 2011 +0300 7.3 @@ -43,7 +43,7 @@ 7.4 segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA); 7.5 segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE); 7.6 segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA); 7.7 - /*task_desc(gdt + SEGM_TASK, 0, 0xffffffff, 3, TSS_BUSY);*/ 7.8 + task_desc(gdt + SEGM_TASK, 0, 0xffffffff, 3, TSS_BUSY); 7.9 7.10 set_gdt((uint32_t)gdt, sizeof gdt - 1); 7.11
8.1 --- a/src/timer.c Thu Jul 28 05:33:59 2011 +0300 8.2 +++ b/src/timer.c Thu Jul 28 05:43:04 2011 +0300 8.3 @@ -69,9 +69,4 @@ 8.4 static void intr_handler() 8.5 { 8.6 nticks++; 8.7 - 8.8 - if(nticks % TICK_FREQ_HZ == 0) { 8.9 - time_t t = time(0); 8.10 - printf("%s", asctime(gmtime(&t))); 8.11 - } 8.12 }
9.1 --- a/src/vm.c Thu Jul 28 05:33:59 2011 +0300 9.2 +++ b/src/vm.c Thu Jul 28 05:43:04 2011 +0300 9.3 @@ -8,7 +8,6 @@ 9.4 #include "panic.h" 9.5 9.6 9.7 -#define KMEM_START 0xc0000000 9.8 #define IDMAP_START 0xa0000 9.9 9.10 #define PGDIR_ADDR 0xfffff000 9.11 @@ -56,6 +55,7 @@ 9.12 void init_vm(void) 9.13 { 9.14 uint32_t idmap_end; 9.15 + int i, kmem_start_pg, pgtbl_base_pg; 9.16 9.17 /* setup the page tables */ 9.18 pgdir = (uint32_t*)alloc_phys_page(); 9.19 @@ -79,15 +79,29 @@ 9.20 /* initialize the virtual page allocator */ 9.21 node_pool = 0; 9.22 9.23 - first_node.start = ADDR_TO_PAGE(KMEM_START); 9.24 - first_node.end = ADDR_TO_PAGE(PGTBL_BASE); 9.25 + kmem_start_pg = ADDR_TO_PAGE(KMEM_START); 9.26 + pgtbl_base_pg = ADDR_TO_PAGE(PGTBL_BASE); 9.27 + 9.28 + first_node.start = kmem_start_pg; 9.29 + first_node.end = pgtbl_base_pg; 9.30 first_node.next = 0; 9.31 pglist[MEM_KERNEL] = &first_node; 9.32 9.33 pglist[MEM_USER] = alloc_node(); 9.34 pglist[MEM_USER]->start = ADDR_TO_PAGE(idmap_end); 9.35 - pglist[MEM_USER]->end = ADDR_TO_PAGE(KMEM_START); 9.36 + pglist[MEM_USER]->end = kmem_start_pg; 9.37 pglist[MEM_USER]->next = 0; 9.38 + 9.39 + /* temporaroly map something into every 1024th page of the kernel address 9.40 + * space to force pre-allocation of all the kernel page-tables 9.41 + */ 9.42 + for(i=kmem_start_pg; i<pgtbl_base_pg; i+=1024) { 9.43 + /* if there's already something mapped here, leave it alone */ 9.44 + if(virt_to_phys_page(i) == -1) { 9.45 + map_page(i, 0, 0); 9.46 + unmap_page(i); 9.47 + } 9.48 + } 9.49 } 9.50 9.51 /* if ppage == -1 we allocate a physical page by calling alloc_phys_page */ 9.52 @@ -298,7 +312,7 @@ 9.53 unsigned int attr = 0; /* TODO */ 9.54 9.55 area = (start >= ADDR_TO_PAGE(KMEM_START)) ? MEM_KERNEL : MEM_USER; 9.56 - if(area == KMEM_USER && start + num > ADDR_TO_PAGE(KMEM_START)) { 9.57 + if(area == MEM_USER && start + num > ADDR_TO_PAGE(KMEM_START)) { 9.58 printf("pgalloc_vrange: invalid range request crossing user/kernel split\n"); 9.59 return -1; 9.60 } 9.61 @@ -447,7 +461,7 @@ 9.62 if(node_pool) { 9.63 node = node_pool; 9.64 node_pool = node_pool->next; 9.65 - printf("alloc_node -> %x\n", (unsigned int)node); 9.66 + /*printf("alloc_node -> %x\n", (unsigned int)node);*/ 9.67 return node; 9.68 } 9.69 9.70 @@ -468,7 +482,7 @@ 9.71 9.72 /* grab the first and return it */ 9.73 node = node_pool++; 9.74 - printf("alloc_node -> %x\n", (unsigned int)node); 9.75 + /*printf("alloc_node -> %x\n", (unsigned int)node);*/ 9.76 return node; 9.77 } 9.78 9.79 @@ -476,26 +490,34 @@ 9.80 { 9.81 node->next = node_pool; 9.82 node_pool = node; 9.83 - printf("free_node\n"); 9.84 + /*printf("free_node\n");*/ 9.85 } 9.86 9.87 9.88 -/* clone_vmem makes a copy of the current page tables, thus duplicating 9.89 - * the virtual address space. 9.90 +/* clone_vm makes a copy of the current page tables, thus duplicating the 9.91 + * virtual address space. 9.92 + * 9.93 + * For the kernel part of the address space (last 256 page directory entries) 9.94 + * we don't want to diplicate the page tables, just point all page directory 9.95 + * entries to the same set of page tables. 9.96 * 9.97 * Returns the physical address of the new page directory. 9.98 */ 9.99 -uint32_t clone_vmem(void) 9.100 +uint32_t clone_vm(void) 9.101 { 9.102 - int i, dirpg, tblpg; 9.103 + int i, dirpg, tblpg, kmem_start_pg; 9.104 uint32_t paddr; 9.105 uint32_t *ndir, *ntbl; 9.106 9.107 + /* allocate the new page directory */ 9.108 if((dirpg = pgalloc(1, MEM_KERNEL)) == -1) { 9.109 panic("clone_vmem: failed to allocate page directory page\n"); 9.110 } 9.111 ndir = (uint32_t*)PAGE_TO_ADDR(dirpg); 9.112 9.113 + /* allocate a virtual page for temporarily mapping all new 9.114 + * page tables while we populate them. 9.115 + */ 9.116 if((tblpg = pgalloc(1, MEM_KERNEL)) == -1) { 9.117 panic("clone_vmem: failed to allocate page table page\n"); 9.118 } 9.119 @@ -506,7 +528,10 @@ 9.120 */ 9.121 free_phys_page(virt_to_phys(tblpg)); 9.122 9.123 - for(i=0; i<1024; i++) { 9.124 + kmem_start_pg = ADDR_TO_PAGE(KMEM_START); 9.125 + 9.126 + /* user space */ 9.127 + for(i=0; i<kmem_start_pg; i++) { 9.128 if(pgdir[i] & PG_PRESENT) { 9.129 paddr = alloc_phys_page(); 9.130 map_page(tblpg, ADDR_TO_PAGE(paddr), 0); 9.131 @@ -521,6 +546,11 @@ 9.132 } 9.133 } 9.134 9.135 + /* kernel space */ 9.136 + for(i=kmem_start_pg; i<1024; i++) { 9.137 + ndir[i] = *PGTBL(i); 9.138 + } 9.139 + 9.140 paddr = virt_to_phys(dirpg); 9.141 9.142 /* unmap before freeing to avoid deallocating the physical pages */
10.1 --- a/src/vm.h Thu Jul 28 05:33:59 2011 +0300 10.2 +++ b/src/vm.h Thu Jul 28 05:43:04 2011 +0300 10.3 @@ -4,6 +4,8 @@ 10.4 #include <stdlib.h> 10.5 #include "mboot.h" 10.6 10.7 +#define KMEM_START 0xc0000000 10.8 + 10.9 /* page mapping flags */ 10.10 #define PG_PRESENT (1 << 0) 10.11 #define PG_WRITABLE (1 << 1) 10.12 @@ -52,10 +54,14 @@ 10.13 }; 10.14 10.15 int pgalloc(int num, int area); 10.16 +int pgalloc_vrange(int start, int num); 10.17 void pgfree(int start, int num); 10.18 10.19 -uint32_t clone_vmem(void); 10.20 +uint32_t clone_vm(void); 10.21 10.22 void dbg_print_vm(int area); 10.23 10.24 +/* defined in vm-asm.S */ 10.25 +void set_pgdir_addr(uint32_t addr); 10.26 + 10.27 #endif /* VM_H_ */