Commit c9fa9d2a authored by Colin Finck's avatar Colin Finck
Browse files

Begin by updating the x86 crate to the latest version.

This comes with many incompatible changes and bugs, so the x86 crate needed to be forked and fixed first (https://github.com/ColinFinck/rust-x86/tree/segmentation).
Using all features of the newly updated x86 crate, the GDT initialization code can be highly simplified!
parent 7f634fdb
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file arch/x86/include/asm/gdt.h
* @brief Definitions and functions related to segmentation
* @author Stefan Lankes
*
* This file defines the interface for segmentation as like structures to describe segments.\n
* There are also some other gdt-private functions in the gdt.c file defined.
*/
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
// 2017 Colin Finck, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef __ARCH_GDT_H__
#define __ARCH_GDT_H__
#include <hermit/stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/// This segment is a data segment
#define GDT_FLAG_DATASEG 0x02
/// This segment is a code segment
#define GDT_FLAG_CODESEG 0x0a
#define GDT_FLAG_TSS 0x09
#define GDT_FLAG_TSS_BUSY 0x02
#define GDT_FLAG_SEGMENT 0x10
/// Privilege level: Ring 0
#define GDT_FLAG_RING0 0x00
/// Privilege level: Ring 1
#define GDT_FLAG_RING1 0x20
/// Privilege level: Ring 2
#define GDT_FLAG_RING2 0x40
/// Privilege level: Ring 3
#define GDT_FLAG_RING3 0x60
/// Segment is present
#define GDT_FLAG_PRESENT 0x80
/// Segment was accessed
#define GDT_FLAG_ACCESSED 0x01
/**
* @brief Granularity of segment limit
* - set: segment limit unit is 4 KB (page size)
* - not set: unit is bytes
*/
#define GDT_FLAG_4K_GRAN 0x80
/**
* @brief Default operand size
* - set: 32 bit
* - not set: 16 bit
*/
#define GDT_FLAG_16_BIT 0x00
#define GDT_FLAG_32_BIT 0x40
#define GDT_FLAG_64_BIT 0x20
/** @brief Defines a GDT entry
*
* A global descriptor table entry consists of:
* - 32 bit base address (chunkwise embedded into this structure)
* - 20 bit limit
*/
typedef struct {
/// Lower 16 bits of limit range
uint16_t limit_low;
/// Lower 16 bits of base address
uint16_t base_low;
/// middle 8 bits of base address
uint8_t base_middle;
/// Access bits
uint8_t access;
/// Granularity bits
uint8_t granularity;
/// Higher 8 bits of base address
uint8_t base_high;
} __attribute__ ((packed)) gdt_entry_t;
/** @brief defines the GDT pointer structure
*
* This structure tells the address and size of the table.
*/
typedef struct {
/// Size of the table in bytes (not the number of entries!)
uint16_t limit;
/// Address of the table
size_t base;
} __attribute__ ((packed)) gdt_ptr_t;
// a TSS descriptor is twice larger than a code/data descriptor
#define GDT_ENTRIES (7+MAX_CORES*2)
#if GDT_ENTRIES > 8192
#error Too many GDT entries!
#endif
// See also: librs/src/arc/x86_64/gdt.rs
#define GDT_FIRST_TSS 3
/** @brief Installs the global descriptor table
* Implemented in Rust (librs/src/arc/x86_64/gdt.rs)
*
* The installation involves the following steps:
* - set up the special GDT pointer
* - set up the entries in our GDT
* - finally call gdt_flush() in our assembler file
* in order to tell the processor where the new GDT is
* - update the new segment registers
* - load the new GDT
* - update the segment registers
*/
void gdt_install(void);
/** @brief Set gate with chosen attributes
*/
void gdt_set_gate(int num, unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran);
/** @brief Configures and returns a GDT descriptor with chosen attributes
*
* Just feed this function with address, limit and the flags
* you have seen in idt.h
*
* @return a preconfigured gdt descriptor
*/
void configure_gdt_entry(gdt_entry_t *dest_entry, unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran);
#ifdef __cplusplus
}
#endif
#endif
......@@ -977,7 +977,7 @@ void udelay(uint32_t usecs);
/// Register a task's TSS at GDT
static inline void register_task(void)
{
uint16_t sel = (apic_cpu_id()*2+7) << 3;
uint16_t sel = (GDT_FIRST_TSS + apic_cpu_id()*2) << 3;
asm volatile ("ltr %%ax" : : "a"(sel));
}
......
/*
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <hermit/stdio.h>
#include <hermit/string.h>
#include <hermit/stdlib.h>
#include <hermit/tasks.h>
#include <hermit/errno.h>
#include <hermit/processor.h>
#include <asm/gdt.h>
#include <asm/tss.h>
#include <asm/page.h>
#if 0
#define MAX_IST 3
gdt_ptr_t gp;
// currently, our kernel has full access to the ioports
static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}};
static tss_t task_state_segments[MAX_CORES] __attribute__ ((aligned (PAGE_SIZE)));
static uint8_t stack_table[MAX_CORES][KERNEL_STACK_SIZE*MAX_IST] __attribute__ ((aligned (PAGE_SIZE)));
extern const void boot_stack;
/*
* This is defined in entry.asm. We use this to properly reload
* the new segment registers
*/
extern void gdt_flush(void);
extern const void boot_stack;
void set_tss(size_t rps0, size_t ist1)
{
task_state_segments[CORE_ID].rsp0 = rps0;
task_state_segments[CORE_ID].ist1 = ist1;
}
/* Setup a descriptor in the Global Descriptor Table */
void gdt_set_gate(int num, unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran)
{
configure_gdt_entry(&gdt[num], base, limit, access, gran);
}
void configure_gdt_entry(gdt_entry_t *dest_entry, unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran)
{
/* Setup the descriptor base address */
dest_entry->base_low = (base & 0xFFFF);
dest_entry->base_middle = (base >> 16) & 0xFF;
dest_entry->base_high = (base >> 24) & 0xFF;
/* Setup the descriptor limits */
dest_entry->limit_low = (limit & 0xFFFF);
dest_entry->granularity = ((limit >> 16) & 0x0F);
/* Finally, set up the granularity and access flags */
dest_entry->granularity |= (gran & 0xF0);
dest_entry->access = access;
}
/*
* This will setup the special GDT
* pointer, set up the entries in our GDT, and then
* finally call gdt_flush() in our assembler file in order
* to tell the processor where the new GDT is and update the
* new segment registers
*/
void gdt_install(void)
{
int i, num = 0;
memset(task_state_segments, 0x00, MAX_CORES*sizeof(tss_t));
/* Setup the GDT pointer and limit */
gp.limit = (sizeof(gdt_entry_t) * GDT_ENTRIES) - 1;
gp.base = (size_t) &gdt;
/* Our NULL descriptor */
gdt_set_gate(num++, 0, 0, 0, 0);
/*
* The second entry is our Code Segment. The base address
* is 0, the limit is 4 GByte, it uses 4KByte granularity,
* and is a Code Segment descriptor.
*/
gdt_set_gate(num++, 0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
/*
* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment
*/
gdt_set_gate(num++, 0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
/*
* Create code segment for 32bit user-space applications (ring 3)
*/
gdt_set_gate(num++, 0, 0xFFFFFFFF,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_32_BIT | GDT_FLAG_4K_GRAN);
/*
* Create data segment for 32bit user-space applications (ring 3)
*/
gdt_set_gate(num++, 0, 0xFFFFFFFF,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_32_BIT | GDT_FLAG_4K_GRAN);
/*
* Create code segment for 64bit user-space applications (ring 3)
*/
gdt_set_gate(num++, 0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
/*
* Create data segment for 64bit user-space applications (ring 3)
*/
gdt_set_gate(num++, 0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
/*
* Create TSS for each core (we use these segments for task switching)
*/
for(i=0; i<MAX_CORES; i++) {
task_state_segments[i].rsp0 = (size_t)&boot_stack + (i+1) * KERNEL_STACK_SIZE - 0x10;
task_state_segments[i].ist1 = 0; // ist will created per task
task_state_segments[i].ist2 = (size_t) stack_table[i] + (2 /*IST number */ - 1) * KERNEL_STACK_SIZE - 0x10;
task_state_segments[i].ist3 = (size_t) stack_table[i] + (3 /*IST number */ - 1) * KERNEL_STACK_SIZE - 0x10;
task_state_segments[i].ist4 = (size_t) stack_table[i] + (4 /*IST number */ - 1) * KERNEL_STACK_SIZE - 0x10;
gdt_set_gate(num+i*2, (unsigned long) (task_state_segments+i), sizeof(tss_t),
GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, 0);
}
/* Flush out the old GDT and install the new changes! */
gdt_flush();
}
#endif
......@@ -18,7 +18,7 @@ raw-cpuid = "3.0.0"
#features = ["spin_no_std"]
[dependencies.x86]
version = "0.7"
path = "../../rust-x86"
default-features = false
# The development profile, used for `cargo build`.
......
// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
// 2017 Colin Finck, RWTH Aachen University
//
// MIT License
//
......@@ -26,53 +27,23 @@
use consts::*;
use spin;
use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, SegmentSelector};
use core::mem::size_of;
use x86::bits64::segmentation::*;
use x86::bits64::task::*;
use x86::shared::PrivilegeLevel;
use x86::shared::dtables::{self, DescriptorTablePointer};
const GDT_NULL: usize = 0;
const GDT_KERNEL_CODE: usize = 1;
const GDT_KERNEL_DATA: usize = 2;
// This segment is a data segment
const GDT_FLAG_DATASEG: u8 = 0x02;
/// This segment is a code segment
const GDT_FLAG_CODESEG: u8 = 0x0a;
const GDT_FLAG_TSS: u8 = 0x09;
const GDT_FLAG_TSS_BUSY: u8 = 0x02;
const GDT_FLAG_SEGMENT: u8 = 0x10;
/// Privilege level: Ring 0
const GDT_FLAG_RING0: u8 = 0x00;
/// Privilege level: Ring 1
const GDT_FLAG_RING1: u8 = 0x20;
/// Privilege level: Ring 2
const GDT_FLAG_RING2: u8 = 0x40;
/// Privilege level: Ring 3
const GDT_FLAG_RING3: u8 = 0x60;
/// Segment is present
const GDT_FLAG_PRESENT: u8 = 0x80;
/// Segment was accessed
const GDT_FLAG_ACCESSED: u8 = 0x01;
/// Granularity of segment limit
/// - set: segment limit unit is 4 KB (page size)
/// - not set: unit is bytes
const GDT_FLAG_4K_GRAN: u8 = 0x80;
/// Default operand size
/// - set: 32 bit
/// - not set: 16 bit
const GDT_FLAG_16_BIT: u8 = 0x00;
const GDT_FLAG_32_BIT: u8 = 0x40;
const GDT_FLAG_64_BIT: u8 = 0x20;
const GDT_FIRST_TSS: usize = 3;
// a TSS descriptor is twice larger than a code/data descriptor
const GDT_ENTRIES: usize = (7+MAX_CORES*2);
const GDT_ENTRIES: usize = (3+MAX_CORES*2);
const MAX_IST: usize = 3;
// thread_local on a static mut, signals that the value of this static may
// change depending on the current thread.
static mut GDT: [GdtEntry; GDT_ENTRIES] = [GdtEntry::new(0, 0, 0, 0); GDT_ENTRIES];
static mut GDTR: DescriptorTablePointer = DescriptorTablePointer { limit: 0, base: 0 };
static mut GDT: [SegmentDescriptor; GDT_ENTRIES] = [SegmentDescriptor::NULL; GDT_ENTRIES];
static mut GDTR: DescriptorTablePointer<SegmentDescriptor> = DescriptorTablePointer { base: 0 as *const SegmentDescriptor, limit: 0 };
static mut TSS_BUFFER: TssBuffer = TssBuffer::new();
static STACK_TABLE: [[IrqStack; MAX_IST]; MAX_CORES] = [[IrqStack::new(); MAX_IST]; MAX_CORES];
static GDT_INIT: spin::Once<()> = spin::Once::new();
......@@ -81,66 +52,7 @@ extern "C" {
static boot_stack: [u8; MAX_CORES*KERNEL_STACK_SIZE];
}
#[derive(Copy, Clone)]
#[repr(C, packed)]
struct GdtEntry {
/// Lower 16 bits of limit range
limit_low: u16,
/// Lower 16 bits of base address
base_low: u16,
/// middle 8 bits of base address
base_middle: u8,
/// Access bits
access: u8,
/// Granularity bits
granularity: u8,
/// Higher 8 bits of base address
base_high: u8
}
impl GdtEntry {
pub const fn new(base: u32, limit: u32, access: u8, gran: u8) -> Self {
GdtEntry {
limit_low: (limit & 0xFFFF) as u16,
base_low: (base & 0xFFFF) as u16,
base_middle: ((base >> 16) & 0xFF) as u8,
access: access,
granularity: (gran & 0xF0) as u8 | ((limit >> 16) & 0x0F) as u8,
base_high: ((base >> 24) & 0xFF) as u8
}
}
}
#[derive(Copy, Clone)]
#[repr(C, packed)]
struct TaskStateSegment {
reserved: u32,
/// The full 64-bit canonical forms of the stack pointers (RSP) for privilege levels 0-2.
rsp: [u64; 3],
reserved2: u64,
/// The full 64-bit canonical forms of the interrupt stack table (IST) pointers.
ist: [u64; 7],
reserved3: u64,
reserved4: u16,
/// The 16-bit offset to the I/O permission bit map from the 64-bit TSS base.
iomap_base: u16,
}
impl TaskStateSegment {
const fn new() -> TaskStateSegment {
TaskStateSegment {
reserved: 0,
rsp: [0; 3],
reserved2: 0,
ist: [0; 7],
reserved3: 0,
reserved4: 0,
iomap_base: 0,
}
}
}
// workaround to use th enew repr(align) feature
// workaround to use the new repr(align) feature
// currently, it is only supported by structs
// => map all TSS in a struct
#[repr(align(4096))]
......@@ -156,7 +68,7 @@ impl TssBuffer {
}
}
// workaround to use th enew repr(align) feature
// workaround to use the new repr(align) feature
// currently, it is only supported by structs
// => map stacks in a struct
#[derive(Copy)]
......@@ -188,63 +100,19 @@ impl IrqStack {
pub unsafe fn gdt_install()
{
GDT_INIT.call_once(|| {
let mut num: usize = 0;
GDTR.limit = (size_of::<GdtEntry>() * GDT.len() - 1) as u16;
GDTR.base = GDT.as_ptr() as u64;
/* Our NULL descriptor */
GDT[num] = GdtEntry::new(0, 0, 0, 0);
num += 1;
/* The NULL descriptor is already inserted as the first entry. */
/*
* The second entry is our Code Segment. The base address
* is 0, the limit is 4 GByte, it uses 4KByte granularity,
* and is a Code Segment descriptor.
* The second entry is a 64-bit Code Segment in kernel-space (ring 0).
* All other parameters are ignored.
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
num += 1;
GDT[GDT_KERNEL_CODE] = SegmentDescriptor::new_memory(0, 0, Type::Code(CODE_READ), false, PrivilegeLevel::Ring0, SegmentBitness::Bits64);
/*
* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment
* The third entry is a 64-bit Data Segment in kernel-space (ring 0).
* All other parameters are ignored.
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING0 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
num += 1;
/*
* Create code segment for 32bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0xFFFFFFFF,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT,
GDT_FLAG_32_BIT | GDT_FLAG_4K_GRAN);
num += 1;
/*
* Create data segment for 32bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0xFFFFFFFF,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT,
GDT_FLAG_32_BIT | GDT_FLAG_4K_GRAN);
num += 1;
/*
* Create code segment for 64bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_CODESEG | GDT_FLAG_PRESENT,
GDT_FLAG_64_BIT);
num += 1;
/*
* Create data segment for 64bit user-space applications (ring 3)
*/
GDT[num] = GdtEntry::new(0, 0,
GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, GDT_FLAG_64_BIT);
num += 1;
GDT[GDT_KERNEL_DATA] = SegmentDescriptor::new_memory(0, 0, Type::Data(DATA_WRITE), false, PrivilegeLevel::Ring0, SegmentBitness::Bits64);
/*
* Create TSS for each core (we use these segments for task switching)
......@@ -260,10 +128,11 @@ pub unsafe fn gdt_install()
TSS_BUFFER.tss[i].ist[3] = (&(STACK_TABLE[i][4 /*IST number */ - 2]) as *const _) as u64;
TSS_BUFFER.tss[i].ist[3] += (KERNEL_STACK_SIZE - 0x10) as u64;
let tss_ptr = &(TSS_BUFFER.tss[i]) as *const TaskStateSegment;
GDT[num+i*2] = GdtEntry::new(tss_ptr as u32, size_of::<TaskStateSegment>() as u32,
GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, 0);
let idx = GDT_FIRST_TSS + i*2;
GDT[idx..idx+2].copy_from_slice(&SegmentDescriptor::new_tss(&(TSS_BUFFER.tss[i]), PrivilegeLevel::Ring0));
}
GDTR = DescriptorTablePointer::new_gdtp(&GDT);
});
gdt_flush();
......@@ -282,10 +151,10 @@ pub unsafe fn gdt_flush()
dtables::lgdt(&GDTR);
// Reload the segment descriptors
segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));
//segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
//segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
set_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16, PrivilegeLevel::Ring0));
load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0));
load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0));
load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16, PrivilegeLevel::Ring0));
//load_fs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
//load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment