Add a CPU interface

This commit is contained in:
apio 2022-11-15 19:10:32 +01:00
parent e16324887f
commit c319336e3d
7 changed files with 132 additions and 35 deletions

View File

@ -5,13 +5,15 @@ set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_CROSSCOMPILING true)
project(Luna LANGUAGES C CXX ASM)
project(Luna LANGUAGES C CXX ASM_NASM)
set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR})
set(CMAKE_C_COMPILER x86_64-luna-gcc)
set(CMAKE_CXX_COMPILER x86_64-luna-g++)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna)
add_subdirectory(kernel)

View File

@ -7,30 +7,45 @@ set(SOURCES
src/arch/Serial.cpp
)
# x86-64 specific
set(SOURCES
${SOURCES}
src/arch/x86_64/IO.cpp
src/arch/x86_64/Serial.cpp
src/arch/x86_64/MMU.cpp
src/arch/x86_64/CPU.cpp
)
add_compile_options(-Os)
# x86-64 specific
set(ASM_SOURCES
src/arch/x86_64/CPU.asm
)
add_compile_options(-pedantic -Wall -Wextra -Werror -Wvla)
add_compile_options(-Wdisabled-optimization -Wformat=2 -Winit-self)
add_compile_options(-Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef)
add_compile_options(-Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion)
add_compile_options(-fno-rtti -ffreestanding -fno-exceptions)
add_compile_options(-fno-asynchronous-unwind-tables -fno-omit-frame-pointer)
add_compile_options(-nostdlib -mcmodel=kernel)
add_compile_options(-mno-red-zone)
add_compile_options(-mno-80387 -mno-mmx -mno-sse -mno-sse2)
add_link_options(-lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel)
add_library(moon-asm STATIC ${ASM_SOURCES})
add_executable(moon ${SOURCES})
target_link_libraries(moon moon-asm)
target_compile_options(moon PRIVATE -Os)
target_compile_options(moon PRIVATE -pedantic -Wall -Wextra -Werror -Wvla)
target_compile_options(moon PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self)
target_compile_options(moon PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef)
target_compile_options(moon PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion)
target_compile_options(moon PRIVATE -fno-rtti -ffreestanding -fno-exceptions)
target_compile_options(moon PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer)
target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel)
# x86-64 specific
target_compile_options(moon PRIVATE -mno-red-zone)
target_compile_options(moon PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2)
target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel)
# x86-64 specific
target_link_options(moon PRIVATE -mno-red-zone)
set_target_properties(moon PROPERTIES CXX_STANDARD 20)
target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna)

View File

@ -1,6 +1,7 @@
#include "Init.h"
#include "Framebuffer.h"
#include "MemoryManager.h"
#include "arch/CPU.h"
#include "arch/Serial.h"
#include "bootboot.h"
#include <String.h>
@ -21,4 +22,6 @@ void Init::early_init()
{
Framebuffer::init();
MemoryManager::init();
CPU::platform_init();
}

10
kernel/src/arch/CPU.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <Result.h>
namespace CPU
{
Result<const char*> identify();
void platform_init();
[[noreturn]] void efficient_halt();
}

View File

@ -0,0 +1,17 @@
global enable_sse
enable_sse:
mov rax, cr0
and ax, 0xFFFB ;clear coprocessor emulation CR0.EM
or ax, 0x2 ;set coprocessor monitoring CR0.MP
mov cr0, rax
mov rax, cr4
or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, rax
ret
global enable_write_protect
enable_write_protect:
mov rax, cr0
or eax, 0x80000 ;set write-protect CR0.WP
mov cr0, rax
ret

View File

@ -0,0 +1,44 @@
#include "arch/CPU.h"
#include <String.h>
#include <Types.h>
#include <cpuid.h>
extern "C" void enable_sse();
extern "C" void enable_write_protect();
namespace CPU
{
Result<const char*> identify()
{
static char brand_string[49];
u32 buf[4];
if (!__get_cpuid(0x80000002, &buf[0], &buf[1], &buf[2], &buf[3])) return err;
memcpy(brand_string, buf, 16);
if (!__get_cpuid(0x80000003, &buf[0], &buf[1], &buf[2], &buf[3])) return err;
memcpy(&brand_string[16], buf, 16);
if (!__get_cpuid(0x80000004, &buf[0], &buf[1], &buf[2], &buf[3])) return err;
memcpy(&brand_string[32], buf, 16);
brand_string[48] = 0; // null-terminate it :)
return brand_string;
}
void platform_init()
{
enable_sse();
enable_write_protect();
}
[[noreturn]] void efficient_halt() // Halt the CPU, using the lowest power possible. On x86-64 we do this using the
// "hlt" instruction, which puts the CPU into a low-power idle state until the
// next interrupt arrives... and we disable interrupts beforehand.
{
asm volatile("cli"); // Disable interrupts
loop:
asm volatile("hlt"); // Let the cpu rest and pause until the next interrupt arrives... which in this case should
// be never (unless an NMI arrives) :)
goto loop; // Safeguard: if we ever wake up, start our low-power rest again
}
}

View File

@ -1,18 +1,13 @@
#include "Framebuffer.h"
#include "Init.h"
#include "MemoryManager.h"
#include "arch/CPU.h"
#include "arch/MMU.h"
#include "arch/Serial.h"
extern u8 fb[1];
void hang()
{
for (;;)
;
}
extern "C" void _start()
extern "C" [[noreturn]] void _start()
{
Init::check_magic();
Init::early_init();
@ -21,6 +16,10 @@ extern "C" void _start()
Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00);
auto cpu_name_or_error = CPU::identify();
Serial::println(cpu_name_or_error.has_error() ? "Unable to determine CPU name" : cpu_name_or_error.release_value());
Serial::println(MMU::get_physical((u64)fb).has_error() ? "fb is not mapped" : "fb is mapped!!");
const u64 address = 0xfffffffff8000000;
@ -31,28 +30,40 @@ extern "C" void _start()
bool success = !rc.has_error();
int flags;
u8* ptr;
volatile u8* ptr;
if (success) Serial::println("Mapped page :)");
else
{
Serial::println("Failed to map page");
hang();
CPU::efficient_halt();
}
if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)");
else
{
Serial::println("Mapping is not active");
hang();
CPU::efficient_halt();
}
flags = MMU::get_flags(address).release_value();
if (flags & MMU::ReadWrite) Serial::println("Mapping is writable");
if (flags & MMU::NoExecute) Serial::println("Mapping is not executable");
if (flags & MMU::User) Serial::println("Mapping is user accessible");
ptr = (u8*)address;
auto rrc = MMU::remap(address, MMU::ReadWrite | MMU::User);
if (rrc.has_error())
{
Serial::println("Failed to change flags of mapping");
CPU::efficient_halt();
}
flags = MMU::get_flags(address).release_value();
if (flags & MMU::ReadWrite) Serial::println("Mapping is now writable");
if (flags & MMU::User) Serial::println("Mapping is now user accessible");
ptr = (volatile u8*)address;
*ptr = 8;
@ -62,21 +73,16 @@ extern "C" void _start()
if (urc.has_error())
{
Serial::println("Failed to unmap page");
hang();
CPU::efficient_halt();
}
if (urc.release_value() != physical)
{
Serial::println("unmap returned a different address than the one we mapped");
hang();
CPU::efficient_halt();
}
Serial::println("Unmapped memory, writing to it should crash");
Serial::println("Successfully unmapped address");
*ptr = 16;
Serial::println("ERROR: we should have crashed by this point");
for (;;)
;
CPU::efficient_halt();
}