I think I fixed a bunch of stuff

This commit is contained in:
Андреев Григорий 2026-04-06 05:20:00 +03:00
parent 2503938fc4
commit 49ce1a2d45
14 changed files with 87 additions and 50 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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