Fix run_elf (still leaking memory now).
This commit is contained in:
parent
62c290f449
commit
117f6423c4
2
Makefile
2
Makefile
@ -92,7 +92,7 @@ fs.img: kernel.bin tools/mkfs user/false user/greet user/div0 user/shout
|
||||
LDFLAGS=-m elf_i386
|
||||
|
||||
user/%: user/%.o user/crt.o
|
||||
$(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $^
|
||||
$(LD) $(LDFLAGS) -o $@ -Ttext 0x401000 $^
|
||||
|
||||
image.bin: mbr.bin fs.img
|
||||
cat $^ >$@
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
#include "gdt.h"
|
||||
#include "x86.h"
|
||||
#include "memlayout.h"
|
||||
#include "../lib/string.h"
|
||||
#include "kernel/mem.h"
|
||||
|
||||
@ -52,7 +54,7 @@ void load_gdt() {
|
||||
asm("lgdt %0": : "m"(gdt_desc));
|
||||
}
|
||||
|
||||
void switchuvm(struct taskstate *tss, void* esp) {
|
||||
void switchuvm(struct taskstate *tss, void* esp, pde_t *pgdir) {
|
||||
memset(tss, 0, sizeof(*tss));
|
||||
seg_desc[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss)-1, 0);
|
||||
seg_desc[SEG_TSS].s = 0;
|
||||
@ -63,4 +65,6 @@ void switchuvm(struct taskstate *tss, void* esp) {
|
||||
tss->iomb = (ushort) 0xFFFF;
|
||||
|
||||
asm("ltr %0": : "r"((ushort)(SEG_TSS << 3)));
|
||||
|
||||
lcr3(V2P(pgdir));
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#define KERN_STACK_BASE 0x90000
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include "kernel/mem.h"
|
||||
typedef unsigned uint;
|
||||
typedef unsigned short ushort;
|
||||
|
||||
@ -73,5 +74,5 @@ struct taskstate {
|
||||
};
|
||||
|
||||
void load_gdt();
|
||||
void switchuvm(struct taskstate *tss, void* esp);
|
||||
void switchuvm(struct taskstate *tss, void* esp, pde_t *pgdir);
|
||||
#endif
|
||||
|
||||
@ -5,7 +5,9 @@
|
||||
#define PHYSTOP 0x8000000
|
||||
|
||||
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
|
||||
#define PGROUNDDOWN(a) (((a)) & ~((uintptr_t)(PGSIZE-1)))
|
||||
|
||||
#define PTXSHIFT 12 // offset of PTX in a linear address
|
||||
#define PDXSHIFT 22 // offset of PDX in a linear address
|
||||
|
||||
#define PXMASK 0x3FF
|
||||
@ -17,6 +19,12 @@
|
||||
|
||||
// page directory index
|
||||
#define PDX(va) (((uintptr_t)(va) >> PDXSHIFT) & PXMASK)
|
||||
|
||||
// page table index
|
||||
#define PTX(va) (((uintptr_t)(va) >> PTXSHIFT) & PXMASK)
|
||||
|
||||
// Address in page table or page directory entry
|
||||
#define PTE_ADDR(pte) ((uintptr_t)(pte) & ~0xFFF)
|
||||
#endif
|
||||
|
||||
// Page table/directory entry flags.
|
||||
|
||||
@ -11,4 +11,7 @@ void freerange(void *vstart, void *vend);
|
||||
void* kalloc(void);
|
||||
void kfree(char*);
|
||||
|
||||
pde_t *setupkvm();
|
||||
void kvmalloc();
|
||||
void switchkvm();
|
||||
int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top);
|
||||
|
||||
84
kernel/vm.c
84
kernel/vm.c
@ -1,11 +1,12 @@
|
||||
#include "mem.h"
|
||||
#include "cpu/memlayout.h"
|
||||
#include "cpu/x86.h"
|
||||
#include "console.h"
|
||||
|
||||
pde_t *kvm;
|
||||
|
||||
void kvmalloc() {
|
||||
kvm = kalloc();
|
||||
pde_t *setupkvm(void) {
|
||||
pde_t *kvm = kalloc();
|
||||
memset(kvm, 0, PGSIZE);
|
||||
|
||||
// Map physical memory to KERNBASE..KERNBASE+PHYSTOP
|
||||
@ -13,6 +14,81 @@ void kvmalloc() {
|
||||
uintptr_t va = KERNBASE + pa;
|
||||
kvm[PDX(va)] = pa | PTE_P | PTE_W | PTE_PS;
|
||||
}
|
||||
|
||||
lcr3(V2P(kvm));
|
||||
return kvm;
|
||||
}
|
||||
|
||||
void kvmalloc() {
|
||||
kvm = setupkvm();
|
||||
switchkvm();
|
||||
}
|
||||
|
||||
void switchkvm(void)
|
||||
{
|
||||
lcr3(V2P(kvm)); // switch to the kernel page table
|
||||
}
|
||||
|
||||
// Return the address of the PTE in page table pgdir
|
||||
// that corresponds to virtual address va. If alloc!=0,
|
||||
// create any required page table pages.
|
||||
static pte_t *
|
||||
walkpgdir(pde_t *pgdir, const void *va, int alloc)
|
||||
{
|
||||
pde_t *pde;
|
||||
pte_t *pgtab;
|
||||
|
||||
pde = &pgdir[PDX(va)];
|
||||
if (*pde & PTE_P) {
|
||||
pgtab = (pte_t *)P2V(PTE_ADDR(*pde));
|
||||
} else {
|
||||
if (!alloc || (pgtab = (pte_t *)kalloc()) == 0)
|
||||
return 0;
|
||||
// Make sure all those PTE_P bits are zero.
|
||||
memset(pgtab, 0, PGSIZE);
|
||||
// The permissions here are overly generous, but they can
|
||||
// be further restricted by the permissions in the page table
|
||||
// entries, if necessary.
|
||||
*pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;
|
||||
}
|
||||
return &pgtab[PTX(va)];
|
||||
}
|
||||
|
||||
// Create PTEs for virtual addresses starting at va that refer to
|
||||
// physical addresses starting at pa. va and size might not
|
||||
// be page-aligned.
|
||||
static int
|
||||
mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa, int perm)
|
||||
{
|
||||
char *a, *last;
|
||||
pte_t *pte;
|
||||
|
||||
a = (char *)PGROUNDDOWN((uintptr_t)va);
|
||||
last = (char *)PGROUNDDOWN(((uintptr_t)va) + size - 1);
|
||||
for (;;)
|
||||
{
|
||||
if ((pte = walkpgdir(pgdir, a, 1)) == 0)
|
||||
return -1;
|
||||
if (*pte & PTE_P)
|
||||
panic("remap");
|
||||
*pte = pa | perm | PTE_P;
|
||||
if (a == last)
|
||||
break;
|
||||
a += PGSIZE;
|
||||
pa += PGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top) {
|
||||
for (uintptr_t a = PGROUNDUP(base); a < top; a += PGSIZE) {
|
||||
char *pa = kalloc();
|
||||
if (pa == 0) {
|
||||
return -1;
|
||||
}
|
||||
memset(pa, 0, PGSIZE);
|
||||
if (mappages(pgdir, (void*)a, PGSIZE, V2P(pa), PTE_W | PTE_U) < 0) {
|
||||
kfree(pa);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
7
proc.c
7
proc.c
@ -3,6 +3,7 @@
|
||||
#include "fs/fs.h"
|
||||
#include "cpu/gdt.h"
|
||||
#include "cpu/isr.h"
|
||||
#include "cpu/memlayout.h"
|
||||
#include "kernel/mem.h"
|
||||
#include "lib/string.h"
|
||||
#include "console.h"
|
||||
@ -43,7 +44,10 @@ void run_elf(const char* name) {
|
||||
}
|
||||
if (!vm.user_task) {
|
||||
vm.user_task = kalloc();
|
||||
switchuvm(&vm.user_task->tss, vm.user_task->stack.bottom);
|
||||
vm.user_task->pgdir = setupkvm();
|
||||
allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size);
|
||||
allocuvm(vm.user_task->pgdir, USER_STACK_BASE - 2 * PGSIZE, USER_STACK_BASE);
|
||||
switchuvm(&vm.user_task->tss, vm.user_task->stack.bottom, vm.user_task->pgdir);
|
||||
}
|
||||
if (read_file(&statbuf, (void*)USER_BASE, 100 << 20) <= 0) {
|
||||
printk(name);
|
||||
@ -75,6 +79,7 @@ void run_elf(const char* name) {
|
||||
|
||||
_Noreturn void killproc() {
|
||||
void* task_stack;
|
||||
switchkvm();
|
||||
swtch(&task_stack, vm.kernel_thread);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user