kern

changeset 43:5f6c5751ae05

- implemented clone_vmem
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 25 Jul 2011 11:29:02 +0300
parents e6de3c6015cb
children 7bc74736c7e8
files src/asmops.h src/main.c src/panic.c src/proc.c src/proc.h src/vm.c src/vm.h
diffstat 7 files changed, 113 insertions(+), 51 deletions(-) [+]
line diff
     1.1 --- a/src/asmops.h	Sun Jul 24 18:29:24 2011 +0300
     1.2 +++ b/src/asmops.h	Mon Jul 25 11:29:02 2011 +0300
     1.3 @@ -1,6 +1,8 @@
     1.4  #ifndef ASMOPS_H_
     1.5  #define ASMOPS_H_
     1.6  
     1.7 +#include <inttypes.h>
     1.8 +
     1.9  /* general purpose registers as they are pushed by pusha */
    1.10  struct registers {
    1.11  	uint32_t edi, esi, ebp, esp;
     2.1 --- a/src/main.c	Sun Jul 24 18:29:24 2011 +0300
     2.2 +++ b/src/main.c	Mon Jul 25 11:29:02 2011 +0300
     2.3 @@ -10,35 +10,6 @@
     2.4  #include "mem.h"
     2.5  #include "vm.h"
     2.6  
     2.7 -static void do_nothing();
     2.8 -
     2.9 -/* special keys */
    2.10 -enum {
    2.11 -	LALT, RALT,
    2.12 -	LCTRL, RCTRL,
    2.13 -	LSHIFT, RSHIFT,
    2.14 -	F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
    2.15 -	CAPSLK, NUMLK, SCRLK, SYSRQ,
    2.16 -	ESC		= 27,
    2.17 -	INSERT, DEL, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN,
    2.18 -	NUM_DOT, NUM_ENTER, NUM_PLUS, NUM_MINUS, NUM_MUL, NUM_DIV,
    2.19 -	NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9,
    2.20 -	BACKSP	= 127
    2.21 -};
    2.22 -
    2.23 -/* table with rough translations from set 1 scancodes to ASCII-ish */
    2.24 -static int keycodes[] = {
    2.25 -	0, ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',		/* 0 - e */
    2.26 -	'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',			/* f - 1c */
    2.27 -	LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',				/* 1d - 29 */
    2.28 -	LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', RSHIFT,			/* 2a - 36 */
    2.29 -	NUM_MUL, LALT, ' ', CAPSLK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10,			/* 37 - 44 */
    2.30 -	NUMLK, SCRLK, NUM_7, NUM_8, NUM_9, NUM_MINUS, NUM_4, NUM_5, NUM_6, NUM_PLUS,	/* 45 - 4e */
    2.31 -	NUM_1, NUM_2, NUM_3, NUM_0, NUM_DOT, SYSRQ, 0, 0, F11, F12,						/* 4d - 58 */
    2.32 -	0, 0, 0, 0, 0, 0, 0,															/* 59 - 5f */
    2.33 -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,									/* 60 - 6f */
    2.34 -	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0									/* 70 - 7f */
    2.35 -};
    2.36  
    2.37  void kmain(struct mboot_info *mbinf)
    2.38  {
    2.39 @@ -72,13 +43,6 @@
    2.40  
    2.41  
    2.42  	for(;;) {
    2.43 -		char c, keypress;
    2.44 -		do {
    2.45 -			inb(keypress, 0x64);
    2.46 -		} while(!(keypress & 1));
    2.47 -		inb(c, 0x60);
    2.48 -		if(!(c & 0x80)) {
    2.49 -			putchar(keycodes[(int)c]);
    2.50 -		}
    2.51 +		halt_cpu();
    2.52  	}
    2.53  }
     3.1 --- a/src/panic.c	Sun Jul 24 18:29:24 2011 +0300
     3.2 +++ b/src/panic.c	Mon Jul 25 11:29:02 2011 +0300
     3.3 @@ -3,7 +3,7 @@
     3.4  #include <stdarg.h>
     3.5  #include "asmops.h"
     3.6  
     3.7 -struct registers {
     3.8 +struct all_registers {
     3.9  	uint32_t eax, ebx, ecx, edx;
    3.10  	uint32_t esp, ebp, esi, edi;
    3.11  	uint32_t eflags;
    3.12 @@ -12,12 +12,12 @@
    3.13  };
    3.14  
    3.15  /* defined in regs.S */
    3.16 -void get_regs(struct registers *regs);
    3.17 +void get_regs(struct all_registers *regs);
    3.18  
    3.19  void panic(const char *fmt, ...)
    3.20  {
    3.21  	va_list ap;
    3.22 -	struct registers regs;
    3.23 +	struct all_registers regs;
    3.24  
    3.25  	disable_intr();
    3.26  
     4.1 --- a/src/proc.c	Sun Jul 24 18:29:24 2011 +0300
     4.2 +++ b/src/proc.c	Mon Jul 25 11:29:02 2011 +0300
     4.3 @@ -11,6 +11,7 @@
     4.4  	/* prepare the first process */
     4.5  
     4.6  	/* create the virtual address space for this process */
     4.7 +	proc[0].ctx.pgtbl_paddr = clone_vmem();
     4.8  
     4.9  	/* allocate a chunk of memory for the process image
    4.10  	 * and copy the code of test_proc there.
    4.11 @@ -28,10 +29,11 @@
    4.12  	 */
    4.13  }
    4.14  
    4.15 +/*
    4.16  void save_context(struct intr_frame *ifrm)
    4.17  {
    4.18  	proc[cur_pid].ctx->regs = ifrm->regs;
    4.19  	proc[cur_pid].ctx->instr_ptr = ifrm->eip;
    4.20  	proc[cur_pid].ctx->stack_ptr = ifrm->esp;
    4.21  	proc[cur_pid].ctx->flags = ifrm->eflags;
    4.22 -}
    4.23 +}*/
     5.1 --- a/src/proc.h	Sun Jul 24 18:29:24 2011 +0300
     5.2 +++ b/src/proc.h	Mon Jul 25 11:29:02 2011 +0300
     5.3 @@ -1,6 +1,7 @@
     5.4  #ifndef PROC_H_
     5.5  #define PROC_H_
     5.6  
     5.7 +#include <inttypes.h>
     5.8  #include "asmops.h"
     5.9  
    5.10  #define MAX_PROC	128
    5.11 @@ -10,6 +11,7 @@
    5.12  	uint32_t instr_ptr;
    5.13  	uint32_t stack_ptr;
    5.14  	uint32_t flags;
    5.15 +	uint32_t pgtbl_paddr;
    5.16  	/* TODO add FPU state */
    5.17  };
    5.18  
     6.1 --- a/src/vm.c	Sun Jul 24 18:29:24 2011 +0300
     6.2 +++ b/src/vm.c	Mon Jul 25 11:29:02 2011 +0300
     6.3 @@ -134,9 +134,10 @@
     6.4  	return 0;
     6.5  }
     6.6  
     6.7 -void unmap_page(int vpage)
     6.8 +int unmap_page(int vpage)
     6.9  {
    6.10  	uint32_t *pgtbl;
    6.11 +	int res = 0;
    6.12  	int diridx = PAGE_TO_PGTBL(vpage);
    6.13  	int pgidx = PAGE_TO_PGTBL_PG(vpage);
    6.14  
    6.15 @@ -157,8 +158,10 @@
    6.16  	if(0) {
    6.17  err:
    6.18  		printf("unmap_page(%d): page already not mapped\n", vpage);
    6.19 +		res = -1;
    6.20  	}
    6.21  	set_intr_state(intr_state);
    6.22 +	return res;
    6.23  }
    6.24  
    6.25  /* if ppg_start is -1, we allocate physical pages to map with alloc_phys_page() */
    6.26 @@ -173,6 +176,18 @@
    6.27  	return 0;
    6.28  }
    6.29  
    6.30 +int unmap_page_range(int vpg_start, int pgcount)
    6.31 +{
    6.32 +	int i, res = 0;
    6.33 +
    6.34 +	for(i=0; i<pgcount; i++) {
    6.35 +		if(unmap_page(vpg_start + i) == -1) {
    6.36 +			res = -1;
    6.37 +		}
    6.38 +	}
    6.39 +	return res;
    6.40 +}
    6.41 +
    6.42  /* if paddr is 0, we allocate physical pages with alloc_phys_page() */
    6.43  int map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr)
    6.44  {
    6.45 @@ -193,21 +208,39 @@
    6.46  
    6.47  uint32_t virt_to_phys(uint32_t vaddr)
    6.48  {
    6.49 +	int pg;
    6.50 +	uint32_t pgaddr;
    6.51 +
    6.52 +	if((pg = virt_to_phys_page(ADDR_TO_PAGE(vaddr))) == -1) {
    6.53 +		return 0;
    6.54 +	}
    6.55 +	pgaddr = PAGE_TO_ADDR(pg);
    6.56 +
    6.57 +	return pgaddr | ADDR_TO_PGOFFS(vaddr);
    6.58 +}
    6.59 +
    6.60 +int virt_to_phys_page(int vpg)
    6.61 +{
    6.62  	uint32_t pgaddr, *pgtbl;
    6.63 -	int diridx = ADDR_TO_PGTBL(vaddr);
    6.64 -	int pgidx = ADDR_TO_PGTBL_PG(vaddr);
    6.65 +	int diridx, pgidx;
    6.66 +
    6.67 +	if(vpg < 0 || vpg >= PAGE_COUNT) {
    6.68 +		return -1;
    6.69 +	}
    6.70 +
    6.71 +	diridx = PAGE_TO_PGTBL(vpg);
    6.72 +	pgidx = PAGE_TO_PGTBL_PG(vpg);
    6.73  
    6.74  	if(!(pgdir[diridx] & PG_PRESENT)) {
    6.75 -		panic("virt_to_phys(%x): page table %d not present\n", vaddr, diridx);
    6.76 +		return -1;
    6.77  	}
    6.78  	pgtbl = PGTBL(diridx);
    6.79  
    6.80  	if(!(pgtbl[pgidx] & PG_PRESENT)) {
    6.81 -		panic("virt_to_phys(%x): page %d not present\n", vaddr, ADDR_TO_PAGE(vaddr));
    6.82 +		return -1;
    6.83  	}
    6.84  	pgaddr = pgtbl[pgidx] & PGENT_ADDR_MASK;
    6.85 -
    6.86 -	return pgaddr | ADDR_TO_PGOFFS(vaddr);
    6.87 +	return ADDR_TO_PAGE(pgaddr);
    6.88  }
    6.89  
    6.90  /* allocate a contiguous block of virtual memory pages along with
    6.91 @@ -266,9 +299,9 @@
    6.92  	disable_intr();
    6.93  
    6.94  	for(i=0; i<num; i++) {
    6.95 -		uint32_t phys = virt_to_phys(PAGE_TO_ADDR(start + i));
    6.96 -		if(phys) {
    6.97 -			free_phys_page(ADDR_TO_PAGE(phys));
    6.98 +		int phys_pg = virt_to_phys_page(start + i);
    6.99 +		if(phys_pg != -1) {
   6.100 +			free_phys_page(phys_pg);
   6.101  		}
   6.102  	}
   6.103  
   6.104 @@ -393,6 +426,60 @@
   6.105  }
   6.106  
   6.107  
   6.108 +/* clone_vmem makes a copy of the current page tables, thus duplicating
   6.109 + * the virtual address space.
   6.110 + *
   6.111 + * Returns the physical address of the new page directory.
   6.112 + */
   6.113 +uint32_t clone_vmem(void)
   6.114 +{
   6.115 +	int i, dirpg, tblpg;
   6.116 +	uint32_t paddr;
   6.117 +	uint32_t *ndir, *ntbl;
   6.118 +
   6.119 +	if((dirpg = pgalloc(1, MEM_KERNEL)) == -1) {
   6.120 +		panic("clone_vmem: failed to allocate page directory page\n");
   6.121 +	}
   6.122 +	ndir = (uint32_t*)PAGE_TO_ADDR(dirpg);
   6.123 +
   6.124 +	if((tblpg = pgalloc(1, MEM_KERNEL)) == -1) {
   6.125 +		panic("clone_vmem: failed to allocate page table page\n");
   6.126 +	}
   6.127 +	ntbl = (uint32_t*)PAGE_TO_ADDR(tblpg);
   6.128 +
   6.129 +	/* we will allocate physical pages and map them to this virtual page
   6.130 +	 * as needed in the loop below.
   6.131 +	 */
   6.132 +	free_phys_page(virt_to_phys(tblpg));
   6.133 +
   6.134 +	for(i=0; i<1024; i++) {
   6.135 +		if(pgdir[i] & PG_PRESENT) {
   6.136 +			paddr = alloc_phys_page();
   6.137 +			map_page(tblpg, ADDR_TO_PAGE(paddr), 0);
   6.138 +
   6.139 +			/* copy the page table */
   6.140 +			memcpy(ntbl, PGTBL(i), PGSIZE);
   6.141 +
   6.142 +			/* set the new page directory entry */
   6.143 +			ndir[i] = paddr | (pgdir[i] & PGOFFS_MASK);
   6.144 +		} else {
   6.145 +			ndir[i] = 0;
   6.146 +		}
   6.147 +	}
   6.148 +
   6.149 +	paddr = virt_to_phys(dirpg);
   6.150 +
   6.151 +	/* unmap before freeing to avoid deallocating the physical pages */
   6.152 +	unmap_page(dirpg);
   6.153 +	unmap_page(tblpg);
   6.154 +
   6.155 +	pgfree(dirpg, 1);
   6.156 +	pgfree(tblpg, 1);
   6.157 +
   6.158 +	return paddr;
   6.159 +}
   6.160 +
   6.161 +
   6.162  void dbg_print_vm(int area)
   6.163  {
   6.164  	struct page_range *node;
     7.1 --- a/src/vm.h	Sun Jul 24 18:29:24 2011 +0300
     7.2 +++ b/src/vm.h	Mon Jul 25 11:29:02 2011 +0300
     7.3 @@ -38,9 +38,12 @@
     7.4  void init_vm(void);
     7.5  
     7.6  int map_page(int vpage, int ppage, unsigned int attr);
     7.7 +int unmap_page(int vpage);
     7.8  int map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr);
     7.9 +int unmap_page_range(int vpg_start, int pgcount);
    7.10  int map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr);
    7.11  
    7.12 +int virt_to_phys_page(int vpg);
    7.13  uint32_t virt_to_phys(uint32_t vaddr);
    7.14  
    7.15  enum {
    7.16 @@ -51,6 +54,8 @@
    7.17  int pgalloc(int num, int area);
    7.18  void pgfree(int start, int num);
    7.19  
    7.20 +uint32_t clone_vmem(void);
    7.21 +
    7.22  void dbg_print_vm(int area);
    7.23  
    7.24  #endif	/* VM_H_ */