[freenos] r399 committed - Added functions for managing per-CPU Global Descriptor Table.

  • From: freenos@xxxxxxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Mon, 18 Oct 2010 23:47:36 +0000

Revision: 399
Author: nieklinnenbank
Date: Mon Oct 18 16:41:04 2010
Log: Added functions for managing per-CPU Global Descriptor Table.

http://code.google.com/p/freenos/source/detail?r=399

Added:
 /branches/scratch/include/x86/gdt.h
 /branches/scratch/system/x86/pc/gdt.c
 /branches/scratch/system/x86/pc/gdt_load.S

=======================================
--- /dev/null
+++ /branches/scratch/include/x86/gdt.h Mon Oct 18 16:41:04 2010
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDT_H
+#define __GDT_H
+
+#include "types.h"
+#include "macro.h"
+
+#define GDT_TYPE_CODE0 0x9a
+#define GDT_TYPE_CODE3 0xfa
+#define GDT_TYPE_DATA0 0x92
+#define GDT_TYPE_DATA3 0xf2
+#define GDT_TYPE_TSS0  0x89
+
+#define GDT_MODE_32 (1 << 2)
+#define GDT_GRAN_4K (1 << 3)
+
+typedef struct gdt_entry
+{
+    u16 limit_low;
+    u16 base_low;
+    u8  base_high1;
+    u8  type;
+    u8  limit_high:4;
+    u8  flags:4;
+    u8  base_high2;
+}
+PACKED gdt_entry_t;
+
+typedef struct gdt
+{
+    gdt_entry_t entries[6];
+}
+PACKED gdt_t;
+
+typedef struct gdt_ptr
+{
+    u16 limit;
+    u32 base;
+}
+PACKED gdt_ptr_t;
+
+extern void gdt_init(void);
+extern void gdt_load(gdt_ptr_t *ptr);
+extern void gdt_set_entry(uint index, addr_t base, uint limit, uint type);
+
+#endif /* __GDT_H */
=======================================
--- /dev/null
+++ /branches/scratch/system/x86/pc/gdt.c       Mon Oct 18 16:41:04 2010
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <FreeNOS/gdt.h>
+#include <FreeNOS/tss.h>
+#include <FreeNOS/smp.h>
+#include <FreeNOS/cpu.h>
+#include <FreeNOS/virt_memory.h>
+
+static gdt_t     ALIGN(PAGE_SIZE) gdt[SMP_MAX];
+static gdt_ptr_t ALIGN(PAGE_SIZE) gdt_ptr[SMP_MAX];
+
+void gdt_init(void)
+{
+    gdt_ptr_t *ptr = &gdt_ptr[smp_id()];
+
+    /* Setup GDT entries. */
+    gdt_set_entry(0, 0, 0, 0);
+    gdt_set_entry(1, 0, 0xffffffff, GDT_TYPE_CODE0);
+    gdt_set_entry(2, 0, 0xffffffff, GDT_TYPE_DATA0);
+    gdt_set_entry(3, 0, 0xffffffff, GDT_TYPE_CODE3);
+    gdt_set_entry(4, 0, 0xffffffff, GDT_TYPE_DATA3);
+    gdt_set_entry(5, (addr_t)tss_get(),
+                     sizeof(tss_t), GDT_TYPE_TSS0);
+
+    /* Set GDT pointer. */
+    ptr->base  = (addr_t) &gdt[smp_id()];
+    ptr->limit = sizeof(gdt_t);
+
+    /* Load the GDT. */
+    gdt_load(&gdt_ptr[smp_id()]);
+}
+
+void gdt_set_entry(uint index, addr_t base, uint limit, uint type)
+{
+    gdt_entry_t *g = &(gdt[smp_id()].entries[index]);
+
+    g->limit_low  =  (limit / 4096) & 0xffff;
+    g->limit_high = ((limit / 4096) >> 16) & 0xf;
+    g->base_low   =   base & 0xffff;
+    g->base_high1 =  (base >> 16) & 0xff;
+    g->base_high2 =  (base >> 24) & 0xff;
+    g->type       =   type;
+
+    if (type != 0)
+       g->flags  =   GDT_GRAN_4K | GDT_MODE_32;
+}
=======================================
--- /dev/null
+++ /branches/scratch/system/x86/pc/gdt_load.S  Mon Oct 18 16:41:04 2010
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <FreeNOS/virt_memory.h>
+#include <FreeNOS/cpu.h>
+
+.global gdt_load
+
+.section ".text"
+.code32
+
+/*
+ * gdt_load(gdt_ptr_t *ptr)
+ */
+gdt_load:
+
+    /* Disable interrupts. */
+    cli
+
+    /* Load GDT. */
+    movl 4(%esp), %eax
+    lgdtl (%eax)
+
+    /* Setup segments. */
+    movl $KERN_DS_SEL, %edx
+    movl %edx, %ds
+    movl %edx, %es
+    movl %edx, %fs
+    movl %edx, %gs
+
+    /* Reload CS. */
+    ljmpl $KERN_CS_SEL, $gdt_load2
+
+gdt_load2:
+    ret

Other related posts:

  • » [freenos] r399 committed - Added functions for managing per-CPU Global Descriptor Table. - freenos