forked from Bananymous/banan-os
				
			Kernel: Remove old GDT, IDT and MMU code from i386
It will be easier to just rewrite them
This commit is contained in:
		
							parent
							
								
									7ce0370b6a
								
							
						
					
					
						commit
						26ed689d30
					
				|  | @ -117,9 +117,6 @@ elseif("${BANAN_ARCH}" STREQUAL "i386") | ||||||
| 	set(KERNEL_SOURCES | 	set(KERNEL_SOURCES | ||||||
| 		${KERNEL_SOURCES} | 		${KERNEL_SOURCES} | ||||||
| 		arch/i386/boot.S | 		arch/i386/boot.S | ||||||
| 		arch/i386/GDT.cpp |  | ||||||
| 		arch/i386/IDT.cpp |  | ||||||
| 		arch/i386/MMU.cpp |  | ||||||
| 		arch/i386/SpinLock.S | 		arch/i386/SpinLock.S | ||||||
| 		arch/i386/Thread.S | 		arch/i386/Thread.S | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
|  | @ -1,147 +0,0 @@ | ||||||
| #include <BAN/Assert.h> |  | ||||||
| #include <kernel/GDT.h> |  | ||||||
| 
 |  | ||||||
| #include <string.h> |  | ||||||
| 
 |  | ||||||
| extern "C" uintptr_t g_boot_stack_top[0]; |  | ||||||
| 
 |  | ||||||
| namespace Kernel::GDT |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| 	struct TaskStateSegment |  | ||||||
| 	{ |  | ||||||
| 		uint16_t link; |  | ||||||
| 		uint16_t reserved1; |  | ||||||
| 		uint32_t esp0; |  | ||||||
| 		uint16_t ss0; |  | ||||||
| 		uint16_t reserved2; |  | ||||||
| 		uint32_t esp1; |  | ||||||
| 		uint16_t ss1; |  | ||||||
| 		uint16_t reserved3; |  | ||||||
| 		uint32_t esp2; |  | ||||||
| 		uint16_t ss2; |  | ||||||
| 		uint16_t reserved4; |  | ||||||
| 		uint32_t cr3; |  | ||||||
| 		uint32_t eip; |  | ||||||
| 		uint32_t eflags; |  | ||||||
| 		uint32_t eax; |  | ||||||
| 		uint32_t ecx; |  | ||||||
| 		uint32_t edx; |  | ||||||
| 		uint32_t ebx; |  | ||||||
| 		uint32_t esp; |  | ||||||
| 		uint32_t ebp; |  | ||||||
| 		uint32_t esi; |  | ||||||
| 		uint32_t edi; |  | ||||||
| 		uint16_t es; |  | ||||||
| 		uint16_t reserved5; |  | ||||||
| 		uint16_t cs; |  | ||||||
| 		uint16_t reserved6; |  | ||||||
| 		uint16_t ss; |  | ||||||
| 		uint16_t reserved7; |  | ||||||
| 		uint16_t ds; |  | ||||||
| 		uint16_t reserved8; |  | ||||||
| 		uint16_t fs; |  | ||||||
| 		uint16_t reserved9; |  | ||||||
| 		uint16_t gs; |  | ||||||
| 		uint16_t reserved10; |  | ||||||
| 		uint16_t ldtr; |  | ||||||
| 		uint16_t reserved11; |  | ||||||
| 		uint16_t reserved12; |  | ||||||
| 		uint16_t iopb; |  | ||||||
| 		uint32_t ssp; |  | ||||||
| 	} __attribute__((packed)); |  | ||||||
| 
 |  | ||||||
| 	union SegmentDescriptor |  | ||||||
| 	{ |  | ||||||
| 		struct |  | ||||||
| 		{ |  | ||||||
| 			uint16_t	limit1; |  | ||||||
| 			uint16_t	base1; |  | ||||||
| 			uint8_t		base2; |  | ||||||
| 			uint8_t		access; |  | ||||||
| 			uint8_t		limit2 : 4; |  | ||||||
| 			uint8_t		flags  : 4; |  | ||||||
| 			uint8_t		base3; |  | ||||||
| 		} __attribute__((packed)); |  | ||||||
| 
 |  | ||||||
| 		struct |  | ||||||
| 		{ |  | ||||||
| 			uint32_t low; |  | ||||||
| 			uint32_t high; |  | ||||||
| 		} __attribute__((packed)); |  | ||||||
| 
 |  | ||||||
| 	} __attribute__((packed)); |  | ||||||
| 
 |  | ||||||
| 	struct GDTR |  | ||||||
| 	{ |  | ||||||
| 		uint16_t size; |  | ||||||
| 		uint32_t address; |  | ||||||
| 	} __attribute__((packed)); |  | ||||||
| 
 |  | ||||||
| 	static TaskStateSegment* s_tss = nullptr; |  | ||||||
| 	static SegmentDescriptor* s_gdt = nullptr; |  | ||||||
| 	static GDTR s_gdtr; |  | ||||||
| 
 |  | ||||||
| 	static void write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags) |  | ||||||
| 	{ |  | ||||||
| 		SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset); |  | ||||||
| 		desc.base1 = base; |  | ||||||
| 		desc.base2 = base >> 16; |  | ||||||
| 		desc.base3 = base >> 24; |  | ||||||
| 
 |  | ||||||
| 		desc.limit1 = limit; |  | ||||||
| 		desc.limit2 = limit >> 16; |  | ||||||
| 
 |  | ||||||
| 		desc.access = access; |  | ||||||
| 
 |  | ||||||
| 		desc.flags = flags; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	static void write_tss(uint8_t offset) |  | ||||||
| 	{ |  | ||||||
| 		s_tss = new TaskStateSegment(); |  | ||||||
| 		ASSERT(s_tss); |  | ||||||
| 
 |  | ||||||
| 		memset(s_tss, 0x00, sizeof(TaskStateSegment)); |  | ||||||
| 		s_tss->ss0 = 0x10; |  | ||||||
| 		s_tss->esp0 = (uintptr_t)g_boot_stack_top; |  | ||||||
| 
 |  | ||||||
| 		write_entry(offset, (uint32_t)s_tss, sizeof(TaskStateSegment), 0x89, 0x0); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void set_tss_stack(uintptr_t esp) |  | ||||||
| 	{ |  | ||||||
| 		s_tss->esp0 = esp; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	static void flush_gdt() |  | ||||||
| 	{ |  | ||||||
| 		asm volatile("lgdt %0" :: "m"(s_gdtr)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	extern "C" void flush_tss(uint16_t offset) |  | ||||||
| 	{ |  | ||||||
| 		asm volatile("ltr %0" :: "m"(offset)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void initialize() |  | ||||||
| 	{ |  | ||||||
| 		constexpr uint32_t descriptor_count = 6; |  | ||||||
| 		s_gdt = new SegmentDescriptor[descriptor_count]; |  | ||||||
| 		ASSERT(s_gdt); |  | ||||||
| 
 |  | ||||||
| 		s_gdtr.address = (uint64_t)s_gdt; |  | ||||||
| 		s_gdtr.size = descriptor_count * sizeof(SegmentDescriptor) - 1; |  | ||||||
| 
 |  | ||||||
| 		write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
 |  | ||||||
| 		write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xC); // kernel code
 |  | ||||||
| 		write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
 |  | ||||||
| 		write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xC); // user code
 |  | ||||||
| 		write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
 |  | ||||||
| 		write_tss(0x28); |  | ||||||
| 
 |  | ||||||
| 		flush_gdt(); |  | ||||||
| 		flush_tss(0x28); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,270 +0,0 @@ | ||||||
| #include <BAN/Errors.h> |  | ||||||
| #include <kernel/IDT.h> |  | ||||||
| #include <kernel/InterruptController.h> |  | ||||||
| #include <kernel/Memory/kmalloc.h> |  | ||||||
| #include <kernel/Panic.h> |  | ||||||
| #include <kernel/Scheduler.h> |  | ||||||
| 
 |  | ||||||
| #define INTERRUPT_HANDLER____(i, msg)													\ |  | ||||||
| 	static void interrupt ## i ()														\ |  | ||||||
| 	{																					\ |  | ||||||
| 		uint32_t eax, ebx, ecx, edx;													\ |  | ||||||
| 		uint32_t esp, ebp;																\ |  | ||||||
| 		uint32_t cr0, cr2, cr3, cr4;													\ |  | ||||||
| 		asm volatile("":"=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx));						\ |  | ||||||
| 		asm volatile("movl %%esp, %%eax":"=a"(esp));									\ |  | ||||||
| 		asm volatile("movl %%ebp, %%eax":"=a"(ebp));									\ |  | ||||||
| 		asm volatile("movl %%cr0, %%eax":"=a"(cr0)); 									\ |  | ||||||
| 		asm volatile("movl %%cr2, %%eax":"=a"(cr2)); 									\ |  | ||||||
| 		asm volatile("movl %%cr3, %%eax":"=a"(cr3)); 									\ |  | ||||||
| 		asm volatile("movl %%cr4, %%eax":"=a"(cr4)); 									\ |  | ||||||
| 		Kernel::panic(msg "\r\nRegister dump\r\n"										\ |  | ||||||
| 			"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n" 						\ |  | ||||||
| 			"esp=0x{8H}, ebp=0x{8H}\r\n" 												\ |  | ||||||
| 			"CR0=0x{8H}, CR2=0x{8H}, CR3=0x{8H}, CR4=0x{8H}\r\n", 						\ |  | ||||||
| 			eax, ebx, ecx, edx, esp, ebp, cr0, cr2, cr3, cr4);							\ |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| #define INTERRUPT_HANDLER_ERR(i, msg)													\ |  | ||||||
| 	static void interrupt ## i ()														\ |  | ||||||
| 	{																					\ |  | ||||||
| 		uint32_t eax, ebx, ecx, edx;													\ |  | ||||||
| 		uint32_t esp, ebp;																\ |  | ||||||
| 		uint32_t cr0, cr2, cr3, cr4;													\ |  | ||||||
| 		uint32_t error_code;															\ |  | ||||||
| 		asm volatile("":"=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx));						\ |  | ||||||
| 		asm volatile("movl %%esp, %%eax":"=a"(esp));									\ |  | ||||||
| 		asm volatile("movl %%ebp, %%eax":"=a"(ebp));									\ |  | ||||||
| 		asm volatile("movl %%cr0, %%eax":"=a"(cr0)); 									\ |  | ||||||
| 		asm volatile("movl %%cr2, %%eax":"=a"(cr2)); 									\ |  | ||||||
| 		asm volatile("movl %%cr3, %%eax":"=a"(cr3)); 									\ |  | ||||||
| 		asm volatile("movl %%cr4, %%eax":"=a"(cr4)); 									\ |  | ||||||
| 		asm volatile("popl %%eax":"=a"(error_code));									\ |  | ||||||
| 		Kernel::panic(msg " (error code: 0x{8H})\r\n"									\ |  | ||||||
| 			"Register dump\r\n"															\ |  | ||||||
| 			"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n" 						\ |  | ||||||
| 			"esp=0x{8H}, ebp=0x{8H}\r\n" 												\ |  | ||||||
| 			"CR0=0x{8H}, CR2=0x{8H}, CR3=0x{8H}, CR4=0x{8H}\r\n", 						\ |  | ||||||
| 			eax, ebx, ecx, edx, esp, ebp, cr0, cr2, cr3, cr4, error_code);				\ |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| #define REGISTER_HANDLER(i) register_interrupt_handler(i, interrupt ## i) |  | ||||||
| 
 |  | ||||||
| namespace IDT |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| 	struct GateDescriptor |  | ||||||
| 	{ |  | ||||||
| 		uint16_t offset1; |  | ||||||
| 		uint16_t selector; |  | ||||||
| 		uint8_t reserved	: 5; |  | ||||||
| 		uint8_t zero1		: 3; |  | ||||||
| 		uint8_t type		: 4; |  | ||||||
| 		uint8_t zero2		: 1; |  | ||||||
| 		uint8_t DPL			: 2; |  | ||||||
| 		uint8_t present		: 1; |  | ||||||
| 		uint16_t offset2; |  | ||||||
| 	} __attribute__((packed)); |  | ||||||
| 
 |  | ||||||
| 	struct IDTR |  | ||||||
| 	{ |  | ||||||
| 		uint16_t size; |  | ||||||
| 		void* offset; |  | ||||||
| 	} __attribute((packed)); |  | ||||||
| 
 |  | ||||||
| 	static IDTR				s_idtr; |  | ||||||
| 	static GateDescriptor*	s_idt = nullptr; |  | ||||||
| 
 |  | ||||||
| 	static void(*s_irq_handlers[16])() { nullptr }; |  | ||||||
| 
 |  | ||||||
| 	INTERRUPT_HANDLER____(0x00, "Division Error") |  | ||||||
| 	INTERRUPT_HANDLER____(0x01, "Debug") |  | ||||||
| 	INTERRUPT_HANDLER____(0x02, "Non-maskable Interrupt") |  | ||||||
| 	INTERRUPT_HANDLER____(0x03, "Breakpoint") |  | ||||||
| 	INTERRUPT_HANDLER____(0x04, "Overflow") |  | ||||||
| 	INTERRUPT_HANDLER____(0x05, "Bound Range Exception") |  | ||||||
| 	INTERRUPT_HANDLER____(0x06, "Invalid Opcode") |  | ||||||
| 	INTERRUPT_HANDLER____(0x07, "Device Not Available") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x08, "Double Fault") |  | ||||||
| 	INTERRUPT_HANDLER____(0x09, "Coprocessor Segment Overrun") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x0A, "Invalid TSS") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x0B, "Segment Not Present") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x0C, "Stack-Segment Fault") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x0D, "General Protection Fault") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x0E, "Page Fault") |  | ||||||
| 	INTERRUPT_HANDLER____(0x0F, "Unknown Exception 0x0F") |  | ||||||
| 	INTERRUPT_HANDLER____(0x10, "x87 Floating-Point Exception") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x11, "Alignment Check") |  | ||||||
| 	INTERRUPT_HANDLER____(0x12, "Machine Check") |  | ||||||
| 	INTERRUPT_HANDLER____(0x13, "SIMD Floating-Point Exception") |  | ||||||
| 	INTERRUPT_HANDLER____(0x14, "Virtualization Exception") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x15, "Control Protection Exception") |  | ||||||
| 	INTERRUPT_HANDLER____(0x16, "Unknown Exception 0x16") |  | ||||||
| 	INTERRUPT_HANDLER____(0x17, "Unknown Exception 0x17") |  | ||||||
| 	INTERRUPT_HANDLER____(0x18, "Unknown Exception 0x18") |  | ||||||
| 	INTERRUPT_HANDLER____(0x19, "Unknown Exception 0x19") |  | ||||||
| 	INTERRUPT_HANDLER____(0x1A, "Unknown Exception 0x1A") |  | ||||||
| 	INTERRUPT_HANDLER____(0x1B, "Unknown Exception 0x1B") |  | ||||||
| 	INTERRUPT_HANDLER____(0x1C, "Hypervisor Injection Exception") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x1D, "VMM Communication Exception") |  | ||||||
| 	INTERRUPT_HANDLER_ERR(0x1E, "Security Exception") |  | ||||||
| 	INTERRUPT_HANDLER____(0x1F, "Unkown Exception 0x1F") |  | ||||||
| 
 |  | ||||||
| 	extern "C" void handle_irq() |  | ||||||
| 	{ |  | ||||||
| 		uint8_t irq; |  | ||||||
| 		for (uint32_t i = 0; i < 16; i++) |  | ||||||
| 		{ |  | ||||||
| 			if (InterruptController::get().is_in_service(i)) |  | ||||||
| 			{ |  | ||||||
| 				irq = i; |  | ||||||
| 				goto found; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		dprintln("Spurious irq"); |  | ||||||
| 		return; |  | ||||||
| found: |  | ||||||
| 		if (s_irq_handlers[irq]) |  | ||||||
| 			s_irq_handlers[irq](); |  | ||||||
| 		else |  | ||||||
| 			dprintln("no handler for irq 0x{2H}\n", irq); |  | ||||||
| 
 |  | ||||||
| 		// NOTE: Scheduler sends PIT eoi's
 |  | ||||||
| 		if (irq != PIT_IRQ) |  | ||||||
| 			InterruptController::get().eoi(irq); |  | ||||||
| 
 |  | ||||||
| 		Kernel::Scheduler::get().reschedule_if_idling(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	extern "C" void handle_irq_common(); |  | ||||||
| 	asm( |  | ||||||
| 	".globl handle_irq_common;" |  | ||||||
| 	"handle_irq_common:" |  | ||||||
| 		"pusha;" |  | ||||||
| 		"pushw %ds;" |  | ||||||
| 		"pushw %es;" |  | ||||||
| 		"pushw %ss;" |  | ||||||
| 		"pushw %ss;" |  | ||||||
| 		"popw %ds;" |  | ||||||
| 		"popw %es;" |  | ||||||
| 		"call handle_irq;" |  | ||||||
| 		"popw %es;" |  | ||||||
| 		"popw %ds;" |  | ||||||
| 		"popa;" |  | ||||||
| 		"iret;" |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	extern "C" void syscall_asm(); |  | ||||||
| 	asm( |  | ||||||
| 	".global syscall_asm;" |  | ||||||
| 	"syscall_asm:" |  | ||||||
| 		"pusha;" |  | ||||||
| 		"pushw %ds;" |  | ||||||
| 		"pushw %es;" |  | ||||||
| 		"pushw %ss;" |  | ||||||
| 		"pushw %ss;" |  | ||||||
| 		"popw %ds;" |  | ||||||
| 		"popw %es;" |  | ||||||
| 		"pushl %edx;" |  | ||||||
| 		"pushl %ecx;" |  | ||||||
| 		"pushl %ebx;" |  | ||||||
| 		"pushl %eax;" |  | ||||||
| 		"call cpp_syscall_handler;" |  | ||||||
| 		"addl $16, %esp;" |  | ||||||
| 		"popw %es;" |  | ||||||
| 		"popw %ds;" |  | ||||||
| 
 |  | ||||||
| 		// NOTE: following instructions are same as in 'popa', except we skip eax
 |  | ||||||
| 		//       since it holds the return value of the syscall.
 |  | ||||||
| 		"popl %edi;" |  | ||||||
| 		"popl %esi;" |  | ||||||
| 		"popl %ebp;" |  | ||||||
| 		"addl $4, %esp;" |  | ||||||
| 		"popl %ebx;" |  | ||||||
| 		"popl %edx;" |  | ||||||
| 		"popl %ecx;" |  | ||||||
| 		"addl $4, %esp;" |  | ||||||
| 
 |  | ||||||
| 		"iret;" |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	static void flush_idt() |  | ||||||
| 	{ |  | ||||||
| 		asm volatile("lidt %0"::"m"(s_idtr)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	static void register_interrupt_handler(uint8_t index, void(*f)()) |  | ||||||
| 	{ |  | ||||||
| 		GateDescriptor& descriptor = s_idt[index]; |  | ||||||
| 		descriptor.offset1 = (uint32_t)f & 0xFFFF; |  | ||||||
| 		descriptor.selector = 0x08; |  | ||||||
| 		descriptor.type = 0xE; |  | ||||||
| 		descriptor.DPL = 0; |  | ||||||
| 		descriptor.present = 1; |  | ||||||
| 		descriptor.offset2 = (uint32_t)f >> 16; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void register_irq_handler(uint8_t irq, void(*f)()) |  | ||||||
| 	{ |  | ||||||
| 		s_irq_handlers[irq] = f; |  | ||||||
| 		register_interrupt_handler(IRQ_VECTOR_BASE + irq, handle_irq_common); |  | ||||||
| 		flush_idt(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void register_syscall_handler(uint8_t offset, void(*handler)()) |  | ||||||
| 	{ |  | ||||||
| 		register_interrupt_handler(offset, handler); |  | ||||||
| 		s_idt[offset].DPL = 3; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void initialize() |  | ||||||
| 	{ |  | ||||||
| 		constexpr size_t idt_size = 0x100 * sizeof(GateDescriptor); |  | ||||||
| 
 |  | ||||||
| 		s_idt = (GateDescriptor*)kmalloc(idt_size); |  | ||||||
| 		ASSERT(s_idt); |  | ||||||
| 		memset(s_idt, 0x00, idt_size); |  | ||||||
| 
 |  | ||||||
| 		s_idtr.offset = s_idt; |  | ||||||
| 		s_idtr.size = idt_size - 1; |  | ||||||
| 
 |  | ||||||
| 		REGISTER_HANDLER(0x00); |  | ||||||
| 		REGISTER_HANDLER(0x01); |  | ||||||
| 		REGISTER_HANDLER(0x02); |  | ||||||
| 		REGISTER_HANDLER(0x03); |  | ||||||
| 		REGISTER_HANDLER(0x04); |  | ||||||
| 		REGISTER_HANDLER(0x05); |  | ||||||
| 		REGISTER_HANDLER(0x06); |  | ||||||
| 		REGISTER_HANDLER(0x07); |  | ||||||
| 		REGISTER_HANDLER(0x08); |  | ||||||
| 		REGISTER_HANDLER(0x09); |  | ||||||
| 		REGISTER_HANDLER(0x0A); |  | ||||||
| 		REGISTER_HANDLER(0x0B); |  | ||||||
| 		REGISTER_HANDLER(0x0C); |  | ||||||
| 		REGISTER_HANDLER(0x0D); |  | ||||||
| 		REGISTER_HANDLER(0x0E); |  | ||||||
| 		REGISTER_HANDLER(0x0F); |  | ||||||
| 		REGISTER_HANDLER(0x10); |  | ||||||
| 		REGISTER_HANDLER(0x11); |  | ||||||
| 		REGISTER_HANDLER(0x12); |  | ||||||
| 		REGISTER_HANDLER(0x13); |  | ||||||
| 		REGISTER_HANDLER(0x14); |  | ||||||
| 		REGISTER_HANDLER(0x15); |  | ||||||
| 		REGISTER_HANDLER(0x16); |  | ||||||
| 		REGISTER_HANDLER(0x17); |  | ||||||
| 		REGISTER_HANDLER(0x18); |  | ||||||
| 		REGISTER_HANDLER(0x19); |  | ||||||
| 		REGISTER_HANDLER(0x1A); |  | ||||||
| 		REGISTER_HANDLER(0x1B); |  | ||||||
| 		REGISTER_HANDLER(0x1C); |  | ||||||
| 		REGISTER_HANDLER(0x1D); |  | ||||||
| 		REGISTER_HANDLER(0x1E); |  | ||||||
| 		REGISTER_HANDLER(0x1F); |  | ||||||
| 
 |  | ||||||
| 		register_syscall_handler(0x80, syscall_asm); |  | ||||||
| 
 |  | ||||||
| 		flush_idt(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,227 +0,0 @@ | ||||||
| #include <BAN/Errors.h> |  | ||||||
| #include <kernel/Debug.h> |  | ||||||
| #include <kernel/Memory/MMU.h> |  | ||||||
| #include <kernel/Memory/kmalloc.h> |  | ||||||
| 
 |  | ||||||
| #include <string.h> |  | ||||||
| 
 |  | ||||||
| #define MMU_DEBUG_PRINT 0 |  | ||||||
| 
 |  | ||||||
| // bits 31-12 set
 |  | ||||||
| #define PAGE_MASK  0xfffff000 |  | ||||||
| #define FLAGS_MASK 0x00000fff |  | ||||||
| 
 |  | ||||||
| namespace Kernel |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| 	static MMU* s_instance = nullptr; |  | ||||||
| 
 |  | ||||||
| 	void MMU::initialize() |  | ||||||
| 	{ |  | ||||||
| 		ASSERT(s_instance == nullptr); |  | ||||||
| 		s_instance = new MMU(); |  | ||||||
| 		ASSERT(s_instance); |  | ||||||
| 		s_instance->initialize_kernel(); |  | ||||||
| 		s_instance->load(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	MMU& MMU::get() |  | ||||||
| 	{ |  | ||||||
| 		ASSERT(s_instance); |  | ||||||
| 		return *s_instance; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	static uint64_t* allocate_page_aligned_page() |  | ||||||
| 	{ |  | ||||||
| 		uint64_t* page = (uint64_t*)kmalloc(PAGE_SIZE, PAGE_SIZE); |  | ||||||
| 		ASSERT(page); |  | ||||||
| 		ASSERT(((uintptr_t)page % PAGE_SIZE) == 0); |  | ||||||
| 		memset(page, 0, PAGE_SIZE); |  | ||||||
| 		return page; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::initialize_kernel() |  | ||||||
| 	{ |  | ||||||
| 		m_highest_paging_struct = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32); |  | ||||||
| 		ASSERT(m_highest_paging_struct); |  | ||||||
| 		ASSERT(((uintptr_t)m_highest_paging_struct % 32) == 0); |  | ||||||
| 
 |  | ||||||
| 		// allocate all page directories
 |  | ||||||
| 		for (int i = 0; i < 4; i++) |  | ||||||
| 		{ |  | ||||||
| 			uint64_t* page_directory = allocate_page_aligned_page(); |  | ||||||
| 			m_highest_paging_struct[i] = (uint64_t)page_directory | Flags::Present; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// FIXME: We should just identity map until g_kernel_end
 |  | ||||||
| 
 |  | ||||||
| 		// create and identity map first 6 MiB
 |  | ||||||
| 		uint64_t* page_directory1 = (uint64_t*)(m_highest_paging_struct[0] & PAGE_MASK); |  | ||||||
| 		for (uint64_t i = 0; i < 3; i++) |  | ||||||
| 		{ |  | ||||||
| 			uint64_t* page_table = allocate_page_aligned_page(); |  | ||||||
| 			for (uint64_t j = 0; j < 512; j++) |  | ||||||
| 				page_table[j] = (i << 21) | (j << 12) | Flags::ReadWrite | Flags::Present; |  | ||||||
| 
 |  | ||||||
| 			page_directory1[i] = (uint64_t)page_table | Flags::ReadWrite | Flags::Present; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// dont map first page (0 -> 4 KiB) so that nullptr dereference
 |  | ||||||
| 		// causes page fault :)
 |  | ||||||
| 		uint64_t* page_table1 = (uint64_t*)(page_directory1[0] & PAGE_MASK); |  | ||||||
| 		page_table1[0] = 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	MMU::MMU() |  | ||||||
| 	{ |  | ||||||
| 		if (s_instance == nullptr) |  | ||||||
| 			return; |  | ||||||
| 
 |  | ||||||
| 		// Here we copy the s_instances paging structs since they are
 |  | ||||||
| 		// global for every process
 |  | ||||||
| 
 |  | ||||||
| 		uint64_t* global_pdpt = s_instance->m_highest_paging_struct; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* pdpt = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32); |  | ||||||
| 		ASSERT(pdpt); |  | ||||||
| 
 |  | ||||||
| 		for (uint32_t pdpte = 0; pdpte < 4; pdpte++) |  | ||||||
| 		{ |  | ||||||
| 			if (!(global_pdpt[pdpte] & Flags::Present)) |  | ||||||
| 				continue; |  | ||||||
| 
 |  | ||||||
| 			uint64_t* global_pd = (uint64_t*)(global_pdpt[pdpte] & PAGE_MASK); |  | ||||||
| 
 |  | ||||||
| 			uint64_t* pd = allocate_page_aligned_page(); |  | ||||||
| 			pdpt[pdpte] = (uint64_t)pd | (global_pdpt[pdpte] & ~PAGE_MASK); |  | ||||||
| 
 |  | ||||||
| 			for (uint32_t pde = 0; pde < 512; pde++) |  | ||||||
| 			{ |  | ||||||
| 				if (!(global_pd[pde] & Flags::Present)) |  | ||||||
| 					continue; |  | ||||||
| 
 |  | ||||||
| 				uint64_t* global_pt = (uint64_t*)(global_pd[pde] & PAGE_MASK); |  | ||||||
| 
 |  | ||||||
| 				uint64_t* pt = allocate_page_aligned_page(); |  | ||||||
| 				pd[pde] = (uint64_t)pt | (global_pd[pde] & ~PAGE_MASK); |  | ||||||
| 
 |  | ||||||
| 				memcpy(pt, global_pt, PAGE_SIZE); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		m_highest_paging_struct = pdpt; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	MMU::~MMU() |  | ||||||
| 	{ |  | ||||||
| 		uint64_t* pdpt = m_highest_paging_struct; |  | ||||||
| 		for (uint32_t pdpte = 0; pdpte < 512; pdpte++) |  | ||||||
| 		{ |  | ||||||
| 			if (!(pdpt[pdpte] & Flags::Present)) |  | ||||||
| 				continue; |  | ||||||
| 			uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK); |  | ||||||
| 			for (uint32_t pde = 0; pde < 512; pde++) |  | ||||||
| 			{ |  | ||||||
| 				if (!(pd[pde] & Flags::Present)) |  | ||||||
| 					continue; |  | ||||||
| 				kfree((void*)(pd[pde] & PAGE_MASK)); |  | ||||||
| 			} |  | ||||||
| 			kfree(pd); |  | ||||||
| 		} |  | ||||||
| 		kfree(pdpt); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::load() |  | ||||||
| 	{ |  | ||||||
| 		asm volatile("movl %0, %%cr3" :: "r"(m_highest_paging_struct)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::map_page_at(paddr_t paddr, vaddr_t vaddr, uint8_t flags) |  | ||||||
| 	{ |  | ||||||
| 	#if MMU_DEBUG_PRINT |  | ||||||
| 		dprintln("AllocatePage(0x{8H})", address); |  | ||||||
| 	#endif |  | ||||||
| 		ASSERT(flags & Flags::Present); |  | ||||||
| 
 |  | ||||||
| 		ASSERT(!(paddr & ~PAGE_MASK)); |  | ||||||
| 		ASSERT(!(vaddr & ~PAGE_MASK)); |  | ||||||
| 
 |  | ||||||
| 		uint32_t pdpte = (vaddr & 0xC0000000) >> 30; |  | ||||||
| 		uint32_t pde   = (vaddr & 0x3FE00000) >> 21; |  | ||||||
| 		uint32_t pte   = (vaddr & 0x001FF000) >> 12; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); |  | ||||||
| 		if (!(page_directory[pde] & Flags::Present)) |  | ||||||
| 		{ |  | ||||||
| 			uint64_t* page_table = allocate_page_aligned_page(); |  | ||||||
| 			page_directory[pde] = (uint64_t)page_table; |  | ||||||
| 		} |  | ||||||
| 		page_directory[pde] |= flags; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); |  | ||||||
| 		page_table[pte] = paddr | flags; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::identity_map_page(paddr_t address, uint8_t flags) |  | ||||||
| 	{ |  | ||||||
| 		address &= PAGE_MASK; |  | ||||||
| 		map_page_at(address, address, flags); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::identity_map_range(paddr_t address, ptrdiff_t size, uint8_t flags) |  | ||||||
| 	{ |  | ||||||
| 		paddr_t s_page = address & PAGE_MASK; |  | ||||||
| 		paddr_t e_page = (address + size - 1) & PAGE_MASK; |  | ||||||
| 		for (paddr_t page = s_page; page <= e_page; page += PAGE_SIZE) |  | ||||||
| 			identity_map_page(page, flags); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::unmap_page(vaddr_t address) |  | ||||||
| 	{ |  | ||||||
| 	#if MMU_DEBUG_PRINT |  | ||||||
| 		dprintln("UnAllocatePage(0x{8H})", address & PAGE_MASK); |  | ||||||
| 	#endif |  | ||||||
| 
 |  | ||||||
| 		uint32_t pdpte = (address & 0xC0000000) >> 30; |  | ||||||
| 		uint32_t pde   = (address & 0x3FE00000) >> 21; |  | ||||||
| 		uint32_t pte   = (address & 0x001FF000) >> 12; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); |  | ||||||
| 		if (!(page_directory[pde] & Flags::Present)) |  | ||||||
| 			return; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); |  | ||||||
| 		if (!(page_table[pte] & Flags::Present)) |  | ||||||
| 			return; |  | ||||||
| 
 |  | ||||||
| 		page_table[pte] = 0; |  | ||||||
| 
 |  | ||||||
| 		// TODO: Unallocate the page table if this was the only allocated page
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void MMU::unmap_range(vaddr_t address, ptrdiff_t size) |  | ||||||
| 	{ |  | ||||||
| 		uintptr_t s_page = address & PAGE_MASK; |  | ||||||
| 		uintptr_t e_page = (address + size - 1) & PAGE_MASK; |  | ||||||
| 		for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE) |  | ||||||
| 			unmap_page(page); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	uint8_t MMU::get_page_flags(vaddr_t address) const |  | ||||||
| 	{ |  | ||||||
| 		uint32_t pdpte = (address & 0xC0000000) >> 30; |  | ||||||
| 		uint32_t pde   = (address & 0x3FE00000) >> 21; |  | ||||||
| 		uint32_t pte   = (address & 0x001FF000) >> 12; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* page_directory = (uint64_t*)(m_highest_paging_struct[pdpte] & PAGE_MASK); |  | ||||||
| 		if (!(page_directory[pde] & Flags::Present)) |  | ||||||
| 			return 0; |  | ||||||
| 
 |  | ||||||
| 		uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK); |  | ||||||
| 		if (!(page_table[pte] & Flags::Present)) |  | ||||||
| 			return 0; |  | ||||||
| 
 |  | ||||||
| 		return page_table[pte] & FLAGS_MASK; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue