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
|
LDFLAGS=-m elf_i386
|
||||||
|
|
||||||
user/%: user/%.o user/crt.o
|
user/%: user/%.o user/crt.o
|
||||||
$(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $^
|
$(LD) $(LDFLAGS) -o $@ -Ttext 0x401000 $^
|
||||||
|
|
||||||
image.bin: mbr.bin fs.img
|
image.bin: mbr.bin fs.img
|
||||||
cat $^ >$@
|
cat $^ >$@
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "memlayout.h"
|
||||||
#include "../lib/string.h"
|
#include "../lib/string.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ void load_gdt() {
|
|||||||
asm("lgdt %0": : "m"(gdt_desc));
|
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));
|
memset(tss, 0, sizeof(*tss));
|
||||||
seg_desc[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss)-1, 0);
|
seg_desc[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss)-1, 0);
|
||||||
seg_desc[SEG_TSS].s = 0;
|
seg_desc[SEG_TSS].s = 0;
|
||||||
@ -63,4 +65,6 @@ void switchuvm(struct taskstate *tss, void* esp) {
|
|||||||
tss->iomb = (ushort) 0xFFFF;
|
tss->iomb = (ushort) 0xFFFF;
|
||||||
|
|
||||||
asm("ltr %0": : "r"((ushort)(SEG_TSS << 3)));
|
asm("ltr %0": : "r"((ushort)(SEG_TSS << 3)));
|
||||||
|
|
||||||
|
lcr3(V2P(pgdir));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#define KERN_STACK_BASE 0x90000
|
#define KERN_STACK_BASE 0x90000
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
#include "kernel/mem.h"
|
||||||
typedef unsigned uint;
|
typedef unsigned uint;
|
||||||
typedef unsigned short ushort;
|
typedef unsigned short ushort;
|
||||||
|
|
||||||
@ -73,5 +74,5 @@ struct taskstate {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void load_gdt();
|
void load_gdt();
|
||||||
void switchuvm(struct taskstate *tss, void* esp);
|
void switchuvm(struct taskstate *tss, void* esp, pde_t *pgdir);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
#define PHYSTOP 0x8000000
|
#define PHYSTOP 0x8000000
|
||||||
|
|
||||||
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
|
#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 PDXSHIFT 22 // offset of PDX in a linear address
|
||||||
|
|
||||||
#define PXMASK 0x3FF
|
#define PXMASK 0x3FF
|
||||||
@ -17,6 +19,12 @@
|
|||||||
|
|
||||||
// page directory index
|
// page directory index
|
||||||
#define PDX(va) (((uintptr_t)(va) >> PDXSHIFT) & PXMASK)
|
#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
|
#endif
|
||||||
|
|
||||||
// Page table/directory entry flags.
|
// Page table/directory entry flags.
|
||||||
|
|||||||
@ -11,4 +11,7 @@ void freerange(void *vstart, void *vend);
|
|||||||
void* kalloc(void);
|
void* kalloc(void);
|
||||||
void kfree(char*);
|
void kfree(char*);
|
||||||
|
|
||||||
|
pde_t *setupkvm();
|
||||||
void kvmalloc();
|
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 "mem.h"
|
||||||
#include "cpu/memlayout.h"
|
#include "cpu/memlayout.h"
|
||||||
#include "cpu/x86.h"
|
#include "cpu/x86.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
pde_t *kvm;
|
pde_t *kvm;
|
||||||
|
|
||||||
void kvmalloc() {
|
pde_t *setupkvm(void) {
|
||||||
kvm = kalloc();
|
pde_t *kvm = kalloc();
|
||||||
memset(kvm, 0, PGSIZE);
|
memset(kvm, 0, PGSIZE);
|
||||||
|
|
||||||
// Map physical memory to KERNBASE..KERNBASE+PHYSTOP
|
// Map physical memory to KERNBASE..KERNBASE+PHYSTOP
|
||||||
@ -13,6 +14,81 @@ void kvmalloc() {
|
|||||||
uintptr_t va = KERNBASE + pa;
|
uintptr_t va = KERNBASE + pa;
|
||||||
kvm[PDX(va)] = pa | PTE_P | PTE_W | PTE_PS;
|
kvm[PDX(va)] = pa | PTE_P | PTE_W | PTE_PS;
|
||||||
}
|
}
|
||||||
|
return kvm;
|
||||||
lcr3(V2P(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 "fs/fs.h"
|
||||||
#include "cpu/gdt.h"
|
#include "cpu/gdt.h"
|
||||||
#include "cpu/isr.h"
|
#include "cpu/isr.h"
|
||||||
|
#include "cpu/memlayout.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
@ -43,7 +44,10 @@ void run_elf(const char* name) {
|
|||||||
}
|
}
|
||||||
if (!vm.user_task) {
|
if (!vm.user_task) {
|
||||||
vm.user_task = kalloc();
|
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) {
|
if (read_file(&statbuf, (void*)USER_BASE, 100 << 20) <= 0) {
|
||||||
printk(name);
|
printk(name);
|
||||||
@ -75,6 +79,7 @@ void run_elf(const char* name) {
|
|||||||
|
|
||||||
_Noreturn void killproc() {
|
_Noreturn void killproc() {
|
||||||
void* task_stack;
|
void* task_stack;
|
||||||
|
switchkvm();
|
||||||
swtch(&task_stack, vm.kernel_thread);
|
swtch(&task_stack, vm.kernel_thread);
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user