[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 4/4] kernel2: GDT für AMD64



 + amd64/gdt.c: ordentliche GDT angelegt und init-Funktionen implementiert
 * amd64/loader/startup.S: die SYSCALL- und SYSRET-Instruktion geht von einer
   bestimmten Reihenfolge der Segmente aus, deshalb sollte das
   64-Bit-Code-Segment auf der 0x18 hinter dem Data-Segment landen.
 - amd64/header.S: das Laden der GDT entfernt, da das in der init-Funktion
   geschieht
 * amd64/smp/trampoline.S: das richtige Segment nach CS laden

Signed-off-by: Andreas Freimuth <m.nemo@xxxxxxx>
---
 src/kernel2/src/arch/amd64/gdt.c            | 134 ++++++++++++++++++++++++++++
 src/kernel2/src/arch/amd64/header.S         |  29 ------
 src/kernel2/src/arch/amd64/loader/startup.S |  42 +++------
 src/kernel2/src/arch/amd64/smp/trampoline.S |  32 +------
 4 files changed, 147 insertions(+), 90 deletions(-)
 create mode 100644 src/kernel2/src/arch/amd64/gdt.c

diff --git a/src/kernel2/src/arch/amd64/gdt.c b/src/kernel2/src/arch/amd64/gdt.c
new file mode 100644
index 0000000..5e7bd60
--- /dev/null
+++ b/src/kernel2/src/arch/amd64/gdt.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2012 The týndur Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * 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 COPYRIGHT HOLDERS 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 <stdint.h>
+
+#include "gdt.h"
+
+#define SEGMENT_DATA    0x0000120000000000ULL
+#define SEGMENT_CODE    0x0000180000000000ULL
+#define SEGMENT_TSS     0x0000090000000000ULL
+#define SEGMENT_USER    0x0000600000000000ULL
+#define SEGMENT_PRESENT 0x0000800000000000ULL
+#define SEGMENT_LM      0x0020000000000000ULL
+#define SEGMENT_32BIT   0x0040000000000000ULL
+#define SEGMENT_GRAN    0x0080000000000000ULL
+#define SEGMENT_BASE(x)   (((x & 0xffffULL) << 16) | ((x & 0xff0000ULL) << 16) | ((x & 0xff000000ULL) << 32))
+#define SEGMENT_BASE64(x) ((x >> 32) & 0xffffffffULL)
+#define SEGMENT_SIZE(x)   ((x & 0xffffULL) | ((x & 0xf0000ULL) << 32))
+
+typedef union Descriptor {
+    struct { /// Segment descriptor
+        uint16_t size1;
+        uint16_t base1;
+        uint8_t base2;
+        uint8_t type:4;
+        uint8_t seg:1;
+        uint8_t dpl:2;
+        uint8_t present:1;
+        uint8_t size2:4;
+        uint8_t avl:1;
+        uint8_t longMode:1;
+        uint8_t operandSize:1;
+        uint8_t granularity:1;
+        uint8_t base3;
+    } __attribute__((__packed__)) segment;
+
+    struct { /// TSS descriptor
+        uint16_t limit1;
+        uint16_t base1;
+        uint8_t base2;
+        uint8_t type:4;
+        uint8_t seg:1;
+        uint8_t dpl:2;
+        uint8_t present:1;
+        uint8_t limit2;
+        uint8_t base3;
+    } __attribute__((__packed__)) tss;
+
+    struct { /// Callgate descriptor
+        uint16_t offset1;
+        uint16_t selector;
+        uint8_t count:5;
+        uint8_t reserved:3;
+        uint8_t type:4;
+        uint8_t seg:1;
+        uint8_t dpl:2;
+        uint8_t present:1;
+        uint16_t offset2;
+    } __attribute__((__packed__)) callgate;
+
+    uint64_t u64;
+
+} Descriptor;
+
+struct {
+    uint16_t limit;
+    uintptr_t base;
+} gdtr;
+
+/// Global Descritpor Table
+static Descriptor gdt[9] = {
+    // NULL Deskriptor
+    { .u64 = 0 },
+
+    // Kernel Code-Segment 32Bit
+    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
+            SEGMENT_CODE | SEGMENT_32BIT | SEGMENT_PRESENT },
+
+    // Kernel Data-Segment
+    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
+            SEGMENT_DATA | SEGMENT_32BIT | SEGMENT_PRESENT },
+
+    // Kernel Code-Segment 64Bit
+    { .u64 = SEGMENT_CODE | SEGMENT_LM | SEGMENT_PRESENT },
+
+    // User Code-Segment 32Bit
+    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
+            SEGMENT_CODE | SEGMENT_32BIT | SEGMENT_USER | SEGMENT_PRESENT },
+
+    // User Data-Segment
+    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
+            SEGMENT_DATA | SEGMENT_32BIT | SEGMENT_USER | SEGMENT_PRESENT },
+
+    // User Code-Segment 64Bit
+    { .u64 = SEGMENT_CODE | SEGMENT_LM | SEGMENT_USER | SEGMENT_PRESENT },
+
+    // Task State - Segment
+    { .u64 = SEGMENT_BASE((uintptr_t) 0 /*TODO*/) |
+            SEGMENT_SIZE(0x67) | SEGMENT_TSS | SEGMENT_PRESENT },
+    { .u64 = SEGMENT_BASE64((uintptr_t) 0 /*TODO*/) }
+};
+
+void gdt_init()
+{
+    gdtr.base = (uintptr_t) gdt;
+    gdtr.limit = sizeof(gdt) - 1;
+}
+
+void gdt_init_local()
+{
+    asm volatile ("lgdt %0\n" : : "m"(gdtr));
+}
diff --git a/src/kernel2/src/arch/amd64/header.S b/src/kernel2/src/arch/amd64/header.S
index e272487..9dc6240 100644
--- a/src/kernel2/src/arch/amd64/header.S
+++ b/src/kernel2/src/arch/amd64/header.S
@@ -40,7 +40,6 @@
 
 .section .text
 _start:
-    lgdt gdtr64
 	// Stack initalisieren
 	lea kernelstack, %rsp
 
@@ -67,31 +66,3 @@ _start:
     .space  16384
 kernelstack:
 
-.section .data
-    gdt64:
-        // Der Nulldeskriptor
-        .word 0x0000
-        .word 0x0000
-        .word 0x0000
-        .word 0x0000
-
-        // Der Code-Deskriptor
-        .word 0x0000
-        .word 0x0000
-        .word 0x9800
-        .word 0x0020
-
-        // Der Daten-Deskriptor:
-        .word 0x0000
-        .word 0x0000
-        .word 0x9000
-        .word 0x0000
-
-    // Struktur um die GDT laden zu koennen
-    .globl gdtr64
-    gdtr64:
-        // Wir haben 3 Eintraege
-        .word 3 * 8
-        .quad gdt64
-
-
diff --git a/src/kernel2/src/arch/amd64/loader/startup.S b/src/kernel2/src/arch/amd64/loader/startup.S
index 6a620de..c08d067 100644
--- a/src/kernel2/src/arch/amd64/loader/startup.S
+++ b/src/kernel2/src/arch/amd64/loader/startup.S
@@ -151,8 +151,8 @@
         movl %eax, %cr0
         
         // Die neue GDT laden
-        lgdt gdtr64
-        jmp  $0x8, $longmode
+        lgdt init_gdtr
+        jmp  $0x18, $longmode
 
     .code64
     longmode:
@@ -226,13 +226,13 @@
     stack_space:
 
 .section .data
-.code16
-    // Die GDT besteht nur aus 3 Deskriptoren: Null, Code und Daten
-    gdt32:
+    // Die GDT besteht nur aus 4 Deskriptoren: Null, 32-Bit-Code, Daten und
+    // 64-Bit-Code
+    init_gdt:
         // Null-Deskriptor
         .quad 0
 
-        // Code-Deskriptor
+        // 32-Bit-Code-Deskriptor
         .word 0xFFFF
         .word 0x0000
         .byte 0x00
@@ -247,38 +247,16 @@
         .byte 0x92
         .byte 0xCF
         .byte 0x00
-        
-    gdtr32:
-        .word 3 * 8
-        .int gdt32
-
-.code32
-    // Die GDT besteht nur aus 3 Deskriptoren: Null, Code und Daten
-    .globl gdt64
-    gdt64:
-        // Der Nulldeskriptor
-        .quad 0
 
-        // Der Code-Deskriptor
+        // 64-Bit-Code-Deskriptor
         .int 0
         .byte 0
         .byte 0x98
         .byte 0x20
         .byte 0
 
-        // Der Daten-Deskriptor:
-        .int 0
-        .byte 0
-        .byte 0x92
-        .byte 0
-        .byte 0
-
-    // Struktur um die GDT laden zu koennen
-    .globl gdtr64
-    gdtr64:
-        // Wir haben 3 Eintraege
-        .word 3 * 8
-        .quad gdt64
-
+    init_gdtr:
+        .word 4 * 8
+        .int init_gdt
 
 
diff --git a/src/kernel2/src/arch/amd64/smp/trampoline.S b/src/kernel2/src/arch/amd64/smp/trampoline.S
index 0edb775..2446982 100644
--- a/src/kernel2/src/arch/amd64/smp/trampoline.S
+++ b/src/kernel2/src/arch/amd64/smp/trampoline.S
@@ -76,9 +76,9 @@ smp_entry_lock_loop:
     movl %eax, %cr0
         
     // Die neue GDT laden
-    .extern gdtr64
-    lgdt gdtr64
-    jmp  $0x8, $smp_entry_longmode
+    .extern gdtr
+    lgdt gdtr
+    jmp  $0x18, $smp_entry_longmode
 
 .code64
 smp_entry_longmode:
@@ -115,32 +115,6 @@ smp_entry_longmode:
     // Geschieht nie
     hlt
 
-/*.section .data
-    gdt64:
-        // Der Nulldeskriptor
-        .word 0x0000
-        .word 0x0000
-        .word 0x0000
-        .word 0x0000
-
-        // Der Code-Deskriptor
-        .word 0x0000
-        .word 0x0000
-        .word 0x9800
-        .word 0x0020
-
-        // Der Daten-Deskriptor:
-        .word 0x0000
-        .word 0x0000
-        .word 0x9000
-        .word 0x0000
-
-    // Struktur um die GDT laden zu koennen
-    gdtr64:
-        // Wir haben 3 Eintraege
-        .word 3 * 8
-        .quad gdt64
-*/
 .section .bss
 
 // Wird fuer den Stack waehrend der SMP-Initialisierung benutzt, solange noch
-- 
1.7.11.7