I think I fixed a bunch of stuff
This commit is contained in:
parent
2503938fc4
commit
49ce1a2d45
1
Makefile
1
Makefile
@ -21,6 +21,7 @@ CFLAGS = -fno-pic -ffreestanding -static -fno-builtin -fno-strict-aliasing \
|
|||||||
-I. \
|
-I. \
|
||||||
-Wall -Wno-unused-result -Wno-unused-variable -Wno-unused-but-set-variable -ggdb -m32 -Werror -fno-omit-frame-pointer -Os
|
-Wall -Wno-unused-result -Wno-unused-variable -Wno-unused-but-set-variable -ggdb -m32 -Werror -fno-omit-frame-pointer -Os
|
||||||
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
|
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
|
||||||
|
CFLAGS += -Wno-unused-variable -Wno-unused-function
|
||||||
ASMFLAGS = -m32 -ffreestanding -c -g -I.
|
ASMFLAGS = -m32 -ffreestanding -c -g -I.
|
||||||
|
|
||||||
ifeq ($(LLVM),on)
|
ifeq ($(LLVM),on)
|
||||||
|
|||||||
@ -27,7 +27,7 @@ bootmain(void)
|
|||||||
void (*entry)(void);
|
void (*entry)(void);
|
||||||
uchar* pa;
|
uchar* pa;
|
||||||
|
|
||||||
elf = (Elf32_Ehdr*)0x20000; // scratch space
|
elf = (Elf32_Ehdr*)0x30000; // scratch space
|
||||||
|
|
||||||
// Read 1st page off disk
|
// Read 1st page off disk
|
||||||
readseg((uchar*)elf, 4096, 0);
|
readseg((uchar*)elf, 4096, 0);
|
||||||
|
|||||||
@ -14,6 +14,6 @@ void panic(const char* msg) {
|
|||||||
printk(msg);
|
printk(msg);
|
||||||
asm("cli");
|
asm("cli");
|
||||||
while (1) {
|
while (1) {
|
||||||
asm("hlt");
|
asm volatile("hlt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
cpu/idt.c
18
cpu/idt.c
@ -117,11 +117,17 @@ void trap(registers_t *r) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* get_userspace_ptr(uint32_t ptr) {
|
/* takes a ptr that is supposed to be from userspace. If it is not, we
|
||||||
if (ptr > KERNBASE) {
|
* return 0, if it is a valid userspace pointer, we return the usable
|
||||||
return 0;
|
* kernelspace pointer
|
||||||
}
|
*/
|
||||||
// FIXME: check if ptr is mapped and a valid 0-terminated string
|
uint32_t is_userspace_ptr_mapped(uint32_t ptr) {
|
||||||
|
// todo: implement
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* get_userspace_cstr(uint32_t ptr) {
|
||||||
|
// todo: implement
|
||||||
return (void*)(ptr);
|
return (void*)(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +157,7 @@ static void handle_syscall(registers_t* r) {
|
|||||||
r->eax = 0;
|
r->eax = 0;
|
||||||
break;
|
break;
|
||||||
case SYS_puts:
|
case SYS_puts:
|
||||||
r->eax = handle_puts(get_userspace_ptr(r->ebx));
|
r->eax = handle_puts(get_userspace_cstr(r->ebx));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("Unknown syscall\n");
|
printk("Unknown syscall\n");
|
||||||
|
|||||||
@ -38,4 +38,5 @@
|
|||||||
#define PTE_PCD 0x010 // Cache-Disable
|
#define PTE_PCD 0x010 // Cache-Disable
|
||||||
#define PTE_A 0x020 // Accessed
|
#define PTE_A 0x020 // Accessed
|
||||||
#define PTE_D 0x040 // Dirty
|
#define PTE_D 0x040 // Dirty
|
||||||
#define PTE_PS 0x080 // Page Size
|
// entries of page tables don't have PS
|
||||||
|
#define PDE_PS 0x080 // Page Size
|
||||||
|
|||||||
@ -62,7 +62,7 @@ void init_pit() {
|
|||||||
add_timer_callback(dec_sleep_counter);
|
add_timer_callback(dec_sleep_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sleep_counter = 0;
|
static volatile int sleep_counter = 0;
|
||||||
|
|
||||||
static void dec_sleep_counter(void) {
|
static void dec_sleep_counter(void) {
|
||||||
sleep_counter--;
|
sleep_counter--;
|
||||||
@ -71,6 +71,6 @@ static void dec_sleep_counter(void) {
|
|||||||
void msleep(int ms) {
|
void msleep(int ms) {
|
||||||
sleep_counter = ms / 10;
|
sleep_counter = ms / 10;
|
||||||
while (sleep_counter > 0) {
|
while (sleep_counter > 0) {
|
||||||
asm("hlt");
|
asm volatile("hlt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
kernel.c
10
kernel.c
@ -45,10 +45,6 @@ void read_line_input(char* buf, size_t* ret_len, size_t cap) {
|
|||||||
} else if (keycode == KEYCODE_BACKSPACE) {
|
} else if (keycode == KEYCODE_BACKSPACE) {
|
||||||
unsigned scr_offset = vga_get_cursor();
|
unsigned scr_offset = vga_get_cursor();
|
||||||
if (len > 0 && scr_offset > 0) {
|
if (len > 0 && scr_offset > 0) {
|
||||||
// if (scr_offset % VGA_COLS) {
|
|
||||||
// vga_set
|
|
||||||
// }
|
|
||||||
// vga_set_char()
|
|
||||||
vga_set_char(scr_offset - 1, ' ');
|
vga_set_char(scr_offset - 1, ' ');
|
||||||
vga_set_cursor(scr_offset - 1);
|
vga_set_cursor(scr_offset - 1);
|
||||||
len--;
|
len--;
|
||||||
@ -68,7 +64,7 @@ void read_line_input(char* buf, size_t* ret_len, size_t cap) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asm("hlt");
|
asm volatile("hlt");
|
||||||
size_t count = kbd_state_shrd.len;
|
size_t count = kbd_state_shrd.len;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
cli();
|
cli();
|
||||||
@ -87,9 +83,9 @@ void read_line_input(char* buf, size_t* ret_len, size_t cap) {
|
|||||||
|
|
||||||
|
|
||||||
void kmain() {
|
void kmain() {
|
||||||
freerange(P2V(2u<<20), P2V(3u<<20));
|
freerange(P2V(3u<<20), P2V(4u<<20));
|
||||||
kvmalloc(); // map all of physical memory at KERNBASE
|
kvmalloc(); // map all of physical memory at KERNBASE
|
||||||
freerange(P2V(3u<<20), P2V(PHYSTOP));
|
freerange(P2V(4u<<20), P2V(PHYSTOP));
|
||||||
|
|
||||||
load_gdt();
|
load_gdt();
|
||||||
init_keyboard();
|
init_keyboard();
|
||||||
|
|||||||
@ -23,11 +23,11 @@ _start:
|
|||||||
mov cr4, eax
|
mov cr4, eax
|
||||||
|
|
||||||
// Identity map low 4 MiB
|
// Identity map low 4 MiB
|
||||||
mov dword ptr [0x1000], 0 | PTE_P | PTE_W | PTE_PS
|
mov dword ptr [0x1000], 0 | PTE_P | PTE_W | PDE_PS
|
||||||
|
|
||||||
// KERNBASE = 0x8000_0000
|
// KERNBASE = 0x8000_0000
|
||||||
// Same mapping for the first 4 MiB after KERNBASE
|
// Same mapping for the first 4 MiB after KERNBASE
|
||||||
mov dword ptr [0x1000 + ((KERNBASE >> 22) * 4)], 0 | PTE_P | PTE_W | PTE_PS
|
mov dword ptr [0x1000 + ((KERNBASE >> 22) * 4)], 0 | PTE_P | PTE_W | PDE_PS
|
||||||
|
|
||||||
// Load physical address of PD into CR3
|
// Load physical address of PD into CR3
|
||||||
mov edi, 0x1000
|
mov edi, 0x1000
|
||||||
|
|||||||
41
kernel/vm.c
41
kernel/vm.c
@ -12,7 +12,7 @@ pde_t *setupkvm(void) {
|
|||||||
// Map physical memory to KERNBASE..KERNBASE+PHYSTOP
|
// Map physical memory to KERNBASE..KERNBASE+PHYSTOP
|
||||||
for (uintptr_t pa = 0; pa < PHYSTOP; pa += 4 << 20) {
|
for (uintptr_t pa = 0; pa < PHYSTOP; pa += 4 << 20) {
|
||||||
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 | PDE_PS;
|
||||||
}
|
}
|
||||||
return kvm;
|
return kvm;
|
||||||
}
|
}
|
||||||
@ -27,6 +27,9 @@ void switchkvm(void)
|
|||||||
lcr3(V2P(kvm)); // switch to the kernel page table
|
lcr3(V2P(kvm)); // switch to the kernel page table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Before that point we worked with 4Mb kernel space huge pages
|
||||||
|
* But now we work with 4Kb userspace normal pages */
|
||||||
|
|
||||||
// Return the address of the PTE in page table pgdir
|
// Return the address of the PTE in page table pgdir
|
||||||
// that corresponds to virtual address va. If alloc!=0,
|
// that corresponds to virtual address va. If alloc!=0,
|
||||||
// create any required page table pages.
|
// create any required page table pages.
|
||||||
@ -38,9 +41,16 @@ walkpgdir(pde_t *pgdir, const void *va, int alloc)
|
|||||||
|
|
||||||
pde = &pgdir[PDX(va)];
|
pde = &pgdir[PDX(va)];
|
||||||
if (*pde & PTE_P) {
|
if (*pde & PTE_P) {
|
||||||
|
// we get an address from that entry of PgDir
|
||||||
|
// (that should point to physical memory of a page table),
|
||||||
|
// then we add KERNBASE, getting a pointer to table
|
||||||
|
// (which means the first table entry) in kernel virtual memory
|
||||||
pgtab = (pte_t *)P2V(PTE_ADDR(*pde));
|
pgtab = (pte_t *)P2V(PTE_ADDR(*pde));
|
||||||
} else {
|
} else {
|
||||||
if (!alloc || (pgtab = (pte_t *)kalloc()) == 0)
|
if (!alloc)
|
||||||
|
return 0;
|
||||||
|
pgtab = (pte_t *)kalloc();
|
||||||
|
if (pgtab == 0)
|
||||||
return 0;
|
return 0;
|
||||||
// Make sure all those PTE_P bits are zero.
|
// Make sure all those PTE_P bits are zero.
|
||||||
memset(pgtab, 0, PGSIZE);
|
memset(pgtab, 0, PGSIZE);
|
||||||
@ -53,19 +63,17 @@ walkpgdir(pde_t *pgdir, const void *va, int alloc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create PTEs for virtual addresses starting at va that refer to
|
// Create PTEs for virtual addresses starting at va that refer to
|
||||||
// physical addresses starting at pa. va and size might not
|
// physical addresses starting at pa.
|
||||||
// be page-aligned.
|
// size might not be page-aligned.
|
||||||
static int
|
static int
|
||||||
mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa, int perm)
|
mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa, int perm){
|
||||||
{
|
if ((uintptr_t)va % PGSIZE != 0)
|
||||||
char *a, *last;
|
panic("Why??");
|
||||||
pte_t *pte;
|
char* a = va;
|
||||||
|
char* last = (char *)PGROUNDDOWN(((uintptr_t)va) + size - 1);
|
||||||
a = (char *)PGROUNDDOWN((uintptr_t)va);
|
for (;;){
|
||||||
last = (char *)PGROUNDDOWN(((uintptr_t)va) + size - 1);
|
pte_t *pte = walkpgdir(pgdir, a, 1);
|
||||||
for (;;)
|
if (pte == 0)
|
||||||
{
|
|
||||||
if ((pte = walkpgdir(pgdir, a, 1)) == 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
if (*pte & PTE_P)
|
if (*pte & PTE_P)
|
||||||
panic("remap");
|
panic("remap");
|
||||||
@ -78,8 +86,11 @@ mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa, int perm)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// top may be not page-aligned
|
||||||
int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top) {
|
int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top) {
|
||||||
for (uintptr_t a = PGROUNDUP(base); a < top; a += PGSIZE) {
|
if (base % PGSIZE != 0)
|
||||||
|
panic("You should at least consider killing yourself");
|
||||||
|
for (uintptr_t a = base; a < top; a += PGSIZE) {
|
||||||
char *pa = kalloc();
|
char *pa = kalloc();
|
||||||
if (pa == 0) {
|
if (pa == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
24
proc.c
24
proc.c
@ -1,12 +1,4 @@
|
|||||||
#include "elf.h"
|
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#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"
|
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
// matches the behavior of swtch()
|
// matches the behavior of swtch()
|
||||||
@ -35,6 +27,10 @@ struct vm {
|
|||||||
void trapret();
|
void trapret();
|
||||||
void swtch(void** oldstack, void* newstack);
|
void swtch(void** oldstack, void* newstack);
|
||||||
|
|
||||||
|
pde_t *get_user_proc_page_directory() {
|
||||||
|
return vm.user_task->pgdir;
|
||||||
|
}
|
||||||
|
|
||||||
void run_elf(const char* name) {
|
void run_elf(const char* name) {
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
if (stat(name, &statbuf) != 0) {
|
if (stat(name, &statbuf) != 0) {
|
||||||
@ -45,9 +41,17 @@ void run_elf(const char* name) {
|
|||||||
if (!vm.user_task) {
|
if (!vm.user_task) {
|
||||||
vm.user_task = kalloc();
|
vm.user_task = kalloc();
|
||||||
}
|
}
|
||||||
|
// todo: this code contains 9999 memory leaks but I don't care
|
||||||
|
// todo: yabloko is fucking shit made my monkeys, I want to forget this fucking nightmare
|
||||||
vm.user_task->pgdir = setupkvm();
|
vm.user_task->pgdir = setupkvm();
|
||||||
allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size);
|
if (allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size)) {
|
||||||
allocuvm(vm.user_task->pgdir, USER_STACK_BASE - 2 * PGSIZE, USER_STACK_BASE);
|
printk("Fail: out of memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (allocuvm(vm.user_task->pgdir, USER_STACK_BASE - 2 * PGSIZE, USER_STACK_BASE)) {
|
||||||
|
printk("Fail: out of memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
switchuvm(&vm.user_task->tss, vm.user_task->stack.bottom, vm.user_task->pgdir);
|
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) {
|
||||||
|
|||||||
12
proc.h
12
proc.h
@ -1,4 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "elf.h"
|
||||||
|
#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"
|
||||||
|
|
||||||
|
|
||||||
|
pde_t* get_user_proc_page_directory();
|
||||||
|
|
||||||
void run_elf(const char* name);
|
void run_elf(const char* name);
|
||||||
_Noreturn void killproc();
|
_Noreturn void killproc();
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
T_SYSCALL = 0x84,
|
T_SYSCALL = 0x84,
|
||||||
SYS_exit = 0,
|
SYS_exit = 0,
|
||||||
@ -8,4 +10,4 @@ enum {
|
|||||||
SYS_puts = 3,
|
SYS_puts = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
int syscall(int call, int arg);
|
int syscall(int call, uintptr_t arg);
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
int main();
|
int main();
|
||||||
|
|
||||||
int syscall(int call, int arg) {
|
int syscall(int call, uintptr_t arg) {
|
||||||
asm("int $0x84": "+a"(call) : "b"(arg));
|
asm volatile("int $0x84": "+a"(call) : "b"(arg));
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,11 @@ void userspace_puts(const char* s) {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
const char* spell = "cra cra trif traf not sgnieflet\n";
|
const char* spell = "cra cra trif traf not sgnieflet\n";
|
||||||
userspace_puts(spell);
|
const char* spell2 = "Pam pam pam pam parapapapapam\n";
|
||||||
syscall(SYS_puts, (uint32_t)spell);
|
const char* spell3 = "Zhopu podotri\n";
|
||||||
|
// userspace_puts(spell);
|
||||||
|
syscall(SYS_puts, (uintptr_t)spell);
|
||||||
|
syscall(SYS_puts, (uint32_t)spell2);
|
||||||
|
syscall(SYS_puts, (uint32_t)spell3);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user