From 41bca35c1e5bc493b96ee50810eaadba40326fb6 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Wed, 1 Apr 2015 11:46:29 -0300 Subject: [PATCH] x86: Initialize Global Descriptor Table This patch adds code to initialize the Global Descriptor Table. For simplicity, the memory is organized following the flat model. Thus, memory appears to Contiki as a single, continuous address space. Code, data, and stack are all contained in this address space (so called linear address space). The macros to manipulate bits from segment descriptor and the set_descriptor() helper are based on the ones described in [1]. [1] http://wiki.osdev.org/GDT_Tutorial --- cpu/x86/Makefile.x86 | 2 +- cpu/x86/gdt.c | 136 +++++++++++++++++++++++++++++++++++++++++++ cpu/x86/gdt.h | 36 ++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 cpu/x86/gdt.c create mode 100644 cpu/x86/gdt.h diff --git a/cpu/x86/Makefile.x86 b/cpu/x86/Makefile.x86 index 899b78bd3..b861117a7 100644 --- a/cpu/x86/Makefile.x86 +++ b/cpu/x86/Makefile.x86 @@ -1,6 +1,6 @@ CONTIKI_CPU_DIRS = . -CONTIKI_SOURCEFILES += mtarch.c +CONTIKI_SOURCEFILES += mtarch.c gdt.c ### Compiler definitions CC = gcc diff --git a/cpu/x86/gdt.c b/cpu/x86/gdt.c new file mode 100644 index 000000000..1ba38a724 --- /dev/null +++ b/cpu/x86/gdt.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2015, Intel Corporation. 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. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 HOLDER 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 + +#define NUM_DESC 3 + +/* Each define here is for a specific flag in the descriptor. Refer to Intel + * Combined Manual (Intel 64 and IA-32 Architectures Software Developer's + * Manual), Vol. 3, Section 3.4.5 for a description of each flag. + */ +#define SEG_DESCTYPE(x) ((x) << 0x04) /* Descriptor type (0 for system, 1 for code/data) */ +#define SEG_PRES(x) ((x) << 0x07) /* Present */ +#define SEG_SAVL(x) ((x) << 0x0C) /* Available for system use */ +#define SEG_LONG(x) ((x) << 0x0D) /* Long mode */ +#define SEG_SIZE(x) ((x) << 0x0E) /* Size (0 for 16-bit, 1 for 32) */ +#define SEG_GRAN(x) ((x) << 0x0F) /* Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB) */ +#define SEG_PRIV(x) (((x) & 0x03) << 0x05) /* Set privilege level (0 - 3) */ + +#define SEG_DATA_RDWR 0x02 /* Read/Write */ +#define SEG_CODE_EXRD 0x0A /* Execute/Read */ + +#define GDT_CODE_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ + SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ + SEG_PRIV(0) | SEG_CODE_EXRD + +#define GDT_DATA_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ + SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ + SEG_PRIV(0) | SEG_DATA_RDWR + +typedef struct gdtr +{ + uint16_t limit; + uint32_t base; +} __attribute__((packed)) gdtr_t; + +typedef uint64_t segment_desc_t; + +/* From Intel Combined Manual, Vol. 3 , Section 3.5.1: The base addresses of + * the GDT should be aligned on an eight-byte boundary to yield the best + * processor performance. + */ +static segment_desc_t gdt[NUM_DESC] __attribute__ ((aligned (8))); + +static void +set_descriptor(unsigned int index, uint32_t base, uint32_t limit, uint16_t flag) +{ + segment_desc_t descriptor; + + if (index >= NUM_DESC) + return; + + /* Create the high 32 bit segment */ + descriptor = limit & 0x000F0000; /* set limit bits 19:16 */ + descriptor |= (flag << 8) & 0x00F0FF00; /* set type, p, dpl, s, g, d/b, l and avl fields */ + descriptor |= (base >> 16) & 0x000000FF; /* set base bits 23:16 */ + descriptor |= base & 0xFF000000; /* set base bits 31:24 */ + + /* Shift by 32 to allow for low part of segment */ + descriptor <<= 32; + + /* Create the low 32 bit segment */ + descriptor |= base << 16; /* set base bits 15:0 */ + descriptor |= limit & 0x0000FFFF; /* set limit bits 15:0 */ + + /* Save descriptor into gdt */ + gdt[index] = descriptor; +} + + +/* This function initializes the Global Offset Table. For simplicity, the + * memory is organized following the flat model. Thus, memory appears to + * Contiki as a single continuous address space. Code, data, and stack + * are all contained in this address space (so called linear address space). + */ +void +gdt_init(void) +{ + gdtr_t gdtr; + + /* Initialize gdtr structure */ + gdtr.limit = sizeof(segment_desc_t) * NUM_DESC - 1; + gdtr.base = (uint32_t) &gdt; + + /* Initialize descriptors */ + set_descriptor(0, 0, 0, 0); + set_descriptor(1, 0, 0x0FFFFF, GDT_CODE_PL0); + set_descriptor(2, 0, 0x0FFFFF, GDT_DATA_PL0); + + /* Load GDTR register and update segment registers. + * + * In protected mode, segment registers should be loaded according to + * the offset in GDT. So DS, SS, ES, FS and GS registers should be + * loadded with 0x10 while CS with 0x08. CS register cannot be changed + * directly. For that reason, we do a far jump. + */ + __asm__ ("lgdt %0\n\t" + "jmp $0x08, $1f\n\t" + "1:\n\t" + "mov $0x10, %%ax\n\t" + "mov %%ax, %%ds\n\t" + "mov %%ax, %%ss\n\t" + "mov %%ax, %%es\n\t" + "mov %%ax, %%fs\n\t" + "mov %%ax, %%gs\n\t" + : + : "m" (gdtr) + ); +} diff --git a/cpu/x86/gdt.h b/cpu/x86/gdt.h new file mode 100644 index 000000000..3db17f08c --- /dev/null +++ b/cpu/x86/gdt.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015, Intel Corporation. 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. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 HOLDER 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. + */ + +#ifndef GDT_H +#define GDT_H + +void gdt_init(void); + +#endif /* GDT_H */