[英]Trouble simplifying GDT on x86
我正在嘗試簡化包含6個段的GDT表,但是其中確實有2個段是必需的(根據我的收集)。 我無法進行更改。
該代碼來自Xbox引導加載程序Cromwell。 CPU是奔騰III。 沒有用戶空間的概念,因此所有內容都應在特權級別為0的段上運行。我想從一個具有單個code32和一個data32段的平面模型開始。
這是相關的原始工作代碼:
.code32
.section .text, "ax"
.org 0x00
jmp start_linux
.global Cromwellconfig
Cromwellconfig:
.org 0x0c
// Space for the SHA1 checksum
.org 0x20
// The Value positions are fixed, do not change them, used everywhere
.long 0x0 // 0x20 if XBE, then this bit is 0, if Cromwell mode, the bit is set to 1 by the Startuploader
.long 0x0 // 0x24 ImageRetryLoads
.long 0x0 // 0x28 Bank, from where Loaded
.long 0x0 // 0x2C 0 .. Bios = 256 k, 1 .. Bios = 1MB
.long 0x0 // 0x30 free
.long _end_complete_rom // 0x34 free
.long 0x0 // 0x38 free
.long 0x0 // free
.align 16
tableGdt:
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00 dummy
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 // 0x08 code32
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 // 0x10 code32
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00 // 0x18 data32
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0x8f, 0x00 // 0x20 code16 (8f indicates 4K granularity, ie, huge limit)
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x8f, 0x00 // 0x28 data16
tableGdtDescriptor:
// This is the GDT header having 8 bytes
.word tableGdtDescriptor-tableGdt // 0x30 byte GDT
.long GDT_LOC // GDT located at 0xA0000
.word 0 // Padding
tableGdtEnd:
.align 16
tableIdtDescriptor:
.word 2048
.long IDT_LOC // IDT located at 0xB0000
.word 0 // fill Word, so we get aligned again
// We are dword aligned now
.align 16
.globl start_linux
start_linux:
// Make SURE the IRQs are turned off
cli
// kill the cache = Disable bit 30 + 29 = CD + NW
// CD = Cache Disable (disable = 1)
// NW Not write through (disable = 1)
// Protected mode enabled
mov $0x60010033, %eax
mov %eax, %cr0
wbinvd
// Flush the TLB
xor %eax, %eax
mov %eax, %cr3
// We kill the Local Descriptor Table
xor %eax, %eax
lldt %ax
// DR6/DR7: Clear the debug registers
xor %eax, %eax
mov %eax, %dr6
mov %eax, %dr7
mov %eax, %dr0
mov %eax, %dr1
mov %eax, %dr2
mov %eax, %dr3
// IMPORTANT! Linux expects the GDT located at a specific position,
// 0xA0000, so we have to move it there.
// Copy the GDT to its final location
movl $GDT_LOC, %edi
movl $tableGdt, %esi
movl $(tableGdtEnd-tableGdt)/4, %ecx
// Moving (tableGdtEnd-tableGdt)/4 DWORDS from &tableGdt to &GDT_LOC
rep movsl
// Load the new GDT (bits0-15: Table limit, bits16-47: Base address)
lgdt GDT_LOC+(tableGdtDescriptor-tableGdt)
// Kill the LDT, if any
xor %eax, %eax
lldt %ax
// Reload CS as 0010 from the new GDT using a far jump
jmp $0x010, $reload_cs
reload_cs:
// CS is now a valid entry in the GDT. Set SS, DS, and ES to valid
// descriptors, but clear FS and GS as they are not necessary.
// Set SS, DS, and ES to a data32 segment with maximum limit.
movw $0x0018, %ax
mov %eax, %ss
mov %eax, %ds
mov %eax, %es
// Clear FS and GS
xor %eax, %eax
mov %eax, %fs
mov %eax, %gs
將以上代碼中的遠距離更改為
jmp $0x008, $reload_cs
順便說一句也可以。
如您所見,一開始就啟用了保護模式。
我想修整GDT,使其在0x08有一個code32段,在0x10有一個data32段。 這是我的看法; 這不起作用:
.code32
.section .text, "ax"
.org 0x00
jmp start_linux
.global Cromwellconfig
Cromwellconfig:
.org 0x0c
// Space for the SHA1 checksum
.org 0x20
// The Value positions are fixed, do not change them, used everywhere
.long 0x0 // 0x20 if XBE, then this bit is 0, if Cromwell mode, the bit is set to 1 by the Startuploader
.long 0x0 // 0x24 ImageRetryLoads
.long 0x0 // 0x28 Bank, from where Loaded
.long 0x0 // 0x2C 0 .. Bios = 256 k, 1 .. Bios = 1MB
.long 0x0 // 0x30 free
.long _end_complete_rom // 0x34 free
.long 0x0 // 0x38 free
.long 0x0 // free
.align 16
tableGdt:
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00 dummy
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 // 0x08 code32
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00 // 0x10 data32
tableGdtDescriptor:
// This is the GDT header having 8 bytes
.word tableGdtDescriptor-tableGdt // 0x18 byte GDT
.long GDT_LOC // GDT located at 0xA0000
.word 0 // Padding
tableGdtEnd:
.align 16
tableIdtDescriptor:
.word 2048
.long IDT_LOC // IDT located at 0xB0000
.word 0 // fill Word, so we get aligned again
// We are dword aligned now
.align 16
.globl start_linux
start_linux:
// Make SURE the IRQs are turned off
cli
// kill the cache = Disable bit 30 + 29 = CD + NW
// CD = Cache Disable (disable = 1)
// NW Not write through (disable = 1)
// Protected mode enabled
mov $0x60010033, %eax
mov %eax, %cr0
wbinvd
// Flush the TLB
xor %eax, %eax
mov %eax, %cr3
// We kill the Local Descriptor Table
xor %eax, %eax
lldt %ax
// DR6/DR7: Clear the debug registers
xor %eax, %eax
mov %eax, %dr6
mov %eax, %dr7
mov %eax, %dr0
mov %eax, %dr1
mov %eax, %dr2
mov %eax, %dr3
// IMPORTANT! Linux expects the GDT located at a specific position,
// 0xA0000, so we have to move it there.
// Copy the GDT to its final location
movl $GDT_LOC, %edi
movl $tableGdt, %esi
movl $(tableGdtEnd-tableGdt)/4, %ecx
// Moving (tableGdtEnd-tableGdt)/4 DWORDS from &tableGdt to &GDT_LOC
rep movsl
// Load the new GDT (bits0-15: Table limit, bits16-47: Base address)
lgdt GDT_LOC+(tableGdtDescriptor-tableGdt)
// Kill the LDT, if any
xor %eax, %eax
lldt %ax
// Reload CS as 0008 from the new GDT using a far jump
jmp $0x008, $reload_cs
reload_cs:
// CS is now a valid entry in the GDT. Set SS, DS, and ES to valid
// descriptors, but clear FS and GS as they are not necessary.
// Set SS, DS, and ES to a data32 segment with maximum limit.
movw $0x0010, %ax
mov %eax, %ss
mov %eax, %ds
mov %eax, %es
// Clear FS and GS
xor %eax, %eax
mov %eax, %fs
mov %eax, %gs
有人可以發現為什么它不起作用嗎?
獎勵問題我無法自行找到答案:
事實證明,問題出在填充IDT。 我將每個IDT條目都指向GDT中偏移量0x10處的代碼段,因此為什么需要在偏移量0x10處的編碼段。
這是我簡化了一些的固定代碼:
.code32
.section .text, "ax"
.org 0x00
jmp start_linux
.global Cromwellconfig
Cromwellconfig:
.org 0x0c
// Space for the SHA1 checksum
.org 0x20
// The Value positions are fixed, do not change them, used everywhere
.long 0x0 // 0x20 if XBE, then this bit is 0, if Cromwell mode, the bit is set to 1 by the Startuploader
.long 0x0 // 0x24 ImageRetryLoads
.long 0x0 // 0x28 Bank, from where Loaded
.long 0x0 // 0x2C 0 .. Bios = 256 k, 1 .. Bios = 1MB
.long 0x0 // 0x30 free
.long _end_complete_rom // 0x34 free
.long 0x0 // 0x38 free
.long 0x0 // free
.align 16
tableGdt:
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x00 dummy
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9b, 0xcf, 0x00 // 0x08 code32
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00 // 0x10 data32
tableGdtDescriptor:
// This is the GDT header having 8 bytes
.word tableGdtDescriptor-tableGdt - 1 // Size - 1byte
.long tableGdt // GDT location
.word 0 // Padding
tableGdtEnd:
.align 16
tableIdtDescriptor:
.word 2048
.long IDT_LOC // IDT located at 0xB0000
.word 0 // fill Word, so we get aligned again
// We are dword aligned now
.align 16
.globl start_linux
start_linux:
//Make SURE the IRQs are turned off
cli
// kill the cache = Disable bit 30 + 29 = CD + NW
// CD = Cache Disable (disable = 1)
// NW Not write through (disable = 1)
// mov %cr0, %eax
//orl $0x60000000, %eax
mov $0x60010033, %eax
mov %eax, %cr0
wbinvd
// Flush the TLB
xor %eax, %eax
mov %eax, %cr3
// We kill the Local Descriptor Table
xor %eax, %eax
lldt %ax
// DR6/DR7: Clear the debug registers
xor %eax, %eax
mov %eax, %dr6
mov %eax, %dr7
mov %eax, %dr0
mov %eax, %dr1
mov %eax, %dr2
mov %eax, %dr3
// Load the new GDT
lgdt tableGdtDescriptor
// Kill the LDT, if any
xor %eax, %eax
lldt %ax
// Reload CS as 0008 from the new GDT using a far jump
jmp $0x0008, $reload_cs
reload_cs:
// CS is now a valid entry in the GDT. Set SS, DS, and ES to valid
// descriptors, but clear FS and GS as they are not necessary.
// Set SS, DS, and ES to a data32 segment with maximum limit.
movw $0x0010, %ax
mov %eax, %ss
mov %eax, %ds
mov %eax, %es
// Clear FS and GS
xor %eax, %eax
mov %eax, %fs
mov %eax, %gs
現在,上面修改的代碼在描述符中設置了正確的GDT大小(總大小減去1個字節)。 同樣,GDT不再復制到內存中的偏移量0xA0000處。 GDT寄存器現在指向GDT的原始位置。
現在,每個IDT條目都將其選擇器設置為0x08,以匹配唯一的code32段位置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.