Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Mikael Pettersson
On Sun, 04 Nov 2007 15:51:43 -0800, H. Peter Anvin wrote:
> Mikael, can you try this patch (rev 3) on your 486?

It works fine.

/Mikael
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Linus Torvalds


On Sun, 4 Nov 2007, Linus Torvalds wrote:
> 
> So I'd suggest having both jumps back-to-back, but realistically, the 
> first regular short jump is actually the one that is more important. 
> That's the one that really matters on i386/i486 class machines, and later 
> CPU's will generally do the right thing even with _neither_ jump there.

That's obviously badly phrased.

The far jump is obviously required on all CPU's in order for us to 
actually finally get to 32-bit protected mode and reload CS, but what I 
*meant* was that we certainly also know that "unreal mode" works and is 
used by various strange DOS extenders, and that not doing the far jump 
isn't really required for having a "working setup" - it's just going to be 
a rather limited mode.

So the short jump is required for the code to *work*. The long jump is 
required only to get us the 32-bit mode we *want* and out of the odd 
"half-way" state. Two different issues.

Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Linus Torvalds


On Sun, 4 Nov 2007, H. Peter Anvin wrote:
> 
> Joy.  Apparently the Intel documentation is actually self-inconsistent.
> Section 9.9.1, page 9-17 does indeed have the "far jump or call" injunction,
> whereas the sample code in section 9.10.1, page 9-27, line 180 does a near
> jump!

See the older code. There's literally two different issues:

 - flushing the pipeline. Using a regular short jump is not only 
   sufficient, but is a good idea because the byte sequence has no 
   dependency on any modes, so it is guaranteed to flush any pipeline 
   without itself having any behavioural differences.

   This part is a no-op for later CPU's: they simply won't care, since 
   they serialize the pipeline on their own (and the have to, since a 
   correctly predicted branch no longer flushes it anyway).

   So this is purely a i386/i486 thing (and *maybe* Pentium, but 
   definitely not PPro and later)

 - setting up the proper protected mode bits in CS. This obviously changes
   the CS itself, and anything that depends on any shadow state in CS will 
   need this to happen first. In practice, very few things really depend 
   on the CS bits, of course.

Doing them back-to-back is obviously the best situation, and leaves the 
minimum footprint for any dubious undocumented behaviour. That said, while 
the whole thing with shadow segment table is strictly speaking probably 
"undocumented" behaviour, it's certainly a reality, and lots of code has 
depended on the fact that even though you haven't reloaded a segment, the 
segment continues to work across mode switches thanks to the shadow table. 

So it's not like there's any real secret to what happens until the 
longjump has been executed: we continue running with the CS shadow table 
entry being in "real mode", and the effect of that tends to be minimal. 
But in theory, the CS table entry could affect how instructions actually 
act, even though in practice I don't think it really has any real effect 
outside of the actual segment access check (and certainly did not in the 
i386/i486 timeframe).

So I'd suggest having both jumps back-to-back, but realistically, the 
first regular short jump is actually the one that is more important. 
That's the one that really matters on i386/i486 class machines, and later 
CPU's will generally do the right thing even with _neither_ jump there.

Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael, can you try this patch (rev 3) on your 486?

-hpa
diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e55923..d93a0c2 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -28,17 +28,21 @@
  * void protected_mode_jump(u32 entrypoint, u32 bootparams);
  */
 protected_mode_jump:
-   xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
-   movl%eax, 2f# Patch ljmpl instruction
+   movl%eax, 3f# Patch ljmpl instruction
jmp 1f  # Short jump to flush instruction q.
-
 1:
+
movw$__BOOT_DS, %cx
+   xorl%ebx, %ebx  # Per protocol
+   xorl%ebp, %ebp  # Per protocol
+   xorl%edi, %edi  # Per protocol
 
movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0
+   jmp 2f  # Short jump to serialize
+2:
 
movw%cx, %ds
movw%cx, %es
@@ -48,7 +52,7 @@ protected_mode_jump:
 
# Jump to the 32-bit entrypoint
.byte   0x66, 0xea  # ljmpl opcode
-2: .long   0   # offset
+3: .long   0   # offset
.word   __BOOT_CS   # segment
 
.size   protected_mode_jump, .-protected_mode_jump


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Jeremy Fitzhardinge wrote:

Maybe not. I had a look in Intel's SDM Vol3, and the
section "switching to protected mode" specifies that
a move to %cr0 that sets PE should immediately be
followed by a far jmp or call.


Yes, that's what the spec says.  I queried this a few months ago, but
hpa used his convincing voice and said that in practice it isn't
necessary; there are no known cpus which need this, and any that do
would cause other things to break.  But I guess now we have the
counter-example...


Joy.  Apparently the Intel documentation is actually self-inconsistent. 
 Section 9.9.1, page 9-17 does indeed have the "far jump or call" 
injunction, whereas the sample code in section 9.10.1, page 9-27, line 
180 does a near jump!


-hpa
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Jeremy Fitzhardinge wrote:


Yes, that's what the spec says.  I queried this a few months ago, but
hpa used his convincing voice and said that in practice it isn't
necessary; there are no known cpus which need this, and any that do
would cause other things to break.  But I guess now we have the
counter-example...



Yup.  I owe you a beverage :)

-hpa
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Jeremy Fitzhardinge
Mikael Pettersson wrote:
> On Sun, 04 Nov 2007 11:41:58 -0800, H. Peter Anvin wrote:
>   
>> Mikael Pettersson wrote:
>> 
>>> First patch didn't build. Second patch builds and boots Ok.
>>>
>>> So this means the 486 DX4 has a buggy mov to %cr0?
>>>
>>>   
>> Apparently.
>> 
>
> Maybe not. I had a look in Intel's SDM Vol3, and the
> section "switching to protected mode" specifies that
> a move to %cr0 that sets PE should immediately be
> followed by a far jmp or call.
>   

Yes, that's what the spec says.  I queried this a few months ago, but
hpa used his convincing voice and said that in practice it isn't
necessary; there are no known cpus which need this, and any that do
would cause other things to break.  But I guess now we have the
counter-example...

J
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Andi Kleen
Mikael Pettersson <[EMAIL PROTECTED]> writes:

> Maybe not. I had a look in Intel's SDM Vol3, and the
> section "switching to protected mode" specifies that
> a move to %cr0 that sets PE should immediately be
> followed by a far jmp or call. They write that "random
> failures can occur if other instructions exist between
> [the move to %cr0] and [the far jmp/call]". The current
> version of pmjump.S does exactly that: it executes
> a bunch of moves to segment registers in that window.

iirc various Intel VT hypervisor implementations also have trouble
with not following this restriction. At least in the early Xen
days it was a frequent reason for boot failure.

-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael Pettersson wrote:


Maybe not. I had a look in Intel's SDM Vol3, and the
section "switching to protected mode" specifies that
a move to %cr0 that sets PE should immediately be
followed by a far jmp or call. They write that "random
failures can occur if other instructions exist between
[the move to %cr0] and [the far jmp/call]". The current
version of pmjump.S does exactly that: it executes
a bunch of moves to segment registers in that window.

(Section 9.9.1 in the Sept. 2005 revision I have in
front of me.)

Similarly, section "serializing instructions" writes
that a move to %cr0 that enables or disables paging
should be followed by a jump. They write that this isn't
required in P4 or P6 family processors, but is required
for compatibility with other ia32 processors. Reading
between the lines, they imply that older ia32 processors
don't treat %cr0 writes as completely serializing.

(Section 7.4 in the Sept. 2005 revision.)



The problem is that Intel has a tendency to exaggerate in their 
documentation; in particular, they tend not to remove restrictions that 
are long-since obsolete.  However, it sounds like you have actually 
found a CPU for which this restriction is motivated.


-hpa
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Mikael Pettersson
On Sun, 04 Nov 2007 11:41:58 -0800, H. Peter Anvin wrote:
> Mikael Pettersson wrote:
> > 
> > First patch didn't build. Second patch builds and boots Ok.
> > 
> > So this means the 486 DX4 has a buggy mov to %cr0?
> > 
> 
> Apparently.

Maybe not. I had a look in Intel's SDM Vol3, and the
section "switching to protected mode" specifies that
a move to %cr0 that sets PE should immediately be
followed by a far jmp or call. They write that "random
failures can occur if other instructions exist between
[the move to %cr0] and [the far jmp/call]". The current
version of pmjump.S does exactly that: it executes
a bunch of moves to segment registers in that window.

(Section 9.9.1 in the Sept. 2005 revision I have in
front of me.)

Similarly, section "serializing instructions" writes
that a move to %cr0 that enables or disables paging
should be followed by a jump. They write that this isn't
required in P4 or P6 family processors, but is required
for compatibility with other ia32 processors. Reading
between the lines, they imply that older ia32 processors
don't treat %cr0 writes as completely serializing.

(Section 7.4 in the Sept. 2005 revision.)

/Mikael
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael Pettersson wrote:


First patch didn't build. Second patch builds and boots Ok.

So this means the 486 DX4 has a buggy mov to %cr0?



Apparently.

-hpa
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Mikael Pettersson
On Sun, 04 Nov 2007 10:29:34 -0800, H. Peter Anvin wrote:
>Could you send me your /proc/cpuinfo?

Sure. It's a 100Mhz Intel 486 DX4:

processor   : 0
vendor_id   : GenuineIntel
cpu family  : 4
model   : 8
model name  : 486 DX/4
stepping: 0
cache size  : 0 KB
fdiv_bug: no
hlt_bug : no
f00f_bug: no
coma_bug: no
fpu : yes
fpu_exception   : yes
cpuid level : 1
wp  : yes
flags   : fpu vme
bogomips: 49.66
clflush size: 32

>Also, I would be very interested if you could try out this patch:
...
>Urk, -ENOTAWAKEYET.  Try *THIS* patch, please.

First patch didn't build. Second patch builds and boots Ok.

So this means the 486 DX4 has a buggy mov to %cr0?

/Mikael
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Urk, -ENOTAWAKEYET.  Try *THIS* patch, please.

-hpa

diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e55923..17e6dec 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -28,27 +28,37 @@
  * void protected_mode_jump(u32 entrypoint, u32 bootparams);
  */
 protected_mode_jump:
-   xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
-   movl%eax, 2f# Patch ljmpl instruction
+
+   xorl%edx, %edx
+   movw%cs, %dx
+   shll$4, %edx# Patch ljmpl instruction
+   addl%edx, 2f
jmp 1f  # Short jump to flush instruction q.
 
 1:
movw$__BOOT_DS, %cx
+   xorl%ebx, %ebx  # Per protocol
+   xorl%ebp, %ebp  # Per protocol
+   xorl%edi, %edi  # Per protocol
 
movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0
+   
+   .byte   0x66, 0xea  # ljmpl opcode
+2: .long   3f  # Offset
+   .word   __BOOT_CS   # Segment
 
-   movw%cx, %ds
-   movw%cx, %es
-   movw%cx, %fs
-   movw%cx, %gs
-   movw%cx, %ss
+   .code32
+3:
+   movl%ecx, %ds
+   movl%ecx, %es
+   movl%ecx, %fs
+   movl%ecx, %gs
+   movl%ecx, %ss
 
# Jump to the 32-bit entrypoint
-   .byte   0x66, 0xea  # ljmpl opcode
-2: .long   0   # offset
-   .word   __BOOT_CS   # segment
-
+   jmpl*%eax
+   
.size   protected_mode_jump, .-protected_mode_jump


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael Pettersson wrote:


The machine in question is a ca 1993 vintage Siemens 486 with
a Quadtel S3 / Phoenix BIOS from 1994, booting via grub-0.95-13
from Fedora Core 4.

Signed-off-by: Mikael Pettersson <[EMAIL PROTECTED]>
---
 arch/x86/boot/compressed/head_32.S |5 +
 1 files changed, 5 insertions(+)

--- linux-2.6.24-rc1-git13/arch/x86/boot/compressed/head_32.S.~1~   
2007-11-04 16:34:33.0 +0100
+++ linux-2.6.24-rc1-git13/arch/x86/boot/compressed/head_32.S   2007-11-04 
16:44:15.0 +0100
@@ -33,6 +33,11 @@
.globl startup_32
 
 startup_32:

+   /* workaround for BIOSen or boot loaders that don't reload %ds
+  after changing the GDT (insane but unfortunately true) */
+   movl %ds,%eax
+   movl %eax,%ds
+
cld
/* test KEEP_SEGMENTS flag to see if the bootloader is asking
 * us to not reload segments */


Double bogus flag here.

It's not an issue of the BIOS or the boot loader (in your case, Grub) 
unless you have a boot loader that does 32-bit entry (e.g. kexec or ELILO.)


Second, the "workaround" you have here effectively disables the meaning 
of the KEEP_SEGMENTS flag, so it's unacceptable.


If one couldn't rely on %ds, then we could load the loadflags with a 
%cs: override, but there is something much more bizarre going on here. 
Since you're doing a normal 16-bit entry (unless your Grub is 
configured/patched to do something extremely weird, not that that would 
be anything out of the ordinary for Grub) the code that should have been 
executed immediately before this point is this code from 
arch/x86/boot/pm_jump.S:


protected_mode_jump:
xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
movl%eax, 2f# Patch ljmpl instruction
jmp 1f  # Short jump to flush 
instruction q.


1:
movw$__BOOT_DS, %cx

movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0

movw%cx, %ds
movw%cx, %es
movw%cx, %fs
movw%cx, %gs
movw%cx, %ss

# Jump to the 32-bit entrypoint
.byte   0x66, 0xea  # ljmpl opcode
2:  .long   0   # offset
.word   __BOOT_CS   # segment

.size   protected_mode_jump, .-protected_mode_jump


As you can see, all the segments should have been properly set up.  I'm 
somewhat wondering if you have found one lone CPU revision in the entire 
x86 menagerie which doesn't properly serialize on mov to %cr0, which 
would casue the mov to %ds immediately after to be misexecuted.  If 
that's the case, I believe I owe Eric Biederman a drink of choice.


Could you send me your /proc/cpuinfo?

Also, I would be very interested if you could try out this patch:

diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e55923..97cf407 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -30,7 +30,6 @@
 protected_mode_jump:
xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
-   movl%eax, 2f# Patch ljmpl instruction
jmp 1f  # Short jump to flush instruction q.
 
 1:
@@ -39,16 +38,17 @@ protected_mode_jump:
movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0
+   ljmpw   __BOOT_CS, 2f
 
-   movw%cx, %ds
-   movw%cx, %es
-   movw%cx, %fs
-   movw%cx, %gs
-   movw%cx, %ss
+   .code32
+2:
+   movl%ecx, %ds
+   movl%ecx, %es
+   movl%ecx, %fs
+   movl%ecx, %gs
+   movl%ecx, %ss
 
# Jump to the 32-bit entrypoint
-   .byte   0x66, 0xea  # ljmpl opcode
-2: .long   0   # offset
-   .word   __BOOT_CS   # segment
-
+   jmpl%eax
+   
.size   protected_mode_jump, .-protected_mode_jump


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael Pettersson wrote:


The machine in question is a ca 1993 vintage Siemens 486 with
a Quadtel S3 / Phoenix BIOS from 1994, booting via grub-0.95-13
from Fedora Core 4.

Signed-off-by: Mikael Pettersson [EMAIL PROTECTED]
---
 arch/x86/boot/compressed/head_32.S |5 +
 1 files changed, 5 insertions(+)

--- linux-2.6.24-rc1-git13/arch/x86/boot/compressed/head_32.S.~1~   
2007-11-04 16:34:33.0 +0100
+++ linux-2.6.24-rc1-git13/arch/x86/boot/compressed/head_32.S   2007-11-04 
16:44:15.0 +0100
@@ -33,6 +33,11 @@
.globl startup_32
 
 startup_32:

+   /* workaround for BIOSen or boot loaders that don't reload %ds
+  after changing the GDT (insane but unfortunately true) */
+   movl %ds,%eax
+   movl %eax,%ds
+
cld
/* test KEEP_SEGMENTS flag to see if the bootloader is asking
 * us to not reload segments */


Double bogus flag here.

It's not an issue of the BIOS or the boot loader (in your case, Grub) 
unless you have a boot loader that does 32-bit entry (e.g. kexec or ELILO.)


Second, the workaround you have here effectively disables the meaning 
of the KEEP_SEGMENTS flag, so it's unacceptable.


If one couldn't rely on %ds, then we could load the loadflags with a 
%cs: override, but there is something much more bizarre going on here. 
Since you're doing a normal 16-bit entry (unless your Grub is 
configured/patched to do something extremely weird, not that that would 
be anything out of the ordinary for Grub) the code that should have been 
executed immediately before this point is this code from 
arch/x86/boot/pm_jump.S:


protected_mode_jump:
xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
movl%eax, 2f# Patch ljmpl instruction
jmp 1f  # Short jump to flush 
instruction q.


1:
movw$__BOOT_DS, %cx

movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0

movw%cx, %ds
movw%cx, %es
movw%cx, %fs
movw%cx, %gs
movw%cx, %ss

# Jump to the 32-bit entrypoint
.byte   0x66, 0xea  # ljmpl opcode
2:  .long   0   # offset
.word   __BOOT_CS   # segment

.size   protected_mode_jump, .-protected_mode_jump


As you can see, all the segments should have been properly set up.  I'm 
somewhat wondering if you have found one lone CPU revision in the entire 
x86 menagerie which doesn't properly serialize on mov to %cr0, which 
would casue the mov to %ds immediately after to be misexecuted.  If 
that's the case, I believe I owe Eric Biederman a drink of choice.


Could you send me your /proc/cpuinfo?

Also, I would be very interested if you could try out this patch:

diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e55923..97cf407 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -30,7 +30,6 @@
 protected_mode_jump:
xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
-   movl%eax, 2f# Patch ljmpl instruction
jmp 1f  # Short jump to flush instruction q.
 
 1:
@@ -39,16 +38,17 @@ protected_mode_jump:
movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0
+   ljmpw   __BOOT_CS, 2f
 
-   movw%cx, %ds
-   movw%cx, %es
-   movw%cx, %fs
-   movw%cx, %gs
-   movw%cx, %ss
+   .code32
+2:
+   movl%ecx, %ds
+   movl%ecx, %es
+   movl%ecx, %fs
+   movl%ecx, %gs
+   movl%ecx, %ss
 
# Jump to the 32-bit entrypoint
-   .byte   0x66, 0xea  # ljmpl opcode
-2: .long   0   # offset
-   .word   __BOOT_CS   # segment
-
+   jmpl%eax
+   
.size   protected_mode_jump, .-protected_mode_jump


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Urk, -ENOTAWAKEYET.  Try *THIS* patch, please.

-hpa

diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e55923..17e6dec 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -28,27 +28,37 @@
  * void protected_mode_jump(u32 entrypoint, u32 bootparams);
  */
 protected_mode_jump:
-   xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
-   movl%eax, 2f# Patch ljmpl instruction
+
+   xorl%edx, %edx
+   movw%cs, %dx
+   shll$4, %edx# Patch ljmpl instruction
+   addl%edx, 2f
jmp 1f  # Short jump to flush instruction q.
 
 1:
movw$__BOOT_DS, %cx
+   xorl%ebx, %ebx  # Per protocol
+   xorl%ebp, %ebp  # Per protocol
+   xorl%edi, %edi  # Per protocol
 
movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0
+   
+   .byte   0x66, 0xea  # ljmpl opcode
+2: .long   3f  # Offset
+   .word   __BOOT_CS   # Segment
 
-   movw%cx, %ds
-   movw%cx, %es
-   movw%cx, %fs
-   movw%cx, %gs
-   movw%cx, %ss
+   .code32
+3:
+   movl%ecx, %ds
+   movl%ecx, %es
+   movl%ecx, %fs
+   movl%ecx, %gs
+   movl%ecx, %ss
 
# Jump to the 32-bit entrypoint
-   .byte   0x66, 0xea  # ljmpl opcode
-2: .long   0   # offset
-   .word   __BOOT_CS   # segment
-
+   jmpl*%eax
+   
.size   protected_mode_jump, .-protected_mode_jump


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Mikael Pettersson
On Sun, 04 Nov 2007 10:29:34 -0800, H. Peter Anvin wrote:
Could you send me your /proc/cpuinfo?

Sure. It's a 100Mhz Intel 486 DX4:

processor   : 0
vendor_id   : GenuineIntel
cpu family  : 4
model   : 8
model name  : 486 DX/4
stepping: 0
cache size  : 0 KB
fdiv_bug: no
hlt_bug : no
f00f_bug: no
coma_bug: no
fpu : yes
fpu_exception   : yes
cpuid level : 1
wp  : yes
flags   : fpu vme
bogomips: 49.66
clflush size: 32

Also, I would be very interested if you could try out this patch:
...
Urk, -ENOTAWAKEYET.  Try *THIS* patch, please.

First patch didn't build. Second patch builds and boots Ok.

So this means the 486 DX4 has a buggy mov to %cr0?

/Mikael
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael Pettersson wrote:


First patch didn't build. Second patch builds and boots Ok.

So this means the 486 DX4 has a buggy mov to %cr0?



Apparently.

-hpa
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Mikael Pettersson
On Sun, 04 Nov 2007 11:41:58 -0800, H. Peter Anvin wrote:
 Mikael Pettersson wrote:
  
  First patch didn't build. Second patch builds and boots Ok.
  
  So this means the 486 DX4 has a buggy mov to %cr0?
  
 
 Apparently.

Maybe not. I had a look in Intel's SDM Vol3, and the
section switching to protected mode specifies that
a move to %cr0 that sets PE should immediately be
followed by a far jmp or call. They write that random
failures can occur if other instructions exist between
[the move to %cr0] and [the far jmp/call]. The current
version of pmjump.S does exactly that: it executes
a bunch of moves to segment registers in that window.

(Section 9.9.1 in the Sept. 2005 revision I have in
front of me.)

Similarly, section serializing instructions writes
that a move to %cr0 that enables or disables paging
should be followed by a jump. They write that this isn't
required in P4 or P6 family processors, but is required
for compatibility with other ia32 processors. Reading
between the lines, they imply that older ia32 processors
don't treat %cr0 writes as completely serializing.

(Section 7.4 in the Sept. 2005 revision.)

/Mikael
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael Pettersson wrote:


Maybe not. I had a look in Intel's SDM Vol3, and the
section switching to protected mode specifies that
a move to %cr0 that sets PE should immediately be
followed by a far jmp or call. They write that random
failures can occur if other instructions exist between
[the move to %cr0] and [the far jmp/call]. The current
version of pmjump.S does exactly that: it executes
a bunch of moves to segment registers in that window.

(Section 9.9.1 in the Sept. 2005 revision I have in
front of me.)

Similarly, section serializing instructions writes
that a move to %cr0 that enables or disables paging
should be followed by a jump. They write that this isn't
required in P4 or P6 family processors, but is required
for compatibility with other ia32 processors. Reading
between the lines, they imply that older ia32 processors
don't treat %cr0 writes as completely serializing.

(Section 7.4 in the Sept. 2005 revision.)



The problem is that Intel has a tendency to exaggerate in their 
documentation; in particular, they tend not to remove restrictions that 
are long-since obsolete.  However, it sounds like you have actually 
found a CPU for which this restriction is motivated.


-hpa
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Andi Kleen
Mikael Pettersson [EMAIL PROTECTED] writes:

 Maybe not. I had a look in Intel's SDM Vol3, and the
 section switching to protected mode specifies that
 a move to %cr0 that sets PE should immediately be
 followed by a far jmp or call. They write that random
 failures can occur if other instructions exist between
 [the move to %cr0] and [the far jmp/call]. The current
 version of pmjump.S does exactly that: it executes
 a bunch of moves to segment registers in that window.

iirc various Intel VT hypervisor implementations also have trouble
with not following this restriction. At least in the early Xen
days it was a frequent reason for boot failure.

-Andi
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Jeremy Fitzhardinge
Mikael Pettersson wrote:
 On Sun, 04 Nov 2007 11:41:58 -0800, H. Peter Anvin wrote:
   
 Mikael Pettersson wrote:
 
 First patch didn't build. Second patch builds and boots Ok.

 So this means the 486 DX4 has a buggy mov to %cr0?

   
 Apparently.
 

 Maybe not. I had a look in Intel's SDM Vol3, and the
 section switching to protected mode specifies that
 a move to %cr0 that sets PE should immediately be
 followed by a far jmp or call.
   

Yes, that's what the spec says.  I queried this a few months ago, but
hpa used his convincing voice and said that in practice it isn't
necessary; there are no known cpus which need this, and any that do
would cause other things to break.  But I guess now we have the
counter-example...

J
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Jeremy Fitzhardinge wrote:


Yes, that's what the spec says.  I queried this a few months ago, but
hpa used his convincing voice and said that in practice it isn't
necessary; there are no known cpus which need this, and any that do
would cause other things to break.  But I guess now we have the
counter-example...



Yup.  I owe you a beverage :)

-hpa
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Jeremy Fitzhardinge wrote:

Maybe not. I had a look in Intel's SDM Vol3, and the
section switching to protected mode specifies that
a move to %cr0 that sets PE should immediately be
followed by a far jmp or call.


Yes, that's what the spec says.  I queried this a few months ago, but
hpa used his convincing voice and said that in practice it isn't
necessary; there are no known cpus which need this, and any that do
would cause other things to break.  But I guess now we have the
counter-example...


Joy.  Apparently the Intel documentation is actually self-inconsistent. 
 Section 9.9.1, page 9-17 does indeed have the far jump or call 
injunction, whereas the sample code in section 9.10.1, page 9-27, line 
180 does a near jump!


-hpa
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread H. Peter Anvin

Mikael, can you try this patch (rev 3) on your 486?

-hpa
diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 2e55923..d93a0c2 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -28,17 +28,21 @@
  * void protected_mode_jump(u32 entrypoint, u32 bootparams);
  */
 protected_mode_jump:
-   xorl%ebx, %ebx  # Flag to indicate this is a boot
movl%edx, %esi  # Pointer to boot_params table
-   movl%eax, 2f# Patch ljmpl instruction
+   movl%eax, 3f# Patch ljmpl instruction
jmp 1f  # Short jump to flush instruction q.
-
 1:
+
movw$__BOOT_DS, %cx
+   xorl%ebx, %ebx  # Per protocol
+   xorl%ebp, %ebp  # Per protocol
+   xorl%edi, %edi  # Per protocol
 
movl%cr0, %edx
orb $1, %dl # Protected mode (PE) bit
movl%edx, %cr0
+   jmp 2f  # Short jump to serialize
+2:
 
movw%cx, %ds
movw%cx, %es
@@ -48,7 +52,7 @@ protected_mode_jump:
 
# Jump to the 32-bit entrypoint
.byte   0x66, 0xea  # ljmpl opcode
-2: .long   0   # offset
+3: .long   0   # offset
.word   __BOOT_CS   # segment
 
.size   protected_mode_jump, .-protected_mode_jump


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Linus Torvalds


On Sun, 4 Nov 2007, H. Peter Anvin wrote:
 
 Joy.  Apparently the Intel documentation is actually self-inconsistent.
 Section 9.9.1, page 9-17 does indeed have the far jump or call injunction,
 whereas the sample code in section 9.10.1, page 9-27, line 180 does a near
 jump!

See the older code. There's literally two different issues:

 - flushing the pipeline. Using a regular short jump is not only 
   sufficient, but is a good idea because the byte sequence has no 
   dependency on any modes, so it is guaranteed to flush any pipeline 
   without itself having any behavioural differences.

   This part is a no-op for later CPU's: they simply won't care, since 
   they serialize the pipeline on their own (and the have to, since a 
   correctly predicted branch no longer flushes it anyway).

   So this is purely a i386/i486 thing (and *maybe* Pentium, but 
   definitely not PPro and later)

 - setting up the proper protected mode bits in CS. This obviously changes
   the CS itself, and anything that depends on any shadow state in CS will 
   need this to happen first. In practice, very few things really depend 
   on the CS bits, of course.

Doing them back-to-back is obviously the best situation, and leaves the 
minimum footprint for any dubious undocumented behaviour. That said, while 
the whole thing with shadow segment table is strictly speaking probably 
undocumented behaviour, it's certainly a reality, and lots of code has 
depended on the fact that even though you haven't reloaded a segment, the 
segment continues to work across mode switches thanks to the shadow table. 

So it's not like there's any real secret to what happens until the 
longjump has been executed: we continue running with the CS shadow table 
entry being in real mode, and the effect of that tends to be minimal. 
But in theory, the CS table entry could affect how instructions actually 
act, even though in practice I don't think it really has any real effect 
outside of the actual segment access check (and certainly did not in the 
i386/i486 timeframe).

So I'd suggest having both jumps back-to-back, but realistically, the 
first regular short jump is actually the one that is more important. 
That's the one that really matters on i386/i486 class machines, and later 
CPU's will generally do the right thing even with _neither_ jump there.

Linus
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Linus Torvalds


On Sun, 4 Nov 2007, Linus Torvalds wrote:
 
 So I'd suggest having both jumps back-to-back, but realistically, the 
 first regular short jump is actually the one that is more important. 
 That's the one that really matters on i386/i486 class machines, and later 
 CPU's will generally do the right thing even with _neither_ jump there.

That's obviously badly phrased.

The far jump is obviously required on all CPU's in order for us to 
actually finally get to 32-bit protected mode and reload CS, but what I 
*meant* was that we certainly also know that unreal mode works and is 
used by various strange DOS extenders, and that not doing the far jump 
isn't really required for having a working setup - it's just going to be 
a rather limited mode.

So the short jump is required for the code to *work*. The long jump is 
required only to get us the 32-bit mode we *want* and out of the odd 
half-way state. Two different issues.

Linus
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] fix i486 boot failure due to stale %ds

2007-11-04 Thread Mikael Pettersson
On Sun, 04 Nov 2007 15:51:43 -0800, H. Peter Anvin wrote:
 Mikael, can you try this patch (rev 3) on your 486?

It works fine.

/Mikael
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/