just when you thought this thread was over! I'm having the same problem. I have successfully implemented virtual memory on GeekOS (my schools OS). Now, I'm trying to get segmentation to work on my OS that I'm writing from complete scratch NoobOS, because OS development is fun! I've been using James M OS tutorial, and also been reading the intel IA-32 manual specifically 3.4.5, which explains the data fields.
Here is my gdt.h file (Yes, I'm using bit fields)
Code: Select all
/*
* Description: Code to Initialize and Manage the Global Descriptor Table.
* (Information about Segment Entries are in the IA32 Manual specifically
* section 3.4.5)
*/
#ifndef GDT_H
#define GDT_H
#include "kstdio.h"
#include "memory.h"
#define GDT_NUM_ENTRIES 3
struct Segment_Entry;
struct GDT;
static struct GDT* gdt;
/* Each Descriptor (Entry) is 8 bytes */
struct Segment_Entry {
unsigned int baseLow:8;
unsigned int access:4;
unsigned int systemFlag:1;
unsigned int ring:2;
unsigned int segmentPresent:1;
unsigned int segmentLimit:4;
unsigned int available:1;
unsigned int mode64:1;
unsigned int defaultOp:1;
unsigned int granularity:1;
unsigned int baseHigh:8;
};
struct GDT {
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/* Just Added The Packed (Still Doesn't Work :( )*/
static struct Segment_Entry s_GDT[GDT_NUM_ENTRIES];
void Init_GDT();
void Init_Kernel_Null_Segment(struct Segment_Entry* desc);
void Init_Kernel_Code_Segment(struct Segment_Entry* desc);
void Init_Kernel_Data_Segment(struct Segment_Entry* desc);
#endif
Here is GDT.c
Code: Select all
/**
* Description: There are only 3 segments in use at the moment, which are
* the null segment, code segemnt, and data segment. Each Segment With
* Supervisor Mode Privledges has a base of 0, and a limit of 4G (This is
* called Flat Mode).
*/
#include "gdt.h"
extern void Load_GDT(unsigned int*);
void Init_GDT() {
memset(s_GDT, 0x0, sizeof(struct Segment_Entry)*GDT_NUM_ENTRIES);
gdt = (struct GDT*)Malloc(sizeof(struct GDT));
memset(gdt, 0x0, sizeof(struct GDT));
Print_String("GDT: Init");
New_Line();
Init_Kernel_Null_Segment(&s_GDT[0]);
Init_Kernel_Code_Segment(&s_GDT[1]);
Init_Kernel_Data_Segment(&s_GDT[2]);
/* Removed Debug Code Here */
gdt->limit = sizeof(struct Segment_Entry)*GDT_NUM_ENTRIES;
gdt->base = (unsigned int)s_GDT;
while(1); // Spin Here To Prevent Triple Fault, So I can Debug xD
Load_GDT(gdt);
Print_String("GDT: Loaded.");
New_Line();
}
void Init_Kernel_Null_Segment(struct Segment_Entry* desc) {
memset(desc, 0x0, sizeof(struct Segment_Entry));
return;
}
void Init_Kernel_Code_Segment(struct Segment_Entry* desc) {
desc->baseLow = 0; // Base = 0
desc->access = 0x08; // Executable
desc->systemFlag = 1; // Code Segment (Therefore Set)
desc->ring = 0; // Ring 0 (Supervisor Mode)
desc->segmentPresent = 1; // Yes!
desc->segmentLimit = 0x0f; // 32 bit addressing
desc->available = 0; // *ignored*
desc->mode64 = 0; // Targeting 32bit architecture
desc->defaultOp = 1; // 32bit Operands
desc->granularity = 1; // 4K block units
desc->baseHigh = 0; // Base = 0
return;
}
/* Init_Kernel_Data_Segment is Very Similar, but access is 0x07 (read/write/expandable) */
Here is lowcode.asm (which contains Load_GDT)
Code: Select all
;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; @author Gary Drocella
;; @date 05/22/11
;; @file lowcode.asm
;;
;; Description: Implementation Of Various Procedures that aren't suitable
;; to develop in C. There are many instructions that C doesn't know about,
;; such as the lgdt (load global descriptor table), which loads the global
;; descriptor table into the GDT Register in the processor.
;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[BITS 32]
GLOBAL Load_GDT
;; =============================================================
;; Code
;; =============================================================
[SECTION .text]
Load_GDT:
mov eax, [esp+4]
lgdt [eax]
;; Reload Segment Registers
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:.here
.here:
ret
Finally My Kernel_Main in kernel.c which calls the Init_GDT
Code: Select all
void Kernel_Main(void* mb, int mn) {
Init_Mem();
Init_Main_Screen();
Print_String("Initializing GDT...");
New_Line();
Init_GDT();
Pretty_Print_Welcome();
New_Line();
while(1) { __asm__ ("nop"); } // Spin
return;
}
Why is the GDT being coded like this? because it's alot better then copying and pasting code from a tutorial, and
not understanding what in the world the GDT is doing, and not understanding the bit fields
There are some Master Hackers on this forum, and any help is Greatly Appreciated Thank You!