I've always called in "The Tim Robinson trick," as that's who I learned it from, but I'm sure others have independently used this trick of segment overflow to achieve, what-looks-to-be, a relocated kernel.
In other words, setting your code selector base to 0x4010000, for example, so that accessing code as 3GB (0xc0000000) will actually access code at 1MB (0x00100000).
This trick is fairly straightforward, but I've noticed it doesn't work in bochs. It works just fine in qemu, however.
This bothers me, as I've always thought that this was a solid mechanism, and that it should work on all systems. Is this not the case? Is anybody else using this mechanism?
Lastly, what of these new 64-bit machines? I assume I should still be able to safely assume a 32-bit overflow will occur when these chips are not configured for long mode?
Any information on this would be greatly appreciated.
Thanks,
Jeff
"Tim Robinson trick" in Bochs?
- carbonBased
- Member
- Posts: 382
- Joined: Sat Nov 20, 2004 12:00 am
- Location: Wellesley, Ontario, Canada
- Contact:
Re: "Tim Robinson trick" in Bochs?
carbonBased wrote:I've always called in "The Tim Robinson trick," as that's who I learned it from, but I'm sure others have independently used this trick of segment overflow to achieve, what-looks-to-be, a relocated kernel.
In other words, setting your code selector base to 0x4010000, for example, so that accessing code as 3GB (0xc0000000) will actually access code at 1MB (0x00100000).
This trick is fairly straightforward, but I've noticed it doesn't work in bochs. It works just fine in qemu, however.
This bothers me, as I've always thought that this was a solid mechanism, and that it should work on all systems. Is this not the case? Is anybody else using this mechanism?
Lastly, what of these new 64-bit machines? I assume I should still be able to safely assume a 32-bit overflow will occur when these chips are not configured for long mode?
You're off by a 0.
Should work on new machines too, I expect, but on the other hand, I dislike the conceptual abuse.
Re: "Tim Robinson trick" in Bochs?
Personally i use a small stub at the very beginning of the kernel that enables paging and maps some temporary pages then the first thing the kernel does is to make proper mapping and memory manager initialization.carbonBased wrote: In other words, setting your code selector base to 0x4010000, for example, so that accessing code as 3GB (0xc0000000) will actually access code at 1MB (0x00100000).
the stub must be carefully written. setup temp stack...
To write an OS you need 2 minds one for coding and other for debugging.
- carbonBased
- Member
- Posts: 382
- Joined: Sat Nov 20, 2004 12:00 am
- Location: Wellesley, Ontario, Canada
- Contact:
Re: "Tim Robinson trick" in Bochs?
I may end up going this route, myself. I'm currently using the overflow trick until the kernel pager is initialized and everything is sorted out in a more ideal manor.ces_mohab wrote: Personally i use a small stub at the very beginning of the kernel that enables paging and maps some temporary pages then the first thing the kernel does is to make proper mapping and memory manager initialization.
Unfortunately, I'm running into issues at this point, and sense bochs doesn't seem to support the overflow trick, I can't use it for debugging! For purposes of my sanity, I think I may write a minimal pager into my startup assemble.
Yes, I'm beginning to myself, as well. I'm attempting to make the location of my kernel configurable at build time, and the overflow trick fit in nicely with this, but I don't think I want to eliminate bochs support, as its a useful debugger.candy wrote: but on the other hand, I dislike the conceptual abuse.
--Jeff
- salil_bhagurkar
- Member
- Posts: 261
- Joined: Mon Feb 19, 2007 10:40 am
- Location: India
- carbonBased
- Member
- Posts: 382
- Joined: Sat Nov 20, 2004 12:00 am
- Location: Wellesley, Ontario, Canada
- Contact:
It relies on a 32-bit overflow of a GDT selector base and an offset to produce code/data that "thinks" it's at one location, when it's really at another, without using the pager.
See the Tim Robinson link in this wiki page:
http://www.osdev.org/wiki/Higher_Half_Kernel
--Jeff
See the Tim Robinson link in this wiki page:
http://www.osdev.org/wiki/Higher_Half_Kernel
--Jeff
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Hmm strange. A test setup (written from scratch) works properly
What version of bochs are you using? (i have 2.2.6 and 2.3, both work correctly)
As for 64 bit cpu's, I doubt they want to break the existing architecture (i should test this again with my amd64).
Anyway, my setup for reference:
What version of bochs are you using? (i have 2.2.6 and 2.3, both work correctly)
As for 64 bit cpu's, I doubt they want to break the existing architecture (i should test this again with my amd64).
Anyway, my setup for reference:
Code: Select all
; we are loaded at 0x7c00
; relocate to higherhalf and
; use GDT to map 0xC0000000 -> 0x0
ORG 0xC0007C00
BITS 16
; some position independent code to avoid multiple ORGs
; (as that doesnt work in NASM, not tested with YASM)
start: CLI ; disable ints to not break protected mode code
XOR AX, AX
MOV DS, AX
MOV ES, AX ; load segments to 0x0
LGDT [0x7C00 + 0x40 - 6] ; load gdtr
MOV EAX, CR0
OR AL, 1
MOV CR0, EAX ; enter protected mode
JMP dword 0x10:pm_entry
times 0x40-6 - ($-$$) DB 0
gdtr: DW 4 * 8 - 1
DD 0x7c00 + 0x40
gdt:
gdtNULLSel EQU $-gdt
DD 0
DD 0
gdtKData:
gdtKDataSel EQU $-gdt
DW 0xFFFF ; limit is 0xFFFFF, lower 16 bits
DW 0
DB 0
DB 0x92
DB 0xCF ; limit is 0xFFFFF, top 4 bits
DB 0x40 ; base is 0x40000000; 0x400..+0xC00.. = 0x100000000 (where the 1 ends up ignored)
gdtKCode:
gdtKCodeSel EQU $-gdt
DW 0xFFFF ; limit is 0xFFFFF, lower 16 bits
DW 0
DB 0
DB 0x9a
DB 0xCF ; limit is 0xFFFFF, top 4 bits
DB 0x40 ; base is 0x40000000
gdtKFlat: EQU $-gdt
DW 0xFFFF ; limit is 0xFFFFF, lower 16 bits
DW 0
DB 0
DB 0x92
DB 0xCF ; limit is 0xFFFFF, top 4 bits
DB 0x00 ; base is 0, for writing to video memory
BITS 32
pm_entry: MOV AX, 0x8
MOV DS, AX
MOV ES, AX
MOV AX, 0x18
MOV FS, AX
MOV GS, AX
MOV EDI, 0xB8000 ; target is video memory
MOV ESI, string ; source is a string somewhere in 0xC0007Cxx
looppoint:
MOV AX, [ESI] ; load from DS using overflow
OR AX, AX ; test for null terminator
JZ done
MOV [FS:EDI], AX ; write to FS which is flat selector
ADD ESI, 2
ADD EDI, 2
JMP looppoint ; increment pointers and loop
; lock up
done: HLT
; On bochs you should get 'All ok' in the top-left
string: DB 'A', 7, 'l', 7, 'l', 7, ' ', 7, 'o', 7, 'k', 7, 0, 0
; boot signature
times 510-($-$$) DB 0
DB 0x55, 0xAA
Re: "Tim Robinson trick" in Bochs?
carbonBased wrote:I've always called in "The Tim Robinson trick," as that's who I learned it from, but I'm sure others have independently used this trick of segment overflow to achieve, what-looks-to-be, a relocated kernel.
In other words, setting your code selector base to 0x4010000, for example, so that accessing code as 3GB (0xc0000000) will actually access code at 1MB (0x00100000).
This trick is fairly straightforward, but I've noticed it doesn't work in bochs. It works just fine in qemu, however.
This bothers me, as I've always thought that this was a solid mechanism, and that it should work on all systems. Is this not the case? Is anybody else using this mechanism?
Lastly, what of these new 64-bit machines? I assume I should still be able to safely assume a 32-bit overflow will occur when these chips are not configured for long mode?
Any information on this would be greatly appreciated.
Thanks,
Jeff
Bochs compiled with 64-bit emulaton support was not working correctly and not implemeted linear address truncation to 32-bit in legacy (non long64) mode.
In Bochs compiled without 64-bit the linear address stored in 32-bit variable so the truncation happens naturally.
I fixed it (hopefully) in todays Bochs's CVS and will be appreciated if you could run your test and see if it works as expected. Hopefully you are still have the code to do that.
Thanks,
Stanislav