Code: Select all
# see gdt.c
.global gdt_flush
.extern gp
gdt_flush:
lgdt gp
mov 0x10, %ax
mov %ds, %ax
mov %es, %ax
mov %fs, %ax
mov %gs, %ax
mov %ss, %ax
jmp flush2
flush2:
ret
Code: Select all
# see gdt.c
.global gdt_flush
.extern gp
gdt_flush:
lgdt gp
mov 0x10, %ax
mov %ds, %ax
mov %es, %ax
mov %fs, %ax
mov %gs, %ax
mov %ss, %ax
jmp flush2
flush2:
ret
I'm pretty sure that jmp is supposed to beehird wrote:Code: Select all
# see gdt.c .global gdt_flush .extern gp gdt_flush: lgdt gp mov 0x10, %ax mov %ds, %ax mov %es, %ax mov %fs, %ax mov %gs, %ax mov %ss, %ax jmp flush2 flush2: ret
Code: Select all
jmp 0x08:flush2
Code: Select all
LGDT [GDTR]
JMP CODESEL:FLUSHCSEIP
[BITS 32]
FLUSHCSEIP:
MOV EAX , DATASEL
MOV DS , EAX
MOV ES , EAX
MOV FS , EAX
MOV GS , EAX
MOV SS , EAX
MOV ESP , 0xFFFF
JMP CODESEL:KERNELENTRY
Code: Select all
gdt_flush:
lgdt gp
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
ljmp $0x08, $flush2
flush2:
ret
Code: Select all
00017504444e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00017504444e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00017504444i[CPU0 ] protected mode
00017504444i[CPU0 ] CS.d_b = 32 bit
00017504444i[CPU0 ] SS.d_b = 32 bit
00017504444i[CPU0 ] | EAX=00106814 EBX=0002bdc0 ECX=00000000 EDX=00000000
00017504444i[CPU0 ] | ESP=00106810 EBP=00106870 ESI=0002bf1a EDI=0002bf1b
00017504444i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf ZF af PF cf
00017504444i[CPU0 ] | SEG selector base limit G D
00017504444i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00017504444i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00017504444i[CPU0 ] | DS:0000( 0000| 0| 0) 00000000 000fffff 1 1
00017504444i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00017504444i[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 000fffff 1 1
00017504444i[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 000fffff 1 1
00017504444i[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 000fffff 1 1
00017504444i[CPU0 ] | EIP=001006fd (001006fd)
00017504444i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00017504444i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00017504444i[CPU0 ] >> mov eax, dword ptr ds:0x100223 : A123021000
00017504444e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00017504444i[SYS ] bx_pc_system_c::Reset(SOFTWARE) called
Code: Select all
interrupt() : gate descriptor is not valid sys seg
Code: Select all
>> mov eax, dword ptr ds:0x100223 : A123021000
Code: Select all
0x100223
Code: Select all
hlt
nop
nop
Why there are null selectors is probably the key event to track: I think the selectors are still loaded with their real-mode values.Intel wrote:A null segment selector can be loaded into the DS, ES, FS, or GS register, but any attempt to access a segment through one of these registers when it is loaded with a null segment selector results in a #GP exception being generated.
Code: Select all
global gdt_flush
extern gp
gdt_flush:
lgdt [gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret
Code: Select all
#include <system.h>
struct gdt_entry {
unsigned short limit_low;
unsigned short base_low;
unsigned short base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
struct gdt_ptr {
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct gdt_entry gdt[3];
struct gdt_ptr gp;
/* code in start.asm */
extern void gdt_flush();
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned
char access, unsigned char gran)
{
/* base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24 & 0xFF);
/* limits */
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
/* granularity + access */
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
void gdt_install(void)
{
/* setup the gdt pointer + limit */
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
gp.base = &gdt;
/* NULL descriptor */
gdt_set_gate(0, 0, 0, 0, 0);
/* code segment: base address 0, limit 4GB, 4KB gran, 32-bit opcodes */
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
/* data segment: same as code segment, but for data */
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
/* install shiny new gdt */
gdt_flush();
}
Code: Select all
...
struct gdt_entry gdt[3];
...
gp.base = &gdt;
...