Fix run_elf (still leaking memory now).

This commit is contained in:
Alexander Myltsev 2025-01-18 02:05:34 +04:00
parent 62c290f449
commit 117f6423c4
7 changed files with 106 additions and 9 deletions

View File

@ -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 $^ >$@

View File

@ -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));
} }

View File

@ -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

View File

@ -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.

View File

@ -11,4 +11,7 @@ void freerange(void *vstart, void *vend);
void* kalloc(void); void* kalloc(void);
void kfree(char*); void kfree(char*);
void kvmalloc(); pde_t *setupkvm();
void kvmalloc();
void switchkvm();
int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top);

View File

@ -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
View File

@ -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();
} }