summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorDanny Holman <dholman@gymli.org>2024-02-16 13:06:43 -0600
committerDanny Holman <dholman@gymli.org>2024-02-16 13:06:43 -0600
commit33fdc9b20c12e6c776ed76fc59d848a3ad7f6bca (patch)
treee305d66a4be29a2446506ee17897957846518125 /arch
parent95606a6be7c64065d295bdabb1a94fb42108e72f (diff)
arch: i386: roll physical memory control into VMM
The VMM should control the physical memory as well as paging. This allows the VMM to grab frames as it sees fit. Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/include/kernel/alloc.h13
-rw-r--r--arch/i386/include/kernel/paging.h33
-rw-r--r--arch/i386/kernel/alloc.c42
-rw-r--r--arch/i386/kernel/paging.c141
-rw-r--r--arch/i386/linker.ld6
-rw-r--r--arch/i386/make.config4
6 files changed, 107 insertions, 132 deletions
diff --git a/arch/i386/include/kernel/alloc.h b/arch/i386/include/kernel/alloc.h
deleted file mode 100644
index 986bcc5..0000000
--- a/arch/i386/include/kernel/alloc.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef I386_ALLOC_H
-#define I386_ALLOC_H
-
-#include <kernel/multiboot.h>
-#include <stdint.h>
-#include <stddef.h>
-
-int alloc_init(struct mboot_info *info);
-void mark_bitmap(uint32_t paddr, int present);
-uint32_t pfa_alloc_frame(void);
-void pfa_free(uint32_t paddr, int num_frames);
-
-#endif
diff --git a/arch/i386/include/kernel/paging.h b/arch/i386/include/kernel/paging.h
index c65718f..bb79d09 100644
--- a/arch/i386/include/kernel/paging.h
+++ b/arch/i386/include/kernel/paging.h
@@ -2,6 +2,8 @@
#define I386_PAGING_H
#include <kernel/isr.h>
+#include <kernel/multiboot.h>
+#include <kernel/data/list.h>
#include <stdint.h>
#define PD_PRES 0x0001
@@ -21,32 +23,27 @@
#define ERR_RESERVED 0x8
#define ERR_INST 0x10
-#define BLOCK_SIZE 4096
-#define BLOCKS_PER_BUCKET 8
-#define BLOCK_ALIGN(addr) (((addr) & 0xFFFFF000) + 0x1000)
+#define PAGE_SIZE 4096
-#define SETBIT(x,i) x[i/BLOCKS_PER_BUCKET] = x[i/BLOCKS_PER_BUCKET] | (1 << (i % BLOCKS_PER_BUCKET))
-#define CLEARBIT(x,i) x[i/BLOCKS_PER_BUCKET] = x[i/BLOCKS_PER_BUCKET] & (~(1 << (i % BLOCKS_PER_BUCKET)))
-#define ISSET(x,i) ((x[i/BLOCKS_PER_BUCKET] >> (i % BLOCKS_PER_BUCKET)) & 0x1)
-#define GETBUCKET(x,i) (*((uint32_t*)&x[i/32]))
+#define DMA_BITMAP_SZ 128
+#define BDY_BITMAP_SZ 32640
-#define PAGE_SIZE 4096
-
-struct page_frame {
- int used;
- uint32_t addr;
+struct pfa_buddy {
+ uintptr_t start;
+ uintptr_t *bitmap;
+ uint8_t size;
+ struct list_head list;
};
-void load_page_dir(uint32_t pd_addr);
+void load_page_dir(uintptr_t pd_addr);
void enable_paging(void);
-void paging_init();
+void paging_init(void);
void page_fault_handler(struct isr_frame *frame);
-uint32_t get_paddr(uint32_t vaddr);
-uint32_t get_vaddr(uint32_t paddr);
+uint32_t get_vaddr(uintptr_t paddr);
-void map_page(uint32_t paddr, uint32_t vaddr, uint32_t flags);
-void unmap_page(uint32_t vaddr);
+void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags);
+void unmap_page(uint32_t *pd, uintptr_t vaddr);
#endif
diff --git a/arch/i386/kernel/alloc.c b/arch/i386/kernel/alloc.c
deleted file mode 100644
index 890c2f1..0000000
--- a/arch/i386/kernel/alloc.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <kernel/alloc.h>
-#include <kernel/paging.h>
-#include <kernel/io.h>
-#include <stdint.h>
-
-extern uint32_t _bitmap_start;
-static uint32_t *bm_start = &_bitmap_start;
-
-static struct mboot_info *info;
-
-int alloc_init(struct mboot_info *info) {
- struct mboot_mmap_entry *mme;
- for (uint32_t i = 0; i < info->mmap_length; i += sizeof(struct mboot_mmap_entry)) {
- mme = (struct mboot_mmap_entry*)(info->mmap_addr + i);
- if (mme->type != MBOOT_MEM_AVAILABLE)
- mark_bitmap(mme->addr_low, 1);
- }
- return 0;
-}
-
-void mark_bitmap(uint32_t paddr, int present) {
- uint32_t index = (paddr & 0xFFFFF000) / 4096 / 32;
- uint32_t bit = (paddr & 0xFFFFF000) / 4096 % 32;
- bm_start[index] |= (present << bit);
-}
-
-uint32_t pfa_alloc_frame(void) {
- for (uint32_t i = 0; i < 4096; i++) {
- uint32_t index = i / 32;
- uint32_t bit = i % 32;
- if ((bm_start[index] & (1 << bit)) == 0) {
- mark_bitmap(i*4096, 1);
- return i * 4096;
- }
- }
- return 0xFFFFFFFF;
-}
-
-void pfa_free(uint32_t paddr, int num_frames) {
- for (int i = 0; i < num_frames; i++)
- mark_bitmap(paddr + (i*4096), 0);
-}
diff --git a/arch/i386/kernel/paging.c b/arch/i386/kernel/paging.c
index d8f72a3..54539ac 100644
--- a/arch/i386/kernel/paging.c
+++ b/arch/i386/kernel/paging.c
@@ -2,87 +2,120 @@
#include <kernel/io.h>
#include <kernel/syscall.h>
#include <kernel/string.h>
-#include <kernel/alloc.h>
-#include <stddef.h>
-extern int halt_catch_fire();
-extern uint32_t _kernel_start;
-extern uint32_t _kernel_end;
-static uint32_t *kstart = &_kernel_start;
-static uint32_t *kend = (uint32_t)(&_kernel_end) - 0xC0000000;
+extern uintptr_t _kernel_start;
+extern uintptr_t _kernel_end;
+static uintptr_t kstart = (uintptr_t)&_kernel_start;
+static uintptr_t kend = (uintptr_t)&_kernel_end - 0xC0000000;
-static uint32_t page_directory[1024] __attribute__((aligned(PAGE_SIZE)));
-static uint32_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
+static uintptr_t page_directory[1024] __attribute__((aligned(PAGE_SIZE)));
+static uintptr_t first_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
static int paging_enabled = 0;
+static uint32_t dma_zone_bitmap[DMA_BITMAP_SZ];
+static uint32_t buddy_bitmap[BDY_BITMAP_SZ];
+static struct pfa_buddy first_buddy;
+
+static void _pfa_init(void) {
+ first_buddy.start = 0x01000000;
+ first_buddy.bitmap = buddy_bitmap;
+}
+
+static void _pfa_alloc(uintptr_t paddr) {
+ uintptr_t index = (paddr & 0xFFFFF000) / 4096 / 32;
+ uintptr_t bit = (paddr & 0xFFFFF000) / 4096 % 32;
+ uint32_t *bitmap;
+ if (paddr < 0x01000000)
+ bitmap = dma_zone_bitmap;
+ else
+ bitmap = first_buddy.bitmap;
+
+ bitmap[index] |= (1 << bit);
+}
+
+static void _pfa_free(uintptr_t paddr) {
+ uintptr_t index = (paddr & 0xFFFFF000) / 4096 / 32;
+ uintptr_t bit = (paddr & 0xFFFFF000) / 4096 % 32;
+ uint32_t *bitmap;
+ if (paddr < 0x01000000)
+ bitmap = dma_zone_bitmap;
+ else
+ bitmap = first_buddy.bitmap;
+
+ bitmap[index] &= ~(1 << bit);
+}
+
void paging_init(void) {
+ _pfa_init();
for (int i = 0; i < 1024; i++)
page_directory[i] = 0x00000002;
- page_directory[1023] = ((uint32_t)&page_directory - 0xC0000000) | 3;
- page_directory[0] = ((uint32_t)&first_page_table - 0xC0000000) | 3;
- page_directory[768] = ((uint32_t)&first_page_table - 0xC0000000) | 3;
- for (uint32_t i = kstart; i < kend; i += 4096) {
- map_page(i, get_vaddr(i), 0x003);
- mark_bitmap(i, 1);
+ page_directory[1023] = ((uintptr_t)&page_directory - 0xC0000000) | 3;
+ page_directory[0] = ((uintptr_t)&first_page_table - 0xC0000000) | 3;
+ page_directory[768] = ((uintptr_t)&first_page_table - 0xC0000000) | 3;
+ for (uintptr_t i = kstart; i < kend; i += 4096) {
+ _pfa_alloc(get_vaddr(i));
+ map_page(page_directory, i, get_vaddr(i), 0x003);
}
- map_page(0xB8000, 0xC03FF000, 0x003);
- mark_bitmap(0xB8000, 1);
-
- load_page_dir(((uint32_t)&page_directory) - 0xC0000000);
+ load_page_dir(((uintptr_t)&page_directory) - 0xC0000000);
enable_paging();
paging_enabled = 1;
return;
}
void page_fault_handler(struct isr_frame *frame) {
- kprintf("Page fault detected\n");
- uint32_t errno = frame->errno;
+ uintptr_t errno = frame->errno;
- uint32_t fault_addr;
+ uintptr_t fault_addr;
__asm__ volatile("movl %%cr2, %0" : "=r"(fault_addr));
- kprintf("Fault occured at address %x\n", fault_addr);
- uint32_t present = errno & ERR_PRESENT;
- uint32_t rw = errno & ERR_RW;
- uint32_t user = errno & ERR_USER;
- uint32_t reserved = errno & ERR_RESERVED;
- uint32_t ifetch = errno & ERR_INST;
- kprintf("Possible causes:\n");
- if (!present) kprintf("\tPage not present\n");
- if (rw || user) kprintf("\tPage is read only\n");
- if (reserved) kprintf("\tOverwrote reserved bits\n");
- if (ifetch) kprintf("\tInstruction fetch\n");
- halt_catch_fire(frame);
-}
-
-uint32_t get_paddr(uint32_t vaddr) {
- uint32_t pdindex = vaddr >> 22;
- uint32_t ptindex = vaddr >> 12 & 0x03FF;
-
- uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
- return (page_table[ptindex] & 0xFFFFF000) | (vaddr & 0x00000FFF);
+ int present = errno & ERR_PRESENT;
+ int rw = errno & ERR_RW;
+ int user = errno & ERR_USER;
+ int reserved = errno & ERR_RESERVED;
+ int ifetch = errno & ERR_INST;
+
+ if (!present)
+ _pfa_alloc(fault_addr);
+ map_page(NULL, fault_addr, fault_addr, 0x003);
+ if (user)
+ panic("Usermode attempted to read supervisor page");
+ if (rw)
+ panic("Task wrote to read only page");
+ if (reserved)
+ panic("Task overwrote reserved page bits");
+ if (ifetch)
+ panic("Task paging instruction fetch failure");
}
-uint32_t get_vaddr(uint32_t paddr) {
+uintptr_t get_vaddr(uintptr_t paddr) {
return paddr + 0xC0000000;
}
-void map_page(uint32_t paddr, uint32_t vaddr, uint32_t flags) {
- uint32_t pdindex = vaddr >> 22;
- uint32_t ptindex = vaddr >> 12 & 0x03FF;
+void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags) {
+ if (pd == NULL)
+ pd = page_directory;
+
+ uintptr_t paddr_aligned = paddr & 0xFFFFF000;
+ uintptr_t vaddr_aligned = vaddr & 0xFFFFF000;
- uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
- uint32_t *pte = (uint32_t*)(&page_table[ptindex]);
- *pte |= paddr | (flags & 0xFFF) | 0x01;
+ uintptr_t pdindex = vaddr_aligned >> 22;
+ uintptr_t ptindex = vaddr_aligned >> 12 & 0x03FF;
+
+ uintptr_t *pt = (pd[pdindex] + 0xC0000000 & 0xFFFFF000);
+ uintptr_t *pte = (uintptr_t*)(&pt[ptindex]);
+ *pte |= paddr_aligned | (flags & 0xFFF) | 0x01;
}
-void unmap_page(uint32_t vaddr) {
- uint32_t pdindex = vaddr >> 22;
- uint32_t ptindex = vaddr >> 12 & 0x03FF;
+void unmap_page(uint32_t *pd, uintptr_t vaddr) {
+ if (pd == NULL)
+ pd = page_directory;
+
+ uintptr_t pdindex = vaddr >> 22;
+ uintptr_t ptindex = vaddr >> 12 & 0x03FF;
- uint32_t *page_table = (page_directory[pdindex] + 0xC0000000 & 0xFFFFF000);
- uint32_t *pte = (uint32_t*)(&page_table[ptindex]);
+ uintptr_t *pt = (pd[pdindex] + 0xC0000000 & 0xFFFFF000);
+ uintptr_t *pte = (uintptr_t*)(&pt[ptindex]);
*pte &= 0;
}
diff --git a/arch/i386/linker.ld b/arch/i386/linker.ld
index 61799c7..7eb9d99 100644
--- a/arch/i386/linker.ld
+++ b/arch/i386/linker.ld
@@ -26,9 +26,9 @@ SECTIONS {
*(.bootstrap_stack)
}
- _bitmap_start = .;
- . += 128K;
- _bitmap_end = .;
+ .usertext ALIGN(4K) : AT(ADDR(.usertext) - 0xC0000000) {
+ *(.usertext)
+ }
_kernel_end = .;
}
diff --git a/arch/i386/make.config b/arch/i386/make.config
index 4729739..2c87912 100644
--- a/arch/i386/make.config
+++ b/arch/i386/make.config
@@ -7,10 +7,10 @@ KERNEL_ARCH_OBJS=$(ARCHDIR)/boot/boot.o \
$(ARCHDIR)/boot/isr.o \
$(ARCHDIR)/boot/idt.o \
$(ARCHDIR)/boot/gdt.o \
- $(ARCHDIR)/kernel/tty.o \
- $(ARCHDIR)/kernel/alloc.o \
+ $(ARCHDIR)/kernel/framebuffer.o \
$(ARCHDIR)/kernel/multiboot.o \
$(ARCHDIR)/kernel/serial.o \
$(ARCHDIR)/kernel/pic.o \
+ $(ARCHDIR)/kernel/timer.o \
$(ARCHDIR)/kernel/syscall.o \
$(ARCHDIR)/kernel/paging.o \