mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
hw_x86_64: assemble TSS and IDT statically
* remove alignment restrictions of code64 entrypoint Ref #2092
This commit is contained in:
parent
bb10afa266
commit
b6490e913f
@ -20,14 +20,12 @@ SRC_CC += spec/x86/io_port_session_support.cc
|
||||
SRC_CC += spec/x86_64/bios_data_area.cc
|
||||
SRC_CC += spec/x86_64/cpu.cc
|
||||
SRC_CC += spec/x86_64/fpu.cc
|
||||
SRC_CC += spec/x86_64/idt.cc
|
||||
SRC_CC += spec/x86_64/kernel/cpu.cc
|
||||
SRC_CC += spec/x86_64/kernel/cpu_context.cc
|
||||
SRC_CC += spec/x86_64/kernel/pd.cc
|
||||
SRC_CC += spec/x86_64/kernel/thread.cc
|
||||
SRC_CC += spec/x86_64/kernel/thread.cc
|
||||
SRC_CC += spec/x86_64/platform_support_common.cc
|
||||
SRC_CC += spec/x86_64/tss.cc
|
||||
|
||||
NR_OF_CPUS = 1
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \brief x86_64 CPU driver for core
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Martin stein
|
||||
* \date 2015-04-20
|
||||
* \author Reto Buerki
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-02-06
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,9 +17,278 @@
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__CPU_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/x86_64/cpu_support.h>
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
#include <kernel/interface_support.h>
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
namespace Genode { typedef __uint128_t sizet_arithm_t; }
|
||||
/* base includes */
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
|
||||
/* core includes */
|
||||
#include <fpu.h>
|
||||
#include <timer.h>
|
||||
|
||||
namespace Genode {
|
||||
class Cpu;
|
||||
using sizet_arithm_t = __uint128_t;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Cpu
|
||||
{
|
||||
public:
|
||||
|
||||
struct Pd {};
|
||||
|
||||
struct Pseudo_descriptor;
|
||||
|
||||
struct Cr0; /* Control register 0 */
|
||||
struct Cr2; /* Control register 2 */
|
||||
struct Cr3; /* Control register 3 */
|
||||
struct Cr4; /* Control register 4 */
|
||||
|
||||
|
||||
/**
|
||||
* Task State Segment (TSS)
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 7.7
|
||||
*/
|
||||
struct Tss { static void init(); };
|
||||
|
||||
|
||||
/**
|
||||
* Interrupt Descriptor Table (IDT)
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 6.10
|
||||
*/
|
||||
struct Idt { static void init(); };
|
||||
|
||||
|
||||
/**
|
||||
* Global Descriptor Table (GDT)
|
||||
* See Intel SDM Vol. 3A, section 3.5.1
|
||||
*/
|
||||
struct Gdt { static void init(); };
|
||||
|
||||
|
||||
/**
|
||||
* Extend basic CPU state by members relevant for 'base-hw' only
|
||||
*/
|
||||
struct Context : Cpu_state
|
||||
{
|
||||
/**
|
||||
* Address of top-level paging structure.
|
||||
*/
|
||||
addr_t cr3;
|
||||
|
||||
/**
|
||||
* Return base of assigned translation table
|
||||
*/
|
||||
addr_t translation_table() const { return cr3; }
|
||||
|
||||
/**
|
||||
* Initialize context
|
||||
*
|
||||
* \param table physical base of appropriate translation table
|
||||
* \param core whether it is a core thread or not
|
||||
*/
|
||||
void init(addr_t const table, bool core);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An usermode execution state
|
||||
*/
|
||||
struct User_context : Context, Fpu::Context
|
||||
{
|
||||
/**
|
||||
* Support for kernel calls
|
||||
*/
|
||||
void user_arg_0(Kernel::Call_arg const arg) { rdi = arg; }
|
||||
void user_arg_1(Kernel::Call_arg const arg) { rsi = arg; }
|
||||
void user_arg_2(Kernel::Call_arg const arg) { rdx = arg; }
|
||||
void user_arg_3(Kernel::Call_arg const arg) { rcx = arg; }
|
||||
void user_arg_4(Kernel::Call_arg const arg) { r8 = arg; }
|
||||
void user_arg_5(Kernel::Call_arg const arg) { r9 = arg; }
|
||||
void user_arg_6(Kernel::Call_arg const arg) { r10 = arg; }
|
||||
void user_arg_7(Kernel::Call_arg const arg) { r11 = arg; }
|
||||
Kernel::Call_arg user_arg_0() const { return rdi; }
|
||||
Kernel::Call_arg user_arg_1() const { return rsi; }
|
||||
Kernel::Call_arg user_arg_2() const { return rdx; }
|
||||
Kernel::Call_arg user_arg_3() const { return rcx; }
|
||||
Kernel::Call_arg user_arg_4() const { return r8; }
|
||||
Kernel::Call_arg user_arg_5() const { return r9; }
|
||||
Kernel::Call_arg user_arg_6() const { return r10; }
|
||||
Kernel::Call_arg user_arg_7() const { return r11; }
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
Fpu _fpu;
|
||||
|
||||
public:
|
||||
|
||||
Fpu & fpu() { return _fpu; }
|
||||
|
||||
static constexpr addr_t exception_entry = 0xffff0000;
|
||||
static constexpr addr_t mtc_size = 1 << 13;
|
||||
|
||||
static addr_t virt_mtc_addr(addr_t virt_base, addr_t label);
|
||||
|
||||
/**
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
static void wait_for_interrupt() { asm volatile ("pause"); }
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*/
|
||||
bool retry_undefined_instr(Context&) { return false; }
|
||||
|
||||
|
||||
/**
|
||||
* Return kernel name of the executing CPU
|
||||
*/
|
||||
static unsigned executing_id() { return 0; }
|
||||
|
||||
/**
|
||||
* Return kernel name of the primary CPU
|
||||
*/
|
||||
static unsigned primary_id() { return 0; }
|
||||
|
||||
/**
|
||||
* Switch to new context
|
||||
*
|
||||
* \param context next CPU context
|
||||
*/
|
||||
void switch_to(User_context &context) { _fpu.switch_to(context); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pseudo Descriptor
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 3.5.1
|
||||
*/
|
||||
struct Genode::Cpu::Pseudo_descriptor
|
||||
{
|
||||
uint16_t const limit = 0;
|
||||
uint64_t const base = 0;
|
||||
|
||||
constexpr Pseudo_descriptor(uint16_t l, uint64_t b) : limit(l), base(b) {}
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
struct Genode::Cpu::Cr0 : Register<64>
|
||||
{
|
||||
struct Pe : Bitfield< 0, 1> { }; /* Protection Enable */
|
||||
struct Mp : Bitfield< 1, 1> { }; /* Monitor Coprocessor */
|
||||
struct Em : Bitfield< 2, 1> { }; /* Emulation */
|
||||
struct Ts : Bitfield< 3, 1> { }; /* Task Switched */
|
||||
struct Et : Bitfield< 4, 1> { }; /* Extension Type */
|
||||
struct Ne : Bitfield< 5, 1> { }; /* Numeric Error */
|
||||
struct Wp : Bitfield<16, 1> { }; /* Write Protect */
|
||||
struct Am : Bitfield<18, 1> { }; /* Alignment Mask */
|
||||
struct Nw : Bitfield<29, 1> { }; /* Not Write-through */
|
||||
struct Cd : Bitfield<30, 1> { }; /* Cache Disable */
|
||||
struct Pg : Bitfield<31, 1> { }; /* Paging */
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mov %0, %%cr0" :: "r" (v) : ); }
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr0, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Control register 2: Page-fault linear address
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 2.5.
|
||||
*/
|
||||
struct Genode::Cpu::Cr2 : Register<64>
|
||||
{
|
||||
struct Addr : Bitfield<0, 63> { };
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr2, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Control register 3: Page-Directory base register
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 2.5.
|
||||
*/
|
||||
struct Genode::Cpu::Cr3 : Register<64>
|
||||
{
|
||||
struct Pwt : Bitfield<3,1> { }; /* Page-level write-through */
|
||||
struct Pcd : Bitfield<4,1> { }; /* Page-level cache disable */
|
||||
struct Pdb : Bitfield<12, 36> { }; /* Page-directory base address */
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mov %0, %%cr3" :: "r" (v) : ); }
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr3, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return initialized value
|
||||
*
|
||||
* \param table base of targeted translation table
|
||||
*/
|
||||
static access_t init(addr_t const table) {
|
||||
return Pdb::masked(table); }
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Cpu::Cr4 : Register<64>
|
||||
{
|
||||
struct Vme : Bitfield< 0, 1> { }; /* Virtual-8086 Mode Extensions */
|
||||
struct Pvi : Bitfield< 1, 1> { }; /* Protected-Mode Virtual IRQs */
|
||||
struct Tsd : Bitfield< 2, 1> { }; /* Time Stamp Disable */
|
||||
struct De : Bitfield< 3, 1> { }; /* Debugging Exceptions */
|
||||
struct Pse : Bitfield< 4, 1> { }; /* Page Size Extensions */
|
||||
struct Pae : Bitfield< 5, 1> { }; /* Physical Address Extension */
|
||||
struct Mce : Bitfield< 6, 1> { }; /* Machine-Check Enable */
|
||||
struct Pge : Bitfield< 7, 1> { }; /* Page Global Enable */
|
||||
struct Pce : Bitfield< 8, 1> { }; /* Performance-Monitoring Counter
|
||||
Enable*/
|
||||
struct Osfxsr : Bitfield< 9, 1> { }; /* OS Support for FXSAVE and
|
||||
FXRSTOR instructions*/
|
||||
struct Osxmmexcpt : Bitfield<10, 1> { }; /* OS Support for Unmasked
|
||||
SIMD/FPU Exceptions */
|
||||
struct Vmxe : Bitfield<13, 1> { }; /* VMX Enable */
|
||||
struct Smxe : Bitfield<14, 1> { }; /* SMX Enable */
|
||||
struct Fsgsbase : Bitfield<16, 1> { }; /* FSGSBASE-Enable */
|
||||
struct Pcide : Bitfield<17, 1> { }; /* PCIDE Enable */
|
||||
struct Osxsave : Bitfield<18, 1> { }; /* XSAVE and Processor Extended
|
||||
States-Enable */
|
||||
struct Smep : Bitfield<20, 1> { }; /* SMEP Enable */
|
||||
struct Smap : Bitfield<21, 1> { }; /* SMAP Enable */
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mov %0, %%cr4" :: "r" (v) : ); }
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr4, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__CPU_H_ */
|
||||
|
@ -1,258 +0,0 @@
|
||||
/*
|
||||
* \brief x86_64 CPU driver for core
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Martin stein
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__CPU_SUPPORT_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__CPU_SUPPORT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
#include <kernel/interface_support.h>
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
/* base includes */
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
|
||||
/* core includes */
|
||||
#include <fpu.h>
|
||||
#include <gdt.h>
|
||||
#include <idt.h>
|
||||
#include <tss.h>
|
||||
#include <timer.h>
|
||||
|
||||
extern int _mt_idt;
|
||||
extern int _mt_tss;
|
||||
|
||||
namespace Genode { class Cpu; }
|
||||
|
||||
|
||||
class Genode::Cpu
|
||||
{
|
||||
public:
|
||||
|
||||
struct Pd {};
|
||||
|
||||
struct Cr0; /* Control register 0 */
|
||||
struct Cr2; /* Control register 2 */
|
||||
struct Cr3; /* Control register 3 */
|
||||
struct Cr4; /* Control register 4 */
|
||||
|
||||
/**
|
||||
* Extend basic CPU state by members relevant for 'base-hw' only
|
||||
*/
|
||||
struct Context : Cpu_state
|
||||
{
|
||||
/**
|
||||
* Address of top-level paging structure.
|
||||
*/
|
||||
addr_t cr3;
|
||||
|
||||
/**
|
||||
* Return base of assigned translation table
|
||||
*/
|
||||
addr_t translation_table() const { return cr3; }
|
||||
|
||||
/**
|
||||
* Initialize context
|
||||
*
|
||||
* \param table physical base of appropriate translation table
|
||||
* \param core whether it is a core thread or not
|
||||
*/
|
||||
void init(addr_t const table, bool core);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An usermode execution state
|
||||
*/
|
||||
struct User_context : Context, Fpu::Context
|
||||
{
|
||||
/**
|
||||
* Support for kernel calls
|
||||
*/
|
||||
void user_arg_0(Kernel::Call_arg const arg) { rdi = arg; }
|
||||
void user_arg_1(Kernel::Call_arg const arg) { rsi = arg; }
|
||||
void user_arg_2(Kernel::Call_arg const arg) { rdx = arg; }
|
||||
void user_arg_3(Kernel::Call_arg const arg) { rcx = arg; }
|
||||
void user_arg_4(Kernel::Call_arg const arg) { r8 = arg; }
|
||||
void user_arg_5(Kernel::Call_arg const arg) { r9 = arg; }
|
||||
void user_arg_6(Kernel::Call_arg const arg) { r10 = arg; }
|
||||
void user_arg_7(Kernel::Call_arg const arg) { r11 = arg; }
|
||||
Kernel::Call_arg user_arg_0() const { return rdi; }
|
||||
Kernel::Call_arg user_arg_1() const { return rsi; }
|
||||
Kernel::Call_arg user_arg_2() const { return rdx; }
|
||||
Kernel::Call_arg user_arg_3() const { return rcx; }
|
||||
Kernel::Call_arg user_arg_4() const { return r8; }
|
||||
Kernel::Call_arg user_arg_5() const { return r9; }
|
||||
Kernel::Call_arg user_arg_6() const { return r10; }
|
||||
Kernel::Call_arg user_arg_7() const { return r11; }
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
Fpu _fpu;
|
||||
Idt * _idt;
|
||||
Tss * _tss;
|
||||
|
||||
public:
|
||||
|
||||
Cpu();
|
||||
|
||||
Fpu & fpu() { return _fpu; }
|
||||
|
||||
static constexpr addr_t exception_entry = 0xffff0000;
|
||||
static constexpr addr_t mtc_size = 1 << 13;
|
||||
|
||||
/**
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
static void wait_for_interrupt() { asm volatile ("pause"); }
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*/
|
||||
bool retry_undefined_instr(Context&) { return false; }
|
||||
|
||||
|
||||
/**
|
||||
* Return kernel name of the executing CPU
|
||||
*/
|
||||
static unsigned executing_id() { return 0; }
|
||||
|
||||
/**
|
||||
* Return kernel name of the primary CPU
|
||||
*/
|
||||
static unsigned primary_id() { return 0; }
|
||||
|
||||
/**
|
||||
* Switch to new context
|
||||
*
|
||||
* \param context next CPU context
|
||||
*/
|
||||
void switch_to(User_context &context) { _fpu.switch_to(context); }
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Cpu::Cr0 : Register<64>
|
||||
{
|
||||
struct Pe : Bitfield< 0, 1> { }; /* Protection Enable */
|
||||
struct Mp : Bitfield< 1, 1> { }; /* Monitor Coprocessor */
|
||||
struct Em : Bitfield< 2, 1> { }; /* Emulation */
|
||||
struct Ts : Bitfield< 3, 1> { }; /* Task Switched */
|
||||
struct Et : Bitfield< 4, 1> { }; /* Extension Type */
|
||||
struct Ne : Bitfield< 5, 1> { }; /* Numeric Error */
|
||||
struct Wp : Bitfield<16, 1> { }; /* Write Protect */
|
||||
struct Am : Bitfield<18, 1> { }; /* Alignment Mask */
|
||||
struct Nw : Bitfield<29, 1> { }; /* Not Write-through */
|
||||
struct Cd : Bitfield<30, 1> { }; /* Cache Disable */
|
||||
struct Pg : Bitfield<31, 1> { }; /* Paging */
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mov %0, %%cr0" :: "r" (v) : ); }
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr0, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Control register 2: Page-fault linear address
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 2.5.
|
||||
*/
|
||||
struct Genode::Cpu::Cr2 : Register<64>
|
||||
{
|
||||
struct Addr : Bitfield<0, 63> { };
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr2, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Control register 3: Page-Directory base register
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 2.5.
|
||||
*/
|
||||
struct Genode::Cpu::Cr3 : Register<64>
|
||||
{
|
||||
struct Pwt : Bitfield<3,1> { }; /* Page-level write-through */
|
||||
struct Pcd : Bitfield<4,1> { }; /* Page-level cache disable */
|
||||
struct Pdb : Bitfield<12, 36> { }; /* Page-directory base address */
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mov %0, %%cr3" :: "r" (v) : ); }
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr3, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return initialized value
|
||||
*
|
||||
* \param table base of targeted translation table
|
||||
*/
|
||||
static access_t init(addr_t const table) {
|
||||
return Pdb::masked(table); }
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Cpu::Cr4 : Register<64>
|
||||
{
|
||||
struct Vme : Bitfield< 0, 1> { }; /* Virtual-8086 Mode Extensions */
|
||||
struct Pvi : Bitfield< 1, 1> { }; /* Protected-Mode Virtual IRQs */
|
||||
struct Tsd : Bitfield< 2, 1> { }; /* Time Stamp Disable */
|
||||
struct De : Bitfield< 3, 1> { }; /* Debugging Exceptions */
|
||||
struct Pse : Bitfield< 4, 1> { }; /* Page Size Extensions */
|
||||
struct Pae : Bitfield< 5, 1> { }; /* Physical Address Extension */
|
||||
struct Mce : Bitfield< 6, 1> { }; /* Machine-Check Enable */
|
||||
struct Pge : Bitfield< 7, 1> { }; /* Page Global Enable */
|
||||
struct Pce : Bitfield< 8, 1> { }; /* Performance-Monitoring Counter
|
||||
Enable*/
|
||||
struct Osfxsr : Bitfield< 9, 1> { }; /* OS Support for FXSAVE and
|
||||
FXRSTOR instructions*/
|
||||
struct Osxmmexcpt : Bitfield<10, 1> { }; /* OS Support for Unmasked
|
||||
SIMD/FPU Exceptions */
|
||||
struct Vmxe : Bitfield<13, 1> { }; /* VMX Enable */
|
||||
struct Smxe : Bitfield<14, 1> { }; /* SMX Enable */
|
||||
struct Fsgsbase : Bitfield<16, 1> { }; /* FSGSBASE-Enable */
|
||||
struct Pcide : Bitfield<17, 1> { }; /* PCIDE Enable */
|
||||
struct Osxsave : Bitfield<18, 1> { }; /* XSAVE and Processor Extended
|
||||
States-Enable */
|
||||
struct Smep : Bitfield<20, 1> { }; /* SMEP Enable */
|
||||
struct Smap : Bitfield<21, 1> { }; /* SMAP Enable */
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mov %0, %%cr4" :: "r" (v) : ); }
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mov %%cr4, %0" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__CPU_SUPPORT_H_ */
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* \brief Global Descriptor Table (GDT)
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__GDT_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__GDT_H_
|
||||
|
||||
/* core includes */
|
||||
#include <pseudo_descriptor.h>
|
||||
#include <mtc_util.h>
|
||||
|
||||
extern int _mt_gdt_start;
|
||||
extern int _mt_gdt_end;
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Global Descriptor Table (GDT)
|
||||
* See Intel SDM Vol. 3A, section 3.5.1
|
||||
*/
|
||||
class Gdt;
|
||||
}
|
||||
|
||||
class Genode::Gdt
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Load GDT from mtc region into GDTR.
|
||||
*
|
||||
* \param virt_base virtual base address of mode transition pages
|
||||
*/
|
||||
static void load(addr_t const virt_base)
|
||||
{
|
||||
addr_t const start = (addr_t)&_mt_gdt_start;
|
||||
uint16_t const limit = _mt_gdt_end - _mt_gdt_start - 1;
|
||||
uint64_t const base = _virt_mtc_addr(virt_base, start);
|
||||
asm volatile ("lgdt %0" :: "m" (Pseudo_descriptor(limit, base)));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__GDT_H_ */
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* \brief Interrupt Descriptor Table (IDT)
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__IDT_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__IDT_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Interrupt Descriptor Table (IDT)
|
||||
* See Intel SDM Vol. 3A, section 6.10
|
||||
*/
|
||||
class Idt;
|
||||
}
|
||||
|
||||
class Genode::Idt
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
SIZE_IDT = 256,
|
||||
SYSCALL_VEC = 0x80,
|
||||
};
|
||||
|
||||
/**
|
||||
* 64-Bit Mode IDT gate, see Intel SDM Vol. 3A, section 6.14.1.
|
||||
*/
|
||||
struct gate
|
||||
{
|
||||
uint16_t offset_15_00;
|
||||
uint16_t segment_sel;
|
||||
uint16_t flags;
|
||||
uint16_t offset_31_16;
|
||||
uint32_t offset_63_32;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
/**
|
||||
* IDT table
|
||||
*/
|
||||
__attribute__((aligned(8))) gate _table[SIZE_IDT];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Setup IDT.
|
||||
*
|
||||
* \param virt_base virtual base address of mode transition pages
|
||||
*/
|
||||
void setup(addr_t const virt_base);
|
||||
|
||||
/**
|
||||
* Load IDT into IDTR.
|
||||
*
|
||||
* \param virt_base virtual base address of mode transition pages
|
||||
*/
|
||||
void load(addr_t const virt_base);
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__IDT_H_ */
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* \brief x86 utility functions
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__MTC_UTIL_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__MTC_UTIL_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
extern int _mt_begin;
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Return virtual mtc address of the given label for the specified
|
||||
* virtual mode transition base.
|
||||
*
|
||||
* \param virt_base virtual base of the mode transition pages
|
||||
*/
|
||||
static addr_t _virt_mtc_addr(addr_t const virt_base, addr_t const label)
|
||||
{
|
||||
addr_t const phys_base = (addr_t)&_mt_begin;
|
||||
return virt_base + (label - phys_base);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__MTC_UTIL_H_ */
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* \brief Pseudo Descriptor class
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__PSEUDO_DESCRIPTOR_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__PSEUDO_DESCRIPTOR_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Pseudo Descriptor
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 3.5.1
|
||||
*/
|
||||
class Pseudo_descriptor;
|
||||
}
|
||||
|
||||
class Genode::Pseudo_descriptor
|
||||
{
|
||||
private:
|
||||
uint16_t _limit;
|
||||
uint64_t _base;
|
||||
|
||||
public:
|
||||
Pseudo_descriptor(uint16_t l, uint64_t b) : _limit(l), _base (b) { };
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__PSEUDO_DESCRIPTOR_H_ */
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* \brief 64-bit Task State Segment (TSS)
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SPEC__X86_64__TSS_H_
|
||||
#define _CORE__INCLUDE__SPEC__X86_64__TSS_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Task State Segment (TSS)
|
||||
*
|
||||
* See Intel SDM Vol. 3A, section 7.7
|
||||
*/
|
||||
class Tss;
|
||||
}
|
||||
|
||||
class Genode::Tss
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
TSS_SELECTOR = 0x28,
|
||||
};
|
||||
|
||||
uint32_t : 32;
|
||||
addr_t rsp0;
|
||||
addr_t rsp1;
|
||||
addr_t rsp2;
|
||||
uint64_t : 64;
|
||||
addr_t ist[7];
|
||||
uint64_t : 64;
|
||||
uint16_t : 16;
|
||||
uint16_t iomap_base;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Setup TSS.
|
||||
*
|
||||
* \param virt_base virtual base address of mode transition pages
|
||||
*/
|
||||
void setup(addr_t const virt_base);
|
||||
|
||||
/**
|
||||
* Load TSS into TR.
|
||||
*/
|
||||
void load();
|
||||
|
||||
}__attribute__((packed));
|
||||
|
||||
#endif /* _CORE__INCLUDE__SPEC__X86_64__TSS_H_ */
|
@ -15,18 +15,16 @@
|
||||
#include <cpu.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
Genode::Cpu::Cpu()
|
||||
{
|
||||
if (primary_id() == executing_id()) {
|
||||
_idt = new (&_mt_idt) Idt();
|
||||
_idt->setup(Cpu::exception_entry);
|
||||
extern int _mt_begin;
|
||||
extern int _mt_tss;
|
||||
extern int _mt_idt;
|
||||
extern int _mt_gdt_start;
|
||||
extern int _mt_gdt_end;
|
||||
|
||||
_tss = new (&_mt_tss) Tss();
|
||||
_tss->load();
|
||||
}
|
||||
_idt->load(Cpu::exception_entry);
|
||||
_tss->setup(Cpu::exception_entry);
|
||||
}
|
||||
|
||||
Genode::addr_t Genode::Cpu::virt_mtc_addr(Genode::addr_t virt_base,
|
||||
Genode::addr_t label) {
|
||||
return virt_base + (label - (addr_t)&_mt_begin); }
|
||||
|
||||
|
||||
void Genode::Cpu::Context::init(addr_t const table, bool core)
|
||||
@ -45,5 +43,30 @@ void Genode::Cpu::Context::init(addr_t const table, bool core)
|
||||
*/
|
||||
eflags = EFLAGS_IF_SET;
|
||||
if (core) eflags |= EFLAGS_IOPL_3;
|
||||
else Gdt::load(Cpu::exception_entry);
|
||||
else Gdt::init();
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::Tss::init()
|
||||
{
|
||||
enum { TSS_SELECTOR = 0x28, };
|
||||
asm volatile ("ltr %w0" : : "r" (TSS_SELECTOR));
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::Idt::init()
|
||||
{
|
||||
Pseudo_descriptor descriptor {
|
||||
(uint16_t)((addr_t)&_mt_tss - (addr_t)&_mt_idt),
|
||||
(uint64_t)(virt_mtc_addr(exception_entry, (addr_t)&_mt_idt)) };
|
||||
asm volatile ("lidt %0" : : "m" (descriptor));
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::Gdt::init()
|
||||
{
|
||||
addr_t const start = (addr_t)&_mt_gdt_start;
|
||||
uint16_t const limit = _mt_gdt_end - _mt_gdt_start - 1;
|
||||
uint64_t const base = virt_mtc_addr(exception_entry, start);
|
||||
asm volatile ("lgdt %0" :: "m" (Pseudo_descriptor(limit, base)));
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* \brief Interrupt Descriptor Table (IDT)
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <pseudo_descriptor.h>
|
||||
#include <mtc_util.h>
|
||||
#include <idt.h>
|
||||
|
||||
extern int _mt_idt;
|
||||
extern int _mt_isrs;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Idt::setup(addr_t const virt_base)
|
||||
{
|
||||
addr_t base = _virt_mtc_addr(virt_base, (addr_t)&_mt_isrs);
|
||||
addr_t isr_addr;
|
||||
|
||||
for (unsigned vec = 0; vec < SIZE_IDT; vec++) {
|
||||
/* ISRs are padded to 4 bytes */
|
||||
isr_addr = base + vec * 0xc;
|
||||
|
||||
_table[vec].offset_15_00 = isr_addr & 0xffff;
|
||||
_table[vec].segment_sel = 8;
|
||||
_table[vec].flags = 0x8e00;
|
||||
_table[vec].offset_31_16 = (isr_addr >> 16);
|
||||
_table[vec].offset_63_32 = (isr_addr >> 32);
|
||||
}
|
||||
|
||||
/* Set DPL of syscall entry to 3 */
|
||||
_table[SYSCALL_VEC].flags = _table[SYSCALL_VEC].flags | 0x6000;
|
||||
}
|
||||
|
||||
|
||||
void Idt::load(addr_t const virt_base)
|
||||
{
|
||||
uint16_t const limit = sizeof(_table) - 1;
|
||||
uint64_t const base = _virt_mtc_addr(virt_base, (addr_t)&_mt_idt);
|
||||
asm volatile ("lidt %0" : : "m" (Pseudo_descriptor(limit, base)));
|
||||
}
|
@ -34,6 +34,9 @@ Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0)
|
||||
|
||||
void Kernel::Cpu::init(Pic &pic, Kernel::Pd &core_pd, Genode::Board&)
|
||||
{
|
||||
Idt::init();
|
||||
Tss::init();
|
||||
|
||||
Timer::disable_pit();
|
||||
|
||||
fpu().init();
|
||||
|
@ -37,9 +37,15 @@
|
||||
|
||||
/* mtc virt addresses */
|
||||
.set MT_BASE, 0xffff0000
|
||||
.set MT_BUFFER, MT_BASE + (_mt_buffer - _mt_begin)
|
||||
.set MT_MASTER, MT_BASE + (_mt_master_context_begin - _mt_begin)
|
||||
.set MT_TSS, MT_BASE + (_mt_tss - _mt_begin)
|
||||
.set MT_BUFFER, MT_BASE + (_mt_buffer - _mt_begin)
|
||||
.set MT_MASTER, MT_BASE + (_mt_master_context_begin - _mt_begin)
|
||||
.set MT_TSS, MT_BASE + (_mt_tss - _mt_begin)
|
||||
.set MT_ISR, MT_BASE
|
||||
.set MT_IRQ_STACK, MT_BASE + (_mt_kernel_interrupt_stack - _mt_begin)
|
||||
.set MT_ISR_ENTRY_SIZE, 12
|
||||
|
||||
.set IDT_FLAGS_PRIVILEGED, 0x8e00
|
||||
.set IDT_FLAGS_UNPRIVILEGED, 0xee00
|
||||
|
||||
.macro _isr_entry
|
||||
.align 4, 0x90
|
||||
@ -60,6 +66,15 @@
|
||||
jmp _mt_kernel_entry_pic
|
||||
.endm
|
||||
|
||||
.macro _idt_entry addr flags
|
||||
.word \addr & 0xffff
|
||||
.word 0x0008
|
||||
.word \flags
|
||||
.word \addr >> 16
|
||||
.long \addr >> 32
|
||||
.long 0
|
||||
.endm
|
||||
|
||||
.section .text
|
||||
|
||||
/*
|
||||
@ -79,8 +94,6 @@
|
||||
* On user exceptions the CPU has to jump to one of the following
|
||||
* Interrupt Service Routines (ISRs) to switch to a kernel context.
|
||||
*/
|
||||
.global _mt_isrs
|
||||
_mt_isrs:
|
||||
_exception 0
|
||||
_exception 1
|
||||
_exception 2
|
||||
@ -254,25 +267,45 @@
|
||||
mov $1, %rax
|
||||
vmcall
|
||||
|
||||
/************************************************
|
||||
** Space for Interrupt Descriptor Table (IDT) **
|
||||
** See Intel SDM Vol. 3A, section 6.10 **
|
||||
************************************************/
|
||||
/*****************************************
|
||||
** Interrupt Descriptor Table (IDT) **
|
||||
** See Intel SDM Vol. 3A, section 6.10 **
|
||||
*****************************************/
|
||||
|
||||
.global _mt_idt
|
||||
.align 8
|
||||
_mt_idt:
|
||||
.space 1 << MIN_PAGE_SIZE_LOG2
|
||||
|
||||
/***********************************************
|
||||
** Space for 64-bit Task State Segment (TSS) **
|
||||
** See Intel SDM Vol. 3A, section 7.7 **
|
||||
***********************************************/
|
||||
/* first 128 entries */
|
||||
.set isr_addr, MT_ISR
|
||||
.rept 0x80
|
||||
_idt_entry isr_addr IDT_FLAGS_PRIVILEGED
|
||||
.set isr_addr, isr_addr + MT_ISR_ENTRY_SIZE
|
||||
.endr
|
||||
|
||||
/* syscall entry 0x80 */
|
||||
_idt_entry isr_addr IDT_FLAGS_UNPRIVILEGED
|
||||
.set isr_addr, isr_addr + MT_ISR_ENTRY_SIZE
|
||||
|
||||
/* remaing entries */
|
||||
.rept 127
|
||||
_idt_entry isr_addr IDT_FLAGS_PRIVILEGED
|
||||
.set isr_addr, isr_addr + MT_ISR_ENTRY_SIZE
|
||||
.endr
|
||||
|
||||
/****************************************
|
||||
** Task State Segment (TSS) **
|
||||
** See Intel SDM Vol. 3A, section 7.7 **
|
||||
****************************************/
|
||||
|
||||
.global _mt_tss
|
||||
.align 8
|
||||
_mt_tss:
|
||||
.space 104
|
||||
.space 4
|
||||
.quad MT_IRQ_STACK
|
||||
.quad MT_IRQ_STACK
|
||||
.quad MT_IRQ_STACK
|
||||
.space 76
|
||||
|
||||
/******************************************
|
||||
** Global Descriptor Table (GDT) **
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* \brief 64-bit Task State Segment (TSS)
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Reto Buerki
|
||||
* \date 2015-02-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <mtc_util.h>
|
||||
#include <tss.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
extern int _mt_kernel_interrupt_stack;
|
||||
|
||||
void Tss::setup(addr_t const virt_base)
|
||||
{
|
||||
addr_t const stack_addr =
|
||||
_virt_mtc_addr(virt_base, (addr_t)&_mt_kernel_interrupt_stack);
|
||||
|
||||
this->rsp0 = stack_addr;
|
||||
this->rsp1 = stack_addr;
|
||||
this->rsp2 = stack_addr;
|
||||
}
|
||||
|
||||
|
||||
void Tss::load()
|
||||
{
|
||||
asm volatile ("ltr %w0" : : "r" (TSS_SELECTOR));
|
||||
}
|
Loading…
Reference in New Issue
Block a user