'lo all,
I setup a stack for my kernel. The limit was 4kb (granularity on) the base was 1mb, type as read/write data, P, DPL-0, S-1, B-1
Typically it looked like this in my %define's...
%define K_STACK1_DWORD2 0x00C09210
%define K_STACK1_DWORD1 0x00000001
These being layed out on screen as they are in the intel manual 3 with the base+limit on the bottom define and all the mixture of everything else on the top one.
I did load them the opposite way around. K_STACK1_DWORD1 loaded before K_STACK1_DWORD2 making it correct in the gdt, my gdtr was loaded correctly with a pointer, ss and esp was loaded without any problems but using the stack caused 3rd exceptions. Untill i changed my base address from 1mb to somewhere at 1.2kb - 500h to be exact when it worked, i had a working stack. But why? I have nothing at 1mb, my kernel is loaded at 16mb and i haven't arranged or loaded anything at 1mb and it fails.
Is my base set correctly for 1mb (100000h) in the descriptor shown above?
Brill.
3rd exceptions and my stack base...
RE:3rd exceptions and my stack base...
I don't know too much about this so someone might have to clarify it, but isn't it true that the stack works down? so pushing stuff stores lower and lower (under 1mb) and also that the bios/video memory is located right under 1mb? there could be a conflict there... try stack @ 1.5 or 2mb...
RE:3rd exceptions and my stack base...
Just a short (OT) question. Is 16mb your virtual address or actual physcial address? I mean to assume your a machine has 16+ mb memory is to do a pretty BIG assumption... Why 16mb and not 1mb?
RE:3rd exceptions and my stack base...
16mb because the isa bus uses physical addressing and not virtual. Because of this it can only access up to 16mb ram thus i have Grub load me at 16mb mark to save relocation and further headaches later.
I haven't yet enabled paging so i am still addressing physcial addresses.
The 'machine' as you call it, is bochs, with an 'arranged' 32mb of ram. My kernel is about 5kb big. Hey, it only has a multiboot header, starting location and gdt setup code (of which doesn't work, my stack .
And in reply to 'osnewbie'.
The stack moves down yes, but the stack moves down from esp's location. my esp is stackbase+stacklimit. If my stack limit is 4kb and my base is 1mb, 1mb+4kb. If i push eax, 4 bytes, onto the stack esp will be 1mb+4kb-4b and thus not yet be at 1mb anyway. Also, the stack base is set by the data descriptor in the gdt. My stacks data descriptor is what defines the stacks base. If i try to push any values onto the stack that would cause it to go past the descriptors base address (1mb) i believe it would cause a stack fault and not a 3rd exception. Ok, since i don't have interrupts enabled, a stack fault would lead to a 3rd exception but then again, the stack is not at at 1mb yet. And i've checked my values given to esp. In fact, apart from the descriptor defines i've got for stack base, none of my code has changed for me to make my stack work at 1.2kb.
Thanks for your replies.
Brill
I haven't yet enabled paging so i am still addressing physcial addresses.
The 'machine' as you call it, is bochs, with an 'arranged' 32mb of ram. My kernel is about 5kb big. Hey, it only has a multiboot header, starting location and gdt setup code (of which doesn't work, my stack .
And in reply to 'osnewbie'.
The stack moves down yes, but the stack moves down from esp's location. my esp is stackbase+stacklimit. If my stack limit is 4kb and my base is 1mb, 1mb+4kb. If i push eax, 4 bytes, onto the stack esp will be 1mb+4kb-4b and thus not yet be at 1mb anyway. Also, the stack base is set by the data descriptor in the gdt. My stacks data descriptor is what defines the stacks base. If i try to push any values onto the stack that would cause it to go past the descriptors base address (1mb) i believe it would cause a stack fault and not a 3rd exception. Ok, since i don't have interrupts enabled, a stack fault would lead to a 3rd exception but then again, the stack is not at at 1mb yet. And i've checked my values given to esp. In fact, apart from the descriptor defines i've got for stack base, none of my code has changed for me to make my stack work at 1.2kb.
Thanks for your replies.
Brill
RE:3rd exceptions and my stack base...
No... I don't get it - I'm sorry.
It doesn't matter whether you put your kernel at 1mb or 16mb or 200mb. The i386 in pmode can access 4GB linearly without any paging. With paging and PAE you can theoritcally access 64GB.
What I do in my kernel startup code is
1) Check whether GRUB loaded me - else display a blinking "B" and hang
2) Check whether data segment has been properly linked, else display "D" and hang
3) load my GDT (two descriptors, code and data 0 - 4GB) (i.e. "flat" mode)
4) Reload CS
5) Reload DS, ES, FS, GS, SS
5) Set up my stack pointer
6) Run global ctors (I use C++)
7) Push the pointer to the mbi
Run my main
9) Clean up the stack after main
10) Run global dtors (I use C++)
11) Display blinking "E"
11) Hang
And here is my code:
The #define ASM is required by multiboot.h
__KERNEL_CS and __KERNEL_DS are located in x86 and should correspond to your actual selectors described in the GDT. GDT_ENTRIES is also defined in x86.h and is curently set to 256
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=->
/* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 021339, USA. */
/* This file is based on boot.S from GRUB's doc/ directory. */
#define ASM 1
#define DMAGIC 0xdeadda7a
#include <x86.h>
#include <multiboot.h>
.text
.globl start, _start, EXT_C(gdt), EXT_C(gdt_descr)
start:
_start:
jmp multiboot_entry
/* Align 32 bits boundary. */
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
multiboot_entry:
/* Reset EFLAGS. */
pushl $0
popf
/* check that we were loaded by a Multiboot loader */
checkboot:
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
je checkdata
/* Blinking 'B' */
movw $0x9F42, 0xb8000
jmp loop
/* Check that the data segment is properly linked */
checkdata:
cmpl $DMAGIC, data_magic(,1)
je kstart
/* Blinking 'D' */
movw $0x9F44, 0xb8000
jmp loop
kstart:
/* setup the new GDT as soon as we can as we can't rely on GRUB's GDT */
lgdt EXT_C(gdt_descr)
ljmp $__KERNEL_CS,$1f
/* Reload data segment registers... */
1: movl $__KERNEL_DS,%eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* Initialize the stack pointer. */
movl $(stack + STACK_SIZE), %esp
/* See libk/runtime.cpp for notes */
call EXT_C(do_global_ctor)
/* Push the pointer to the Multiboot information structure. */
pushl %ebx
call EXT_C(main)
/* we shouldn't get here */
addl $4, %esp
call EXT_C(do_global_dtor)
cli
/* Blinking 'E' */
movw $0x9F45, 0xb8000
loop: jmp loop
/* data section */
.data
.align 4
data_magic:
.long DMAGIC
.align 2
EXT_C(gdt_descr):
.word GDT_ENTRIES * 8 - 1
.long EXT_C(gdt)
.align 16 /* align on 64 bit boundary */
EXT_C(gdt):
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00cf9a000000ffff /* 0x8 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x10 kernel 4GB data at 0x00000000 */
.fill GDT_ENTRIES - 3,8,0 /* Space for LDT, TSS and whatever */
/* Our stack area. */
.comm stack, STACK_SIZE
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=->
It doesn't matter whether you put your kernel at 1mb or 16mb or 200mb. The i386 in pmode can access 4GB linearly without any paging. With paging and PAE you can theoritcally access 64GB.
What I do in my kernel startup code is
1) Check whether GRUB loaded me - else display a blinking "B" and hang
2) Check whether data segment has been properly linked, else display "D" and hang
3) load my GDT (two descriptors, code and data 0 - 4GB) (i.e. "flat" mode)
4) Reload CS
5) Reload DS, ES, FS, GS, SS
5) Set up my stack pointer
6) Run global ctors (I use C++)
7) Push the pointer to the mbi
Run my main
9) Clean up the stack after main
10) Run global dtors (I use C++)
11) Display blinking "E"
11) Hang
And here is my code:
The #define ASM is required by multiboot.h
__KERNEL_CS and __KERNEL_DS are located in x86 and should correspond to your actual selectors described in the GDT. GDT_ENTRIES is also defined in x86.h and is curently set to 256
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=->
/* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 021339, USA. */
/* This file is based on boot.S from GRUB's doc/ directory. */
#define ASM 1
#define DMAGIC 0xdeadda7a
#include <x86.h>
#include <multiboot.h>
.text
.globl start, _start, EXT_C(gdt), EXT_C(gdt_descr)
start:
_start:
jmp multiboot_entry
/* Align 32 bits boundary. */
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
multiboot_entry:
/* Reset EFLAGS. */
pushl $0
popf
/* check that we were loaded by a Multiboot loader */
checkboot:
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
je checkdata
/* Blinking 'B' */
movw $0x9F42, 0xb8000
jmp loop
/* Check that the data segment is properly linked */
checkdata:
cmpl $DMAGIC, data_magic(,1)
je kstart
/* Blinking 'D' */
movw $0x9F44, 0xb8000
jmp loop
kstart:
/* setup the new GDT as soon as we can as we can't rely on GRUB's GDT */
lgdt EXT_C(gdt_descr)
ljmp $__KERNEL_CS,$1f
/* Reload data segment registers... */
1: movl $__KERNEL_DS,%eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* Initialize the stack pointer. */
movl $(stack + STACK_SIZE), %esp
/* See libk/runtime.cpp for notes */
call EXT_C(do_global_ctor)
/* Push the pointer to the Multiboot information structure. */
pushl %ebx
call EXT_C(main)
/* we shouldn't get here */
addl $4, %esp
call EXT_C(do_global_dtor)
cli
/* Blinking 'E' */
movw $0x9F45, 0xb8000
loop: jmp loop
/* data section */
.data
.align 4
data_magic:
.long DMAGIC
.align 2
EXT_C(gdt_descr):
.word GDT_ENTRIES * 8 - 1
.long EXT_C(gdt)
.align 16 /* align on 64 bit boundary */
EXT_C(gdt):
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00cf9a000000ffff /* 0x8 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x10 kernel 4GB data at 0x00000000 */
.fill GDT_ENTRIES - 3,8,0 /* Space for LDT, TSS and whatever */
/* Our stack area. */
.comm stack, STACK_SIZE
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=->
RE:3rd exceptions and my stack base...
ok but isa still access more than 16mb of ram which apparently includes the floppy drive.
My code...
gdt.asm
[BITS 32]
[SECTION .text]
%include "include/gdt.h"
setup_gdt:
xor eax, eax
; Load dummy descriptor into gdt
mov dword [gdt+eax], 0x00000000
mov dword [gdt+eax+4], 0x00000000
add eax, 8
; Load kernel stack 1 into gdt
mov dword [gdt+eax], K_STACK1_DWORD1
mov dword [gdt+eax+4], K_STACK1_DWORD2
add eax, 8
; Load kernel stack 2 into gdt
mov dword [gdt+eax], K_STACK2_DWORD1
mov dword [gdt+eax+4], K_STACK2_DWORD2
add eax, 8
; Load level 0 code segment into gdt
mov dword [gdt+eax], LEVEL0_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL0_CODE_DWORD2
add eax, 8
; Load level 0 data segment into gdt
mov dword [gdt+eax], LEVEL0_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL0_DATA_DWORD2
add eax, 8
; Load level 1 code segment into gdt
mov dword [gdt+eax], LEVEL1_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL1_CODE_DWORD2
add eax, 8
; Load level 1 data segment into gdt
mov dword [gdt+eax], LEVEL1_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL1_DATA_DWORD2
add eax, 8
; Load level 2 code segment into gdt
mov dword [gdt+eax], LEVEL2_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL2_CODE_DWORD2
add eax, 8
; Load level 2 data segment into gdt
mov dword [gdt+eax], LEVEL2_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL2_DATA_DWORD2
add eax, 8
; Load level 3 code segment into gdt
mov dword [gdt+eax], LEVEL3_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL3_CODE_DWORD2
add eax, 8
; Load level 3 data segment into gdt
mov dword [gdt+eax], LEVEL3_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL3_DATA_DWORD2
add eax, 8
lea ebx, [gdt]
mov dword [gdt_base], ebx
sub ax, 0x01
mov word [gdt_limit], ax
lgdt [gdt_pntr]
mov ax, LEVEL0_DATA_SELECT
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, K_STACK1_SELECT
mov ss, ax
mov esp, K_STACK1_ESP
jmp LEVEL0_CODE_SELECT:set_cs
set_cs:
jmp gdt_setup_complete ; Jump back to start.asm
[SECTION .data]
gdt_pntr:
gdt_limit dw 0x0000
gdt_base dd 0x00000000
[SECTION .bss]
align 4, db 0
gdt RESB GDT_SIZE
gdt.h
; Globals
[GLOBAL setup_gdt]
; Externs
[EXTERN gdt_setup_complete]
; Defines
%define GDT_SIZE 16384 ; Reserved space the the gdt
; Kernel Stacks x2 data descriptors
%define K_STACK1_SELECT 0x08
%define K_STACK1_DWORD2 0x00C09200 ; G-1, B-1, Limit-16kb, Type-R/W, Accessed
%define K_STACK1_DWORD1 0x05000001 ; Base-31kb
%define K_STACK1_BASE 0x00000500 ; Stack 1 details for esp
%define K_STACK1_LIMIT 0x00001000
%define K_STACK1_ESP (K_STACK1_BASE + K_STACK1_LIMIT)
%define K_STACK2_SELECT 0x10
%define K_STACK2_DWORD2 0x00C09200 ; G-1, B-1, Limit-16kb, Type-R/W, Accessed
%define K_STACK2_DWORD1 0xBC000004 ; Base-48kb
%define K_STACK2_BASE 0x0000BC00 ; Stack 2 details for esp
%define K_STACK2_LIMIT 0x00004000
%define K_STACK2_ESP (K_STACK2_BASE + K_STACK2_LIMIT)
; Level 0 code/data descriptors
%define LEVEL0_CODE_SELECT 0x18
%define LEVEL0_CODE_DWORD2 0x00CF9A00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL0_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL0_DATA_SELECT 0x20
%define LEVEL0_DATA_DWORD2 0x00CF9200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL0_DATA_DWORD1 0x0000FFFF ; Base-0b
; Level 1 code/data descriptors
%define LEVEL1_CODE_SELECT 0x28
%define LEVEL1_CODE_DWORD2 0x00CFBA00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL1_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL1_DATA_SELECT 0x30
%define LEVEL1_DATA_DWORD2 0x00CFB200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL1_DATA_DWORD1 0x0000FFFF ; Base-0b
; Level 2 code/data descriptors
%define LEVEL2_CODE_SELECT 0x38
%define LEVEL2_CODE_DWORD2 0x00CFDA00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL2_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL2_DATA_SELECT 0x40
%define LEVEL2_DATA_DWORD2 0x00CFD200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL2_DATA_DWORD1 0x0000FFFF ; Base-0b
; Level 3 code/data descriptors
%define LEVEL3_CODE_SELECT 0x48
%define LEVEL3_CODE_DWORD2 0x00CFFA00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL3_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL3_DATA_SELECT 0x50
%define LEVEL3_DATA_DWORD2 0x00CFF200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL3_DATA_DWORD1 0x0000FFFF ; Base-0b
My code...
gdt.asm
[BITS 32]
[SECTION .text]
%include "include/gdt.h"
setup_gdt:
xor eax, eax
; Load dummy descriptor into gdt
mov dword [gdt+eax], 0x00000000
mov dword [gdt+eax+4], 0x00000000
add eax, 8
; Load kernel stack 1 into gdt
mov dword [gdt+eax], K_STACK1_DWORD1
mov dword [gdt+eax+4], K_STACK1_DWORD2
add eax, 8
; Load kernel stack 2 into gdt
mov dword [gdt+eax], K_STACK2_DWORD1
mov dword [gdt+eax+4], K_STACK2_DWORD2
add eax, 8
; Load level 0 code segment into gdt
mov dword [gdt+eax], LEVEL0_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL0_CODE_DWORD2
add eax, 8
; Load level 0 data segment into gdt
mov dword [gdt+eax], LEVEL0_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL0_DATA_DWORD2
add eax, 8
; Load level 1 code segment into gdt
mov dword [gdt+eax], LEVEL1_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL1_CODE_DWORD2
add eax, 8
; Load level 1 data segment into gdt
mov dword [gdt+eax], LEVEL1_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL1_DATA_DWORD2
add eax, 8
; Load level 2 code segment into gdt
mov dword [gdt+eax], LEVEL2_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL2_CODE_DWORD2
add eax, 8
; Load level 2 data segment into gdt
mov dword [gdt+eax], LEVEL2_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL2_DATA_DWORD2
add eax, 8
; Load level 3 code segment into gdt
mov dword [gdt+eax], LEVEL3_CODE_DWORD1
mov dword [gdt+eax+4], LEVEL3_CODE_DWORD2
add eax, 8
; Load level 3 data segment into gdt
mov dword [gdt+eax], LEVEL3_DATA_DWORD1
mov dword [gdt+eax+4], LEVEL3_DATA_DWORD2
add eax, 8
lea ebx, [gdt]
mov dword [gdt_base], ebx
sub ax, 0x01
mov word [gdt_limit], ax
lgdt [gdt_pntr]
mov ax, LEVEL0_DATA_SELECT
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, K_STACK1_SELECT
mov ss, ax
mov esp, K_STACK1_ESP
jmp LEVEL0_CODE_SELECT:set_cs
set_cs:
jmp gdt_setup_complete ; Jump back to start.asm
[SECTION .data]
gdt_pntr:
gdt_limit dw 0x0000
gdt_base dd 0x00000000
[SECTION .bss]
align 4, db 0
gdt RESB GDT_SIZE
gdt.h
; Globals
[GLOBAL setup_gdt]
; Externs
[EXTERN gdt_setup_complete]
; Defines
%define GDT_SIZE 16384 ; Reserved space the the gdt
; Kernel Stacks x2 data descriptors
%define K_STACK1_SELECT 0x08
%define K_STACK1_DWORD2 0x00C09200 ; G-1, B-1, Limit-16kb, Type-R/W, Accessed
%define K_STACK1_DWORD1 0x05000001 ; Base-31kb
%define K_STACK1_BASE 0x00000500 ; Stack 1 details for esp
%define K_STACK1_LIMIT 0x00001000
%define K_STACK1_ESP (K_STACK1_BASE + K_STACK1_LIMIT)
%define K_STACK2_SELECT 0x10
%define K_STACK2_DWORD2 0x00C09200 ; G-1, B-1, Limit-16kb, Type-R/W, Accessed
%define K_STACK2_DWORD1 0xBC000004 ; Base-48kb
%define K_STACK2_BASE 0x0000BC00 ; Stack 2 details for esp
%define K_STACK2_LIMIT 0x00004000
%define K_STACK2_ESP (K_STACK2_BASE + K_STACK2_LIMIT)
; Level 0 code/data descriptors
%define LEVEL0_CODE_SELECT 0x18
%define LEVEL0_CODE_DWORD2 0x00CF9A00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL0_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL0_DATA_SELECT 0x20
%define LEVEL0_DATA_DWORD2 0x00CF9200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL0_DATA_DWORD1 0x0000FFFF ; Base-0b
; Level 1 code/data descriptors
%define LEVEL1_CODE_SELECT 0x28
%define LEVEL1_CODE_DWORD2 0x00CFBA00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL1_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL1_DATA_SELECT 0x30
%define LEVEL1_DATA_DWORD2 0x00CFB200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL1_DATA_DWORD1 0x0000FFFF ; Base-0b
; Level 2 code/data descriptors
%define LEVEL2_CODE_SELECT 0x38
%define LEVEL2_CODE_DWORD2 0x00CFDA00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL2_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL2_DATA_SELECT 0x40
%define LEVEL2_DATA_DWORD2 0x00CFD200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL2_DATA_DWORD1 0x0000FFFF ; Base-0b
; Level 3 code/data descriptors
%define LEVEL3_CODE_SELECT 0x48
%define LEVEL3_CODE_DWORD2 0x00CFFA00 ; G-1, B-1, Limit-4gb, Type-X/R, Accessed
%define LEVEL3_CODE_DWORD1 0x0000FFFF ; Base-0b
%define LEVEL3_DATA_SELECT 0x50
%define LEVEL3_DATA_DWORD2 0x00CFF200 ; G-1, B-1, Limit-4gb, Type-R/W, Accessed
%define LEVEL3_DATA_DWORD1 0x0000FFFF ; Base-0b