mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
MSR and syscall changes
- Moved MSR code to separate files with an enum class - Implemented syscall_enable in C++ using new MSR calls
This commit is contained in:
@@ -14,22 +14,6 @@ outb(uint16_t port, uint8_t val)
|
|||||||
__asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) );
|
__asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) );
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
|
||||||
rdmsr(uint64_t addr)
|
|
||||||
{
|
|
||||||
uint32_t low, high;
|
|
||||||
__asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr));
|
|
||||||
return (static_cast<uint64_t>(high) << 32) | low;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wrmsr(uint64_t addr, uint64_t value)
|
|
||||||
{
|
|
||||||
uint32_t low = value & 0xffffffff;
|
|
||||||
uint32_t high = value >> 32;
|
|
||||||
__asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
io_wait(unsigned times)
|
io_wait(unsigned times)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,16 +14,6 @@ uint8_t inb(uint16_t port);
|
|||||||
/// \arg val The byte to write
|
/// \arg val The byte to write
|
||||||
void outb(uint16_t port, uint8_t val);
|
void outb(uint16_t port, uint8_t val);
|
||||||
|
|
||||||
/// Read the value of a MSR
|
|
||||||
/// \arg addr The MSR address
|
|
||||||
/// \returns The current value of the MSR
|
|
||||||
uint64_t rdmsr(uint64_t addr);
|
|
||||||
|
|
||||||
/// Write to a MSR
|
|
||||||
/// \arg addr The MSR address
|
|
||||||
/// \arg value The value to write
|
|
||||||
void wrmsr(uint64_t addr, uint64_t value);
|
|
||||||
|
|
||||||
/// Pause briefly by doing IO to port 0x80
|
/// Pause briefly by doing IO to port 0x80
|
||||||
/// \arg times Number of times to delay by writing
|
/// \arg times Number of times to delay by writing
|
||||||
void io_wait(unsigned times = 1);
|
void io_wait(unsigned times = 1);
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void kernel_main(popcorn_data *header);
|
void kernel_main(popcorn_data *header);
|
||||||
void syscall_enable();
|
|
||||||
|
|
||||||
void *__bss_start, *__bss_end;
|
void *__bss_start, *__bss_end;
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/kernel/msr.cpp
Normal file
18
src/kernel/msr.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "msr.h"
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
rdmsr(msr addr)
|
||||||
|
{
|
||||||
|
uint32_t low, high;
|
||||||
|
__asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr));
|
||||||
|
return (static_cast<uint64_t>(high) << 32) | low;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wrmsr(msr addr, uint64_t value)
|
||||||
|
{
|
||||||
|
uint32_t low = value & 0xffffffff;
|
||||||
|
uint32_t high = value >> 32;
|
||||||
|
__asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high));
|
||||||
|
}
|
||||||
|
|
||||||
27
src/kernel/msr.h
Normal file
27
src/kernel/msr.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
/// \file msr.h
|
||||||
|
/// Routines and definitions for dealing with Model-Specific Registers
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum class msr : uint32_t
|
||||||
|
{
|
||||||
|
ia32_efer = 0xc0000080,
|
||||||
|
ia32_star = 0xc0000081,
|
||||||
|
ia32_lstar = 0xc0000082,
|
||||||
|
ia32_fmask = 0xc0000084,
|
||||||
|
|
||||||
|
ia32_gs_base = 0xc0000101,
|
||||||
|
ia32_kernel_gs_base = 0xc0000102
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Read the value of a MSR
|
||||||
|
/// \arg addr The MSR address
|
||||||
|
/// \returns The current value of the MSR
|
||||||
|
uint64_t rdmsr(msr addr);
|
||||||
|
|
||||||
|
/// Write to a MSR
|
||||||
|
/// \arg addr The MSR address
|
||||||
|
/// \arg value The value to write
|
||||||
|
void wrmsr(msr addr, uint64_t value);
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "msr.h"
|
||||||
#include "page_manager.h"
|
#include "page_manager.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
|
||||||
@@ -194,12 +195,10 @@ scheduler::schedule(addr_t rsp0)
|
|||||||
m_current = m_runlists[pri].pop_front();
|
m_current = m_runlists[pri].pop_front();
|
||||||
rsp0 = m_current->rsp;
|
rsp0 = m_current->rsp;
|
||||||
|
|
||||||
static const uint64_t ia32_gs_base = 0xc0000101;
|
|
||||||
static const uint64_t ia32_kernel_gs_base = 0xc0000102;
|
|
||||||
|
|
||||||
// Set rsp0 to after the end of the about-to-be-popped cpu state
|
// Set rsp0 to after the end of the about-to-be-popped cpu state
|
||||||
tss_set_stack(0, rsp0 + sizeof(cpu_state));
|
tss_set_stack(0, rsp0 + sizeof(cpu_state));
|
||||||
wrmsr(ia32_gs_base, rsp0);
|
wrmsr(msr::ia32_kernel_gs_base, rsp0);
|
||||||
|
log::debug(logs::task, "Scheduler set kernel_gs_base to %016lx", rsp0);
|
||||||
|
|
||||||
// Swap page tables
|
// Swap page tables
|
||||||
page_table *pml4 = m_current->pml4;
|
page_table *pml4 = m_current->pml4;
|
||||||
|
|||||||
@@ -1,11 +1,36 @@
|
|||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "msr.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void _halt();
|
void _halt();
|
||||||
|
void syscall_handler_prelude();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
syscall_enable()
|
||||||
|
{
|
||||||
|
// IA32_EFER - set bit 0, syscall enable
|
||||||
|
uint64_t efer = rdmsr(msr::ia32_efer);
|
||||||
|
wrmsr(msr::ia32_efer, efer|1);
|
||||||
|
|
||||||
|
// IA32_STAR - high 32 bits contain k+u CS
|
||||||
|
// Kernel CS: GDT[1] ring 0 bits[47:32]
|
||||||
|
// User CS: GDT[3] ring 3 bits[63:48]
|
||||||
|
uint64_t star =
|
||||||
|
(((1ull << 3) | 0) << 32) |
|
||||||
|
(((3ull << 3) | 3) << 48);
|
||||||
|
wrmsr(msr::ia32_star, star);
|
||||||
|
|
||||||
|
// IA32_LSTAR - RIP for syscall
|
||||||
|
wrmsr(msr::ia32_lstar,
|
||||||
|
reinterpret_cast<addr_t>(&syscall_handler_prelude));
|
||||||
|
|
||||||
|
// IA32_FMASK - FLAGS mask inside syscall
|
||||||
|
wrmsr(msr::ia32_fmask, 0x200);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_t
|
addr_t
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "kutil/memory.h"
|
#include "kutil/memory.h"
|
||||||
|
|
||||||
|
struct cpu_state;
|
||||||
|
|
||||||
enum class syscall : uint64_t
|
enum class syscall : uint64_t
|
||||||
{
|
{
|
||||||
noop,
|
noop,
|
||||||
@@ -13,6 +15,6 @@ enum class syscall : uint64_t
|
|||||||
last_syscall
|
last_syscall
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpu_state;
|
void syscall_enable();
|
||||||
addr_t syscall_dispatch(addr_t, const cpu_state &);
|
addr_t syscall_dispatch(addr_t, const cpu_state &);
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,7 @@
|
|||||||
%include "push_all.inc"
|
%include "push_all.inc"
|
||||||
|
|
||||||
global syscall_enable
|
|
||||||
syscall_enable:
|
|
||||||
; IA32_EFER - set bit 0, syscall enable
|
|
||||||
mov rcx, 0xc0000080
|
|
||||||
rdmsr
|
|
||||||
or rax, 0x1
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
; IA32_STAR - cs for syscall
|
|
||||||
mov rcx, 0xc0000081
|
|
||||||
mov rax, 0 ; not used
|
|
||||||
mov rdx, 0x00180008 ; GDT:3 (user code), GDT:1 (kernel code)
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
; IA32_LSTAR - RIP for syscall
|
|
||||||
mov rcx, 0xc0000082
|
|
||||||
lea rax, [rel syscall_handler_prelude]
|
|
||||||
mov rdx, rax
|
|
||||||
shr rdx, 32
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
; IA32_FMASK - FLAGS mask inside syscall
|
|
||||||
mov rcx, 0xc0000084
|
|
||||||
mov rax, 0x200
|
|
||||||
mov rdx, 0
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
extern syscall_handler
|
extern syscall_handler
|
||||||
|
global syscall_handler_prelude
|
||||||
syscall_handler_prelude:
|
syscall_handler_prelude:
|
||||||
push 0 ; ss, doesn't matter here
|
push 0 ; ss, doesn't matter here
|
||||||
push rsp
|
push rsp
|
||||||
|
|||||||
Reference in New Issue
Block a user