Page 1 of 1

"Tim Robinson trick" in Bochs?

Posted: Fri Mar 09, 2007 6:26 pm
by carbonBased
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

Re: "Tim Robinson trick" in Bochs?

Posted: Sat Mar 10, 2007 2:51 am
by Candy
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?

Posted: Sat Mar 10, 2007 5:54 am
by ces_mohab
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).
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.

the stub must be carefully written. setup temp stack...

Re: "Tim Robinson trick" in Bochs?

Posted: Sat Mar 10, 2007 10:07 am
by carbonBased
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.
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.

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.
candy wrote: but on the other hand, I dislike the conceptual abuse.
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.

--Jeff

Posted: Sat Mar 10, 2007 11:38 am
by salil_bhagurkar
What is this overflow trick and whats the purpose?

Posted: Sat Mar 10, 2007 6:44 pm
by carbonBased
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

Posted: Sun Mar 11, 2007 7:17 am
by Combuster
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:

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?

Posted: Mon Apr 07, 2008 12:58 pm
by stlw
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