EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Trying to load GDT into a psycho-Pentium

Started by Ignacio G.T. September 30, 2004
Hello everybody.

I'm having problems trying to start up a new Pentium-based CPU. It has 8 MB of
RAM (lowest addresses) and 8 MB of FLASH memory (highest addresses).

I can load programs with a PC via JTAG into the FLASH (4 chips of 1Mx16,
arranged as 1 Mibi of 64-bit words), and I can control the CPU with a Microtek
JTAG-ICE (with no trace memory).

I can start the programs, step by step or with a 'go forever' command, and all
my real-mode programs work as expected. But when I try to load the GDT before
switching to protected mode, the program seems to jump to a random address,
where it sometimes stops (perhaps after executing a break instruction) and
sometimes not (in which cause I can stop the ICE, and CS:EIP is pointing to a
random address, anyway)

I tried to stop the program with a HLT instruction after the LGDT instruction,
to no avail.

This is the reset vector, as disassembled by the ICE:

dasm cs:fff0 cs:fff1
// CS:FFF0 FA           CLI
// CS:FFF1 E90CF8       JMP         F800

This is the code from the first jump target. Remeber, I can execute the code
just up to (and excluding) CS:F810.

dasm cs:f800
// CS:F800 FA           CLI
// CS:F801 B001         MOV         AL,01
// CS:F803 B200         MOV         DL,00
// CS:F805 B602         MOV         DH,02
// CS:F807 EE           OUT         DX,AL
// CS:F808 67668D1D4BF8 LEA         EBX,[FFFFF84B]
// CS:F80E FFFF
// CS:F810 67660F011588 LGDT        [FFFFF888]
// CS:F816 F8FFFF
// CS:F819 F4           HLT
// CS:F81A 90           NOP
// CS:F81B 90           NOP

This the GDT length + linear address:

dump fffff888p
// FFFFF888P  17 00 90 F8 FF FF

i.e., length = 0x17 +1 = 24 (3 entries), address = 0xFFFFF890

This is the GDT:

dump fffff890p fffff8a7p word 
// FFFFF890P  0000 0000 0000 0000 FFFF 0000 9A00 00CF 
// FFFFF8A0P  FFFF 0000 9200 00CF 

i.e.:
selector 0 (0x00): null descriptor
selector 1 (0x08): code, 32 GB, read-only
selector 2 (0x10): data, 32 GB, read-write

These are the CPU registers before execution the LGDT instruction:

//      EIP = 0x0000F810
//      ESP = 0x00000000
//      EBP = 0x00000000
//      EAX = 0x00000001
//      EBX = 0xFFFFF84B
//      ECX = 0x00000000
//      EDX = 0x00000200
//      ESI = 0x00000000
//      EDI = 0x00000000
//   EFLAGS = 0x00000002
//          = ivfavrn0oditszapc
//       CS = 0xF000
//       DS = 0x0000
//       ES = 0x0000
//       FS = 0x0000
//       GS = 0x0000
//       SS = 0x0000
//  GDTBASE = 0x00000000
// GDTLIMIT = 0xFFFF
//  IDTBASE = 0x00000000
// IDTLIMIT = 0xFFFF
//     LDTR = 0x0000
//       TR = 0x0000
//      CR0 = 0x60000010
//      CR2 = 0x00000000
//      CR3 = 0x00000000
//      CR4 = 0x00000008
//  LDTBASE = 0x00000000
// LDTLIMIT = 0xFFFF
//   CSBASE = 0xFFFF0000
//   DSBASE = 0x00000000
//   ESBASE = 0x00000000
//   FSBASE = 0x00000000
//   GSBASE = 0x00000000
//   SSBASE = 0x00000000
//  CSLIMIT = 0x0000FFFF
//  DSLIMIT = 0x0000FFFF
//  ESLIMIT = 0x0000FFFF
//  FSLIMIT = 0x0000FFFF
//  GSLIMIT = 0x0000FFFF
//  SSLIMIT = 0x0000FFFF
//     CSAR = 0x00009300
//     DSAR = 0x00009300
//     ESAR = 0x00009300
//     FSAR = 0x00009300
//     GSAR = 0x00009300
//     SSAR = 0x00009300
//    GDTAR = 0x00008200
//    IDTAR = 0x00008200
//    LDTAR = 0x00008200
//  TSSBASE = 0x00000000
// TSSLIMIT = 0x0000FFFF
//    TSSAR = 0x00008200

And these are the CPU register after the LGDT instruction + unknown
instructions:

register 
//      EIP = 0x00007D07
//      ESP = 0x0000FFF3
//      EBP = 0x00000000
//      EAX = 0x00000001
//      EBX = 0xFFFFA04B
//      ECX = 0x00005FBE
//      EDX = 0x000001FF
//      ESI = 0x00000000
//      EDI = 0x00000000
//   EFLAGS = 0x00000016
//          = ivfavrn0oditszAPc
//       CS = 0x46BB
//       DS = 0x0000
//       ES = 0x0000
//       FS = 0x0000
//       GS = 0x0000
//       SS = 0x0000
//  GDTBASE = 0x00000000
// GDTLIMIT = 0xFFFF
//  IDTBASE = 0x00000000
// IDTLIMIT = 0xFFFF
//     LDTR = 0x0000
//       TR = 0x0000
//      CR0 = 0x60000010
//      CR2 = 0x00000000
//      CR3 = 0x00000000
//      CR4 = 0x00000008
//  LDTBASE = 0x00000000
// LDTLIMIT = 0xFFFF
//   CSBASE = 0x00046BB0
//   DSBASE = 0x00000000
//   ESBASE = 0x00000000
//   FSBASE = 0x00000000
//   GSBASE = 0x00000000
//   SSBASE = 0x00000000
//  CSLIMIT = 0x0000FFFF
//  DSLIMIT = 0x0000FFFF
//  ESLIMIT = 0x0000FFFF
//  FSLIMIT = 0x0000FFFF
//  GSLIMIT = 0x0000FFFF
//  SSLIMIT = 0x0000FFFF
//     CSAR = 0x00009300
//     DSAR = 0x00009300
//     ESAR = 0x00009300
//     FSAR = 0x00009300
//     GSAR = 0x00009300
//     SSAR = 0x00009300
//    GDTAR = 0x00008200
//    IDTAR = 0x00008200
//    LDTAR = 0x00008200
//  TSSBASE = 0x00000000
// TSSLIMIT = 0x0000FFFF
//    TSSAR = 0x00008200

Can anybody please throw some light ?

--
Ignacio G.T.
bear in mind the processor WILL do segmentation faults while in real mode, I don't
remember whether it is a catch-all or if there are more restrictive rules though.
So if you really can't figure things like this out you might hook int 0x0d and see
if it gets triggered.

It has been a while since I did raw protected mode, but the one thing that jumps
out at me is you are
reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on
DS is 0ffffh according to your dumps.  This is I think what you do get when you
boot...   I am wondering if you may get a segmentation fault under these
conditions?   I don't know for sure on this since I haven't dealt with the boot-up
process personally.  But if this is the case you can get around it by forcing a
CS: prefix on the faulting instruction and changing the offset accordingly.

David

"Ignacio G.T." wrote:

> Hello everybody. > > I'm having problems trying to start up a new Pentium-based CPU. It has 8 MB of > RAM (lowest addresses) and 8 MB of FLASH memory (highest addresses). > > I can load programs with a PC via JTAG into the FLASH (4 chips of 1Mx16, > arranged as 1 Mibi of 64-bit words), and I can control the CPU with a Microtek > JTAG-ICE (with no trace memory). > > I can start the programs, step by step or with a 'go forever' command, and all > my real-mode programs work as expected. But when I try to load the GDT before > switching to protected mode, the program seems to jump to a random address, > where it sometimes stops (perhaps after executing a break instruction) and > sometimes not (in which cause I can stop the ICE, and CS:EIP is pointing to a > random address, anyway) > > I tried to stop the program with a HLT instruction after the LGDT instruction, > to no avail. > > This is the reset vector, as disassembled by the ICE: > > dasm cs:fff0 cs:fff1 > // CS:FFF0 FA CLI > // CS:FFF1 E90CF8 JMP F800 > > This is the code from the first jump target. Remeber, I can execute the code > just up to (and excluding) CS:F810. > > dasm cs:f800 > // CS:F800 FA CLI > // CS:F801 B001 MOV AL,01 > // CS:F803 B200 MOV DL,00 > // CS:F805 B602 MOV DH,02 > // CS:F807 EE OUT DX,AL > // CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] > // CS:F80E FFFF > // CS:F810 67660F011588 LGDT [FFFFF888] > // CS:F816 F8FFFF > // CS:F819 F4 HLT > // CS:F81A 90 NOP > // CS:F81B 90 NOP > > This the GDT length + linear address: > > dump fffff888p > // FFFFF888P 17 00 90 F8 FF FF > > i.e., length = 0x17 +1 = 24 (3 entries), address = 0xFFFFF890 > > This is the GDT: > > dump fffff890p fffff8a7p word > // FFFFF890P 0000 0000 0000 0000 FFFF 0000 9A00 00CF > // FFFFF8A0P FFFF 0000 9200 00CF > > i.e.: > selector 0 (0x00): null descriptor > selector 1 (0x08): code, 32 GB, read-only > selector 2 (0x10): data, 32 GB, read-write > > These are the CPU registers before execution the LGDT instruction: > > // EIP = 0x0000F810 > // ESP = 0x00000000 > // EBP = 0x00000000 > // EAX = 0x00000001 > // EBX = 0xFFFFF84B > // ECX = 0x00000000 > // EDX = 0x00000200 > // ESI = 0x00000000 > // EDI = 0x00000000 > // EFLAGS = 0x00000002 > // = ivfavrn0oditszapc > // CS = 0xF000 > // DS = 0x0000 > // ES = 0x0000 > // FS = 0x0000 > // GS = 0x0000 > // SS = 0x0000 > // GDTBASE = 0x00000000 > // GDTLIMIT = 0xFFFF > // IDTBASE = 0x00000000 > // IDTLIMIT = 0xFFFF > // LDTR = 0x0000 > // TR = 0x0000 > // CR0 = 0x60000010 > // CR2 = 0x00000000 > // CR3 = 0x00000000 > // CR4 = 0x00000008 > // LDTBASE = 0x00000000 > // LDTLIMIT = 0xFFFF > // CSBASE = 0xFFFF0000 > // DSBASE = 0x00000000 > // ESBASE = 0x00000000 > // FSBASE = 0x00000000 > // GSBASE = 0x00000000 > // SSBASE = 0x00000000 > // CSLIMIT = 0x0000FFFF > // DSLIMIT = 0x0000FFFF > // ESLIMIT = 0x0000FFFF > // FSLIMIT = 0x0000FFFF > // GSLIMIT = 0x0000FFFF > // SSLIMIT = 0x0000FFFF > // CSAR = 0x00009300 > // DSAR = 0x00009300 > // ESAR = 0x00009300 > // FSAR = 0x00009300 > // GSAR = 0x00009300 > // SSAR = 0x00009300 > // GDTAR = 0x00008200 > // IDTAR = 0x00008200 > // LDTAR = 0x00008200 > // TSSBASE = 0x00000000 > // TSSLIMIT = 0x0000FFFF > // TSSAR = 0x00008200 > > And these are the CPU register after the LGDT instruction + unknown > instructions: > > register > // EIP = 0x00007D07 > // ESP = 0x0000FFF3 > // EBP = 0x00000000 > // EAX = 0x00000001 > // EBX = 0xFFFFA04B > // ECX = 0x00005FBE > // EDX = 0x000001FF > // ESI = 0x00000000 > // EDI = 0x00000000 > // EFLAGS = 0x00000016 > // = ivfavrn0oditszAPc > // CS = 0x46BB > // DS = 0x0000 > // ES = 0x0000 > // FS = 0x0000 > // GS = 0x0000 > // SS = 0x0000 > // GDTBASE = 0x00000000 > // GDTLIMIT = 0xFFFF > // IDTBASE = 0x00000000 > // IDTLIMIT = 0xFFFF > // LDTR = 0x0000 > // TR = 0x0000 > // CR0 = 0x60000010 > // CR2 = 0x00000000 > // CR3 = 0x00000000 > // CR4 = 0x00000008 > // LDTBASE = 0x00000000 > // LDTLIMIT = 0xFFFF > // CSBASE = 0x00046BB0 > // DSBASE = 0x00000000 > // ESBASE = 0x00000000 > // FSBASE = 0x00000000 > // GSBASE = 0x00000000 > // SSBASE = 0x00000000 > // CSLIMIT = 0x0000FFFF > // DSLIMIT = 0x0000FFFF > // ESLIMIT = 0x0000FFFF > // FSLIMIT = 0x0000FFFF > // GSLIMIT = 0x0000FFFF > // SSLIMIT = 0x0000FFFF > // CSAR = 0x00009300 > // DSAR = 0x00009300 > // ESAR = 0x00009300 > // FSAR = 0x00009300 > // GSAR = 0x00009300 > // SSAR = 0x00009300 > // GDTAR = 0x00008200 > // IDTAR = 0x00008200 > // LDTAR = 0x00008200 > // TSSBASE = 0x00000000 > // TSSLIMIT = 0x0000FFFF > // TSSAR = 0x00008200 > > Can anybody please throw some light ? > > -- > Ignacio G.T.
igtorque.remove@evomer.yahoo.es (Ignacio G.T.) wrote:

>// CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] >// CS:F80E FFFF >// CS:F810 67660F011588 LGDT [FFFFF888] >// CS:F816 F8FFFF >// CS:F819 F4 HLT
32-bit addresses greater than 0xFFFF are illegal in real mode, and cause CPU interrupt 13 (the "pseudo-GPF"). Maybe the CPU jumps to the int 13 vector before HLT is executed. I don't think the LEA instruction causes an exception because the 32-bit address is not de-referenced.
>These are the CPU registers before execution the LGDT instruction: >// EIP = 0x0000F810 >// CS = 0xF000 >// CSBASE = 0xFFFF0000
>And these are the CPU register after the LGDT instruction + unknown >instructions: > >// EIP = 0x00007D07 >// CS = 0x46BB >// CSBASE = 0x00046BB0
_Something_ has caused a far JMP. The INT 13 vector is stored in the 32-bit value at memory location 0x34. Is this value 0x46BB7D07 by chance? P.S. - notice the strange value of CSBASE after reset. If you change the value of the CS register while still in real mode, the CS segment descriptor cache (CSBASE) will be reloaded, and your program will fall down into conventional memory (below 1 megabyte). P.P.S. - I ran your code through Bochs and got this: ======================================================================== Bochs x86 Emulator 2.0 December 21, 2002 ======================================================================== [0x000ffff0] f000:fff0 (unk. ctxt): cli ; fa <bochs:1> setpmem 0x18 4 0x100dead0 (exception 6 -- illegal instruction) <bochs:2> setpmem 0x30 4 0x200dead0 (exception 12 -- stack fault) <bochs:3> setpmem 0x34 4 0x300dead0 (exception 13 -- GPF) <bochs:4> s Next at t=1 (0) [0x000ffff1] f000:fff1 (unk. ctxt): jmp f800 ; e90cf8 <bochs:5> s Next at t=2 (0) [0x000ff800] f000:f800 (unk. ctxt): cli ; fa <bochs:6> s Next at t=3 (0) [0x000ff801] f000:f801 (unk. ctxt): mov AL, 01 ; b001 <bochs:7> s Next at t=4 (0) [0x000ff803] f000:f803 (unk. ctxt): mov DL, 00 ; b200 <bochs:8> s Next at t=5 (0) [0x000ff805] f000:f805 (unk. ctxt): mov DH, 02 ; b602 <bochs:9> s Next at t=6 (0) [0x000ff807] f000:f807 (unk. ctxt): out DX, AL ; ee <bochs:10> s Next at t=7 (0) [0x000ff808] f000:f808 (unk. ctxt): lea EBX, DS:fffff84b ; 66678d1d4bf8ffff <bochs:11> s Next at t=8 (0) [0x000ff810] f000:f810 (unk. ctxt): lgdt DS:fffff888 ; 670f011588f8ffff <bochs:12> s Next at t=9 (0) [0x0003eba2] 300d:ead2 (unk. ctxt): add DS:[BX+SI], AL ; 0000 <bochs:13>
On Fri, 01 Oct 2004 00:20:59 GMT, David Lindauer <camille@bluegrass.net> wrote:

>bear in mind the processor WILL do segmentation faults while in real mode, I don't >remember whether it is a catch-all or if there are more restrictive rules though. >So if you really can't figure things like this out you might hook int 0x0d and see >if it gets triggered.
You are right. In fact, after posting the original message, I filled the interrupt vectors zone with pointers to difrent HLT instructions, and the GP vector (0x0d) was triggered.
>It has been a while since I did raw protected mode, but the one thing that jumps >out at me is you are >reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on >DS is 0ffffh according to your dumps. This is I think what you do get when you >boot... I am wondering if you may get a segmentation fault under these >conditions? I don't know for sure on this since I haven't dealt with the boot-up >process personally. But if this is the case you can get around it by forcing a >CS: prefix on the faulting instruction and changing the offset accordingly.
It sounds reasonable. I'm trying it right now. Thank you, David. -- Ignacio G.T.
On Fri, 01 Oct 2004 01:31:12 GMT, NoEmailAds@execpc.com (Chris Giese) wrote:

>igtorque.remove@evomer.yahoo.es (Ignacio G.T.) wrote: > >>// CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] >>// CS:F80E FFFF >>// CS:F810 67660F011588 LGDT [FFFFF888] >>// CS:F816 F8FFFF >>// CS:F819 F4 HLT > >32-bit addresses greater than 0xFFFF are illegal in real mode, >and cause CPU interrupt 13 (the "pseudo-GPF"). Maybe the CPU >jumps to the int 13 vector before HLT is executed. >
Mmm. I've read that, although on startup, CS = F000 and EIP = FFF0, the "hidden" part of CS is 0xFFFF0000, so, in fact, you are accessing the highest part of the 4GB linear address space on startup, although only through CS, not through DS, ES, ES or GS.
>I don't think the LEA instruction causes an exception because >the 32-bit address is not de-referenced.
I agree. In fact, EBX is loaded with FFFFF84B after LEA, and the processor remains controlled by the ICE at this point.
> >>These are the CPU registers before execution the LGDT instruction: >>// EIP = 0x0000F810 >>// CS = 0xF000 >>// CSBASE = 0xFFFF0000 > >>And these are the CPU register after the LGDT instruction + unknown >>instructions: >> >>// EIP = 0x00007D07 >>// CS = 0x46BB >>// CSBASE = 0x00046BB0 > >_Something_ has caused a far JMP. The INT 13 vector is stored >in the 32-bit value at memory location 0x34. Is this value >0x46BB7D07 by chance?
You are right. I know now that a GP is being caused by the LGDT instruction.
> >P.S. - notice the strange value of CSBASE after reset. If you >change the value of the CS register while still in real mode, >the CS segment descriptor cache (CSBASE) will be reloaded, and your >program will fall down into conventional memory (below 1 megabyte). > >P.P.S. - I ran your code through Bochs and got this: > >======================================================================== > Bochs x86 Emulator 2.0 > December 21, 2002 >======================================================================== >[0x000ffff0] f000:fff0 (unk. ctxt): cli ; fa ><bochs:1> setpmem 0x18 4 0x100dead0 (exception 6 -- illegal instruction) ><bochs:2> setpmem 0x30 4 0x200dead0 (exception 12 -- stack fault) ><bochs:3> setpmem 0x34 4 0x300dead0 (exception 13 -- GPF) ><bochs:4> s >Next at t=1 >(0) [0x000ffff1] f000:fff1 (unk. ctxt): jmp f800 ; e90cf8 ><bochs:5> s >Next at t=2 >(0) [0x000ff800] f000:f800 (unk. ctxt): cli ; fa ><bochs:6> s >Next at t=3 >(0) [0x000ff801] f000:f801 (unk. ctxt): mov AL, 01 ; b001 ><bochs:7> s >Next at t=4 >(0) [0x000ff803] f000:f803 (unk. ctxt): mov DL, 00 ; b200 ><bochs:8> s >Next at t=5 >(0) [0x000ff805] f000:f805 (unk. ctxt): mov DH, 02 ; b602 ><bochs:9> s >Next at t=6 >(0) [0x000ff807] f000:f807 (unk. ctxt): out DX, AL ; ee ><bochs:10> s >Next at t=7 >(0) [0x000ff808] f000:f808 (unk. ctxt): lea EBX, DS:fffff84b ; 66678d1d4bf8ffff ><bochs:11> s >Next at t=8 >(0) [0x000ff810] f000:f810 (unk. ctxt): lgdt DS:fffff888 ; 670f011588f8ffff ><bochs:12> s >Next at t=9 >(0) [0x0003eba2] 300d:ead2 (unk. ctxt): add DS:[BX+SI], AL ; 0000 ><bochs:13> >
Thank you very much, Chris. -- Ignacio G.T.
On Fri, 01 Oct 2004 09:30:57 GMT, igtorque.remove@evomer.yahoo.es (Ignacio G.T.)
wrote:

>On Fri, 01 Oct 2004 00:20:59 GMT, David Lindauer <camille@bluegrass.net> wrote: > >>bear in mind the processor WILL do segmentation faults while in real mode, I don't >>remember whether it is a catch-all or if there are more restrictive rules though. >>So if you really can't figure things like this out you might hook int 0x0d and see >>if it gets triggered. > >You are right. In fact, after posting the original message, I filled the >interrupt vectors zone with pointers to difrent HLT instructions, and the GP >vector (0x0d) was triggered. > >>It has been a while since I did raw protected mode, but the one thing that jumps >>out at me is you are >>reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on >>DS is 0ffffh according to your dumps. This is I think what you do get when you >>boot... I am wondering if you may get a segmentation fault under these >>conditions? I don't know for sure on this since I haven't dealt with the boot-up >>process personally. But if this is the case you can get around it by forcing a >>CS: prefix on the faulting instruction and changing the offset accordingly. > >It sounds reasonable. I'm trying it right now. > >Thank you, David. >
Bad news, David. I've just tried LGDT CS:[FFFFF888] and the results are the same. Intel's manual says this, for the LGDT instruction: === Real-Address Mode Exceptions ------------------------------------ #UD If source operand is not a memory location. #GP If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. #SS If a memory operand effective address is outside the SS segment limit. === We know its a #GP, but I still don't know why. Perhaps I should try copying the GDT to RAM and trying to load it from there... -- Ignacio G.T.
>=== > >We know its a #GP, but I still don't know why. Perhaps I should try copying the >GDT to RAM and trying to load it from there... >
Well, that has worked. Copy the GTD to RAM (0x0400), copy the GDT descriptor just after the GDT (0x0418), and load the GDT with LGDT 0x00000418. Now, switching to protected mode. Stay tuned... -- Ignacio G.T.
Ignacio G.T. wrote:
> Bad news, David. I've just tried > > LGDT CS:[FFFFF888] > > and the results are the same. > > Intel's manual says this, for the LGDT instruction: >
Did you try LGDT CS:[f888] Please note that the processor is in *16* bit mode till the descriptors are in and protected mode is turned on. There is somewhere in the back of my trash box a piece of code that boots an i386 into 32-bit protected mode. If it is of any help, I could find it among the dusty backup CD's. Tauno Voipio tauno voipio (at) iki fi
Looks like you have had some good advice and thinking already.  Rather than try
and understand it all, I'll just add some quick thoughts of my own.

When the processor starts up, it starts in 'real' mode.  It's still actually in
protected mode, but the internal cached versions of descriptor entries are
pre-loaded by the processor reset to use USE16 segment interpretations and to
specify default behavior that 'appears' to be real mode behavior.

In your case, you correctly identify the fact that the CPU, by default, starts
up at the end of 32-bit memory, using CS = F000 and EIP = 0000FFF0.  However,
the CS register's contents are essentially ignored during operation, as they are
meaningless to the actual hardware.  Instead, the hardware uses the "hidden"
cached copies of the descriptor, which on reset for the CS are:

  Value = F000H
  Base = FFFF0000H
  Limit = FFFFH
  AR = Present,
  R/W,
  Accessed

The value, as I said, isn't used by the bus interface unit.  It is always
ignored.  When you load a segment/selector register, the processor looks at CR0
to determine "real or protected" and then either precodes the base and limit
through a fixed calculation on the loaded value (if in real mode) or else goes
out into memory and loads them from the indicated place.  But in no case, not
ever, whether CR0 says real or protected mode, does the processor's BIU ever use
the value field.  It's ignored, except for a tiny moment in time when it first
gets loaded.

So when you say the "hidden part of CS is 0xFFFF0000" what you really mean is
that the base field of the cached area related to CS is that value.

Note that the Limit is still 0xFFFF!

This will be used, whether or not you like it, to validate any offset values you
try and apply when referring to CS.  You need your offset to remain within a 64k
area of where the CS base refers.

I *do* have to disagree with Chris when he says, "32-bit addresses greater than
0xFFFF are illegal in real mode."  It is CR0 that decides what mode your are in,
but that has absolutely nothing to do with what kind of offsets are accepted.
It is strictly the Limit field of the cached region in the CPU associated with
the selector that decides this.  And it does so without any regard whatsoever
for the CR0 status.  You can load up the CS when in protected mode and thereby
control what goes into this cache and then you can switch back to real mode and
the cached Limit field will still operate.  If you set it to some very large
limit, you will be allowed to use very large offsets even while in what is
supposed to be real mode, according to the CR0 condition.  So long as you don't
reload CS while in real mode you won't blow that cached value.  Of course, if
you do change CS while in real mode, that Limit field will immediately get
recoded back to 0xFFFF and your CS segment will again be limited.

One thing to keep in mind is that when the processor first comes out of reset it
does NOT have paging enabled.  Without paging, it is impossible to generate
anything other than 0 for the upper 4 bits of the 36 bit physical addresses.
Instead, only the low-order 32-bits are used.  The initial address executed has
to be found in the flash or ROM that must be located at that place.  The first
JMP you encounter, the one going to 0xF800, does not change the CS.  So these
addresses are still "high."

Your LGDT is executed quite quickly, I gather, after that point.  I assume that
your CR0 still has you in real mode at this point in time and that the Limit
field for the CS still applies and is tiny.  As such, your offset there is far
too big.

Also, take a close look at the description for the LGDT instruction.  I've
usually used a DB 66h before the instruction to force the operand size from the
USE16 I'm currently running in to the USE32 interpretation, because I want the
16-bit limit and 32-bit base, not the 16-bit limit and 24-bit base for the data
I'm pointing to.  Also, you'll need to then change CR0 and perform a JMP to
flush the instruction pipeline to start new instruction interpretations
afterwards.

Does any of that help?

Jon
that won't work because you have to take into account the base address of CS:...  which
is FFFF0000.
you should do:

LGDT CS:[F888]

what you did GPFs because the limit on CS is 64K as well, and when you add in the base
you are out
of range.

David
"Ignacio G.T." wrote:

> On Fri, 01 Oct 2004 09:30:57 GMT, igtorque.remove@evomer.yahoo.es (Ignacio G.T.) > wrote: > > >On Fri, 01 Oct 2004 00:20:59 GMT, David Lindauer <camille@bluegrass.net> wrote: > > > >>bear in mind the processor WILL do segmentation faults while in real mode, I don't > >>remember whether it is a catch-all or if there are more restrictive rules though. > >>So if you really can't figure things like this out you might hook int 0x0d and see > >>if it gets triggered. > > > >You are right. In fact, after posting the original message, I filled the > >interrupt vectors zone with pointers to difrent HLT instructions, and the GP > >vector (0x0d) was triggered. > > > >>It has been a while since I did raw protected mode, but the one thing that jumps > >>out at me is you are > >>reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on > >>DS is 0ffffh according to your dumps. This is I think what you do get when you > >>boot... I am wondering if you may get a segmentation fault under these > >>conditions? I don't know for sure on this since I haven't dealt with the boot-up > >>process personally. But if this is the case you can get around it by forcing a > >>CS: prefix on the faulting instruction and changing the offset accordingly. > > > >It sounds reasonable. I'm trying it right now. > > > >Thank you, David. > > > > Bad news, David. I've just tried > > LGDT CS:[FFFFF888] > > and the results are the same. > > Intel's manual says this, for the LGDT instruction: > > === > Real-Address Mode Exceptions > ------------------------------------ > #UD If source operand is not a memory location. > #GP If a memory operand effective address is outside the CS, DS, ES, FS, or > GS segment limit. > #SS If a memory operand effective address is outside the SS segment limit. > === > > We know its a #GP, but I still don't know why. Perhaps I should try copying the > GDT to RAM and trying to load it from there... > > -- > Ignacio G.T.

The 2024 Embedded Online Conference