Now that we are using romcc, and all functions are inline, it is getting increasingly painful to deal with linuxbios images smaller than 64k. This problem happens as we need a 16-bit jump to the start of the linuxbios code, which limits us to jumping to 0xffff0000. But if linuxbios is bigger than that, we need to be able to jmp to 0xfffe0000, which is not possible with the current setup.
We can grow this if we do the following:
make reset a rel jump to 0xfffffff0 - (sizeof entry16). Then put entry 16 right before 0xfffffff0. Entry16 code turns on 32-bit mode and then jumps to the real start of the linuxbios image -- which can now be anywhere in the flash image. I could use this now, as could others.
here is sample code which I am trying. It now assembles and inspection of the object reveals that it is certainly close to correct.
Here's where I wish I had a really good emulator for linux -- checking this out would be a whole lot easier.
The test reset16 code:
.section .reset .code16
.globl rgdtptr16 .globl reset_start .type reset_start, @function
reset_start: cli
xorl %eax, %eax movl %eax, %cr3 /* Invalidate TLB*/ invd movw %cs, %ax shlw $4, %ax movw $gdtptr16_offset, %bx subw %ax, %bx data32 lgdt %cs:(%bx)
movl %cr0, %eax andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ orl $0x60000001, %eax /* CD, NW, PE = 1 */ movl %eax, %cr0
/* Now that we are in protected mode jump to a 32 bit code segment. */ data32 ljmp $ROM_CODE_SEG, $__protected_start
/** The gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment * at 0x18; these are Linux-compatible. */
.align 4 .globl rgdtptr16 rgdtptr16: .word gdt_end - gdt -1 /* compute the table limit */ .long gdt /* we know the offset */
.globl reset_vector .align 4 reset_vector: jmp reset_start
The net effect is this: 16-bit reset jmps to a very small startup code right before 0xfffffff0 that enables full 32-bit mode. We can then jmp anywhere we want -- to 0xfffe0000 for example -- which we can't do now. This will alleviate the problem of linuxbios images growing to > 64K which is a consequence of romcc right now. This will allow us to live with really big linuxbios images until romcc makes tighter code.
Comments? Errors in the code?
thanks
ron
* ron minnich rminnich@lanl.gov [030723 02:48]:
make reset a rel jump to 0xfffffff0 - (sizeof entry16). Then put entry 16 right before 0xfffffff0. Entry16 code turns on 32-bit mode and then jumps to the real start of the linuxbios image -- which can now be anywhere in the flash image. I could use this now, as could others.
Sounds pretty good!
Here's where I wish I had a really good emulator for linux -- checking this out would be a whole lot easier.
Have you tried this in bochs? It showed up to be pretty ok for bios testing (as long as you don't test hw init of course)
Stefan
On Wed, 23 Jul 2003, Stefan Reinauer wrote:
- ron minnich rminnich@lanl.gov [030723 02:48]:
make reset a rel jump to 0xfffffff0 - (sizeof entry16). Then put entry 16 right before 0xfffffff0. Entry16 code turns on 32-bit mode and then jumps to the real start of the linuxbios image -- which can now be anywhere in the flash image. I could use this now, as could others.
Sounds pretty good!
it sounded good to me too :-)
sadly, it appears that 0xffe0000 is not enabled at hardware startup.
Stefan, what makes sense to do for this problem?
One option is to grow this idea a bit: have the 32-bit mode enable right below 0xfffffff0, but include in that a flash enable. Then it would work.
By far the simplest thing to do is make it possible to move c_payload around, say to 0xfffe0000
ron
* ron minnich rminnich@lanl.gov [030723 16:58]:
make reset a rel jump to 0xfffffff0 - (sizeof entry16). Then put entry 16 right before 0xfffffff0. Entry16 code turns on 32-bit mode and then jumps to the real start of the linuxbios image -- which can now be anywhere in the flash image. I could use this now, as could others.
sadly, it appears that 0xffe0000 is not enabled at hardware startup.
One option is to grow this idea a bit: have the 32-bit mode enable right below 0xfffffff0, but include in that a flash enable. Then it would work.
If a flash enable can always happen that early, this is definitely a good idea, as we want to know our code as soon as possible.
On the K8 this might mean that this early code has to contain all of:
* check if BSP * coherent ht init * non coherent ht enumeration * enable flash
before actually jumping anywhere down. Don't know if that would all fit.
By far the simplest thing to do is make it possible to move c_payload around, say to 0xfffe0000
if this means that we can easily make linuxbios fallback and normal share the same payload, it would be my fav.
Stefan
On Wed, 23 Jul 2003, Stefan Reinauer wrote:
By far the simplest thing to do is make it possible to move c_payload around, say to 0xfffe0000
if this means that we can easily make linuxbios fallback and normal share the same payload, it would be my fav.
not sure about that. Currently the layout is something like this:
0xffff0000: linuxbios startup ffff9a30: c_payload fffffff0: reset16
If linuxbios startup enables flash in lower addresses, we ought to be able to do this: 0xfffe0000: c_payload 0xffff0000: linuxbios startup 0xfffffff0: reset16
Life would be easier ... we could have lots of debug ...
ron
* ron minnich rminnich@lanl.gov [030723 17:15]:
On Wed, 23 Jul 2003, Stefan Reinauer wrote:
if this means that we can easily make linuxbios fallback and normal share the same payload, it would be my fav.
not sure about that. Currently the layout is something like this:
ah,.. my fault.. i mixed up c_payload with the elf payload.
0xffff0000: linuxbios startup ffff9a30: c_payload fffffff0: reset16
If linuxbios startup enables flash in lower addresses, we ought to be able to do this: 0xfffe0000: c_payload 0xffff0000: linuxbios startup 0xfffffff0: reset16
since linuxbios startup does ht enumeration anyways before jumping into c_payload, this should not be a problem
Stefan
ron minnich wrote:
make reset a rel jump to 0xfffffff0 - (sizeof entry16). Then put entry 16 right before 0xfffffff0. Entry16 code turns on 32-bit mode and then jumps to the real start of the linuxbios image -- which can now be anywhere in the flash image. I could use this now, as could others.
I suggested this last year, with the comment that this is a more traditional way that embedded systems start up. Your objections at the time were that it would cause trouble with some motherboards, but I don't remember the specifics. I was wanting to do this since it is clear that we will be getting 2 Mbyte LPC soon and be able to boot Linux easily out of flash (as I think you have already done).
One caveat I discovered, I could never get Linux to boot with a gdt located higher than 1M. So even if you put a linux compatible gdt high, it has to be moved to ram < 1M or linux hangs on boot. Never figured out why (true for 2.4 anyway).
Also, on the dynamic/static trees, one thing to consider in the mix is the serial ATA. I think it is an external chip now but will be subsumed into the bridge chips at some point. Not sure how a chip function moving around like this affects the software design.
-Steve
On Wed, 23 Jul 2003, Steve Gehlbach wrote:
I suggested this last year, with the comment that this is a more traditional way that embedded systems start up. Your objections at the time were that it would cause trouble with some motherboards, but I don't remember the specifics. I was wanting to do this since it is clear that we will be getting 2 Mbyte LPC soon and be able to boot Linux easily out of flash (as I think you have already done).
you have an inconvenient memory: you were right and I was wrong :-)
One caveat I discovered, I could never get Linux to boot with a gdt located higher than 1M. So even if you put a linux compatible gdt high, it has to be moved to ram < 1M or linux hangs on boot. Never figured out why (true for 2.4 anyway).
we're not seeing this. We have GDTs in very high memory and it all works. Interesting.
Also, on the dynamic/static trees, one thing to consider in the mix is the serial ATA. I think it is an external chip now but will be subsumed into the bridge chips at some point. Not sure how a chip function moving around like this affects the software design.
I think it might work. On the Acer, the IDE controller has always been in that static initialization. In fact, the superio architecture was motivated by the acer chip.
ron
* ron minnich rminnich@lanl.gov [030723 18:08]:
On Wed, 23 Jul 2003, Steve Gehlbach wrote:
One caveat I discovered, I could never get Linux to boot with a gdt located higher than 1M. So even if you put a linux compatible gdt high, it has to be moved to ram < 1M or linux hangs on boot. Never figured out why (true for 2.4 anyway).
we're not seeing this. We have GDTs in very high memory and it all works. Interesting.
Could this cause the hang with ADLO/rombios when booting grub on K8? Grub seems to hang right when it switches to pmode the first time.
Stefan
Stefan Reinauer wrote:
One caveat I discovered, I could never get Linux to boot with a gdt located higher than 1M. So even if you put a linux compatible gdt high, it has to be moved to ram < 1M or linux hangs on boot. Never figured out why (true for 2.4 anyway).
Could this cause the hang with ADLO/rombios when booting grub on K8? Grub seems to hang right when it switches to pmode the first time.
For me, it happened every time, so I don't know what "first time" means. I guess I could have been doing something really stupid (I regret to admit this is possible), but I do recall making a number of before and after tests with a number of different memory addresses.
-Steve
* Steve Gehlbach steve@nexpath.com [030723 19:24]:
One caveat I discovered, I could never get Linux to boot with a gdt located higher than 1M. So even if you put a linux compatible gdt high, it has to be moved to ram < 1M or linux hangs on boot. Never figured out why (true for 2.4 anyway).
Could this cause the hang with ADLO/rombios when booting grub on K8? Grub seems to hang right when it switches to pmode the first time.
For me, it happened every time, so I don't know what "first time" means. I guess I could have been doing something really stupid (I regret to admit this is possible), but I do recall making a number of before and after tests with a number of different memory addresses.
Ah, i should have been more exact. I traced the code and grub runs fine, loads it's second stage boot loader, and then early in second stage, it switches to protected mode. I think it switches back and forth a couple of times (prot_to_real/real_to_prot), but I never get over the very first switching that occurs at all. But it does hang every time.
Stefan
ron minnich wrote:
One caveat I discovered, I could never get Linux to boot with a gdt located higher than 1M. So even if you put a linux compatible gdt high, it has to be moved to ram < 1M or linux hangs on boot. Never figured out why (true for 2.4 anyway).
we're not seeing this. We have GDTs in very high memory and it all works. Interesting.
Hmm... are you sure? I tested this many times, and it was also reported on the Xbox project as well. Since Eric put in c_start.S, it has been located in RAM < 1M (moved with the C code), but I don't know how v2 is doing it, haven't looked at it. The latest kernel I tested was 2.4.18 I believe. I have never gotten the kernel to boot with the gdt in flash, where the addresses were just under 4G. And it doesn't seem to have anything to do with the RO nature of flash.
-Steve
On Wed, 23 Jul 2003, Steve Gehlbach wrote:
Hmm... are you sure? I tested this many times, and it was also reported on the Xbox project as well. Since Eric put in c_start.S, it has been located in RAM < 1M (moved with the C code), but I don't know how v2 is doing it, haven't looked at it. The latest kernel I tested was 2.4.18 I believe. I have never gotten the kernel to boot with the gdt in flash, where the addresses were just under 4G. And it doesn't seem to have anything to do with the RO nature of flash.
I'll try to find the code for you.
ron