Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'feature/availbits' into unborn

  • Loading branch information...
commit f62c8bbaae68510b907f84cb2f1fd153917f091d 2 parents 19e4377 + 15dc66c
James Larkby-Lahet wolfwood authored
Showing with 1,498 additions and 2,213 deletions.
  1. +5 −5 app/c/hello/hello.c
  2. +1 −1  app/c/simplyfft/simplyfft.c
  3. +2 −2 app/c/simplymd5/simplymd5.c
  4. +1 −1  app/c/simplymm/simplymm.c
  5. +9 −9 app/d/hello/console.d
  6. +4 −6 app/d/hello/hello.d
  7. +9 −9 app/d/init/console.d
  8. +2 −2 app/d/init/embeddedfs.d
  9. +9 −14 app/d/init/init.d
  10. +6 −8 app/d/posix/posix.d
  11. +9 −9 app/d/xsh/console.d
  12. +20 −18 app/d/xsh/xsh.d
  13. +17 −21 kernel/arch/x86_64/architecture/cpu.d
  14. +4 −4 kernel/arch/x86_64/architecture/keyboard.d
  15. +3 −3 kernel/arch/x86_64/architecture/main.d
  16. +2 −2 kernel/arch/x86_64/architecture/perfmon.d
  17. +4 −6 kernel/arch/x86_64/architecture/syscall.d
  18. +66 −25 kernel/arch/x86_64/architecture/vm.d
  19. +3 −1 kernel/arch/x86_64/boot/boot.s
  20. +1 −1  kernel/arch/x86_64/boot/trampoline.s
  21. +4 −2 kernel/arch/x86_64/core/gdt.d
  22. +6 −3 kernel/arch/x86_64/core/info.d
  23. +5 −2 kernel/arch/x86_64/core/ioapic.d
  24. +6 −3 kernel/arch/x86_64/core/lapic.d
  25. +337 −523 kernel/arch/x86_64/core/paging.d
  26. +4 −2 kernel/arch/x86_64/core/tss.d
  27. +0 −16 kernel/arch/x86_64/imports/architecture.d
  28. +0 −137 kernel/arch/x86_64/pagetable.d
  29. +42 −41 kernel/arch/x86_64/specs/acpitables.d
  30. +3 −2 kernel/arch/x86_64/specs/mp.d
  31. +17 −17 kernel/core/initprocess.d
  32. +3 −3 kernel/core/kmain.d
  33. +1 −1  kernel/core/log.d
  34. +28 −38 kernel/core/syscall.d
  35. +1 −1  kernel/core/util.d
  36. +20 −21 kernel/dev/console.d
  37. +11 −10 kernel/dev/keyboard.d
  38. +14 −14 kernel/mem/bestbin.d
  39. +4 −4 kernel/mem/binhop.d
  40. +7 −61 kernel/mem/bitmap.d
  41. +14 −29 kernel/mem/pageallocator.d
  42. +3 −3 kernel/mem/pagecolor.d
  43. +4 −4 kernel/mem/private_cache.d
  44. +1 −1  kernel/runtime/std/c/stdarg.d
  45. +5 −5 kernel/runtime/std/intrinsic.d
  46. +1 −1  kernel/runtime/std/stdarg.d
  47. +4 −2 kernel/system/definitions.d
  48. +5 −3 kernel/system/multiboot.d
  49. +7 −9 libos/console.d
  50. +6 −6 libos/elf/elf.d
  51. +7 −9 libos/elf/loader.d
  52. +1 −1  libos/elf/segment.d
  53. +35 −31 libos/fs/minfs.d
  54. +1 −1  libos/keyboard.d
  55. +25 −22 libos/libdeepmajik/threadscheduler.d
  56. +6 −23 libos/libdeepmajik/umm.d
  57. +0 −348 libos/ramfs.d
  58. +1 −1  libos/video.d
  59. +8 −8 runtimes/mindrt/Makefile
  60. +1 −1  runtimes/mindrt/assocarray.d
  61. +3 −3 runtimes/mindrt/entry.S
  62. +4 −34 runtimes/mindrt/entry.d
  63. +3 −3 runtimes/mindrt/object.d
  64. +1 −1  runtimes/mindrt/typeinfo/ti_array_cfloat.d
  65. +1 −1  tools/dtoc/test.c
  66. +2 −2 user/c/Makefile
  67. +5 −4 user/c/csyscall.d
  68. +415 −586 user/environment.d
  69. +170 −0 user/ipc.d
  70. +0 −1  user/ramfs.d
  71. +13 −20 user/syscall.d
  72. +54 −0 user/types.d
  73. +2 −2 user/util.d
10 app/c/hello/hello.c
View
@@ -11,10 +11,10 @@ int main(int argc, char** argv){
char *hello = "hello world\n";
fprintf(stdout, "%s!\n", hello);
-
+
wconsole(hello, 11);
-
+
printf("Hello wizzerld!\n");
int fd = open("/LICENSE", O_RDONLY);
@@ -24,7 +24,7 @@ int main(int argc, char** argv){
do{
err = read(fd, foo, 10);
-
+
if(err > 0){
foo[err] = '\0';
printf(foo);
@@ -35,9 +35,9 @@ int main(int argc, char** argv){
printf("\n");
int wfd = open("/out", O_WRONLY);
-
+
char* moo = "The quick brown w0lfwood jumped over the lazy cl0ckw0rk.\n";
-
+
printf("write to fd %d\n", wfd);
write(wfd, moo, strlen(moo));
2  app/c/simplyfft/simplyfft.c
View
@@ -5,7 +5,7 @@
* Code computes fft of an array of complex doubles and mutates
* in-place this array to give a complex double result.
*
- * Code is from a module by Dmitry Karasik, and available:
+ * Code is from a module by Dmitry Karasik, and available:
* http://cpansearch.perl.org/src/KARASIK/IPA-1.07/Global/fft.c
*
*/
4 app/c/simplymd5/simplymd5.c
View
@@ -40,7 +40,7 @@ void MD5Transform(uint32 buf[4], uint32 const in[16]);
int mdfile(char *fn, unsigned char *digest);
int mdbinfile(char *fn, unsigned char *bindigest);
-/* These assume a little endian machine and return incorrect results!
+/* These assume a little endian machine and return incorrect results!
* They are here for compatibility with old (broken) versions of RPM */
int mdfileBroken(char *fn, unsigned char *digest);
int mdbinfileBroken(char *fn, unsigned char *bindigest);
@@ -173,7 +173,7 @@ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
}
/*
- * * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * * Final wrapup - pad to 64-byte boundary with the bit pattern
* * 1 0* (64-bit count of bits processed, MSB-first)
* */
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
2  app/c/simplymm/simplymm.c
View
@@ -20,7 +20,7 @@ struct bigint {
};
void main() {
-
+
ticks header_t0, header_t1, read_t0, read_t1, compute_t0, compute_t1, write_t0, write_t1;
header_t0 = getticks();
18 app/d/hello/console.d
View
@@ -43,7 +43,7 @@ static:
void putChar(char foo) {
return SysConsole.Console.putChar(foo);
- }
+ }
uint width() {
return SysConsole.Console.width();
@@ -278,7 +278,7 @@ string ftoa(float val, uint base = 10) {
ret ~= cast(char)((fracPart >> 24) + '0');
fracPart &= 0xffffff;
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
@@ -373,7 +373,7 @@ string dtoa(double val, uint base = 10, bool doIntPart = true) {
ret ~= cast(char)((fracPart >> 53) + '0');
fracPart &= 0x1fffffffffffff;
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
@@ -422,7 +422,7 @@ string rtoa(real val, uint base = 10) {
long mantissa;
long intPart;
long fracPart;
-
+
long exp;
longReal iF;
@@ -441,7 +441,7 @@ string rtoa(real val, uint base = 10) {
mantissa = iF.l.frac;
fracPart = 0;
intPart = 0;
-
+
if (exp >= 31) {
return "0";
}
@@ -463,18 +463,18 @@ string rtoa(real val, uint base = 10) {
if (iF.l.exp < 0) {
ret = "-";
}
-
+
ret ~= itoa(intPart, base);
ret ~= ".";
for (uint k; k < 7; k++) {
fracPart *= 10;
ret ~= cast(char)((fracPart >> 64) + '0');
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
-
+
while (roundUp) {
if (ret.length == 0) {
return "0";
@@ -486,7 +486,7 @@ string rtoa(real val, uint base = 10) {
ret[$-1]++;
break;
}
-
+
// get rid of useless zeroes (and point if necessary)
foreach_reverse(uint i, chr; ret) {
if (chr != '0' && chr != '.') {
10 app/d/hello/hello.d
View
@@ -6,22 +6,20 @@
module hello;
-import user.syscall;
-
import console;
-import libos.keyboard;
-import user.environment;
+// requied by entry.
+import libos.keyboard;
import libos.libdeepmajik.threadscheduler;
void main(char[][] argv) {
- Console.backcolor = Color.Black;
+ Console.backcolor = Color.Black;
Console.forecolor = Color.Green;
Console.putString("\nHello, and Welcome to XOmB\n");
Console.putString( "-=-=-=-=-=-=-=-\n\n");
- Console.backcolor = Color.Black;
+ Console.backcolor = Color.Black;
Console.forecolor = Color.LightGray;
foreach(str; argv){
18 app/d/init/console.d
View
@@ -43,7 +43,7 @@ static:
void putChar(char foo) {
return SysConsole.Console.putChar(foo);
- }
+ }
uint width() {
return SysConsole.Console.width();
@@ -278,7 +278,7 @@ string ftoa(float val, uint base = 10) {
ret ~= cast(char)((fracPart >> 24) + '0');
fracPart &= 0xffffff;
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
@@ -373,7 +373,7 @@ string dtoa(double val, uint base = 10, bool doIntPart = true) {
ret ~= cast(char)((fracPart >> 53) + '0');
fracPart &= 0x1fffffffffffff;
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
@@ -422,7 +422,7 @@ string rtoa(real val, uint base = 10) {
long mantissa;
long intPart;
long fracPart;
-
+
long exp;
longReal iF;
@@ -441,7 +441,7 @@ string rtoa(real val, uint base = 10) {
mantissa = iF.l.frac;
fracPart = 0;
intPart = 0;
-
+
if (exp >= 31) {
return "0";
}
@@ -463,18 +463,18 @@ string rtoa(real val, uint base = 10) {
if (iF.l.exp < 0) {
ret = "-";
}
-
+
ret ~= itoa(intPart, base);
ret ~= ".";
for (uint k; k < 7; k++) {
fracPart *= 10;
ret ~= cast(char)((fracPart >> 64) + '0');
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
-
+
while (roundUp) {
if (ret.length == 0) {
return "0";
@@ -486,7 +486,7 @@ string rtoa(real val, uint base = 10) {
ret[$-1]++;
break;
}
-
+
// get rid of useless zeroes (and point if necessary)
foreach_reverse(uint i, chr; ret) {
if (chr != '0' && chr != '.') {
4 app/d/init/embeddedfs.d
View
@@ -8,7 +8,7 @@ struct EmbeddedFS{
static:
void makeFS(){
MinFS.format();
-
+
// binaries
xsh = makeFile!("binaries/xsh", true)();
makeFile!("binaries/hello", true)();
@@ -24,7 +24,7 @@ struct EmbeddedFS{
MinFS.link("/binaries/posix", "/binaries/echo");
MinFS.link("/binaries/posix", "/binaries/ls");
MinFS.link("/binaries/posix", "/binaries/ln");
-
+
// data
makeFile!("LICENSE", false)();
}
23 app/d/init/init.d
View
@@ -8,20 +8,15 @@ module init;
import embeddedfs;
-import user.syscall;
-import user.environment;
-
-import libos.fs.minfs;
+import Syscall = user.syscall;
+import user.ipc;
+import user.types;
import console;
-import libos.keyboard;
-
-import user.keycodes;
+import libos.keyboard;
import libos.libdeepmajik.threadscheduler;
-import mindrt.util;
-
void main(char[][] argv) {
MessageInAbottle* bottle = MessageInAbottle.getMyBottle();
@@ -31,21 +26,21 @@ void main(char[][] argv) {
EmbeddedFS.makeFS();
// say hello
- Console.backcolor = Color.Black;
+ Console.backcolor = Color.Black;
Console.forecolor = Color.Green;
Console.putString("\nWelcome to XOmB\n");
Console.putString( "-=-=-=-=-=-=-=-\n\n");
-
- Console.backcolor = Color.Black;
+
+ Console.backcolor = Color.Black;
Console.forecolor = Color.LightGray;
// yield to xsh
- AddressSpace xshAS = createAddressSpace();
+ AddressSpace xshAS = Syscall.createAddressSpace();
const char[][] args = ["xsh", "arg"];
- File xsh = EmbeddedFS.shell();
+ ubyte[] xsh = EmbeddedFS.shell();
if(xsh !is null){
populateChild(args, xshAS, xsh);
14 app/d/posix/posix.d
View
@@ -10,9 +10,7 @@ import libos.keyboard;
import libos.libdeepmajik.threadscheduler;
import libos.fs.minfs;
-// exit
-import user.syscall;
-import user.environment;
+import user.ipc;
void main(char[][] argv){
if(argv.length < 1){
@@ -101,7 +99,7 @@ void main(char[][] argv){
Console.putString("File ");
Console.putString(argv[1]);
Console.putString(" Does Not Exist!\n");
-
+
exit(1);
}
@@ -110,10 +108,10 @@ void main(char[][] argv){
Console.putString("File ");
Console.putString(argv[2]);
Console.putString(" Does Not Exist!\n");
-
+
exit(1);
}
-
+
ulong* size = cast(ulong*)f.ptr;
memcpy(g.ptr, f.ptr, *size + ulong.sizeof);
@@ -169,7 +167,7 @@ void main(char[][] argv){
Console.putString("target already exists!\n");
//return(1);
}
-
+
//return(0);
break;
case "ls":
@@ -191,7 +189,7 @@ void main(char[][] argv){
}
}
break;
- default:
+ default:
Console.putString("Posix: command '");
foreach(str; argv){
Console.putString(str);
18 app/d/xsh/console.d
View
@@ -43,7 +43,7 @@ static:
void putChar(char foo) {
return SysConsole.Console.putChar(foo);
- }
+ }
uint width() {
return SysConsole.Console.width();
@@ -278,7 +278,7 @@ string ftoa(float val, uint base = 10) {
ret ~= cast(char)((fracPart >> 24) + '0');
fracPart &= 0xffffff;
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
@@ -373,7 +373,7 @@ string dtoa(double val, uint base = 10, bool doIntPart = true) {
ret ~= cast(char)((fracPart >> 53) + '0');
fracPart &= 0x1fffffffffffff;
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
@@ -422,7 +422,7 @@ string rtoa(real val, uint base = 10) {
long mantissa;
long intPart;
long fracPart;
-
+
long exp;
longReal iF;
@@ -441,7 +441,7 @@ string rtoa(real val, uint base = 10) {
mantissa = iF.l.frac;
fracPart = 0;
intPart = 0;
-
+
if (exp >= 31) {
return "0";
}
@@ -463,18 +463,18 @@ string rtoa(real val, uint base = 10) {
if (iF.l.exp < 0) {
ret = "-";
}
-
+
ret ~= itoa(intPart, base);
ret ~= ".";
for (uint k; k < 7; k++) {
fracPart *= 10;
ret ~= cast(char)((fracPart >> 64) + '0');
}
-
+
// round last digit
bool roundUp = (ret[$-1] >= '5');
ret = ret[0..$-1];
-
+
while (roundUp) {
if (ret.length == 0) {
return "0";
@@ -486,7 +486,7 @@ string rtoa(real val, uint base = 10) {
ret[$-1]++;
break;
}
-
+
// get rid of useless zeroes (and point if necessary)
foreach_reverse(uint i, chr; ret) {
if (chr != '0' && chr != '.') {
38 app/d/xsh/xsh.d
View
@@ -6,7 +6,7 @@
module xsh;
-import user.syscall;
+import Syscall = user.syscall;
import console;
import libos.keyboard;
@@ -15,9 +15,11 @@ import user.keycodes;
import libos.libdeepmajik.threadscheduler;
import libos.fs.minfs;
+import user.ipc;
+
void main() {
- Console.backcolor = Color.Black;
+ Console.backcolor = Color.Black;
Console.forecolor = Color.Green;
MinFS.initialize();
@@ -127,15 +129,15 @@ void interpret(char[] str) {
}
else if (streq(cmd, "run")) {
// Open the file, parse the ELF into a new address space, and execute
-
+
if (argument.length > 0) {
createArgumentPath(arguments[1]);
- AddressSpace child = createAddressSpace();
+ AddressSpace child = Syscall.createAddressSpace();
File f = MinFS.open(argumentPath, AccessMode.User|AccessMode.Writable|AccessMode.Executable);
- if(f is null){Console.putString("Binary Not Found!\n"); return;}
+ if(f is null){Console.putString("Binary Not Found!\n"); return;}
// trim path of or binary name for argv[0]
int i = 0;
@@ -145,7 +147,7 @@ void interpret(char[] str) {
}
}
arguments[1] = arguments[1][(i+1)..$];
-
+
populateChild(arguments[1..argc], child, f);
@@ -200,21 +202,21 @@ void interpret(char[] str) {
Console.putString("xsh: cd: Path does not exist.\n");
return;
}
- }
+ }
}*/
}
else {
- if (str.length > 0) {
- AddressSpace child = createAddressSpace();
+ if (str.length > 0) {
+ AddressSpace child = Syscall.createAddressSpace();
File infile = null, outfile = null;
// XXX: really lame redirects
if(argc > 2){
if(arguments[argc-2] == ">"){
- outfile = MinFS.open(arguments[argc-1], AccessMode.Writable, true);
+ outfile = MinFS.open(arguments[argc-1], AccessMode.Writable, true);
argc -= 2;
}else if(arguments[argc-2] == "<"){
- infile = MinFS.open(arguments[argc-1], AccessMode.Read, true);
+ infile = MinFS.open(arguments[argc-1], AccessMode.Read, true);
argc -= 2;
}
}
@@ -224,16 +226,16 @@ void interpret(char[] str) {
pathName[0..10] = "/binaries/";
uint pathNameLength = 10;
-
+
bool fallback = true;
File f;
-
+
uint idx;
-
+
if(arguments[0][0] != '/'){
- uint len = arguments[0].length < pathName.length - pathNameLength ? arguments[0].length : pathName.length - pathNameLength;
+ uint len = arguments[0].length < pathName.length - pathNameLength ? arguments[0].length : pathName.length - pathNameLength;
char[] testPathName = pathName[0..(pathNameLength+len)];
-
+
testPathName[pathNameLength..(pathNameLength+len)] = arguments[0];
if(testPathName == MinFS.findPrefix(testPathName, idx)){
@@ -254,8 +256,8 @@ void interpret(char[] str) {
assert(f !is null);
- populateChild(arguments[0..argc], child, f, infile.ptr, outfile.ptr);
-
+ populateChild(arguments[0..argc], child, f, infile, outfile);
+
XombThread.yieldToAddressSpace(child,0);
}
}
38 kernel/arch/x86_64/architecture/cpu.d
View
@@ -29,9 +29,6 @@ import kernel.system.definitions;
import architecture.syscall;
import architecture.vm;
-// For stack tracing
-import user.environment;
-
private {
extern(C) {
extern ubyte _stack;
@@ -46,12 +43,12 @@ public:
ErrorVal initialize() {
LocalAPIC.reportCore();
+ // enable NX bit support (has to happen before any kprintf for APs)
+ Cpu.writeMSR(0xC0000080, Cpu.readMSR(0xC0000080)|0x800UL);
+
Log.print("Cpu: Verifying");
Log.result(verify());
- // enable NX bit support
- Cpu.writeMSR(0xC0000080, Cpu.readMSR(0xC0000080)|0x800UL);
-
Log.print("Cpu: Installing Page Table");
Log.result(Paging.install());
@@ -189,7 +186,7 @@ public:
}
T ioIn(T)(uint port) {
- // The argument is passed as RDI
+ // The argument is passed as RDI
asm {
naked;
mov EDX, EDI;
@@ -264,7 +261,7 @@ public:
asm {
// move the MSR index to ECX
mov ECX, MSR;
-
+
// read MSR
rdmsr;
@@ -279,7 +276,7 @@ public:
return ret;
}
-
+
/*
added by pmcclory.
calls cpuid with EAX set as 0x2.
@@ -328,7 +325,7 @@ public:
ebx_ret = getBX();
ecx_ret = getCX();
edx_ret = getDX();
- i++;
+ i++;
} while (i < count);
@@ -337,12 +334,12 @@ public:
return ErrorVal.Success;
}
- void* stack() {
+ ubyte* stack() {
return _stacks[identifier];
}
//noreturn
- void enterUserspace(ulong idx, ulong calleePhysAddr){
+ void enterUserspace(ulong idx, PhysicalAddress calleePhysAddr){
// use CPUid as vector index and sysret to 1 GB
// jump using sysret to 1GB for stackless entry
@@ -355,7 +352,7 @@ public:
asm{
movq R11, mySS;
pushq R11;
-
+
movq R11, myRSP;
pushq R11;
@@ -374,7 +371,7 @@ public:
iretq;
}
}
-
+
private:
/*
@@ -385,7 +382,7 @@ private:
void examineRegister(uint reg) {
uint i;
uint temp;
-
+
for(i=0; i<4; i++) {
temp = reg >> (8 * i);
temp = temp & 0xFF;
@@ -675,19 +672,18 @@ private:
}
}
- private void* _stacks[256];
+ private ubyte* _stacks[256];
// Will create and install a new kernel stack
// Note: You have to preserve the current stack
ErrorVal installStack() {
- ubyte* stackSpace = cast(ubyte*)PageAllocator.allocPage();
- stackSpace = cast(ubyte*)VirtualMemory.mapStack(stackSpace);
+ ubyte* stackSpace = VirtualMemory.mapStack(PageAllocator.allocPage());
ubyte* currentStack = cast(ubyte*)(&_stack-4096);
stackSpace[0..4096] = currentStack[0..4096];
- _stacks[identifier] = cast(void*)stackSpace + 4096;
- TSS.table.RSP0 = cast(void*)stackSpace + 4096;
+ _stacks[identifier] = cast(ubyte*)stackSpace + 4096;
+ TSS.table.RSP0 = cast(ubyte*)stackSpace + 4096;
StackFrame* curr = null;
@@ -715,7 +711,7 @@ private:
while(isValidAddress(cast(ubyte*)curr.next) && cast(ulong)curr.next > Paging.PAGESIZE) {
curr.next = cast(StackFrame*)(cast(ulong)curr.next & (Paging.PAGESIZE - 1));
- curr.next = cast(StackFrame*)(cast(ulong)curr.next + stackSpace);
+ curr.next = cast(StackFrame*)(cast(ulong)curr.next + stackSpace);
curr = curr.next;
}
8 kernel/arch/x86_64/architecture/keyboard.d
View
@@ -39,7 +39,7 @@ static:
while((status & 0x1) == 1) {
-
+
code = Cpu.ioIn!(ubyte, "0x60")();
status = Cpu.ioIn!(ubyte, "0x64")();
@@ -88,7 +88,7 @@ static:
// bit 2 - Keyboard Power (0: normal, 1: no power)
// bit 3 - Unused
// bit 4 - RAM (0: 512KB, 1: 256KB)
- // bit 5 - Manufacturing Jumper (0: installed, 1: not installed)
+ // bit 5 - Manufacturing Jumper (0: installed, 1: not installed)
// With jumper BIOS runs an infinite diagnostic loop.
// bit 6 - Display (0: CGA, 1: MDA)
// bit 7 - Keyboard Lock (0: locked, 1: unlocked)
@@ -99,7 +99,7 @@ static:
// bit 1 - A20 (0: line is forced, 1: A20 enabled)
// bit 2 - Mouse Data
// bit 3 - Mouse Clock
- // bit 4 - IRQ 1 (0: active, 1: inactive)
+ // bit 4 - IRQ 1 (0: active, 1: inactive)
// commonly Keyboard IRQ, tells whether or not the IRQ is currently firing
// bit 5 - IRQ 12 (0: active, 1: inactive) // commonly Mouse IRQ
// bit 6 - Keyboard Clock
@@ -140,7 +140,7 @@ private:
if (data == 0x00) {
return;
}
-
+
Key key = Key.Null;
if (data == 0xe0) {
6 kernel/arch/x86_64/architecture/main.d
View
@@ -32,12 +32,12 @@ import kernel.system.info;
struct Architecture {
static:
public:
-
+
// This function will initialize the architecture upon boot
ErrorVal initialize() {
// Reading from the linker script
// We want the length of the kernel module
- System.kernel.start = cast(ubyte*)0x0;
+ System.kernel.start = null;
System.kernel.length = LinkerScript.ekernel - LinkerScript.kernelVMA;
System.kernel.virtualStart = cast(ubyte*)LinkerScript.kernelVMA;
@@ -56,7 +56,7 @@ public:
Log.print("Cpu: Polling Cache Info");
Log.result(Cpu.getCacheInfo());
- Console.virtualAddress = cast(void*)(cast(ubyte*)System.kernel.virtualStart + 0xB8000);
+ Console.switchToHigherHalfVirtualAddress();
// Everything must have succeeded
return ErrorVal.Success;
4 kernel/arch/x86_64/architecture/perfmon.d
View
@@ -24,7 +24,7 @@ public:
L2WriteRequests,
L2Locks,
}
-
+
ErrorVal initialize() {
// Determine capabilites
ulong ia32_misc_enable = Cpu.readMSR(0x1A0);
@@ -136,7 +136,7 @@ private:
// : to this value
// 23 : Invert flag - used with CMASK, makes CMASK operate as less than
// 22 : * Enable Counters - 1=counting is enabled
- // 20 : INT (APIC int enable) - 1=processor will generate
+ // 20 : INT (APIC int enable) - 1=processor will generate
// : local APIC exception on counter overflow
// 19 : PC (pin control)
// 18 : Edge Detect
10 kernel/arch/x86_64/architecture/syscall.d
View
@@ -7,14 +7,12 @@ import kernel.core.util;
import kernel.core.syscall;
import user.syscall;
-import user.environment;
import kernel.mem.pageallocator;
import architecture.vm;
-import kernel.core.kprintf;
-const ulong FSBASE_MSR = 0xc000_0100;
-const ulong GSBASE_MSR = 0xc000_0101;
+const ulong FSBASE_MSR = 0xc000_0100;
+const ulong GSBASE_MSR = 0xc000_0101;
struct Syscall {
@@ -70,7 +68,7 @@ static:
Cpu.writeMSR(SFMASK_MSR, 0);
// stash a syscall stack in GS.Base
- void* stackPtr = PageAllocator.allocPage();
+ PhysicalAddress stackPtr = PageAllocator.allocPage();
ulong syscallStack = cast(ulong)VirtualMemory.mapStack(stackPtr) + 4096;
asm{
@@ -103,7 +101,7 @@ void syscallHandler() {
swapgs;
mov R8, 0;
lea R8, GS:[R8];
-
+
// new stack
mov RSP, R8;
*/
91 kernel/arch/x86_64/architecture/vm.d
View
@@ -14,7 +14,7 @@ import kernel.arch.x86_64.core.paging;
// Normal kernel modules
import kernel.core.error;
-import user.environment;
+public import user.environment;
class VirtualMemory {
static:
@@ -35,22 +35,63 @@ public:
// Create a new segment that will fit the indicated size
// into the global address space.
- ubyte[] createSegment(ubyte* location, ulong size, AccessMode flags) {
- Paging.createGib(location, size, flags);
+ ubyte[] createSegment(ubyte[] location, AccessMode flags) {
+ bool success;
+ uint pagelevel = sizeToPageLevel(location.length);
+
+ switch(pagelevel){
+ case 1:
+ // create the segment in the AddressSpace
+ success = Paging.createGib!(PageLevel!(1))(location.ptr, flags);
+ break;
+ case 2:
+ success = Paging.createGib!(PageLevel!(2))(location.ptr, flags);
+ break;
+ case 3:
+ success = Paging.createGib!(PageLevel!(3))(location.ptr, flags);
+ break;
+ case 4:
+ success = Paging.createGib!(PageLevel!(4))(location.ptr, flags);
+ break;
+ }
- return location[0 .. size];
+ if(success){
+ return location;
+ }else{
+ return null;
+ }
}
- // Open a segment indicated by location into the
- // virtual address space of dest.
- bool openSegment(ubyte* location, AccessMode flags) {
- // We should open this in our address space.
- return Paging.openGib(location, flags);
- }
+ bool mapSegment(AddressSpace dest, ubyte[] location, ubyte* destination, AccessMode flags) {
+ if(location is null){
+ return false;
+ }
+
+ ErrorVal result;
+ uint pagelevel = sizeToPageLevel(location.length);
+
+ switch(pagelevel){
+ //case 1:
+ //result = Paging.mapGib!(PageLevel!(1))(dest, location.ptr, destination, flags);
+ //break;
+ case 2:
+ result = Paging.mapGib!(PageLevel!(2))(dest, location.ptr, destination, flags);
+ break;
+ case 3:
+ result = Paging.mapGib!(PageLevel!(3))(dest, location.ptr, destination, flags);
+ break;
+ case 4:
+ result = Paging.mapGib!(PageLevel!(4))(dest, location.ptr, destination, flags);
+ break;
+ default:
+ return false;
+ }
- bool mapSegment(AddressSpace dest, ubyte* location, ubyte* destination, AccessMode flags) {
- Paging.mapGib(dest, location, destination, flags);
- return false;
+ if(result == ErrorVal.Success){
+ return true;
+ }else{
+ return false;
+ }
}
bool closeSegment(ubyte* location) {
@@ -64,7 +105,7 @@ public:
return Paging.createAddressSpace();
}
- ErrorVal switchAddressSpace(AddressSpace as, out ulong oldRoot){
+ ErrorVal switchAddressSpace(AddressSpace as, out PhysicalAddress oldRoot){
return Paging.switchAddressSpace(as, oldRoot);
}
@@ -75,26 +116,26 @@ public:
return Paging.PAGESIZE;
}
- synchronized void* mapStack(void* physAddr) {
+ synchronized ubyte* mapStack(PhysicalAddress physAddr) {
if(stackSegment is null){
stackSegment = findFreeSegment();
- Paging.createGib(stackSegment, oneGB, AccessMode.Writable);
+ createSegment(stackSegment, AccessMode.Writable|AccessMode.AllocOnAccess);
}
- stackSegment += Paging.PAGESIZE;
+ stackSegment = stackSegment[Paging.PAGESIZE..$];
- if(Paging.mapRegion(stackSegment, physAddr, Paging.PAGESIZE) == ErrorVal.Fail){
- return null;
- }else{
- return stackSegment;
- }
+ return Paging.mapRegion(stackSegment.ptr, physAddr, Paging.PAGESIZE).ptr;
}
// --- OLD --- //
- synchronized ErrorVal mapRegion(void* gib, void* physAddr, ulong regionLength) {
- return Paging.mapRegion(gib, physAddr, regionLength);
+ synchronized ErrorVal mapRegion(ubyte* gib, PhysicalAddress physAddr, ulong regionLength) {
+ if(Paging.mapRegion(gib, physAddr, regionLength) !is null){
+ return ErrorVal.Fail;
+ }
+
+ return ErrorVal.Success;
}
private:
- ubyte* stackSegment;
+ ubyte[] stackSegment;
}
4 kernel/arch/x86_64/boot/boot.s
View
@@ -147,7 +147,9 @@ pml4_base:
dq (pml3_base + 0x7)
times 255 dq 0
dq (pml3_base + 0x7)
- times 255 dq 0
+ times 253 dq 0
+ dq (pml4_base + 0x7) ; paging trick
+ dq 0
align 4096
pml3_base:
2  kernel/arch/x86_64/boot/trampoline.s
View
@@ -24,7 +24,7 @@ _trampoline_start:
cli
; establish a stack
- mov sp, (trampoline_stack_end - trampoline_start)
+ mov sp, (trampoline_stack_end - trampoline_start)
; clear segment registers
mov ax, cs
6 kernel/arch/x86_64/core/gdt.d
View
@@ -33,9 +33,11 @@ static:
}
ErrorVal install() {
+ PhysicalAddress gdtPage = PageAllocator.allocPage();
+
// Create a new GDT structure
- GlobalDescriptorTable* gdt = cast(GlobalDescriptorTable*)PageAllocator.allocPage();
- gdt = cast(GlobalDescriptorTable*)Paging.mapRegion(cast(ubyte*)gdt, VirtualMemory.pagesize);
+ GlobalDescriptorTable* gdt = cast(GlobalDescriptorTable*)gdtPage;
+ gdt = cast(GlobalDescriptorTable*)Paging.mapRegion(gdtPage, VirtualMemory.pagesize);
*gdt = GlobalDescriptorTable.init;
tables[Cpu.identifier] = gdt;
initializeTable(Cpu.identifier);
9 kernel/arch/x86_64/core/info.d
View
@@ -9,6 +9,9 @@
module kernel.arch.x86_64.core.info;
+import user.types;
+
+
struct Info {
static:
public:
@@ -68,8 +71,8 @@ public:
// Whether or not this IO APIC is enabled
bool enabled;
- // Virtual address of the IO APIC register
- void* address;
+ // address of the IO APIC register
+ PhysicalAddress address;
}
IOAPICInfo[16] IOAPICs;
@@ -88,7 +91,7 @@ public:
}
// The address of the apic registers
- void* localAPICAddress;
+ PhysicalAddress localAPICAddress;
LAPICInfo[256] LAPICs;
uint numLAPICs;
7 kernel/arch/x86_64/core/ioapic.d
View
@@ -25,6 +25,9 @@ import kernel.core.error;
import kernel.core.log;
import kernel.core.kprintf;
+import user.types;
+
+
struct IOAPIC
{
static:
@@ -112,7 +115,7 @@ private:
// -- Setup -- //
- void initUnit(ubyte ioAPICID, void* ioAPICAddress, bool hasIMCR) {
+ void initUnit(ubyte ioAPICID, PhysicalAddress ioAPICAddress, bool hasIMCR) {
// disable the IMCR
if (hasIMCR) {
@@ -124,7 +127,7 @@ private:
// map IOAPIC region
//kprintfln!("IOAPIC Addr {x}")(ioAPICAddress);
- void* IOAPICVirtAddr = Paging.mapRegion(ioAPICAddress, 4096);
+ ubyte* IOAPICVirtAddr = Paging.mapRegion(ioAPICAddress, 4096).ptr;
//kprintfln!("IOAPIC Addr {x}")(IOAPICVirtAddr);
// set the addresses for the data register and window
9 kernel/arch/x86_64/core/lapic.d
View
@@ -21,6 +21,9 @@ import kernel.core.log;
import kernel.system.info;
+import user.types;
+
+
struct LocalAPIC {
static:
public:
@@ -117,7 +120,7 @@ private:
uint[256] logicalIDToAPICId = 0;
uint[256] APICIdToLogicalID = 0;
- void initLocalApic(void* localAPICAddr) {
+ void initLocalApic(PhysicalAddress localAPICAddr) {
ubyte* apicRange;
ulong MSRValue = Cpu.readMSR(0x1B);
@@ -134,7 +137,7 @@ private:
// Map in the first megabyte of space
ubyte* bootRange;
- bootRange = cast(ubyte*)Paging.mapRegion(cast(void*)0x0, trampolineLength);
+ bootRange = cast(ubyte*)Paging.mapRegion(null, trampolineLength);
//kprintfln!("bootRange: {} trampolineLength: {} trampolineCode: {x} trampoline: {x} Kernel: {x}")(bootRange, trampolineLength, trampolineCode, LinkerScript.trampoline, System.kernel.start);
@@ -151,7 +154,7 @@ private:
if (apicRegisters is null) {
return 0;
}
-
+
uint ID = apicRegisters.localApicId;
return ID >> 24;
}
860 kernel/arch/x86_64/core/paging.d
View
@@ -17,64 +17,54 @@ import kernel.mem.pageallocator;
// Import some arch-dependent modules
import kernel.arch.x86_64.linker; // want linker info
-
import kernel.arch.x86_64.core.idt;
// Import information about the system
// (we need to know where the kernel is)
import kernel.system.info;
-// We need to restart the console driver
-import kernel.dev.console;
-
import architecture.mutex;
+// for reporting userspacepage fault errors to parent
+import architecture.cpu;
+
import user.environment;
+
align(1) struct StackFrame{
StackFrame* next;
ulong returnAddr;
}
void printStackTrace(StackFrame* start){
- kprintfln!(" YOU LOOK SAD, SO I GOT YOU A STACK TRACE!")();
-
- StackFrame* curr = start, limit = start;
-
- limit += Paging.PAGESIZE;
- limit = cast(StackFrame*) ( cast(ulong)limit & ~(Paging.PAGESIZE-1));
-
int count = 10;
- //&& curr < limit
- while(cast(ulong)curr > Paging.PAGESIZE && count > 0 && isValidAddress(cast(ubyte*)curr)){
- kprintfln!("return addr: {x} rbp: {x}")(curr.returnAddr, curr);
- curr = curr.next;
+ kprintfln!(" YOU LOOK SAD, SO I GOT YOU A STACK TRACE!")();
+
+ while(count > 0 && isValidAddress(cast(ubyte*)start)){
+ kprintfln!("return addr: {x} rbp: {x}")(start.returnAddr, start);
+ start = start.next;
count--;
}
}
class Paging {
static:
-
- // The page size we are using
- const auto PAGESIZE = 4096;
-
- // This function will initialize paging and install a core page table.
- ErrorVal initialize() {
+ // --- Set Up ---
+ ErrorVal initialize(){
+ // Save the physical address for later
+ rootPhysical = PageAllocator.allocPage();
// Create a new page table.
- root = cast(PageLevel4*)PageAllocator.allocPage();
- PageLevel3* globalRoot = cast(PageLevel3*)PageAllocator.allocPage();
-
- //kprintfln!("root: {} pl3: {} pl2: {}")(root, pl3, pl2);
+ PageLevel!(4)* newRoot = cast(PageLevel!(4)*)rootPhysical;
+ PageLevel!(3)* globalRoot = cast(PageLevel!(3)*)PageAllocator.allocPage();
// Initialize the structure. (Zero it)
- *root = PageLevel4.init;
- *globalRoot = PageLevel3.init;
+ *newRoot = (PageLevel!(4)).init;
+ *globalRoot = (PageLevel!(3)).init;
// Map entries 510 to the PML4
- root.entries[510].pml = cast(ulong)root;
- root.entries[510].setMode(AccessMode.Read|AccessMode.User);
+ newRoot.entries[510].pml = cast(ulong)rootPhysical;
+ newRoot.entries[510].setMode(AccessMode.Read|AccessMode.User);
/* currently the kernel isn't forced to respect the rw bit. if
this is enabled, another paging trick will be needed with
@@ -82,56 +72,86 @@ static:
*/
// Map entry 509 to the global root
- root.entries[509].pml = cast(ulong)globalRoot;
- root.entries[509].setMode(AccessMode.Read);
+ newRoot.entries[509].pml = cast(ulong)globalRoot;
+ newRoot.entries[509].setMode(AccessMode.Read);
// The current position of the kernel space. All gets appended to this address.
- heapAddress = LinkerScript.kernelVMA;
+ heapAddress = cast(ubyte*)LinkerScript.kernelVMA + System.kernel.length;
- // We need to map the kernel
- kernelAddress = heapAddress;
+ // map kernel into bootstrap root page table, so we can use paging trick
+ ubyte* addr = createAddress(0, 0, 0, 257);//findFreeSegment(true, 512*oneGB).ptr;
- //kprintfln!("About to map kernel")();
- mapRegion(System.kernel.start, System.kernel.length);
+ createGib!(PageLevel!(3))(addr, AccessMode.Writable|AccessMode.Executable);
+ mapRegion(addr, System.kernel.start, System.kernel.length);
- void* bitmapLocation = heapAddress;
-
- // The first gib for the kernel
- nextGib++;
+ // copy physical address to new root
+ ulong idx, frag = cast(ulong)addr;
+ getNextIndex(frag, idx);
+ newRoot.entries[256].pml = root.entries[idx].pml;
// Assign the page fault handler
- IDT.assignHandler(&faultHandler, 14);
+ IDT.assignHandler(&pageFaultHandler, 14);
+ IDT.assignHandler(&generalProtectionFaultHandler, 13);
- IDT.assignHandler(&gpfHandler, 13);
+ // All is well.
+ return ErrorVal.Success;
+ }
- // We now have the kernel mapped
- kernelMapped = true;
+ ErrorVal install() {
+ ulong rootAddr = cast(ulong)rootPhysical;
+ asm {
+ mov RAX, rootAddr;
+ mov CR3, RAX;
+ }
- // Save the physical address for later
- rootPhysical = cast(void*)root;
+ /*
+ if(heapAddress is null){
- // This is the virtual address for the page table
- root = cast(PageLevel4*)0xFFFFFF7F_BFDFE000;
+ // put mapRegion heap into its own segment
+ heapAddress = findFreeSegment().ptr;
+
+ assert(heapAddress !is null);
+
+ bool success = createGib!(PageLevel!(3))(heapAddress, AccessMode.Writable);
+
+ assert(success);
+ }
+ */
- // All is well.
return ErrorVal.Success;
}
- void gpfHandler(InterruptStack* stack) {
- stack.dump();
+
+ // --- Handlers ---
+ void generalProtectionFaultHandler(InterruptStack* stack) {
+ bool recoverable;
if (stack.rip < 0xf_0000_0000_0000) {
- kprintfln!("User Mode General Protection Fault: instruction address {x}")(stack.rip);
+ kprintf!("User Mode ")();
+ recoverable = true;
}else{
- kprintfln!("Kernel Mode Level 3 Page Fault: instruction address {x}")(stack.rip);
+ kprintf!("Kernel Mode ")();
}
+
+ kprintfln!("General Protection Fault: instruction address {x}")(stack.rip);
+
+ stack.dump();
printStackTrace(cast(StackFrame*)stack.rbp);
-
- for(;;){}
+
+
+ if(recoverable){
+ PhysicalAddress deadChild;
+
+ switchAddressSpace(null, deadChild);
+ Cpu.enterUserspace(3, deadChild);
+ }else{
+ for(;;){}
+ }
+ // >>> Never reached <<<
}
- void faultHandler(InterruptStack* stack) {
+ void pageFaultHandler(InterruptStack* stack) {
ulong cr2;
asm {
@@ -139,149 +159,138 @@ static:
mov cr2, RAX;
}
- void* addr = cast(void*)cr2;
+ // page not present or privilege violation?
+ if((stack.errorCode & 1) == 0){
+ bool allocate;
+ root.walk!(pageFaultHelper)(cr2, allocate);
- if((stack.errorCode & 7) == 7){
- // XXX: 'kill' child and return to parent?
- stack.dump();
- kprintfln!("User Mode Write Fault at {x} on Read-only page {x}, Error Code {x}")(stack.rip, addr, stack.errorCode);
- printStackTrace(cast(StackFrame*)stack.rbp);
- for(;;){}
- }
-
-
- if(stack.errorCode == 3){
- kprintfln!("Kernel Mode Write Fault at {x} on Read-only page {x}, Error Code {x}")(stack.rip, addr, stack.errorCode);
- printStackTrace(cast(StackFrame*)stack.rbp);
- for(;;){}
+ if(allocate){
+ return;
+ }else{
+ kprintf!("found incomplete page mapping without Alloc-On-Access permission on a ")();
+ }
}
+ // --- an error has occured ---
+ bool recoverable;
- ulong indexL4, indexL3, indexL2, indexL1;
- translateAddress(addr, indexL1, indexL2, indexL3, indexL4);
-
- // check for gib status
- PageLevel3* pl3 = root.getTable(indexL4);
- if (pl3 is null) {
- // NOT AVAILABLE
+ if(stack.errorCode & 8){
+ kprintfln!("You look angry that I wrote some bits in a reserved field. Have some PTEs.")();
+ uint depth = 4;
+ root.walk!(pageEntryPrinter)(cr2, depth);
- if (stack.rip < 0xf_0000_0000_0000) {
- kprintfln!("User Mode Level 3 Page Fault: instruction address {x}")(stack.rip);
+ kprintf!("Reserved bit ")();
+ }else{
+ if(stack.errorCode & 4){
+ kprintf!("User Mode ")();
+ recoverable = true;
+ }else{
+ kprintf!("Kernel Mode ")();
+ }
+ if(stack.errorCode & 16){
+ kprintf!("Instruction Fetch ")();
+ }else{
+ if(stack.errorCode & 2){
+ kprintf!("Write ")();
}else{
- kprintfln!("Kernel Mode Level 3 Page Fault: instruction address {x}")(stack.rip);
+ kprintf!("Read ")();
}
+ }
+ }
- kprintfln!("Non-Gib access. looping 4eva. CR2 = {}")(addr);
-
- printStackTrace(cast(StackFrame*)stack.rbp);
+ kprintfln!("Fault at instruction {x} to address {x}")(stack.rip, cast(ubyte*)cr2);
- for(;;){}
- }
- else {
- PageLevel2* pl2 = pl3.getTable(indexL3);
- if (pl2 is null) {
- // NOT AVAILABLE (FOR SOME REASON)
+ stack.dump();
+ printStackTrace(cast(StackFrame*)stack.rbp);
- if (stack.rip < 0xf_0000_0000_0000) {
- kprintfln!("User Mode Level 2 Page Fault {x}, Error Code {x}")(stack.rip, stack.errorCode);
- }else{
- kprintfln!("Kernel Mode Level 2 Page Fault {x}, Error Code {x}")(stack.rip, stack.errorCode);
- }
+ if(recoverable){
+ PhysicalAddress deadChild;
- kprintfln!("Non-Gib access. looping 4eva. CR2 = {}")(addr);
+ switchAddressSpace(null, deadChild);
+ Cpu.enterUserspace(3, deadChild);
+ }else{
+ for(;;){}
+ }
+ // >>> Never reached <<<
+ }
- printStackTrace(cast(StackFrame*)stack.rbp);
-
- for(;;){}
- }
- else {
+ template pageFaultHelper(T){
+ bool pageFaultHelper(T table, uint idx, ref bool allocate){
+ const AccessMode allocatingSegment = AccessMode.AllocOnAccess | AccessMode.Segment;
- // Allocate Page
- // XXX: only if gib is allocate on access!!
- addr = cast(void*)(cast(ulong)addr & 0xffff_ffff_ffff_f000UL);
+ if(table.entries[idx].present){
+ if((table.entries[idx].getMode() & allocatingSegment) == allocatingSegment){
+ allocate = true;
+ }
- void* page = PageAllocator.allocPage();
+ return true;
+ }else{
+ if(allocate){
+ static if(T.level == 1){
+ ubyte* page = PageAllocator.allocPage();
+
+ if(page is null){
+ allocate = false;
+ }else{
+ table.entries[idx].pml = cast(ulong)page;
+ table.entries[idx].pat = 1;
+ table.entries[idx].setMode(AccessMode.User|AccessMode.Writable|AccessMode.Executable);
+ }
+ }else{
+ auto intermediate = table.getOrCreateTable(idx, true);
- mapRegion(null, page, PAGESIZE, addr, true);
+ if(intermediate is null){
+ allocate = false;
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
}
}
}
- ErrorVal install() {
- ulong rootAddr = cast(ulong)rootPhysical;
- asm {
- mov RAX, rootAddr;
- mov CR3, RAX;
- }
- return ErrorVal.Success;
- }
+ bool pageEntryPrinter(T)(T table, uint idx, ref uint depth){
+ if(table.entries[idx].present){
+ kprintfln!("Level {}: {x}")(depth--, table.entries[idx].pml);
- // This function will get the physical address that is mapped from the
- // specified virtual address.
- void* translateAddress(void* virtAddress) {
- ulong vAddr = cast(ulong)virtAddress;
-
- vAddr >>= 12;
- uint indexLevel1 = vAddr & 0x1ff;
- vAddr >>= 9;
- uint indexLevel2 = vAddr & 0x1ff;
- vAddr >>= 9;
- uint indexLevel3 = vAddr & 0x1ff;
- vAddr >>= 9;
- uint indexLevel4 = vAddr & 0x1ff;
-
- return root.getTable(indexLevel4).getTable(indexLevel3).getTable(indexLevel2).physicalAddress(indexLevel1);
- }
+ return true;
+ }
- void translateAddress( void* virtAddress,
- out ulong indexLevel1,
- out ulong indexLevel2,
- out ulong indexLevel3,
- out ulong indexLevel4) {
- ulong vAddr = cast(ulong)virtAddress;
-
- vAddr >>= 12;
- indexLevel1 = vAddr & 0x1ff;
- vAddr >>= 9;
- indexLevel2 = vAddr & 0x1ff;
- vAddr >>= 9;
- indexLevel3 = vAddr & 0x1ff;
- vAddr >>= 9;
- indexLevel4 = vAddr & 0x1ff;
+ return false;
}
- Mutex pagingLock;
+ // --- AddressSpace Manipulation ---
AddressSpace createAddressSpace() {
- // XXX: the place where the address foo is stored is hard coded in context :(
- // and now it is going to be hardcoded here :(
-
// Make a new root pagetable
- ubyte* newRootPhysAddr = cast(ubyte*)PageAllocator.allocPage();
+ PhysicalAddress newRootPhysAddr = PageAllocator.allocPage();
- PageLevel3* addressRoot = root.getOrCreateTable(255);
+ bool success;
+ ulong idx, addrFrag;
+ ubyte* vAddr;
+ PageLevel!(3)* segmentParent;
+ AccessMode flags = AccessMode.RootPageTable|AccessMode.Writable;
- PageLevel2* addressSpace;
+ // --- find a free slot to store the child's root, then map it in ---
+ root.traverse!(preorderFindFreeSegmentHelper, noop)(cast(ulong)createAddress(0,0,1,255), cast(ulong)createAddress(0,0,255,255), vAddr, segmentParent);
+ if(vAddr is null)
+ return null;
- uint idx = 0;
- for(uint i = 1; i < 512; i++) {
- if (addressRoot.getTable(i) is null) {
- addressRoot.setTable(i, newRootPhysAddr, false);
- addressRoot.entries[i].setMode(AccessMode.RootPageTable);
- addressSpace = addressRoot.getTable(i);
- idx = i;
- break;
- }
- }
+ addrFrag = cast(ulong)vAddr;
+ root.walk!(mapSegmentHelper)(addrFrag, flags, success, segmentParent, newRootPhysAddr);
- if(idx == 0){
- return null;
- }
+ root.walk!(zeroPageTableHelper)(addrFrag, segmentParent);
+
+ getNextIndex(addrFrag, idx);
+ getNextIndex(addrFrag, idx);
+ PageLevel!(2)* addressSpace = root.getTable(255).getTable(idx);
- // Initialize the address space root page table
- *(cast(PageLevel4*)addressSpace) = PageLevel4.init;
+ // --- initialize root ---
+ *(cast(PageLevel!(4)*)addressSpace) = (PageLevel!(4)).init;
// Map in kernel pages
addressSpace.entries[256].pml = root.entries[256].pml;
@@ -290,19 +299,20 @@ static:
addressSpace.entries[510].pml = cast(ulong)newRootPhysAddr;
addressSpace.entries[510].setMode(AccessMode.User);
-
// insert parent into child
- PageLevel1* fakePl3 = addressSpace.getOrCreateTable(255);
+ PageLevel!(1)* fakePl3 = addressSpace.getOrCreateTable(255);
+
+ if(fakePl3 is null)
+ return null;
+
fakePl3.entries[0].pml = root.entries[510].pml;
// child should not be able to edit parent's root table
fakePl3.entries[0].setMode(AccessMode.RootPageTable);
-
return cast(AddressSpace)addressSpace;
}
- synchronized ErrorVal switchAddressSpace(AddressSpace as, out ulong oldRoot){
-
+ ErrorVal switchAddressSpace(AddressSpace as, out PhysicalAddress oldRoot){
if(as is null){
// XXX - just decode phys addr directly?
as = cast(AddressSpace)root.getTable(255).getTable(0);
@@ -313,439 +323,243 @@ static:
return ErrorVal.Fail;
}
+ oldRoot = switchAddressSpace(findPhysicalAddressOfSegment(as));
- ulong indexL4, indexL3, indexL2, indexL1;
-
- translateAddress(cast(ubyte*)as, indexL1, indexL2, indexL3, indexL4);
-
- PageLevel3* pl3 = root.getTable(indexL4);
- PageLevel2* pl2 = pl3.getTable(indexL3);
- PageLevel1* pl1 = pl2.getTable(indexL2);
-
- ulong newPhysRoot = cast(ulong)pl1.entries[indexL1].location();
+ return ErrorVal.Success;
+ }
- oldRoot = cast(ulong)root.entries[510].location();
+private:
+ PhysicalAddress switchAddressSpace(PhysicalAddress newRoot){
+ PhysicalAddress oldRoot = root.entries[510].location();
asm{
- mov RAX, newPhysRoot;
+ mov RAX, newRoot;
mov CR3, RAX;
}
-
- return ErrorVal.Success;
+ return oldRoot;
}
+public:
- synchronized ErrorVal mapGib(AddressSpace destinationRoot, ubyte* location, ubyte* destination, AccessMode flags) {
-
- if(flags & AccessMode.Global){
- ulong indexL1, indexL2, indexL3, indexL4;
- PageLevel3* pl3 = root.getOrCreateTable(509, true);
- PageLevel2* pl2;
- translateAddress(location, indexL1, indexL2, indexL3, indexL4);
- pl2 = pl3.getOrCreateTable(indexL4, true);
- ubyte* locationAddr = cast(ubyte*)pl2.entries[indexL3].location();
+ // --- Segment Manipulation ---
+ // dropped synchronized because of an ldc bug w/ templates
+ ErrorVal mapGib(T)(AddressSpace destinationRoot, ubyte* location, ubyte* destination, AccessMode flags) {
+ bool success;
- indexL1 = indexL2 = indexL3 = indexL4 = 0;
-
- translateAddress(destination, indexL1, indexL2, indexL3, indexL4);
- pl2 = pl3.getOrCreateTable(indexL4, true);
- pl2.setTable(indexL3, locationAddr, true);
-
- return ErrorVal.Success;
- }
-
+ if(flags & AccessMode.Global){
+ PageLevel!(T.level -1)* globalSegmentParent;
- PageLevel4* addressSpace;
+ PhysicalAddress locationAddr = getPhysicalAddressOfSegment!(typeof(globalSegmentParent))(cast(ubyte*)getGlobalAddress(cast(AddressFragment)location));
+ if(locationAddr is null)
+ return ErrorVal.Fail;
- if(destinationRoot is null){
- addressSpace = root;
- destinationRoot = cast(AddressSpace)addressSpace;
+ if(destination is null){ // our open, segment mapped from global space to destination address
+ T* segmentParent;
+ root.walk!(mapSegmentHelper)(cast(ulong)location, flags, success, segmentParent, locationAddr);
+ }else{
+ root.walk!(mapSegmentHelper)(getGlobalAddress(cast(ulong)destination), flags, success, globalSegmentParent, locationAddr);
+ }
}else{
- // verify destinationRoot is a valid root page table
- if((modesForAddress(destinationRoot) & AccessMode.RootPageTable) == 0){
+ // verify destinationRoot is a valid root page table (or null for a local operation)
+ if((destinationRoot !is null) && ((modesForAddress(destinationRoot) & AccessMode.RootPageTable) == 0)){
return ErrorVal.Fail;
}
- addressSpace = cast(PageLevel4*)destinationRoot;
- }
-
-
- // So. destinationRoot is the virtual address of the destination
- // root page table within the source (current) page table.
- // Due to paging trick magic.
-
- ulong indexL4, indexL3, indexL2, indexL1;
-
- translateAddress(cast(ubyte*)destinationRoot, indexL1, indexL2, indexL3, indexL4);
+ T* segmentParent;
+ PhysicalAddress locationAddr = getPhysicalAddressOfSegment!(typeof(segmentParent))(location), oldRoot;
- PageLevel3* pl3 = root.getTable(indexL4);
- PageLevel2* pl2 = pl3.getTable(indexL3);
- PageLevel1* pl1 = pl2.getTable(indexL2);
- ulong addr = cast(ulong)pl1.entries[indexL1].location();
+ if(locationAddr is null)
+ return ErrorVal.Fail;
- ulong oldRoot = cast(ulong)root.entries[510].location();
-
- // Now, figure out the physical address of the gib root.
+ if(destinationRoot !is null){
+ // Goto the other address space
+ switchAddressSpace(destinationRoot, oldRoot);
+ }
- translateAddress(location, indexL1, indexL2, indexL3, indexL4);
- pl3 = root.getTable(indexL4);
- ubyte* locationAddr = cast(ubyte*)pl3.entries[indexL3].location();
+ root.walk!(mapSegmentHelper)(cast(ulong)destination, flags, success, segmentParent, locationAddr);
- // Goto the other address space
- // XXX: use switchAddressSpace() ?
- asm {
- mov RAX, addr;
- mov CR3, RAX;
+ if(destinationRoot !is null){
+ // Return to our old address space
+ switchAddressSpace(oldRoot);
+ }
}
- // Add an entry into the new address space that shares the gib of the old
- translateAddress(destination, indexL1, indexL2, indexL3, indexL4);
- pl3 = root.getOrCreateTable(indexL4, true);
- pl3.setTable(indexL3, locationAddr, true);
-
- // Return to our old address space
- asm {
- mov RAX, oldRoot;
- mov CR3, RAX;
+ if(success){
+ return ErrorVal.Success;
+ }else{
+ return ErrorVal.Fail;
}
-
- return ErrorVal.Success;
}
+ // dropped synchronized because of an ldc bug w/ templates
+ template createGib(T){
+ bool createGib(ubyte* location, AccessMode flags){
+ bool global = (flags & AccessMode.Global) != 0, success;
- bool createGib(ubyte* location, ulong size, AccessMode flags) {
- // Find page translation
- ulong indexL4, indexL3, indexL2, indexL1;
- translateAddress(location, indexL1, indexL2, indexL3, indexL4);
-
- bool usermode = (flags & AccessMode.User) != 0;
+ ulong vAddr = cast(ulong)location;
+ PhysicalAddress phys = PageAllocator.allocPage();
- if (flags & AccessMode.Global) {
- //XXX: instead, getTable and isure this is created elsewhere for kernel/init
- PageLevel3* globalRoot = root.getOrCreateTable(509);
+ if(phys is null)
+ return false;
- PageLevel2* global_pl3 = globalRoot.getOrCreateTable(indexL4, usermode);
- PageLevel1* global_pl2 = global_pl3.getOrCreateTable(indexL3, usermode);
+ T* segmentParent;
+ root.walk!(mapSegmentHelper)(vAddr, flags, success, segmentParent, phys);
- // Now, global_pl2 is the global root of the gib!!!
+ root.walk!(zeroPageTableHelper)(vAddr, segmentParent);
- // Allocate paging structures
- PageLevel3* pl3 = root.getOrCreateTable(indexL4, usermode);
- pl3.setTable(indexL3, cast(ubyte*)global_pl3.entries[indexL3].location(), usermode);
- }
- else {
- PageLevel3* pl3 = root.getOrCreateTable(indexL4, usermode);
- PageLevel2* pl2 = pl3.getOrCreateTable(indexL3, usermode);
- }
+ static if(T.level != 1){
+ // 'map' the segment into the Global Space
+ if(success && global){
+ PageLevel!(T.level -1)* globalSegmentParent;
+ success = false;
- // XXX: Check for errors, maybe handle flags?!
- // XXX: return false if it is already there
- return true;
- }
-
- // XXX support multiple sizes
- bool closeGib(ubyte* location) {
- // Find page translation
- ulong indexL4, indexL3, indexL2, indexL1;
- translateAddress(location, indexL1, indexL2, indexL3, indexL4);
+ root.walk!(mapSegmentHelper)(getGlobalAddress(vAddr), flags, success, globalSegmentParent, phys);
+ }
+ }
- PageLevel3* pl3 = root.getTable(indexL4);
- if (pl3 is null) {
- return false;
+ return success;
}
-
- pl3.setTable(indexL3, null, false);
- return true;
}
+ template mapSegmentHelper(U, T){
+ bool mapSegmentHelper(T table, uint idx, ref AccessMode flags, ref bool success, ref U segmentParent, ref PhysicalAddress phys){
+ static if(is(T == U)){
+ if(table.entries[idx].present)
+ return false;
- // OLD
- // Return an address to a new gib (kernel)
- ulong nextGib = (256 * 512);
- const ulong MAX_GIB = (512 * 512);
- const ulong GIB_SIZE = (512 * 512 * PAGESIZE);
+ table.entries[idx].pml = cast(ulong)phys;
+ table.entries[idx].setMode(AccessMode.Segment | flags);
- ubyte* gibAddress(uint gibIndex) {
- // Find initial address of gib
- ubyte* gibAddr = cast(ubyte*)0x0;
- gibAddr += (GIB_SIZE * cast(ulong)gibIndex);
+ success = true;
+ return false;
+ }else{
+ static if(T.level != 1){
+ auto intermediate = table.getOrCreateTable(idx, true);
- // Make Canonical
- if (cast(ulong)gibAddr >= 0x800000000000UL) {
- gibAddr = cast(ubyte*)(cast(ulong)gibAddr | 0xffff000000000000UL);
- }
+ if(intermediate is null)
+ return false;
- return gibAddr;
+ return true;
+ }else{
+ // will nevar happen
+ return false;
+ }
+ }
+ }
}
- bool openGib(ubyte* location, uint flags) {
- // Find page translation
- ulong indexL4, indexL3, indexL2, indexL1;
- translateAddress(location, indexL1, indexL2, indexL3, indexL4);
+ bool zeroPageTableHelper(U, T)(T table, uint idx, ref U segmentParent){
+ static if(is(T == U)){
+ static if(U.level > 1){
+ auto zeroTarget = table.getTable(idx);
- bool usermode = (flags & AccessMode.User) != 0;
- PageLevel3* pl3 = root.getOrCreateTable(indexL4, usermode);
+ if(zeroTarget !is null)
+ *zeroTarget = typeof(*zeroTarget).init;
+ }else{
+ // only matters if we allow 4k segment
+ }
- pl3.setTable(indexL3, location, usermode);
+ return false;
+ }else{
+ static if(T.level != 1){
+ auto intermediate = table.getOrCreateTable(idx, true);
- return true;
+ if(intermediate is null)
+ return false;
+ }
+ return true;
+ }
}
- ErrorVal mapRegion(void* gib, void* physAddr, ulong regionLength) {
- mapRegion(null, physAddr, regionLength, gib, true);
- return ErrorVal.Success;
+ // XXX support multiple sizes
+ bool closeGib(ubyte* location) {
+ return true;
}
- // Using heapAddress, this will add a region to the kernel space
- // It returns the virtual address to this region.
- synchronized void* mapRegion(void* physAddr, ulong regionLength) {
- // Sanitize inputs
-
- // physAddr should be floored to the page boundary
- // regionLength should be ceilinged to the page boundary
- pagingLock.lock();
- ulong curPhysAddr = cast(ulong)physAddr;
- ulong diff = curPhysAddr % PAGESIZE;
-
- regionLength += diff;
- curPhysAddr -= diff;
- // Set the new starting address
- physAddr = cast(void*)curPhysAddr;
+ // --- Making Specific Physical Addresses Available ---
- // Get the end address
- curPhysAddr += regionLength;
-
- // Align the end address
- if ((curPhysAddr % PAGESIZE) > 0)
- {
- curPhysAddr += PAGESIZE - (curPhysAddr % PAGESIZE);
- }
+ // Using heapAddress, this will add a region to the kernel space
+ // It returns the virtual address to this region. Use sparingly
+ ubyte[] mapRegion(PhysicalAddress physAddr, ulong regionLength) {
- // Define the end address
- void* endAddr = cast(void*)curPhysAddr;
+ heapLock.lock();
// This region will be located at the current heapAddress
- void* location = heapAddress;
+ ubyte* location = heapAddress;
- if (kernelMapped) {
- doHeapMap(physAddr, endAddr);
- }
- else {
- heapMap!(true)(physAddr, endAddr);
+ ubyte[] result = mapRegion(location, physAddr, regionLength);
+
+ if(result !is null){
+ heapAddress = result[$..$].ptr;
}
- // Return the position of this region
- pagingLock.unlock();
- return location + diff;
+ heapLock.unlock();
+
+ return result;
}
- synchronized ulong mapRegion(PageLevel4* rootTable, void* physAddr, ulong regionLength, void* virtAddr = null, bool writeable = false) {
- if (virtAddr is null) {
- virtAddr = physAddr;
- }
- // Sanitize inputs
+ synchronized ubyte[] mapRegion(ubyte* virtAddr, PhysicalAddress physAddr, ulong regionLength) {
+ assert((cast(ulong)virtAddr % PAGESIZE) == 0);
- pagingLock.lock();
// physAddr should be floored to the page boundary
// regionLength should be ceilinged to the page boundary
- ulong curPhysAddr = cast(ulong)physAddr;
- regionLength += (curPhysAddr % PAGESIZE);
- curPhysAddr -= (curPhysAddr % PAGESIZE);
-
- // Set the new starting address
- physAddr = cast(void*)curPhysAddr;
-
- // Get the end address
- curPhysAddr += regionLength;
+ ulong diff = cast(ulong)physAddr % PAGESIZE;
+ regionLength += diff;
+ physAddr = physAddr - diff;
// Align the end address
- if ((curPhysAddr % PAGESIZE) > 0) {
- curPhysAddr += PAGESIZE - (curPhysAddr % PAGESIZE);
+ if ((regionLength % PAGESIZE) > 0) {
+ regionLength += PAGESIZE - (regionLength % PAGESIZE);
}
// Define the end address
- void* endAddr = cast(void*)curPhysAddr;
-
- heapMap!(false, false)(physAddr, endAddr, virtAddr, writeable);
- pagingLock.unlock();
+ ubyte* endAddr = virtAddr + regionLength;
- return regionLength;
- }
+ bool failed;
+ PhysicalAddress pAddr = cast(PhysicalAddress)physAddr;
+ root.traverse!(preorderMapPhysicalAddressHelper, noop)(cast(ulong)virtAddr, cast(ulong)endAddr, pAddr, failed);
- PageLevel4* kernelPageTable() {
- return cast(PageLevel4*)0xfffffffffffff000;
+ if(failed){
+ return null;
+ }else{
+ return (virtAddr)[diff..regionLength];
+ }
}
-private:
-
-
-// -- Flags -- //
-
-
- bool systemMapped;
- bool kernelMapped;
-
-
-// -- Positions -- //
-
-
- void* systemAddress;
- void* kernelAddress;
- void* heapAddress;
-
-
-// -- Main Page Table -- //
-
-
- PageLevel4* root;
- void* rootPhysical;
-
-
-// -- Mapping Functions -- //
-
- template heapMap(bool initialMapping = false, bool kernelLevel = true) {
- void heapMap(void* physAddr, void* endAddr, void* virtAddr = heapAddress, bool writeable = true) {
+ template preorderMapPhysicalAddressHelper(T){
+ TraversalDirective preorderMapPhysicalAddressHelper(T table, uint idx, uint startIdx, uint endIdx, ref PhysicalAddress physAddr, ref bool failed){
+ static if(T.level != 1){
+ auto next = table.getOrCreateTable(idx, true);
- // Do the mapping
- PageLevel3* pl3;
- PageLevel2* pl2;
- PageLevel1* pl1;
- ulong indexL1, indexL2, indexL3, indexL4;
-
- void* startAddr = physAddr;
-
- // Find the initial page
- translateAddress(virtAddr, indexL1, indexL2, indexL3, indexL4);
-
- // From there, map the region
- ulong done = 0;
- for ( ; indexL4 < 512 && physAddr < endAddr ; indexL4++ )
- {
- // get the L3 table
- static if (initialMapping) {
- if (root.entries[indexL4].present) {
- pl3 = cast(PageLevel3*)(root.entries[indexL4].address << 12);
- }
- else {
- pl3 = cast(PageLevel3*)PageAllocator.allocPage();
- *pl3 = PageLevel3.init;
- root.entries[indexL4].pml = cast(ulong)pl3;
- root.entries[indexL4].present = 1;
- root.entries[indexL4].rw = 1;
- static if (!kernelLevel) {
- root.entries[indexL4].us = 1;
- }
- }
- }
- else {
- pl3 = root.getOrCreateTable(indexL4, !kernelLevel);
- //static if (!kernelLevel) { kprintfln!("pl3 {}")(indexL4); }
+ if(next is null){
+ failed = true;
+ return TraversalDirective.Stop;
}
- for ( ; indexL3 < 512 ; indexL3++ )
- {
- // get the L2 table
- static if (initialMapping) {
- if (pl3.entries[indexL3].present) {
- pl2 = cast(PageLevel2*)(pl3.entries[indexL3].address << 12);
- }
- else {
- pl2 = cast(PageLevel2*)PageAllocator.allocPage();
- *pl2 = PageLevel2.init;
- pl3.entries[indexL3].pml = cast(ulong)pl2;
- pl3.entries[indexL3].present = 1;
- pl3.entries[indexL3].rw = 1;
- static if (!kernelLevel) {
- pl3.entries[indexL3].us = 1;
- }
- }
- }
- else {
- pl2 = pl3.getOrCreateTable(indexL3, !kernelLevel);
-// static if (!kernelLevel) { kprintfln!("pl2 {}")(indexL3); }
- }
+ return TraversalDirective.Descend;
+ }else{
+ table.entries[idx].pml = cast(ulong)physAddr;
+ table.entries[idx].pat = 1;
+ table.entries[idx].setMode(AccessMode.User|AccessMode.Writable|AccessMode.Executable);
- for ( ; indexL2 < 512 ; indexL2++ )
- {
- // get the L1 table
- static if (initialMapping) {
- if (pl2.entries[indexL2].present) {
- pl1 = cast(PageLevel1*)(pl2.entries[indexL2].address << 12);
- }
- else {
- pl1 = cast(PageLevel1*)PageAllocator.allocPage();
- *pl1 = PageLevel1.init;
- pl2.entries[indexL2].pml = cast(ulong)pl1;
- pl2.entries[indexL2].present = 1;
- pl2.entries[indexL2].rw = 1;
- static if (!kernelLevel) {
- pl2.entries[indexL2].us = 1;
- }
- }
- }
- else {
- //static if (!kernelLevel) { kprintfln!("attempting pl1 {}")(indexL2); }
- pl1 = pl2.getOrCreateTable(indexL2, !kernelLevel);
- //static if (!kernelLevel) { kprintfln!("pl1 {}")(indexL2); }
- }
+ physAddr += PAGESIZE;
- for ( ; indexL1 < 512 ; indexL1++ )
- {
- // set the address
- if (pl1.entries[indexL1].present) {
- // Page already allocated
- // XXX: Fail
- }
-
- pl1.entries[indexL1].pml = cast(ulong)physAddr;
-
- pl1.entries[indexL1].present = 1;
- pl1.entries[indexL1].rw = writeable;
- pl1.entries[indexL1].pat = 1;
- static if (!kernelLevel) {
- pl1.entries[indexL1].us = 1;
- }
-
- physAddr += PAGESIZE;
- done += PAGESIZE;
-
- if (physAddr >= endAddr)
- {
- indexL2 = 512;
- indexL3 = 512;
- break;
- }
- }
-
- indexL1 = 0;
- }
-
- indexL2 = 0;
- }
-
- indexL3 = 0;
- }
-
- if (indexL4 >= 512)
- {
- // we have depleted our table!
- assert(false, "Virtual Memory depleted");
- }
-
- // Recalculate the region length
- ulong regionLength = cast(ulong)endAddr - cast(ulong)startAddr;
-
- // Relocate heap address
- static if (kernelLevel) {
- heapAddress += regionLength;
+ return TraversalDirective.Skip;
}
}
}
- alias heapMap!(false) doHeapMap;
+ const auto PAGESIZE = 4096;
+
+private:
+ // XXX: should be an array, so we can check for overflow
+ ubyte* heapAddress;
+ Mutex heapLock;
+ // This is the physical address for the page table
+ PhysicalAddress rootPhysical;
}
6 kernel/arch/x86_64/core/tss.d
View
@@ -46,8 +46,10 @@ static:
// To reset the TSS, you will need to reset the Segment Type to
// AvailableTSS.
ErrorVal install() {
- TaskStateSegment* tss = cast(TaskStateSegment*)PageAllocator.allocPage();
- tss = cast(TaskStateSegment*)Paging.mapRegion(cast(ubyte*)tss, VirtualMemory.pagesize);
+ PhysicalAddress tssPage = PageAllocator.allocPage();
+
+ TaskStateSegment* tss = cast(TaskStateSegment*)tssPage;
+ tss = cast(TaskStateSegment*)Paging.mapRegion(tssPage, VirtualMemory.pagesize);
*tss = TaskStateSegment.init;
segments[Cpu.identifier] = tss;
GDT.tables[Cpu.identifier].setSystemSegment((tssBase >> 3), 0x67, (cast(ulong)tss), SystemSegmentType.AvailableTSS, 0, true, false, false);