From 388ac8e7f95ce2dacf8bdaf283a18ce6d77e49b1 Mon Sep 17 00:00:00 2001 From: Nigel Date: Tue, 16 Aug 2022 19:06:16 +0200 Subject: [PATCH] Added checks to be sure paging is actually enabled on the cpu. - Made a special assembly file to put CPU check function in. E.G. functions to get the state of specific registers In this case I have created a simple assembly function to get the contents of the CR0 register. With the help of the c++ preprocessor the value can then be used to check if certains bits are set. For example to check if the PG (paging) bit is set, indicating that paging is enabled for the processor. --- src/kernel/boot.s | 2 +- src/kernel/cpu.h | 68 +++++++++++++++++++++++++++--------- src/kernel/cpu.s | 25 +++++++++++++ src/kernel/memory/paging.cpp | 24 ++++++++++++- src/kernel/memory/paging.h | 4 ++- src/kernel/paging.s | 28 +++++++++++++-- 6 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 src/kernel/cpu.s diff --git a/src/kernel/boot.s b/src/kernel/boot.s index 4b38316..4e4ba36 100644 --- a/src/kernel/boot.s +++ b/src/kernel/boot.s @@ -26,7 +26,7 @@ stack_top: .include "./src/kernel/irq_table.s" .include "./src/kernel/idt/idt.s" .include "./src/kernel/paging.s" - +.include "./src/kernel/cpu.s" .global _start .type _start, @function diff --git a/src/kernel/cpu.h b/src/kernel/cpu.h index 6e9f95a..cd241c7 100644 --- a/src/kernel/cpu.h +++ b/src/kernel/cpu.h @@ -1,17 +1,53 @@ -#include // NOTE: Only available in GCC -// NOT currently usefull! -/* static int get_model(){ - int ebx, unused; - __cpuid(0, unused, ebx, unused, unused); - return ebx; - } +#pragma once - enum { - CPUID_FEAT_EDX_APIC = 1 << 9 - }; - static int check_apic (){ - unsigned int eax, unused, edx; - __get_cpuid(1, &eax, &unused, &unused, &edx); - return edx & CPUID_FEAT_EDX_APIC; - } -*/ \ No newline at end of file +/* +Based on Intel specifications. + +C++ interface for the cpu.s assembly file. + +©Nigel Barink - 2022 +*/ + + +/* +* EFLAGS FUNCTIONS +*/ + +extern "C" uint32_t GetEFLAGS(); + + + +/* +* CONTROL_REGISTER_0 FUNCTIONS +*/ +extern "C" uint32_t GetCR0(); + +/* + struct CR0_Register { + uint8_t PE :1; // Protection Mode Enabled 0 + uint8_t MP :1; // Monitor co-processor 1 + uint8_t EM :1; // Emulation 2 + uint8_t TS :1; // Task switched 3 + uint8_t ET :1; // Extension Type 4 + uint8_t NE :1; // Numeric error 5 + uint16_t Reserved :10; // 6,7,8,9,10,11,12,13,14,15 + uint8_t WP :1; // Write Protect 16 + uint8_t Reserved :1; // 17 + uint8_t AM :1; // Alligment Task 18 + uint16_t Reserved :10; // 19,20,21,22,23,24,25,26,27,28 + uint8_t NW :1; // Not-write through 29 + uint8_t CD :1; // Cache disable 30 + uint8_t PG :1; // Paging 31 + };*/ + + + +#define GET_PE_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x1) +#define GET_MP_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x2) +#define GET_EM_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x3) +#define GET_TS_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x4) +#define GET_ET_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x5) +#define GET_NE_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0&0x6) + + +#define GET_PG_BIT(CONTROL_REGISTER_0) (CONTROL_REGISTER_0>>31) \ No newline at end of file diff --git a/src/kernel/cpu.s b/src/kernel/cpu.s new file mode 100644 index 0000000..aa662dd --- /dev/null +++ b/src/kernel/cpu.s @@ -0,0 +1,25 @@ +# Basic cpu functions +.globl GetCR0 +GetCR0: + push %ebp # save the base pointer on the stack + mov %esp, %ebp # Set the base pointer to the current stack pointer + + xor %eax, %eax # Clear EAX to make sure no weird stuff is going on + mov %cr0, %eax # Copy the value of the CR0 register into EAX + + mov %ebp, %esp # restore the base pointer + pop %ebp + ret + +.globl GetEFLAGS +GetEFLAGS: + push %ebp + mov %esp, %ebp + + xor %eax, %eax + pushfl # Push the EFLAGS register content onto the stack, should be pushfd but GAS apparently doesn't agree + mov 4(%esp) , %eax + + mov %ebp, %esp + pop %ebp + ret \ No newline at end of file diff --git a/src/kernel/memory/paging.cpp b/src/kernel/memory/paging.cpp index 9ea4859..70dd0a6 100644 --- a/src/kernel/memory/paging.cpp +++ b/src/kernel/memory/paging.cpp @@ -2,6 +2,9 @@ PageDirectoryEntry kernel_directory[MAX_DIRECTORY_ENTRIES]__attribute__((aligned(4096))); PageTableEntry first_page_table[1024]__attribute__((aligned(4096))); + + + #define KERNEL_VRT_MEMORY_BEGIN 0xC0000000 #define KERNEL_VRT_MEMORY_END 0xCFFFFFFF #define PAGE_SIZE 0xFA0; @@ -105,10 +108,29 @@ void Unmap(VIRTUAL_ADDRESS vaddr, PageDirectoryEntry& page_directory) void Enable() -{ +{ + + //TODO: Write protect will not be turned on + // for the moment altough according to the intel + // developer manual this should happen. + + uint32_t CR0; + + CR0 = GetCR0(); + printf("PG bit = %d \n" , GET_PG_BIT(CR0)); + printf("Load into CR3 address: 0x%x\n", (uint32_t)(&kernel_directory[0])); loadPageDirectory(&kernel_directory[0]); enablePaging(); printf("Paging enabled!\n"); + + + CR0 = GetCR0(); + printf("PG bit = %d \n" , GET_PG_BIT(CR0) ); + + + uint32_t EFLAGS = GetEFLAGS(); + + } diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index 789574e..612c757 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -2,7 +2,7 @@ #include "./memory.h" #include "./../tty/kterm.h" #include "paging.definitions.h" - +#include "../cpu.h" extern "C" void loadPageDirectory (uint32_t* addr ); extern "C" void enablePaging(); @@ -16,3 +16,5 @@ void FreePage(VIRTUAL_ADDRESS, PageDirectoryEntry&); void Map(PHYSICAL_ADDRESS, VIRTUAL_ADDRESS, PageDirectoryEntry&); void Unmap (VIRTUAL_ADDRESS, PageDirectoryEntry&); + + diff --git a/src/kernel/paging.s b/src/kernel/paging.s index fa25003..ca25a7d 100644 --- a/src/kernel/paging.s +++ b/src/kernel/paging.s @@ -1,10 +1,17 @@ +# NOTE: I wish this wasn't AT&T Syntax its horrible +# REMINDER: INSTRUCTION FROM_REGISTER, TO_REGISTER .globl enablePaging enablePaging: + # Create a new call frame push %ebp mov %esp, %ebp + + # Set the PG bit of CR0 mov %cr0, %eax or $0x80000000, %eax mov %eax, %cr0 + + # Restore to the previous call frame mov %ebp, %esp pop %ebp ret @@ -13,8 +20,25 @@ enablePaging: loadPageDirectory: push %ebp mov %esp, %ebp - mov 8(%esp), %eax - mov %eax, %cr3 + + /* NOTE: We should probably check if paging is already enabled. + Changing the CR3 register whilst paging is enabled might + result in unwanted behaviour (in the worst case) or cause a + fault (in the best case). + */ + + mov 8(%esp), %eax # Move the first argument in the eax register + + mov %eax, %cr3 # Move the value of eax into the CR3 register + + /* + Moving the value of the argument passed to this function + into the CR3 register will allow the MMU to access the paging + structure we setup in memory once we enable paging + */ + mov %ebp, %esp pop %ebp ret + +