Page 1 of 1
LGDT and RETF
Posted: Tue May 17, 2005 11:50 am
by fraserjgordon
My kernel uses dynamically allocated segment selectors so I cannot do the traditional "ljmp Selector, Offset" jump after loading the GDT without resorting to self-modifying code, which I prefer to avoid.
Is it safe (and portable among Intel-compatible processors) to instead use:
Code: Select all
pushl %edx;
pushl $Offset;
lgdt (%ecx);
lret
Where edx contains the selector and ecx contains the GDT Descriptor address.
I believe pushing 32-bits is correct for the selector, as a lret (retf) pops 32-bits for the selector and discards the top 16-bits (according to Intel
)
This seems to work on Bochs and my Pentium 4, but I don't have other PCs to test it on. Does anyone else have experience of using this method?
Thanks in advance,
Fraser
Re:LGDT and RETF
Posted: Tue May 17, 2005 2:28 pm
by gaf
Hello,
I don't know about the portability of your code, but there's an alternative from which I know that it's supported by all 386+. These processors support a (far) jump that gets its destination selector and offset from the memory address that is given as an operator.
Code: Select all
; still in real-mode..
mov dword [pmode_jump], pmode_entry
mov word [pmode_jump+4], selector
lgdt [label]
pmode_entry:
...
pmode_jump:
offset dd 0
selector dw 0
http://alien.dowling.edu/~rohit/nasmdocb.html#section-B.133
"The JMP FAR mem forms execute a far jump by loading the destination address out of memory. The address loaded consists of 16 or 32 bits of offset (depending on the operand size), and 16 bits of segment. The operand size may be overridden using JMP WORD FAR mem or JMP DWORD FAR mem."
regards,
gaf
Re:LGDT and RETF
Posted: Wed May 18, 2005 5:27 am
by Pype.Clicker
afaik, the 'retf' technique should work. you could also make sure that a few segments are pre-allocated so that you can hardcode the jump to pmode.
@gaf: what you suggest actually do use 'self-modifying code' which Gordon seems to try to avoid. Note that iirc, a 'jmp .next" would be welcome after the mov [pmode_jmp+4] instruction to flush pre-decoded instructions.
Re:LGDT and RETF
Posted: Wed May 18, 2005 9:31 am
by gaf
Hi,
what I've posted is not self-modifying code, it's just wrong
For some reason I have forgotten the all important jump-instruction..
Code: Select all
mov dword [destination], pmode_entry
mov word [destination+4], selector
lgdt [my_gdt]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp far dword [destination] ; <---
pmode_entry:
; add tons of pmode code here
destination:
dd 0 ; offset
dw 0 ; selector to be used
It works (more or less) the same way as the retf-trick, except that it's more offical and therefore probably also more reliable..
regards,
gaf
Re:LGDT and RETF
Posted: Wed May 18, 2005 5:12 pm
by fraserjgordon
Thanks very much for the quick replies. If you were wondering, I'm not using self-modifying code because the pages covering kernel code are marked as read-only and this reloading of the GDT is after enabling paging to update it to the new linear address. The entire read-only code thing is to allow for post-mortem debugging of crashes. I know Bochs lets you do this, but it doesn't really help you when on real hardware!
Thanks again,
Fraser
Re:LGDT and RETF
Posted: Thu May 26, 2005 1:12 pm
by Kim
Using retf should work without any probs (tested it on a old 386), even intel docs say you can use it as an option to setup CS.
[tt]
Implied load instructions such as the far pointer versions of the CALL, JMP, and RET
instructions, the SYSENTER and SYSEXIT instructions, and the IRET, INTn, INTO and
INT3 instructions. These instructions change the contents of the CS register (and
sometimes other segment registers) as an incidental part of their operation.
[/tt]
Code: Select all
procedure kload_gdt(); assembler; [public, alias: 'kload_gdt'];
asm
push dword GDT_KERNEL_CODE_SEL
push dword offset @loadedcs
lgdt gdtr
retf
@loadedcs:
mov ax, GDT_KERNEL_DATA_SEL
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
end ['EAX'];