Hello to all,
my bootloader enters PM & jumps to image load address 0x600. GDT includes null,linear code(0x08) & linear data (0x10) descriptors.
C kernel entry function (kmain()) adds to this GDT a TSS descriptor . Then it loads this TSS into task register using LTR. But now it restarts :
what goes wrong here ? is there anything that needs to be done before setting up TSS.
I will be very greatful & thankful if anybody gives me the solution.
Thanks in advance........
Prasad.
I use gcc(i mean djgpp) , nasm & ld.
// ___________________global.h______________________
// some stuff is copied from alexfru os .
#define GDT_entries 4
#define ACS_PRESENT 0x80
#define ACS_CODE 0x18
#define ACS_DATA 0x10
#define ACS_EXP_DOWN 0x04
#define ACS_CONFORM 0x04
#define ACS_READABLE 0x02
#define ACS_WRITEABLE 0x02
#define ACS_CODE_SEG (ACS_CODE | ACS_PRESENT)
#define ACS_DATA_SEG (ACS_DATA | ACS_PRESENT | ACS_WRITEABLE)
#define ACS_STACK_SEG ACS_DATA_SEG
#define ACS_IDT ACS_DATA_SEG
#define ACS_INT 0x0E
#define ACS_TRAP 0x0F
#define ACS_TASK 0x05
#define ACS_INT_GATE (ACS_INT | ACS_PRESENT)
#define ACS_TRAP_GATE (ACS_TRAP | ACS_PRESENT)
#define ACS_TSS (0x09 | ACS_PRESENT)
#define ACS_TASK_GATE (ACS_TASK | ACS_PRESENT)
#define ACS_DPL_0 0x00
#define ACS_DPL_1 0x20
#define ACS_DPL_2 0x40
#define ACS_DPL_3 0x60
#define ATTR_32BIT 0x40
#define ATTR_BIG 0x40
#define ATTR_GRANUL 0x80
#define RPL_0 0x00
#define RPL_1 0x01
#define RPL_2 0x02
#define RPL_3 0x03
typedef struct SEG_DESCRIPTOR
{
word limit;
word base0_15;
byte base16_23;
byte attrs0_7;
byte attrs8_15;
byte base24_31;
} SEG_DESCRIPTOR;
typedef struct GDT_REG
{
word limit;
dword base;
}GDT_REG;
typedef struct TSS
{
dword link,
esp0,
ss0,
esp1,
ss1,
esp2,
ss2,
cr3,
eip,
eflags,
eax,
ecx,
edx,
ebx,
esp,
ebp,
esi,
edi,
es,
cs,
ss,
ds,
fs,
gs,
ldtr;
word trace,
io_map_addr;
} TSS;
void kmain();
void setup_GDT();
void setup_IDT();
void setup_TSS();
......... // other function declaration...
// asm routines are extern..
extern void LGDT (GDT_REG *gdtr);
extern void SGDT (GDT_REG *gdtr);
extern void LIDT (IDT_REG *idtr);
extern void SIDT (IDT_REG *idtr);
extern void LTR (dword sel);
extern dword STR();
// _________________ kernel.c __________________________
#include "global.h"
static SEG_DESCRIPTOR gdt[4];
static INT_DESCRIPTOR idt[0x31];
static GDT_REG gdtr;
static IDT_REG idtr;
TSS tss;
void kmain()
{
setup_GDT();
setup_TSS();
asm("hlt"); // it does not halt here.
// setup_IDT();
// remap_PIC(0x20,0x28);
// enable_IRQ(1);
// asm("hlt");
}
void setup_TSS()
{
memset (&tss, 0, sizeof(TSS)); // tested works correctly...
tss.ss0 = 0x10; // linear data segment descriptor
LTR (0x18); // asm routine.
// restarts now..... If asm("hlt"); is placed before LTR() , it
// hangs .
// esp is set to oxffff & ss = 0x10 (i.e.linear data seg.desc) by bootloader.
// here is asm part :
}
static void setup_GDT() {
SEG_DESCRIPTOR *old_gdt;
GDT_REG old_gdtr;
int i;
/* let's copy contents of the old GDT to new GDT and set up the new one */
SGDT (&old_gdtr); // asm routine. works correctly.
old_gdt = (SEG_DESCRIPTOR *) old_gdtr.base;
for (i=0;i<3;i++)
gdt[i] = old_gdt[i];
// TSS (18h)
gdt[3].limit = sizeof(TSS)-1;
gdt[3].base0_15 = ((dword)(&tss)) & 0xFFFF;
gdt[3].base16_23 = (((dword)(&tss)) >> 16) & 0xFF;
gdt[3].base24_31 = (((dword)(&tss)) >> 24) & 0xFF;
gdt[3].attrs0_7 = ACS_TSS;
gdt[3].attrs8_15 = 0;
gdtr.base = (dword) &gdt;
gdtr.limit = GDT_entries * sizeof(SEG_DESCRIPTOR) - 1;
LGDT (&gdtr); // asm routine works correctly...
}
// here is asm part
GLOBAL _LGDT, _SGDT, _LTR, _STR
%define PARAM_1 ebp+8+4*0
[SECTION .text]
[BITS 32]
_LGDT:
push ebp
mov ebp, esp
mov eax, [PARAM_1]
lgdt [eax]
pop ebp
ret
_SGDT:
push ebp
mov ebp, esp
mov eax, [PARAM_1]
sgdt [eax]
pop ebp
ret
_LTR:
push ebp
mov ebp, esp
ltr [PARAM_1]
pop ebp
ret