All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] grub2 int15 hook for e820/e801 does not return CF correctly; makes recent Linux detect only 64MB (via BIOS-88)
@ 2010-06-25 21:28 Josh Triplett
  2010-06-25 22:20 ` [PATCHv2] " Josh Triplett
  0 siblings, 1 reply; 3+ messages in thread
From: Josh Triplett @ 2010-06-25 21:28 UTC (permalink / raw)
  To: grub-devel; +Cc: 584846

As I originally reported in http://bugs.debian.org/584846 , and later
tracked down, grub2's int15 hook, used to augment functions e820/e801/88
for additional reserved memory (such as for drivemap), fails to return
its error status correctly, causing recent Linux (and possibly other
OSes) to detect only 64MB via BIOS-88, ignoring e820 and e801.

This occurs because the interrupt must return a status in CF, but after
using clc or stc to clear or set CF, it calls iret, which restores the
flags from the stack.  Since recent Linux has CF set when it calls
int15, CF remains set when the interrupt returns, indicating an error.
Linux's detect_memory_e820 and detect_memory_e801 functions thus cannot
retrieve any memory map, and Linux must fall back to function 88, which
cannot return more than 64MB.

To reproduce this problem, just use the "drivemap" command and then boot
a recent Linux kernel (git commit
c549e71d073a6e9a4847497344db28a784061455 or newer, meaning v2.6.30-rc1
or newer).  In my case, I booted a USB drive with grub2 on it, used
"drivemap -s (hd1) (hd0)", then chainloaded the hard drive.

The following patch against latest bzr fixes this problem.  (Thanks to
H. Peter Anvin for noticing a bug in my original patch and suggesting a
fix.)  With this patch, Linux's memory detection can use e820 again, and
detect all memory.

=== modified file 'mmap/i386/pc/mmap_helper.S'
--- mmap/i386/pc/mmap_helper.S	2010-03-26 23:04:14 +0000
+++ mmap/i386/pc/mmap_helper.S	2010-06-25 21:03:04 +0000
@@ -59,7 +59,7 @@
 	movw %bx, %dx
 	pop %ds
 	clc
-	iret
+	jmp LOCAL (iret_cf)
 
 LOCAL (h88):
 	popf
@@ -69,7 +69,7 @@
 	movw DS (LOCAL (kbin16mb)), %ax
 	pop %ds
 	clc
-	iret
+	jmp LOCAL (iret_cf)
 
 LOCAL (e820):
 	popf
@@ -101,12 +101,19 @@
 	mov $0x534d4150, %eax
 	pop %ds
 	clc
-	iret
+	jmp LOCAL (iret_cf)
 LOCAL (errexit):
 	mov $0x534d4150, %eax
 	pop %ds
+	xor %bx, %bx
 	stc
-	xor %bx, %bx
+	jmp LOCAL (iret_cf)
+
+LOCAL (iret_cf):
+	push %bp
+	mov %sp, %bp
+	setc 6(%bp)
+	pop %bp
 	iret
 
 VARIABLE(grub_machine_mmaphook_mmap_num)


ChangeLog entry for this patch:


2010-06-25  Josh Triplett  <josh@joshtriplett.org>

	* mmap/i386/pc/mmap_helper.S: Preserve CF by propagating it into the
	flags on the stack before popping them with iret.  Add a new iret_cf
	label implementing this logic, and make the e820, e801, and 88
	handlers jump to it after setting or clearing CF.  This fixes memory
	detection with recent Linux (git commit
	c549e71d073a6e9a4847497344db28a784061455 or newer, meaning v2.6.30-rc1
	or newer), which sets CF on entry to int15, and treats the preserved
	CF on exit as an error in e820 and e801; without this change, it can
	only successfully use BIOS-88 and detect only up to 64MB of RAM.
	Originally reported as Debian bug #584846.


- Josh Triplett


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCHv2] grub2 int15 hook for e820/e801 does not return CF correctly; makes recent Linux detect only 64MB (via BIOS-88)
  2010-06-25 21:28 [PATCH] grub2 int15 hook for e820/e801 does not return CF correctly; makes recent Linux detect only 64MB (via BIOS-88) Josh Triplett
@ 2010-06-25 22:20 ` Josh Triplett
  2010-06-28  8:18   ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 3+ messages in thread
From: Josh Triplett @ 2010-06-25 22:20 UTC (permalink / raw)
  To: grub-devel; +Cc: 584846

On Fri, Jun 25, 2010 at 02:28:01PM -0700, Josh Triplett wrote:
> As I originally reported in http://bugs.debian.org/584846 , and later
> tracked down, grub2's int15 hook, used to augment functions e820/e801/88
> for additional reserved memory (such as for drivemap), fails to return
> its error status correctly, causing recent Linux (and possibly other
> OSes) to detect only 64MB via BIOS-88, ignoring e820 and e801.
> 
> This occurs because the interrupt must return a status in CF, but after
> using clc or stc to clear or set CF, it calls iret, which restores the
> flags from the stack.  Since recent Linux has CF set when it calls
> int15, CF remains set when the interrupt returns, indicating an error.
> Linux's detect_memory_e820 and detect_memory_e801 functions thus cannot
> retrieve any memory map, and Linux must fall back to function 88, which
> cannot return more than 64MB.
> 
> To reproduce this problem, just use the "drivemap" command and then boot
> a recent Linux kernel (git commit
> c549e71d073a6e9a4847497344db28a784061455 or newer, meaning v2.6.30-rc1
> or newer).  In my case, I booted a USB drive with grub2 on it, used
> "drivemap -s (hd1) (hd0)", then chainloaded the hard drive.
> 
> The following patch against latest bzr fixes this problem.  (Thanks to
> H. Peter Anvin for noticing a bug in my original patch and suggesting a
> fix.)  With this patch, Linux's memory detection can use e820 again, and
> detect all memory.

Revised patch, incorporating suggestion from phcoder to eliminate the
unnecessary jmp right before the iret_cf label:


=== modified file 'mmap/i386/pc/mmap_helper.S'
--- mmap/i386/pc/mmap_helper.S	2010-03-26 23:04:14 +0000
+++ mmap/i386/pc/mmap_helper.S	2010-06-25 22:16:53 +0000
@@ -59,7 +59,7 @@
 	movw %bx, %dx
 	pop %ds
 	clc
-	iret
+	jmp LOCAL (iret_cf)
 
 LOCAL (h88):
 	popf
@@ -69,7 +69,7 @@
 	movw DS (LOCAL (kbin16mb)), %ax
 	pop %ds
 	clc
-	iret
+	jmp LOCAL (iret_cf)
 
 LOCAL (e820):
 	popf
@@ -101,12 +101,18 @@
 	mov $0x534d4150, %eax
 	pop %ds
 	clc
-	iret
+	jmp LOCAL (iret_cf)
 LOCAL (errexit):
 	mov $0x534d4150, %eax
 	pop %ds
+	xor %bx, %bx
 	stc
-	xor %bx, %bx
+
+LOCAL (iret_cf):
+	push %bp
+	mov %sp, %bp
+	setc 6(%bp)
+	pop %bp
 	iret
 
 VARIABLE(grub_machine_mmaphook_mmap_num)


ChangeLog entry for this patch:


2010-06-25  Josh Triplett  <josh@joshtriplett.org>

	* mmap/i386/pc/mmap_helper.S: Preserve CF by propagating it into the
	flags on the stack before popping them with iret.  Add a new iret_cf
	label implementing this logic, and make the e820, e801, and 88
	handlers jump to it after setting or clearing CF.  This fixes memory
	detection with recent Linux (git commit
	c549e71d073a6e9a4847497344db28a784061455 or newer, meaning v2.6.30-rc1
	or newer), which sets CF on entry to int15, and treats the preserved
	CF on exit as an error in e820 and e801; without this change, it can
	only successfully use BIOS-88 and detect only up to 64MB of RAM.
	Originally reported as Debian bug #584846.


- Josh Triplett


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCHv2] grub2 int15 hook for e820/e801 does not return CF correctly; makes recent Linux detect only 64MB (via BIOS-88)
  2010-06-25 22:20 ` [PATCHv2] " Josh Triplett
@ 2010-06-28  8:18   ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 3+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-06-28  8:18 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 3548 bytes --]

On 06/26/2010 12:20 AM, Josh Triplett wrote:
> On Fri, Jun 25, 2010 at 02:28:01PM -0700, Josh Triplett wrote:
>   
>> As I originally reported in http://bugs.debian.org/584846 , and later
>> tracked down, grub2's int15 hook, used to augment functions e820/e801/88
>> for additional reserved memory (such as for drivemap), fails to return
>> its error status correctly, causing recent Linux (and possibly other
>> OSes) to detect only 64MB via BIOS-88, ignoring e820 and e801.
>>
>> This occurs because the interrupt must return a status in CF, but after
>> using clc or stc to clear or set CF, it calls iret, which restores the
>> flags from the stack.  Since recent Linux has CF set when it calls
>> int15, CF remains set when the interrupt returns, indicating an error.
>> Linux's detect_memory_e820 and detect_memory_e801 functions thus cannot
>> retrieve any memory map, and Linux must fall back to function 88, which
>> cannot return more than 64MB.
>>
>> To reproduce this problem, just use the "drivemap" command and then boot
>> a recent Linux kernel (git commit
>> c549e71d073a6e9a4847497344db28a784061455 or newer, meaning v2.6.30-rc1
>> or newer).  In my case, I booted a USB drive with grub2 on it, used
>> "drivemap -s (hd1) (hd0)", then chainloaded the hard drive.
>>
>> The following patch against latest bzr fixes this problem.  (Thanks to
>> H. Peter Anvin for noticing a bug in my original patch and suggesting a
>> fix.)  With this patch, Linux's memory detection can use e820 again, and
>> detect all memory.
>>     
> Revised patch, incorporating suggestion from phcoder to eliminate the
> unnecessary jmp right before the iret_cf label:
>
>   
Comitted. Thanks
> === modified file 'mmap/i386/pc/mmap_helper.S'
> --- mmap/i386/pc/mmap_helper.S	2010-03-26 23:04:14 +0000
> +++ mmap/i386/pc/mmap_helper.S	2010-06-25 22:16:53 +0000
> @@ -59,7 +59,7 @@
>  	movw %bx, %dx
>  	pop %ds
>  	clc
> -	iret
> +	jmp LOCAL (iret_cf)
>  
>  LOCAL (h88):
>  	popf
> @@ -69,7 +69,7 @@
>  	movw DS (LOCAL (kbin16mb)), %ax
>  	pop %ds
>  	clc
> -	iret
> +	jmp LOCAL (iret_cf)
>  
>  LOCAL (e820):
>  	popf
> @@ -101,12 +101,18 @@
>  	mov $0x534d4150, %eax
>  	pop %ds
>  	clc
> -	iret
> +	jmp LOCAL (iret_cf)
>  LOCAL (errexit):
>  	mov $0x534d4150, %eax
>  	pop %ds
> +	xor %bx, %bx
>  	stc
> -	xor %bx, %bx
> +
> +LOCAL (iret_cf):
> +	push %bp
> +	mov %sp, %bp
> +	setc 6(%bp)
> +	pop %bp
>  	iret
>  
>  VARIABLE(grub_machine_mmaphook_mmap_num)
>
>
> ChangeLog entry for this patch:
>
>
> 2010-06-25  Josh Triplett  <josh@joshtriplett.org>
>
> 	* mmap/i386/pc/mmap_helper.S: Preserve CF by propagating it into the
> 	flags on the stack before popping them with iret.  Add a new iret_cf
> 	label implementing this logic, and make the e820, e801, and 88
> 	handlers jump to it after setting or clearing CF.  This fixes memory
> 	detection with recent Linux (git commit
> 	c549e71d073a6e9a4847497344db28a784061455 or newer, meaning v2.6.30-rc1
> 	or newer), which sets CF on entry to int15, and treats the preserved
> 	CF on exit as an error in e820 and e801; without this change, it can
> 	only successfully use BIOS-88 and detect only up to 64MB of RAM.
> 	Originally reported as Debian bug #584846.
>
>
> - Josh Triplett
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>   


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-06-28  8:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-25 21:28 [PATCH] grub2 int15 hook for e820/e801 does not return CF correctly; makes recent Linux detect only 64MB (via BIOS-88) Josh Triplett
2010-06-25 22:20 ` [PATCHv2] " Josh Triplett
2010-06-28  8:18   ` Vladimir 'φ-coder/phcoder' Serbinenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.