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