2007年11月7日水曜日

GDTの設定

ではまず、GDTの設定ですが、Gdtというクラスを作成しました。

とりあえず、Kernel用のセグメントとして、Code Segment = 1

Data Segment = 2 ということにしました。

gdt.h は下記のとおり。


#ifndef __GDT_H__
#define __GDT_H__

#include "types.h"
#include "descripter.h"

struct GdtEntry
{
enum {
G_FLAG = 0x0800,
D_FLAG = 0x0400,
AVL_FLAG = 0x0100,
P_FLAG = 0x0080,
DPL0 = 0x0000,
DPL1 = 0x0020,
DPL2 = 0x0040,
DPL3 = 0x0060,
S_FLAG = 0x0010,
TYPE_CS = 0x000A,
TYPE_DS = 0x0002,
TYPE_SS = 0x0006,
A_FLAG = 0x0001
};
uint16 limit_low;
uint16 segbase_low;
uint8 segbase_mid;
uint8 type_low;
uint8 type_hi :4;
uint8 limit_hi :4;
uint8 segbase_hi;
} __attribute__ ((packed));

class Gdt
{
public:
static const int NUM = 8192;

enum {
NULL_S = 0,
KERNEL_CS = 1,
KERNEL_DS = 2
};

static const uint16 KERNEL_CS_FLAG =
(GdtEntry::G_FLAG | GdtEntry::D_FLAG | GdtEntry::P_FLAG |
GdtEntry::DPL0 | GdtEntry::S_FLAG | GdtEntry::TYPE_CS);
static const uint16 KERNEL_DS_FLAG =
(GdtEntry::G_FLAG | GdtEntry::D_FLAG | GdtEntry::P_FLAG |
GdtEntry::DPL0 | GdtEntry::S_FLAG | GdtEntry::TYPE_DS);

void init(void);
void set(int index, uint32 segbase, uint32 limit, uint16 type);
void load(void) const;

private:
DescripterTable table __attribute__((aligned(8)));
GdtEntry entry[NUM] __attribute__((aligned(8)));
};

#endif /* __GDT_H__ */


gdt.cc は以下のとおり。


#include "gdt.h"

void Gdt::init(void) {
table.limit = Gdt::NUM * sizeof(GdtEntry) - 1;
table.offset = (uint32)entry;
for (int i = 0; i < Gdt::NUM; i++) {
set(i, 0, 0, 0);
}

set(NULL_S, 0, 0, 0); // for Null seg
set(KERNEL_CS, 0, 0xFFFFF, KERNEL_CS_FLAG); // for Kernel code
set(KERNEL_DS, 0, 0xFFFFF, KERNEL_DS_FLAG); // for Kernel data

load();

/* Change segments */
asm("ljmp %0, $1f; 1:" : : "i" (KERNEL_CS * sizeof(GdtEntry)));
asm("mov %0, %%ax" : : "i" (KERNEL_DS * sizeof(GdtEntry)));
asm("mov %ax, %ds");
asm("mov %ax, %es");
asm("mov %ax, %fs");
asm("mov %ax, %gs");
asm("mov %ax, %ss");
}

void Gdt::set(int index, uint32 segbase, uint32 limit, uint16 type) {
GdtEntry& desc = entry[index];

desc.limit_low = limit & 0xFFFF;
desc.limit_hi = (limit >> 16) & 0xF;
desc.segbase_low = segbase & 0xFFFF;
desc.segbase_mid = (segbase >> 16) & 0xFF;
desc.segbase_hi = (segbase >> 24) & 0xFF;
desc.type_low = type & 0xFF;
desc.type_hi = (type >> 8) & 0xF;
}

void Gdt::load(void) const {
__asm__ __volatile__("lgdt %0" :: "m" (table));
}

0 件のコメント: