hw_x86_64: assemble TSS and IDT statically

* remove alignment restrictions of code64 entrypoint

Ref #2092
This commit is contained in:
Stefan Kalkowski 2016-11-16 11:50:57 +01:00 committed by Christian Helmuth
parent bb10afa266
commit b6490e913f
13 changed files with 363 additions and 644 deletions

View File

@ -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

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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)));
}

View File

@ -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)));
}

View File

@ -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();

View File

@ -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) **

View File

@ -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));
}