diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index 56b3e986..a1720bd7 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -150,6 +150,8 @@ #define SYSCALL_GETUMASK 126 #define SYSCALL_FSTATVFS 127 #define SYSCALL_FSTATVFSAT 128 -#define SYSCALL_MAX_NUM 129 /* index of highest constant + 1 */ +#define SYSCALL_RDMSR 129 +#define SYSCALL_WRMSR 130 +#define SYSCALL_MAX_NUM 131 /* index of highest constant + 1 */ #endif diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index 901fc039..1ee67d1c 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. This file is part of Sortix. @@ -94,9 +94,13 @@ #include "uart.h" #include "vga.h" #include "vgatextbuffer.h" + +#if defined(__i386__) || defined(__x86_64__) #include "x86-family/cmos.h" #include "x86-family/float.h" #include "x86-family/gdt.h" +#include "x86-family/x86-family.h" +#endif // Keep the stack size aligned with $CPU/base.s const size_t STACK_SIZE = 64*1024; @@ -408,6 +412,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) // Stage 2. Transition to Multithreaded Environment // + // Initialize CPU system calls. + CPU::Init(); + // Initialize the clocks. Time::Init(); diff --git a/kernel/x86-family/x86-family.cpp b/kernel/x86-family/x86-family.cpp index 893d98aa..16debf2b 100644 --- a/kernel/x86-family/x86-family.cpp +++ b/kernel/x86-family/x86-family.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. This file is part of Sortix. @@ -22,9 +22,14 @@ *******************************************************************************/ +#include +#include #include #include +#include + +#include "gdt.h" namespace Sortix { namespace CPU { @@ -107,5 +112,61 @@ void ShutDown() Reboot(); } +static uint64_t sys_rdmsr(uint32_t msrid) +{ + switch ( msrid ) + { + case MSRID_FSBASE: +#if defined(__i386__) + return GDT::GetFSBase(); +#elif defined(__x86_64__) + return rdmsr(msrid); +#endif + case MSRID_GSBASE: +#if defined(__i386__) + return GDT::GetGSBase(); +#elif defined(__x86_64__) + return rdmsr(msrid); +#endif + default: + return errno = EPERM, UINT64_MAX; + }; +} + +static uint64_t sys_wrmsr(uint32_t msrid, uint64_t value) +{ + switch ( msrid ) + { + case MSRID_FSBASE: +#if defined(__i386__) + if ( UINT32_MAX < value ) + return errno = EINVAL, UINT64_MAX; + return GDT::SetFSBase((uint32_t) value), value; +#elif defined(__x86_64__) + if ( value >> 48 != 0x0000 && value >> 48 != 0xFFFF ) + return errno = EINVAL, UINT64_MAX; + return wrmsr(msrid, value); +#endif + case MSRID_GSBASE: +#if defined(__i386__) + if ( UINT32_MAX < value ) + return errno = EINVAL, UINT64_MAX; + return GDT::SetGSBase((uint32_t) value), value; +#elif defined(__x86_64__) + if ( value >> 48 != 0x0000 && value >> 48 != 0xFFFF ) + return errno = EINVAL, UINT64_MAX; + return wrmsr(msrid, value); +#endif + default: + return errno = EPERM, UINT64_MAX; + }; +} + +void Init() +{ + Syscall::Register(SYSCALL_RDMSR, (void*) sys_rdmsr); + Syscall::Register(SYSCALL_WRMSR, (void*) sys_wrmsr); +} + } // namespace CPU } // namespace Sortix diff --git a/kernel/x86-family/x86-family.h b/kernel/x86-family/x86-family.h index 6c335bc4..1be4970b 100644 --- a/kernel/x86-family/x86-family.h +++ b/kernel/x86-family/x86-family.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. This file is part of Sortix. @@ -22,51 +22,17 @@ *******************************************************************************/ -#ifndef SORTIX_X86_FAMILY_H -#define SORTIX_X86_FAMILY_H +#ifndef SORTIX_X86_FAMILY_X86_FAMILY_H +#define SORTIX_X86_FAMILY_X86_FAMILY_H -#include -#include +#include namespace Sortix { namespace CPU { -void OutPortB(uint16_t port, uint8_t value); -void OutPortW(uint16_t port, uint16_t value); -void OutPortL(uint16_t port, uint32_t value); -uint8_t InPortB(uint16_t port); -uint16_t InPortW(uint16_t port); -uint32_t InPortL(uint16_t port); -void Reboot(); -void ShutDown(); +void Init(); } // namespace CPU } // namespace Sortix -namespace Sortix { - -const size_t FLAGS_CARRY = 1 << 0; // 0x000001 -const size_t FLAGS_RESERVED1 = 1 << 1; // 0x000002, read as one -const size_t FLAGS_PARITY = 1 << 2; // 0x000004 -const size_t FLAGS_RESERVED2 = 1 << 3; // 0x000008 -const size_t FLAGS_AUX = 1 << 4; // 0x000010 -const size_t FLAGS_RESERVED3 = 1 << 5; // 0x000020 -const size_t FLAGS_ZERO = 1 << 6; // 0x000040 -const size_t FLAGS_SIGN = 1 << 7; // 0x000080 -const size_t FLAGS_TRAP = 1 << 8; // 0x000100 -const size_t FLAGS_INTERRUPT = 1 << 9; // 0x000200 -const size_t FLAGS_DIRECTION = 1 << 10; // 0x000400 -const size_t FLAGS_OVERFLOW = 1 << 11; // 0x000800 -const size_t FLAGS_IOPRIVLEVEL = 1 << 12) | 1 << 13; -const size_t FLAGS_NESTEDTASK = 1 << 14; // 0x004000 -const size_t FLAGS_RESERVED4 = 1 << 15; // 0x008000 -const size_t FLAGS_RESUME = 1 << 16; // 0x010000 -const size_t FLAGS_VIRTUAL8086 = 1 << 17; // 0x020000 -const size_t FLAGS_ALIGNCHECK = 1 << 18; // 0x040000 -const size_t FLAGS_VIRTINTR = 1 << 19; // 0x080000 -const size_t FLAGS_VIRTINTRPEND = 1 << 20; // 0x100000 -const size_t FLAGS_ID = 1 << 21; // 0x200000 - -} // namespace Sortix - #endif diff --git a/libc/Makefile b/libc/Makefile index f55b7230..8ecf0c18 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -302,6 +302,8 @@ libgen/basename.o \ libgen/dirname.o \ locale/localeconv.o \ locale/setlocale.o \ +msr/rdmsr.o \ +msr/wrmsr.o \ netdb/endhostent.o \ netdb/endnetent.o \ netdb/endprotoent.o \ diff --git a/libc/include/msr.h b/libc/include/msr.h index da190177..111263a9 100644 --- a/libc/include/msr.h +++ b/libc/include/msr.h @@ -38,7 +38,7 @@ __BEGIN_DECLS #define MSRID_GSBASE __UINT32_C(0xC0000101) __attribute__((unused)) -static __inline uint64_t rdmsr(uint32_t msrid) +static __inline uint64_t rdmsr_instruction(uint32_t msrid) { uint32_t low; uint32_t high; @@ -47,7 +47,7 @@ static __inline uint64_t rdmsr(uint32_t msrid) } __attribute__((unused)) -static __inline uint64_t wrmsr(uint32_t msrid, uint64_t value) +static __inline uint64_t wrmsr_instruction(uint32_t msrid, uint64_t value) { uint32_t low = value >> 0 & 0xFFFFFFFF; uint32_t high = value >> 32 & 0xFFFFFFFF;; @@ -55,6 +55,27 @@ static __inline uint64_t wrmsr(uint32_t msrid, uint64_t value) return value; } +#if __STDC_HOSTED__ + +uint64_t rdmsr(uint32_t msrid); +uint64_t wrmsr(uint32_t msrid, uint64_t value); + +#else + +__attribute__((unused)) +static __inline uint64_t rdmsr(uint32_t msrid) +{ + return rdmsr_instruction(msrid); +} + +__attribute__((unused)) +static __inline uint64_t wrmsr(uint32_t msrid, uint64_t value) +{ + return wrmsr_instruction(msrid, value); +} + +#endif + __attribute__((unused)) static __inline void rdmsr_split(uint32_t msrid, uint32_t* low, uint32_t* high) { diff --git a/libc/msr/rdmsr.cpp b/libc/msr/rdmsr.cpp new file mode 100644 index 00000000..5b0a8754 --- /dev/null +++ b/libc/msr/rdmsr.cpp @@ -0,0 +1,39 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013 + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + msr/rdmsr.cpp + Reads a model specific register. + +*******************************************************************************/ + +#include + +#include +#include + +#if defined(__i386__) || defined(__x86_64__) + +DEFN_SYSCALL1(uint64_t, sys_rdmsr, SYSCALL_RDMSR, uint32_t); + +extern "C" uint64_t rdmsr(uint32_t msrid) +{ + return sys_rdmsr(msrid); +} + +#endif diff --git a/libc/msr/wrmsr.cpp b/libc/msr/wrmsr.cpp new file mode 100644 index 00000000..600f767b --- /dev/null +++ b/libc/msr/wrmsr.cpp @@ -0,0 +1,39 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013 + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + msr/rdmsr.cpp + Sets a model specific register. + +*******************************************************************************/ + +#include + +#include +#include + +#if defined(__i386__) || defined(__x86_64__) + +DEFN_SYSCALL2(uint64_t, sys_wrmsr, SYSCALL_WRMSR, uint32_t, uint64_t); + +extern "C" uint64_t wrmsr(uint32_t msrid, uint64_t value) +{ + return sys_wrmsr(msrid, value); +} + +#endif diff --git a/libc/x64/fork.S b/libc/x64/fork.S index af789a22..1bbbba75 100644 --- a/libc/x64/fork.S +++ b/libc/x64/fork.S @@ -41,8 +41,13 @@ __call_tfork_with_regs: # of each register in the child. Since we create an identical copy, we # simply set each member of the structure to our own state. Note that since # the stack goes downwards, we create it in the reverse order. - pushq $0 # gsbase - pushq $0 # fsbase + movl $MSRID_GSBASE, %edi + call rdmsr + pushq %rax + movl $MSRID_FSBASE, %edi + call rdmsr + pushq %rax + movq -8(%rbp), %rdi pushfq pushq %r15 pushq %r14 diff --git a/libc/x86/fork.S b/libc/x86/fork.S index d3c0879f..3b31e7cb 100644 --- a/libc/x86/fork.S +++ b/libc/x86/fork.S @@ -37,8 +37,12 @@ __call_tfork_with_regs: # of each register in the child. Since we create an identical copy, we # simply set each member of the structure to our own state. Note that since # the stack goes downwards, we create it in the reverse order. - pushl $0 # gsbase - pushl $0 # fsbase + pushl $MSRID_GSBASE + call rdmsr + movl %eax, (%esp) + pushl $MSRID_FSBASE + call rdmsr + movl %eax, (%esp) pushfl pushl %ebp pushl %esp