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.
This commit is contained in:
Nigel Barink 2022-08-16 19:06:16 +02:00
parent 9172da075a
commit 388ac8e7f9
6 changed files with 130 additions and 21 deletions

View File

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

View File

@ -1,17 +1,53 @@
#include <cpuid.h> // 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;
}
*/
/*
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)

25
src/kernel/cpu.s Normal file
View File

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

View File

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

View File

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

View File

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