From a495a08cc0aead159328175dac86a083bed7083b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Ortega=20Froysa?= Date: Wed, 4 Apr 2018 17:50:29 +0200 Subject: [PATCH] Loading GDT in C. --- CMakeLists.txt | 2 + src/kernel/arch/x86/boot.s | 17 ++------ src/kernel/arch/x86/gdt.c | 58 ++++++++++++++++++++++++++++ src/kernel/arch/x86/gdt.h | 26 +++++++++++++ src/kernel/arch/x86/gdt.s | 73 +++++++++-------------------------- src/kernel/arch/x86/structs.h | 9 ++++- 6 files changed, 117 insertions(+), 68 deletions(-) create mode 100644 src/kernel/arch/x86/gdt.c create mode 100644 src/kernel/arch/x86/gdt.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f3e31bc..6ec2f32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,8 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "i.86") set(SRCS src/kernel/arch/x86/boot.s ${SRCS} + src/kernel/arch/x86/gdt.s + src/kernel/arch/x86/gdt.c src/kernel/arch/x86/tty.c) set(CMAKE_EXE_LINKER_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/src/kernel/arch/x86/linker.ld -ffreestanding -nostdlib") diff --git a/src/kernel/arch/x86/boot.s b/src/kernel/arch/x86/boot.s index 3b498ed..05d0457 100644 --- a/src/kernel/arch/x86/boot.s +++ b/src/kernel/arch/x86/boot.s @@ -45,8 +45,8 @@ stack_bottom: .skip 16384 # 16 KiB stack_top: -.section .data -.include "gdt.s" +/*.section .data +.include "gdt.s"*/ /* * The linker script specifies the `_start' label as the entry point to the kernel @@ -59,19 +59,10 @@ stack_top: _start: # set the position of `%esp' to the top of the stack mov $stack_top, %esp + mov %esp, %ebp # GDT, paging, and other features -flush_gdt: - cli - lgdt (gdtr) - movw $0x10, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - ljmp $0x08, $flush_end -flush_end: + call gdt_install boot_kernel: # enter high-level kernel (C) diff --git a/src/kernel/arch/x86/gdt.c b/src/kernel/arch/x86/gdt.c new file mode 100644 index 0000000..b850640 --- /dev/null +++ b/src/kernel/arch/x86/gdt.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 Ortega Froysa, Nicolás + * Author: Ortega Froysa, Nicolás + * + * 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 . + */ + +#include "gdt.h" + +/* + * ENTRIES: + * 0 - NULL entry + * 1/2 - kernel entries + * 3/4 - user entries + * 5 - TSS entry + */ +#define GDT_SIZE 3 + +struct segdesc gdt[GDT_SIZE]; +struct segreg gdtr; + +void gdt_entry_set(struct segdesc *entry, uint32_t base, + uint32_t limit, uint8_t access, uint8_t gran) { + // base + entry->base_low = base & 0xFFFF; + entry->base_mid = (base >> 16) & 0xFF; + entry->base_high = (base >> 24) & 0xFF; + + // limit + entry->limit_low = limit & 0xFFFF; + entry->gran = (limit >> 16) & 0x0F; + + // access and granularity flags + entry->gran |= gran & 0xF0; + entry->access = access; +} + +void gdt_install() { + gdtr.base = (uint32_t)gdt; + gdtr.limit = sizeof(gdt)-1; + + gdt_entry_set(&gdt[0], 0, 0, 0, 0); + gdt_entry_set(&gdt[1], 0, 0xFFFFFFFF, 0x9A, 0xCF); + gdt_entry_set(&gdt[2], 0, 0xFFFFFFFF, 0x92, 0xCF); + + gdt_flush(&gdtr); +} diff --git a/src/kernel/arch/x86/gdt.h b/src/kernel/arch/x86/gdt.h new file mode 100644 index 0000000..3581e45 --- /dev/null +++ b/src/kernel/arch/x86/gdt.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 Ortega Froysa, Nicolás + * Author: Ortega Froysa, Nicolás + * + * 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 . + */ + +#pragma once + +#include "structs.h" + +extern void gdt_flush(struct segreg *gdtr); +void gdt_entry_set(struct segdesc *entry, uint32_t base, + uint32_t limit, uint8_t access, uint8_t gran); +void gdt_install(); diff --git a/src/kernel/arch/x86/gdt.s b/src/kernel/arch/x86/gdt.s index e3896ab..85d9acf 100644 --- a/src/kernel/arch/x86/gdt.s +++ b/src/kernel/arch/x86/gdt.s @@ -16,57 +16,22 @@ * along with this program. If not, see . */ -/* - * Create the GDT - */ -gdt_start: -gdt_null: -.long 0x0 -.long 0x0 - -gdt_kcode: -.word 0xFFFF # limit -.word 0x0 # base -.byte 0x0 # base -.byte 0b10011010 # 1st flags | type flags -.byte 0b11001111 # 2nd flags | limit -.byte 0x0 # base - -gdt_kdata: -.word 0xFFFF # limit -.word 0x0 # base -.byte 0x0 # base -.byte 0b10010010 # 1st flags | type flags -.byte 0b11001111 # 2nd flags | limit -.byte 0x0 # base - -gdt_ucode: -.word 0xFFFF # limit -.word 0x0 # base -.byte 0x0 # base -.byte 0b11111010 # 1st flags | type flags -.byte 0b11001111 # 2nd flags | limit -.byte 0x0 # base - -gdt_udata: -.word 0xFFFF # limit -.word 0x0 # base -.byte 0x0 # base -.byte 0b11110010 # 1st flags | type flags -.byte 0b11001111 # 2nd flags | limit -.byte 0x0 # base - -# TODO: setup the TSS -gdt_tss: -.word 0x0 # size of TSS (set later) -.word 0x0 # address of TSS (set later) -.byte 0x0 # address of TSS (set later) -.byte 0b10010001 # 1st flags | type flags -.byte 0b01000000 # 2nd flags | size of TSS (set later -.byte 0x0 # address of TSS (set later) - -gdt_end: - -gdtr: -.word (gdt_end - gdt_start - 1) -.long gdt_start +.section .text +.global gdt_flush +.type gdt_flush, @function +gdt_flush: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax + cli + lgdt (%eax) + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + ljmp $0x0008, $gdt_flush_end +gdt_flush_end: + popl %ebp + ret diff --git a/src/kernel/arch/x86/structs.h b/src/kernel/arch/x86/structs.h index 74c5ea7..fefb5df 100644 --- a/src/kernel/arch/x86/structs.h +++ b/src/kernel/arch/x86/structs.h @@ -18,10 +18,12 @@ #pragma once +#include + struct segdesc { uint16_t limit_low; uint16_t base_low; - uint8_t base_middle; + uint8_t base_mid; uint8_t access; uint8_t gran; uint8_t base_high; @@ -72,3 +74,8 @@ struct tss { uint16_t iopb_r; // reserved uint16_t iopb; } __attribute__((packed)); + +struct segreg { + uint16_t limit; + uint32_t base; +} __attribute__((packed));