summaryrefslogtreecommitdiff
path: root/kernel/gdt.c
diff options
context:
space:
mode:
authorMiguel <m.i@gmx.at>2018-08-21 19:42:33 +0200
committerMiguel <m.i@gmx.at>2018-08-21 19:42:33 +0200
commit72c6e9763ca61bc9d7de5f7080ee1c8a1c7c1562 (patch)
tree839bce03c26e96f1137d4b4d3550ad3e909d351c /kernel/gdt.c
parent6c926175afbf1f9ec2715fb007acc28588b36c4a (diff)
cleaning up a bit
Diffstat (limited to 'kernel/gdt.c')
-rw-r--r--kernel/gdt.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/kernel/gdt.c b/kernel/gdt.c
new file mode 100644
index 0000000..06a0949
--- /dev/null
+++ b/kernel/gdt.c
@@ -0,0 +1,136 @@
+// http://wiki.osdev.org/GDT_Tutorial
+#include "lib/logger/log.h"
+#include "usermode.h"
+#define FOOLOS_MODULE_NAME "GDT"
+
+#include <stdint.h>
+#define GDT_SIZE 6
+
+extern sys_tss;
+
+typedef struct GDT_struct
+{
+ uint32_t base;
+ uint32_t limit;
+ uint32_t type;
+
+}GDT;
+
+//alternative
+struct gdt_entry_bits
+{
+ unsigned int limit_low:16;
+ unsigned int base_low : 24;
+ //attribute byte split into bitfields
+ unsigned int accessed :1;
+ unsigned int read_write :1; //readable for code, writable for data
+ unsigned int conforming_expand_down :1; //conforming for code, expand down for data
+ unsigned int code :1; //1 for code, 0 for data
+ unsigned int always_1 :1; //should be 1 for everything but TSS and LDT
+ unsigned int DPL :2; //priveledge level
+ unsigned int present :1;
+ //and now into granularity
+ unsigned int limit_high :4;
+ unsigned int available :1;
+ unsigned int always_0 :1; //should always be 0
+ unsigned int big :1; //32bit opcodes for code, uint32_t stack for data
+ unsigned int gran :1; //1 to use 4k page addressing, 0 for byte addressing
+ unsigned int base_high :8;
+} __packed; //or __attribute__((packed))
+
+
+static GDT myGDT[GDT_SIZE];
+static uint8_t gdt_struct[GDT_SIZE*8];
+
+/**
+ * \param target A pointer to the 8-byte GDT entry
+ * \param source An arbitrary structure describing the GDT entry
+ */
+void encodeGdtEntry(uint8_t *target, GDT source)
+{
+ // Check the limit to make sure that it can be encoded
+ if ((source.limit > 65536) && (source.limit & 0xFFF) != 0xFFF)
+ {
+ panic(FOOLOS_MODULE_NAME,"trying to set an invalid GDT source.limit!");
+ }
+ if (source.limit > 65536) {
+ // Adjust granularity if required
+ source.limit = source.limit >> 12;
+ target[6] = 0xC0;
+ } else {
+ target[6] = 0x40;
+ }
+
+ // Encode the limit
+ target[0] = source.limit & 0xFF;
+ target[1] = (source.limit >> 8) & 0xFF;
+
+ // Encode the base
+ target[2] = source.base & 0xFF;
+ target[3] = (source.base >> 8) & 0xFF;
+ target[4] = (source.base >> 16) & 0xFF;
+ target[7] = (source.base >> 24) & 0xFF;
+
+ target[5] = source.type;
+ target[6] |= (source.limit >> 16) & 0xF;
+
+ // And... Type
+
+ /*
+
+0 1 dw 0xffff ;limit
+2 3 dw 0x0 ;base
+4 db 0x0 ;base
+5 db 10011010b ;flags
+6 db 11001111b ;flags & seg.limit
+7 db 0x0 ;base
+ */
+
+
+}
+
+void gdt_init()
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"setting up Global Descriptor Table");
+ //selector 0x0
+ myGDT[0].base=0;
+ myGDT[0].limit=0;
+ myGDT[0].type=0;
+
+ //selector 0x8 code
+ myGDT[1].base=0;
+ myGDT[1].limit=0xffffffff;
+ myGDT[1].type=0x9a;
+
+ //selector 0x10 data
+ myGDT[2].base=0;
+ myGDT[2].limit=0xffffffff;
+ myGDT[2].type=0x92;
+
+ //selector 0x18 code user
+ myGDT[3].base=0;
+ myGDT[3].limit=0xffffffff;
+ myGDT[3].type=0xFa;
+
+ //selector 0x20 data user
+ myGDT[4].base=0;
+ myGDT[4].limit=0xffffffff;
+ myGDT[4].type=0xF2;
+
+ //TSS 0x28
+ myGDT[5].base=&sys_tss; //tss start?
+ myGDT[5].limit=sizeof(tss_struct); //tss end?
+ myGDT[5].type=0x89;
+
+
+ // transcript to format the processor wants
+ for(int i=0;i<GDT_SIZE;i++)
+ encodeGdtEntry(&gdt_struct[8*i],myGDT[i]);
+
+
+ // updat
+ install_tss();
+ setup_gdt(&gdt_struct[0],8*GDT_SIZE);
+
+
+}