aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2025-01-02 09:49:33 -0500
committerRaghuram Subramani <raghus2247@gmail.com>2025-01-02 09:49:33 -0500
commit0dde3ff57bbbf90eb7d9ce1b7aff0dd706875653 (patch)
treef6bbec7df77b14a14dda18a2d44e435cbb9dcd31
parent49fa3246c0e19a089ffcebe85b65acdcbb478411 (diff)
kernel: Properly initialize GDT
-rw-r--r--kernel/CMakeLists.txt1
-rw-r--r--kernel/boot/gdt.c21
-rw-r--r--kernel/boot/gdt.s26
-rw-r--r--kernel/boot/init/boot.s2
-rw-r--r--kernel/include/boot/gdt.h20
-rw-r--r--kernel/kernel/kernel.c7
6 files changed, 65 insertions, 12 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index d2a019b..94d0e15 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -4,6 +4,7 @@ project(kernel C ASM)
set(KERNEL_SRC
boot/init/boot.s
boot/gdt.c
+ boot/gdt.s
kernel/kernel.c
kernel/halt.c
diff --git a/kernel/boot/gdt.c b/kernel/boot/gdt.c
index 34bbfe3..4644b3d 100644
--- a/kernel/boot/gdt.c
+++ b/kernel/boot/gdt.c
@@ -18,6 +18,8 @@
#include <stdint.h>
+#include <kernel/io.h>
+
#include <boot/gdt.h>
GDT_entry GDT[] = {
@@ -28,7 +30,22 @@ GDT_entry GDT[] = {
GDT_ENTRY(0, 0xfffff, KERNEL_CODE_SEGMENT_ACCESS_FLAGS, FLAGS),
/* Kernel Mode Data Segment */
- GDT_ENTRY(0, 0xfffff, KERNEL_DATA_SEGMENT_ACCESS_FLAGS, FLAGS)
+ GDT_ENTRY(0, 0xfffff, KERNEL_DATA_SEGMENT_ACCESS_FLAGS, FLAGS),
+
+ /* User Mode Code Segment */
+ GDT_ENTRY(0, 0xfffff, USER_CODE_SEGMENT_ACCESS_FLAGS, FLAGS),
+
+ /* User Mode Data Segment */
+ GDT_ENTRY(0, 0xfffff, USER_DATA_SEGMENT_ACCESS_FLAGS, FLAGS)
+
+ /* TODO: TSS? */
+ /* TODO: LDT? */
};
-GDT_descriptor g_GDT_descriptor = { sizeof(GDT) - 1, GDT };
+GDT_descriptor g_GDT_descriptor = { sizeof(GDT_entry) * 5 - 1, &GDT[0] };
+
+void
+GDT_load(void)
+{
+ _GDT_flush(&g_GDT_descriptor);
+}
diff --git a/kernel/boot/gdt.s b/kernel/boot/gdt.s
new file mode 100644
index 0000000..ee50e4e
--- /dev/null
+++ b/kernel/boot/gdt.s
@@ -0,0 +1,26 @@
+.intel_syntax noprefix
+
+.global _GDT_flush
+.type _GDT_flush, @function
+_GDT_flush:
+ /* First Argument (Pointer to the GDT) */
+ mov eax, [esp + 4]
+
+ /* Load GDT */
+ lgdt [eax]
+
+ /* Offset For Kernel Data Segment (16 bits) */
+ mov eax, 0x10
+
+ /* Set the Data Segment Selectors */
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ /* Set the Code Segment Selector */
+ jmp 0x08:.flush
+
+.flush:
+ ret
diff --git a/kernel/boot/init/boot.s b/kernel/boot/init/boot.s
index 32ebe8f..35a89a2 100644
--- a/kernel/boot/init/boot.s
+++ b/kernel/boot/init/boot.s
@@ -96,8 +96,6 @@ _start:
runtime support to work as well.
*/
- /* TODO: Initialize global descriptor table */
-
/* Call the global constructors. */
call _init
diff --git a/kernel/include/boot/gdt.h b/kernel/include/boot/gdt.h
index b07d64d..7cf7d35 100644
--- a/kernel/include/boot/gdt.h
+++ b/kernel/include/boot/gdt.h
@@ -19,6 +19,8 @@
#ifndef __boot_gdt_h
#define __boot_gdt_h
+#include <stdint.h>
+
/* Access Flags:
* 7 PRESENT
* 6 PRIVILEGE
@@ -38,14 +40,20 @@
#define READABLE_WRITABLE(x) (x << 1)
#define ACCESSED(x) x
-#define KERNEL_CODE_SEGMENT_ACCESS_FLAGS \
- PRESENT(1) | PRIVILEGE(0) | TYPE(1) | EXECUTABLE(1) \
+#define CODE_SEGMENT_ACCESS_FLAGS(privilege) \
+ PRESENT(1) | PRIVILEGE(privilege) | TYPE(1) | EXECUTABLE(1) \
| DIRECTION_CONFORMING(0) | READABLE_WRITABLE(1) | ACCESSED(0)
-#define KERNEL_DATA_SEGMENT_ACCESS_FLAGS \
- PRESENT(1) | PRIVILEGE(0) | TYPE(1) | EXECUTABLE(0) \
+#define DATA_SEGMENT_ACCESS_FLAGS(privilege) \
+ PRESENT(1) | PRIVILEGE(privilege) | TYPE(1) | EXECUTABLE(0) \
| DIRECTION_CONFORMING(0) | READABLE_WRITABLE(1) | ACCESSED(0)
+#define KERNEL_CODE_SEGMENT_ACCESS_FLAGS CODE_SEGMENT_ACCESS_FLAGS(0)
+#define KERNEL_DATA_SEGMENT_ACCESS_FLAGS DATA_SEGMENT_ACCESS_FLAGS(0)
+
+#define USER_CODE_SEGMENT_ACCESS_FLAGS CODE_SEGMENT_ACCESS_FLAGS(3)
+#define USER_DATA_SEGMENT_ACCESS_FLAGS DATA_SEGMENT_ACCESS_FLAGS(3)
+
/* Other Flags:
* 3 GRANULARITY
* 2 SIZE
@@ -92,7 +100,7 @@ typedef struct {
GDT_entry *ptr; /* Address of GDT */
} __attribute__((packed)) GDT_descriptor;
-/* TODO: Implement GDT_load() */
-void __attribute((cdecl)) GDT_load(void);
+extern void _GDT_flush(GDT_descriptor *);
+void GDT_load(void);
#endif
diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c
index 20e5bb4..7deb6ec 100644
--- a/kernel/kernel/kernel.c
+++ b/kernel/kernel/kernel.c
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <boot/gdt.h>
#include <kernel/halt.h>
#include <libk/io.h>
@@ -26,11 +27,13 @@
void
kernel_main(void)
{
- vga_text_buffer_initialize();
- serial_initialize();
+ GDT_load();
printk("Kernel", "Started.");
+ vga_text_buffer_initialize();
+ serial_initialize();
+
// exit();
halt(); /* If exit() fails (on real hardware) */
}