Add a CPU interface
This commit is contained in:
parent
e16324887f
commit
c319336e3d
@ -5,13 +5,15 @@ set(CMAKE_CXX_COMPILER_WORKS 1)
|
|||||||
|
|
||||||
set(CMAKE_CROSSCOMPILING true)
|
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(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER x86_64-luna-gcc)
|
set(CMAKE_C_COMPILER x86_64-luna-gcc)
|
||||||
set(CMAKE_CXX_COMPILER x86_64-luna-g++)
|
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)
|
set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/x86-64-luna)
|
||||||
|
|
||||||
add_subdirectory(kernel)
|
add_subdirectory(kernel)
|
@ -7,30 +7,45 @@ set(SOURCES
|
|||||||
src/arch/Serial.cpp
|
src/arch/Serial.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# x86-64 specific
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
${SOURCES}
|
${SOURCES}
|
||||||
src/arch/x86_64/IO.cpp
|
src/arch/x86_64/IO.cpp
|
||||||
src/arch/x86_64/Serial.cpp
|
src/arch/x86_64/Serial.cpp
|
||||||
src/arch/x86_64/MMU.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_library(moon-asm STATIC ${ASM_SOURCES})
|
||||||
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_executable(moon ${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)
|
set_target_properties(moon PROPERTIES CXX_STANDARD 20)
|
||||||
|
|
||||||
target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna)
|
target_include_directories(moon PUBLIC ${LUNA_ROOT}/luna)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "Init.h"
|
#include "Init.h"
|
||||||
#include "Framebuffer.h"
|
#include "Framebuffer.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
|
#include "arch/CPU.h"
|
||||||
#include "arch/Serial.h"
|
#include "arch/Serial.h"
|
||||||
#include "bootboot.h"
|
#include "bootboot.h"
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
@ -21,4 +22,6 @@ void Init::early_init()
|
|||||||
{
|
{
|
||||||
Framebuffer::init();
|
Framebuffer::init();
|
||||||
MemoryManager::init();
|
MemoryManager::init();
|
||||||
|
|
||||||
|
CPU::platform_init();
|
||||||
}
|
}
|
10
kernel/src/arch/CPU.h
Normal file
10
kernel/src/arch/CPU.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Result.h>
|
||||||
|
|
||||||
|
namespace CPU
|
||||||
|
{
|
||||||
|
Result<const char*> identify();
|
||||||
|
void platform_init();
|
||||||
|
|
||||||
|
[[noreturn]] void efficient_halt();
|
||||||
|
}
|
17
kernel/src/arch/x86_64/CPU.asm
Normal file
17
kernel/src/arch/x86_64/CPU.asm
Normal 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
|
44
kernel/src/arch/x86_64/CPU.cpp
Normal file
44
kernel/src/arch/x86_64/CPU.cpp
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,13 @@
|
|||||||
#include "Framebuffer.h"
|
#include "Framebuffer.h"
|
||||||
#include "Init.h"
|
#include "Init.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
|
#include "arch/CPU.h"
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "arch/Serial.h"
|
#include "arch/Serial.h"
|
||||||
|
|
||||||
extern u8 fb[1];
|
extern u8 fb[1];
|
||||||
|
|
||||||
void hang()
|
extern "C" [[noreturn]] void _start()
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void _start()
|
|
||||||
{
|
{
|
||||||
Init::check_magic();
|
Init::check_magic();
|
||||||
Init::early_init();
|
Init::early_init();
|
||||||
@ -21,6 +16,10 @@ extern "C" void _start()
|
|||||||
|
|
||||||
Framebuffer::rect(0, 0, 200, 200, 0xFF00FF00);
|
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!!");
|
Serial::println(MMU::get_physical((u64)fb).has_error() ? "fb is not mapped" : "fb is mapped!!");
|
||||||
|
|
||||||
const u64 address = 0xfffffffff8000000;
|
const u64 address = 0xfffffffff8000000;
|
||||||
@ -31,28 +30,40 @@ extern "C" void _start()
|
|||||||
bool success = !rc.has_error();
|
bool success = !rc.has_error();
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
u8* ptr;
|
volatile u8* ptr;
|
||||||
|
|
||||||
if (success) Serial::println("Mapped page :)");
|
if (success) Serial::println("Mapped page :)");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial::println("Failed to map page");
|
Serial::println("Failed to map page");
|
||||||
hang();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)");
|
if (MMU::get_physical(address).release_value() == physical) Serial::println("Mapping is active ;)");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial::println("Mapping is not active");
|
Serial::println("Mapping is not active");
|
||||||
hang();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = MMU::get_flags(address).release_value();
|
flags = MMU::get_flags(address).release_value();
|
||||||
|
|
||||||
if (flags & MMU::ReadWrite) Serial::println("Mapping is writable");
|
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;
|
*ptr = 8;
|
||||||
|
|
||||||
@ -62,21 +73,16 @@ extern "C" void _start()
|
|||||||
if (urc.has_error())
|
if (urc.has_error())
|
||||||
{
|
{
|
||||||
Serial::println("Failed to unmap page");
|
Serial::println("Failed to unmap page");
|
||||||
hang();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urc.release_value() != physical)
|
if (urc.release_value() != physical)
|
||||||
{
|
{
|
||||||
Serial::println("unmap returned a different address than the one we mapped");
|
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;
|
CPU::efficient_halt();
|
||||||
|
|
||||||
Serial::println("ERROR: we should have crashed by this point");
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
;
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user