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_ */