The Pedigree Project  0.1
x64/gdt.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "gdt.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/processor/Processor.h"
23 #include "pedigree/kernel/processor/ProcessorInformation.h"
24 #include "pedigree/kernel/processor/x64/tss.h"
25 #include "pedigree/kernel/stddef.h"
26 #include "pedigree/kernel/utilities/Vector.h"
27 #include "pedigree/kernel/utilities/utility.h"
28 
29 // These will all be safe for use when entering a double fault handler
30 #define SAFE_STACK_SIZE 8192
31 static char g_SafeStack[SAFE_STACK_SIZE] = {0};
32 
34 
35 void X64GdtManager::initialise(size_t processorCount)
36 {
37  // Calculate the number of entries
38  m_DescriptorCount = 7 + 2 * processorCount;
39 
40  // Allocate the GDT
42 
43  // Fill the GDT
44  setSegmentDescriptor(0, 0, 0, 0, 0);
45  setSegmentDescriptor(1, 0, 0, 0x98, 0x2); // Kernel code - 0x08
46  setSegmentDescriptor(2, 0, 0, 0x92, 0x2); // Kernel data - 0x10
47  setSegmentDescriptor(3, 0, 0, 0xF8, 0x2); // User code32 - 0x18
48  setSegmentDescriptor(4, 0, 0, 0xF2, 0x2); // User data32 - 0x20
49  setSegmentDescriptor(5, 0, 0, 0xF8, 0x22); // User code64 - 0x28
50  setSegmentDescriptor(6, 0, 0, 0xF2, 0x22); // User data64 - 0x30
51 
52 #ifdef MULTIPROCESSOR
53 
55 
56  size_t i = 0;
59  it != Processor::m_ProcessorInformation.end(); it++, i += 2)
60  {
61  NOTICE("Setting up TSS segment for CPU #" << Dec << i << Hex << ".");
62 
64  initialiseTss(Tss);
65  setTssDescriptor(i + 7, reinterpret_cast<uint64_t>(Tss));
66 
67  ProcessorInformation *processorInfo = *it;
68  processorInfo->setTss(Tss);
69  processorInfo->setTssSelector((i + 7) << 3);
70  processorInfo->setTlsSelector((i + 8) << 3);
71  }
72 #else
73 
75  initialiseTss(Tss);
76  setTssDescriptor(7, reinterpret_cast<uint64_t>(Tss));
77 
78  ProcessorInformation &processorInfo = Processor::information();
79  processorInfo.setTss(Tss);
80  processorInfo.setTssSelector(7 << 3);
81  processorInfo.setTlsSelector(8 << 3);
82 #endif
83 }
84 
86 {
87  struct
88  {
89  uint16_t size;
90  uint64_t gdt;
91  } PACKED gdtr;
92 
93  gdtr.size = (m_Instance.m_DescriptorCount * 8) - 1;
94  gdtr.gdt = reinterpret_cast<uint64_t>(m_Instance.m_Gdt);
95 
96  asm volatile("lgdt %0" ::"m"(gdtr));
97  asm volatile("ltr %%ax" ::"a"(Processor::information().getTssSelector()));
98 
100 }
101 
103 {
104 }
106 {
107 }
108 
110  size_t index, uint64_t base, uint32_t limit, uint8_t flags, uint8_t flags2)
111 {
112  m_Gdt[index].limit0 = limit & 0xFFFF;
113  m_Gdt[index].base0 = base & 0xFFFF;
114  m_Gdt[index].base1 = (base >> 16) & 0xFF;
115  m_Gdt[index].flags = flags;
116  m_Gdt[index].flags_limit1 = ((flags2 & 0x0F) << 4) | ((limit >> 16) & 0x0F);
117  m_Gdt[index].base2 = (base >> 24) & 0xFF;
118 }
119 void X64GdtManager::setTssDescriptor(size_t index, uint64_t base)
120 {
122  index, base & 0xFFFFFFFF, sizeof(X64TaskStateSegment), 0x89, 0x00);
123  tss_descriptor *Tss = reinterpret_cast<tss_descriptor *>(&m_Gdt[index + 1]);
124  Tss->base3 = (base >> 32) & 0xFFFFFFFF;
125  Tss->res = 0;
126 }
128 {
129  ByteSet(reinterpret_cast<void *>(pTss), 0, sizeof(X64TaskStateSegment));
130 
131  pTss->ist[1] = reinterpret_cast<uint64_t>(g_SafeStack) + SAFE_STACK_SIZE;
132 
133  // All entries will be zero by default (all ports accessible to all IOPLs)
135  pTss->ioPermBitmap = offsetof(X64TaskStateSegment, ioPermBitmapData);
136 }
137 
138 void X64GdtManager::initialiseDoubleFaultTss(X64TaskStateSegment *pTss)
139 {
140  // IST used on amd64
141 }
void initialiseTss(X64TaskStateSegment *pTss) INITIALISATION_ONLY
Definition: x64/gdt.cc:127
void setSegmentDescriptor(size_t index, uint64_t base, uint32_t limit, uint8_t flags, uint8_t flags2)
Definition: x64/gdt.cc:109
void initialise(size_t processorCount) INITIALISATION_ONLY
Definition: x64/gdt.cc:35
X64GdtManager() INITIALISATION_ONLY
Definition: x64/gdt.cc:102
static ProcessorInformation & information()
Definition: Processor.cc:45
static X64GdtManager m_Instance
Definition: x64/gdt.h:119
void setTssDescriptor(size_t index, uint64_t base) INITIALISATION_ONLY
Definition: x64/gdt.cc:119
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
T * Iterator
Definition: Vector.h:37
static void loadSegmentRegisters()
Definition: Log.h:138
static ProcessorInformation m_ProcessorInformation
Definition: Processor.h:386
static void initialiseProcessor() INITIALISATION_ONLY
Definition: x64/gdt.cc:85
size_t m_DescriptorCount
Definition: x64/gdt.h:116
segment_descriptor * m_Gdt
Definition: x64/gdt.h:114