Skip to contentSkip to conversation

x86, setup: "glove box" BIOS interrupts

PATCH In review H. Peter Anvin 9 participants 37 messages Apr 9, 2009 – Apr 14, 2009

Subsystems (3)
lore
Share & tools
lore

H. Peter Anvin

author reviewer
#0 lore raw

cover x86, setup: "glove box" BIOS interrupts

This is a patchset to "glove box" off BIOS interrupts in the x86 setup code, thus hopefully dealing once and for all with the problems of BIOSes touching registers they shouldn't.

The concept is simple: we manipulate a register image in memory, then swap it in immediately before calling the BIOS, and then switch the register file back. All BIOS interrupts are channeled through this path.

The increase in size is about 8% or ~1.3K in the maximal case.

 arch/x86/boot/Makefile                   |    5 +-
 arch/x86/boot/a20.c                      |    9 +-
 arch/x86/boot/apm.c                      |   76 +++++--------
 arch/x86/boot/bioscall.S                 |   82 +++++++++++++
 arch/x86/boot/boot.h                     |   48 ++++++++
 arch/x86/boot/edd.c                      |   71 +++++-------
 arch/x86/boot/header.S                   |    2 +-
 arch/x86/boot/main.c                     |   39 ++++---
 arch/x86/boot/mca.c                      |   27 ++---
 arch/x86/boot/memory.c                   |   81 +++++++-------
 arch/x86/boot/regs.c                     |   29 +++++
 arch/x86/boot/setup.ld                   |    6 +
 arch/x86/boot/tty.c                      |   52 +++++----
 arch/x86/boot/video-bios.c               |   27 ++---
 arch/x86/boot/video-vesa.c               |  137 ++++++++++------------
 arch/x86/boot/video-vga.c                |   95 +++++++++------
 arch/x86/boot/video.c                    |   42 +++----
 arch/x86/boot/video.h                    |   14 ---
 arch/x86/kernel/acpi/realmode/Makefile   |    2 +-
 arch/x86/kernel/acpi/realmode/bioscall.S |    1 +
 arch/x86/kernel/acpi/realmode/regs.c     |    1 +
 21 files changed, 490 insertions(+), 356 deletions(-)
#1 lore raw

[tip:x86/setup] x86, setup: "glove box" BIOS interrupts in the core boot code

Commit-ID:  df7699c56421c0476704f24a43409ac8c505f3d2
Gitweb:     http://git.kernel.org/tip/df7699c56421c0476704f24a43409ac8c505f3d2
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:13:46 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:11 -0700

x86, setup: "glove box" BIOS interrupts in the core boot code

Impact: BIOS proofing

"Glove box" off BIOS interrupts in the core boot code.

LKML-Reference: <[email protected]>

---
 arch/x86/boot/a20.c    |    9 +++--
 arch/x86/boot/main.c   |   39 ++++++++++++----------
 arch/x86/boot/memory.c |   81 +++++++++++++++++++++++------------------------
 arch/x86/boot/tty.c    |   52 ++++++++++++++++--------------
 4 files changed, 95 insertions(+), 86 deletions(-)
arch/x86/boot/a20.c +6 -3
index 7c19ce8..64a31a6 100644
@@ -2,7 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
- *   Copyright 2009 Intel Corporation
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -90,8 +90,11 @@ static int a20_test_long(void)
 
 static void enable_a20_bios(void)
 {
-	asm volatile("pushfl; int $0x15; popfl"
-		     : : "a" ((u16)0x2401));
+	struct biosregs ireg;
+
+	initregs(&ireg);
+	ireg.ax = 0x2401;
+	intcall(0x15, &ireg, NULL);
 }
 
 static void enable_a20_kbc(void)
arch/x86/boot/main.c +21 -18
index 58f0415..140172b 100644
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -61,11 +62,10 @@ static void copy_boot_params(void)
  */
 static void keyboard_set_repeat(void)
 {
-	u16 ax = 0x0305;
-	u16 bx = 0;
-	asm volatile("int $0x16"
-		     : "+a" (ax), "+b" (bx)
-		     : : "ecx", "edx", "esi", "edi");
+	struct biosregs ireg;
+	initregs(&ireg);
+	ireg.ax = 0x0305;
+	intcall(0x16, &ireg, NULL);
 }
 
 /*
@@ -73,18 +73,22 @@ static void keyboard_set_repeat(void)
  */
 static void query_ist(void)
 {
+	struct biosregs ireg, oreg;
+
 	/* Some older BIOSes apparently crash on this call, so filter
 	   it from machines too old to have SpeedStep at all. */
 	if (cpu.level < 6)
 		return;
 
-	asm("int $0x15"
-	    : "=a" (boot_params.ist_info.signature),
-	      "=b" (boot_params.ist_info.command),
-	      "=c" (boot_params.ist_info.event),
-	      "=d" (boot_params.ist_info.perf_level)
-	    : "a" (0x0000e980),	 /* IST Support */
-	      "d" (0x47534943)); /* Request value */
+	initregs(&ireg);
+	ireg.ax  = 0xe980;	 /* IST Support */
+	ireg.edx = 0x47534943;	 /* Request value */
+	intcall(0x15, &ireg, &oreg);
+
+	boot_params.ist_info.signature  = oreg.eax;
+	boot_params.ist_info.command    = oreg.ebx;
+	boot_params.ist_info.event      = oreg.ecx;
+	boot_params.ist_info.perf_level = oreg.edx;
 }
 
 /*
@@ -93,13 +97,12 @@ static void query_ist(void)
 static void set_bios_mode(void)
 {
 #ifdef CONFIG_X86_64
-	u32 eax, ebx;
+	struct biosregs ireg;
 
-	eax = 0xec00;
-	ebx = 2;
-	asm volatile("int $0x15"
-		     : "+a" (eax), "+b" (ebx)
-		     : : "ecx", "edx", "esi", "edi");
+	initregs(&ireg);
+	ireg.ax = 0xec00;
+	ireg.bx = 2;
+	intcall(0x15, &ireg, NULL);
 #endif
 }
 
arch/x86/boot/memory.c +40 -41

139 lines not on this page · raw message

arch/x86/boot/tty.c +28 -24

91 lines not on this page · raw message

#2 lore raw

[tip:x86/setup] x86, setup: "glove box" BIOS interrupts in the APM code

In reply to H. Peter Anvin
Commit-ID:  d54ea252e4c92357226992cf65d94616a96e6fce
Gitweb:     http://git.kernel.org/tip/d54ea252e4c92357226992cf65d94616a96e6fce
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:14:26 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:11 -0700

x86, setup: "glove box" BIOS interrupts in the APM code

Impact: BIOS proofing

"Glove box" off BIOS interrupts in the APM code.

LKML-Reference: <[email protected]>

Cc Stephen Rothwell <[email protected]>
---
 arch/x86/boot/apm.c |   76 +++++++++++++++++++-------------------------------
 1 files changed, 29 insertions(+), 47 deletions(-)
arch/x86/boot/apm.c +29 -47
index 7aa6033..ee27483 100644
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   Original APM BIOS checking by Stephen Rothwell, May 1994
  *   ([email protected])
@@ -19,75 +20,56 @@
 
 int query_apm_bios(void)
 {
-	u16 ax, bx, cx, dx, di;
-	u32 ebx, esi;
-	u8 err;
+	struct biosregs ireg, oreg;
 
 	/* APM BIOS installation check */
-	ax = 0x5300;
-	bx = cx = 0;
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
-		     : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
-		     : : "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x53;
+	intcall(0x15, &ireg, &oreg);
 
-	if (err)
+	if (oreg.flags & X86_EFLAGS_CF)
 		return -1;		/* No APM BIOS */
 
-	if (bx != 0x504d)	/* "PM" signature */
+	if (oreg.bx != 0x504d)		/* "PM" signature */
 		return -1;
 
-	if (!(cx & 0x02))		/* 32 bits supported? */
+	if (!(oreg.cx & 0x02))		/* 32 bits supported? */
 		return -1;
 
 	/* Disconnect first, just in case */
-	ax = 0x5304;
-	bx = 0;
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
-		     : "+a" (ax), "+b" (bx)
-		     : : "ecx", "edx", "esi", "edi");
-
-	/* Paranoia */
-	ebx = esi = 0;
-	cx = dx = di = 0;
+	ireg.al = 0x04;
+	intcall(0x15, &ireg, NULL);
 
 	/* 32-bit connect */
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6"
-		     : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx),
-		       "+S" (esi), "+D" (di), "=m" (err)
-		     : "a" (0x5303));
-
-	boot_params.apm_bios_info.cseg = ax;
-	boot_params.apm_bios_info.offset = ebx;
-	boot_params.apm_bios_info.cseg_16 = cx;
-	boot_params.apm_bios_info.dseg = dx;
-	boot_params.apm_bios_info.cseg_len = (u16)esi;
-	boot_params.apm_bios_info.cseg_16_len = esi >> 16;
-	boot_params.apm_bios_info.dseg_len = di;
-
-	if (err)
+	ireg.al = 0x03;
+	intcall(0x15, &ireg, &oreg);
+
+	boot_params.apm_bios_info.cseg        = oreg.ax;
+	boot_params.apm_bios_info.offset      = oreg.ebx;
+	boot_params.apm_bios_info.cseg_16     = oreg.cx;
+	boot_params.apm_bios_info.dseg        = oreg.dx;
+	boot_params.apm_bios_info.cseg_len    = oreg.si;
+	boot_params.apm_bios_info.cseg_16_len = oreg.hsi;
+	boot_params.apm_bios_info.dseg_len    = oreg.di;
+
+	if (oreg.flags & X86_EFLAGS_CF)
 		return -1;
 
 	/* Redo the installation check as the 32-bit connect;
 	   some BIOSes return different flags this way... */
 
-	ax = 0x5300;
-	bx = cx = 0;
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
-		     : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
-		     : : "esi", "edi");
+	ireg.al = 0x00;
+	intcall(0x15, &ireg, &oreg);
 
-	if (err || bx != 0x504d) {
+	if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) {
 		/* Failure with 32-bit connect, try to disconect and ignore */
-		ax = 0x5304;
-		bx = 0;
-		asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
-			     : "+a" (ax), "+b" (bx)
-			     : : "ecx", "edx", "esi", "edi");
+		ireg.al = 0x04;
+		intcall(0x15, &ireg, NULL);
 		return -1;
 	}
 
-	boot_params.apm_bios_info.version = ax;
-	boot_params.apm_bios_info.flags = cx;
+	boot_params.apm_bios_info.version = oreg.ax;
+	boot_params.apm_bios_info.flags   = oreg.cx;
 	return 0;
 }
 
#3 lore raw

[tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to H. Peter Anvin
Commit-ID:  7a734e7dd93b9aea08ed51036a9a0e2c9dfd8dac
Gitweb:     http://git.kernel.org/tip/7a734e7dd93b9aea08ed51036a9a0e2c9dfd8dac
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:08:28 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:11 -0700

x86, setup: "glove box" BIOS calls -- infrastructure

Impact: new interfaces (not yet used)

For all the platforms out there, there is an infinite number of buggy BIOSes. This adds infrastructure to treat BIOS interrupts more like toxic waste and "glove box" them -- we switch out the register set, perform the BIOS interrupt, and then restore the previous state.

LKML-Reference: <[email protected]>

Cc Pavel Machek <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
---
 arch/x86/boot/Makefile                   |    5 +-
 arch/x86/boot/bioscall.S                 |   82 ++++++++++++++++++++++++++++++
 arch/x86/boot/boot.h                     |   48 +++++++++++++++++
 arch/x86/boot/header.S                   |    2 +-
 arch/x86/boot/regs.c                     |   29 +++++++++++
 arch/x86/boot/setup.ld                   |    6 ++
 arch/x86/kernel/acpi/realmode/Makefile   |    2 +-
 arch/x86/kernel/acpi/realmode/bioscall.S |    1 +
 arch/x86/kernel/acpi/realmode/regs.c     |    1 +
 9 files changed, 172 insertions(+), 4 deletions(-)
arch/x86/boot/Makefile +3 -2
index 6633b6e..658bc52 100644
@@ -26,9 +26,10 @@ targets		:= vmlinux.bin setup.bin setup.elf bzImage
 targets		+= fdimage fdimage144 fdimage288 image.iso mtools.conf
 subdir-		:= compressed
 
-setup-y		+= a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y		+= a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
 setup-y		+= header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y		+= printf.o string.o tty.o video.o video-mode.o version.o
+setup-y		+= printf.o regs.o string.o tty.o video.o video-mode.o
+setup-y		+= version.o
 setup-$(CONFIG_X86_APM_BOOT) += apm.o
 
 # The link order of the video-*.o modules can matter.  In particular,
arch/x86/boot/bioscall.S new file +82 -0

82 lines not on this page · raw message

arch/x86/boot/boot.h +48 -0

72 lines not on this page · raw message

arch/x86/boot/header.S +1 -1
index 5d84d1c..486d97f 100644
@@ -221,7 +221,7 @@ setup_data:		.quad 0			# 64-bit physical pointer to
 
 # End of setup header #####################################################
 
-	.section ".inittext", "ax"
+	.section ".entrytext", "ax"
 start_of_setup:
 #ifdef SAFE_RESET_DISK_CONTROLLER
 # Reset the disk controller.
arch/x86/boot/regs.c new file +29 -0
new file mode 100644
index 0000000..958019b
@@ -0,0 +1,29 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Simple helper function for initializing a register set.
+ *
+ * Note that this sets EFLAGS_CF in the input register set; this
+ * makes it easier to catch functions which do nothing but don't
+ * explicitly set CF.
+ */
+
+#include "boot.h"
+
+void initregs(struct biosregs *reg)
+{
+	memset(reg, 0, sizeof *reg);
+	reg->eflags |= X86_EFLAGS_CF;
+	reg->ds = ds();
+	reg->es = ds();
+	reg->fs = fs();
+	reg->gs = gs();
+}
arch/x86/boot/setup.ld +6 -0
index bb8dc2d..0f6ec45 100644
@@ -15,8 +15,11 @@ SECTIONS
 
 	. = 497;
 	.header		: { *(.header) }
+	.entrytext	: { *(.entrytext) }
 	.inittext	: { *(.inittext) }
 	.initdata	: { *(.initdata) }
+	__end_init = .;
+
 	.text		: { *(.text) }
 	.text32		: { *(.text32) }
 
@@ -52,4 +55,7 @@ SECTIONS
 
 	. = ASSERT(_end <= 0x8000, "Setup too big!");
 	. = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
+	/* Necessary for the very-old-loader check to work... */
+	. = ASSERT(__end_init <= 5*512, "init sections too big!");
+
 }
arch/x86/kernel/acpi/realmode/Makefile +1 -1
index 1c31cc0..167bc16 100644
@@ -9,7 +9,7 @@
 always		:= wakeup.bin
 targets		:= wakeup.elf wakeup.lds
 
-wakeup-y	+= wakeup.o wakemain.o video-mode.o copy.o
+wakeup-y	+= wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o
 
 # The link order of the video-*.o modules can matter.  In particular,
 # video-vga.o *must* be listed first, followed by video-vesa.o.
arch/x86/kernel/acpi/realmode/bioscall.S new file +1 -0
new file mode 100644
index 0000000..f51eb0b
@@ -0,0 +1 @@
+#include "../../../boot/bioscall.S"
arch/x86/kernel/acpi/realmode/regs.c new file +1 -0
new file mode 100644
index 0000000..6206033
@@ -0,0 +1 @@
+#include "../../../boot/regs.c"
#4 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Hi!

Quoted 4 lines

x86, setup: "glove box" BIOS calls -- infrastructure

Impact: new interfaces (not yet used)

Quoted 8 lines

For all the platforms out there, there is an infinite number of buggy BIOSes. This adds infrastructure to treat BIOS interrupts more like toxic waste and "glove box" them -- we switch out the register set, perform the BIOS interrupt, and then restore the previous state.

LKML-Reference: <[email protected]>

Sounds quite sane. Disadvantage is that we will no longer detect those buggy BIOSen.

Quoted 4 lines

+/*
+ * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes
+ * touching memory they shouldn't be.
+ */

Touching memory? AFAICT it only prevents touching registers.

arch/x86/boot/bioscall.S line 26

Quoted 11 lines
arch/x86/boot/bioscall.S new file +11 -0
+	.code16
+	.text
+	.globl	intcall
+	.type	intcall, @function
+intcall:
+	/* Self-modify the INT instruction.  Ugly, but works. */
+	cmpb	%al, 3f
+	je	1f
+	movb	%al, 3f
+	jmp	1f		/* Synchronize pipeline */
+1:

There are various CPU bugs with self-modifying code, but I guess we are not using it heavily enough. Also we are single-threaded so that should be ok.
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#5 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 11 lines · Pavel Machek

Hi!

Quoted 9 lines

x86, setup: "glove box" BIOS calls -- infrastructure

Impact: new interfaces (not yet used)

For all the platforms out there, there is an infinite number of buggy BIOSes. This adds infrastructure to treat BIOS interrupts more like toxic waste and "glove box" them -- we switch out the register set, perform the BIOS interrupt, and then restore the previous state.

Quoted 6 lines
Quoted 3 lines

LKML-Reference: <[email protected]>

Sounds quite sane. Disadvantage is that we will no longer detect those buggy BIOSen.

I'd call that an advantage: sandboxing BIOS calls as much as we can and trusting all data from it as if it were a random packet from the Internet is the only sane way forward IMHO.

If we really care we could put in checks for unexpected register state changes ... but is it worth the trouble?

Ingo

#6 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 18 lines · Ingo Molnar
Quoted 15 lines · Pavel Machek

Hi!

Quoted 12 lines

x86, setup: "glove box" BIOS calls -- infrastructure

Impact: new interfaces (not yet used)

For all the platforms out there, there is an infinite number of buggy BIOSes. This adds infrastructure to treat BIOS interrupts more like toxic waste and "glove box" them -- we switch out the register set, perform the BIOS interrupt, and then restore the previous state.

LKML-Reference: <[email protected]>

Quoted 6 lines
Quoted 2 lines

Sounds quite sane. Disadvantage is that we will no longer detect those buggy BIOSen.

I'd call that an advantage: sandboxing BIOS calls as much as we can and trusting all data from it as if it were a random packet from the Internet is the only sane way forward IMHO.

Well, difference is that you can defend against arbitrary network packet, but you can't defend against arbitrarily broken BIOS. If it loops forever, or overwrites random memory place, we lost...

Quoted 2 lines

If we really care we could put in checks for unexpected register state changes ... but is it worth the trouble?

So maybe we do need to cooperate with BIOS people, making them fix their code. Checking for unexpected changes would certainly be good idea for firmware testing kit... and it would probably make sense to complain during regular boot, too.
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#7 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 22 lines · Pavel Machek
Quoted 21 lines · Ingo Molnar
Quoted 17 lines · Pavel Machek

Hi!

Quoted 4 lines

x86, setup: "glove box" BIOS calls -- infrastructure

Impact: new interfaces (not yet used)

Quoted 8 lines

For all the platforms out there, there is an infinite number of buggy BIOSes. This adds infrastructure to treat BIOS interrupts more like toxic waste and "glove box" them -- we switch out the register set, perform the BIOS interrupt, and then restore the previous state.

LKML-Reference: <[email protected]>

Sounds quite sane. Disadvantage is that we will no longer detect those buggy BIOSen.

Quoted 7 lines
Quoted 3 lines

I'd call that an advantage: sandboxing BIOS calls as much as we can and trusting all data from it as if it were a random packet from the Internet is the only sane way forward IMHO.

Well, difference is that you can defend against arbitrary network packet, but you can't defend against arbitrarily broken BIOS. If it loops forever, or overwrites random memory place, we lost...

We could protect against random memory corruption too, if it ever became a widespread problem: by executing the BIOS call in a virtual machine. (We can probably use the KVM code to properly emulate big real mode, etc.)

That way we can monitor and warn about any undue access patterns.

The solution Peter did here sandboxes the CPU context: which was observed to be randomly corrupted by BIOSen and depending on register layout details of other OSs (Windows mostly) it might not have caused trouble there.

Memory corruption would be noticed under Windows too, so while it does show up every now and then, it rarely remains unfixed. Register corruptions will stay unfixed forever if they dont affect Windows (which they often dont) - so these are far more of a priority to sandbox.

Quoted 7 lines
Quoted 2 lines

If we really care we could put in checks for unexpected register state changes ... but is it worth the trouble?

So maybe we do need to cooperate with BIOS people, making them fix their code. Checking for unexpected changes would certainly be good idea for firmware testing kit... and it would probably make sense to complain during regular boot, too.

"BIOS people" are operating in a completely different culture. Time to market, hardware workarounds, short-term differentiators, secret bootstrap sequences and code compactness are king in that space. Code quality is dead last in the list. I strongly doubt that given the radically conflicting priorities a reasonable dialogue can be established.

Reasonable dialogue could be established with efforts that turn Linux into a replacement of the firmware: CoreBoot a'ka LinuxBIOS. Having an end-to-end Linux solution for all things bootstrap is a very strong concept IMHO. For various reasons that relationship is not unstrained either, unfortunately.

Ingo

#8 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Hi!

Quoted 8 lines
Quoted 3 lines

Well, difference is that you can defend against arbitrary network packet, but you can't defend against arbitrarily broken BIOS. If it loops forever, or overwrites random memory place, we lost...

We could protect against random memory corruption too, if it ever became a widespread problem: by executing the BIOS call in a virtual machine. (We can probably use the KVM code to properly emulate big real mode, etc.)

We already have problems where bios corrupts low memory area during suspend/resume. Not sure how KVM helps.

Anyway I do agree with the patches.

Quoted 6 lines

"BIOS people" are operating in a completely different culture. Time to market, hardware workarounds, short-term differentiators, secret bootstrap sequences and code compactness are king in that space. Code quality is dead last in the list. I strongly doubt that given the radically conflicting priorities a reasonable dialogue can be established.

"BIOS people" control stuff like SMM mode. We can workaround some BIOS problems, but definitely not all of them.

For servers, I guess Linux has enough of market share that we could certify known-good servers (and maybe warn against known-bad).
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#9 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 7 lines · Pavel Machek
Quoted 6 lines

"BIOS people" are operating in a completely different culture. Time to market, hardware workarounds, short-term differentiators, secret bootstrap sequences and code compactness are king in that space. Code quality is dead last in the list. I strongly doubt that given the radically conflicting priorities a reasonable dialogue can be established.

Quoted 6 lines

"BIOS people" control stuff like SMM mode. We can workaround some BIOS problems, but definitely not all of them.

For servers, I guess Linux has enough of market share that we could certify known-good servers (and maybe warn against known-bad).

Server space is somewhat less of a problem BIOS quality wise: the design cycles are longer, the features are more complex and the profit margins are higher - which all results in saner practices and more care. They even do server BIOS fixes for Linux.

The problem are the "Does it boot Windows? Ship it, forget it, buldoze the factory" kind of desktop operations.

Ingo

#10 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to Pavel Machek
Quoted 12 lines · Pavel Machek

Hi!

Quoted 4 lines
Quoted 2 lines

Well, difference is that you can defend against arbitrary network packet, but you can't defend against arbitrarily broken BIOS. If it loops forever, or overwrites random memory place, we lost...

We could protect against random memory corruption too, if it ever became a widespread problem: by executing the BIOS call in a virtual machine. (We can probably use the KVM code to properly emulate big real mode, etc.)

We already have problems where bios corrupts low memory area during suspend/resume. Not sure how KVM helps.

kvm might help detecting these issues, but not in fixing them. If you isolate the BIOS, then you've prevented corruption, but you've also prevented it from doing whatever it is it was supposed to do. If you give it access to memory and the rest of the system, then whatever evil it has wrought affects the system.

You could try to allow the BIOS access to selected pieces of memory and hardware, virtualizing the rest, but it seems to me it would be more like a recipe for a giant headache that a solution.

Signature · 1 line
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
author reviewer
#11 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 5 lines · Avi Kivity

kvm might help detecting these issues, but not in fixing them. If you isolate the BIOS, then you've prevented corruption, but you've also prevented it from doing whatever it is it was supposed to do. If you give it access to memory and the rest of the system, then whatever evil it has wrought affects the system.

You could try to allow the BIOS access to selected pieces of memory and hardware, virtualizing the rest, but it seems to me it would be more like a recipe for a giant headache that a solution.

The main thing you could do is drop or virtualize memory accesses to RAM it should never access in the first place, like some BIOSes which scribble over random locations in low memory.

-hpa

#12 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 8 lines · H. Peter Anvin
Quoted 7 lines · Avi Kivity

kvm might help detecting these issues, but not in fixing them. If you isolate the BIOS, then you've prevented corruption, but you've also prevented it from doing whatever it is it was supposed to do. If you give it access to memory and the rest of the system, then whatever evil it has wrought affects the system.

Quoted 8 lines
Quoted 4 lines

You could try to allow the BIOS access to selected pieces of memory and hardware, virtualizing the rest, but it seems to me it would be more like a recipe for a giant headache that a solution.

The main thing you could do is drop or virtualize memory accesses to RAM it should never access in the first place, like some BIOSes which scribble over random locations in low memory.

it would be enough to get the information out. That way we could see (from the access patterns) what the heck it is trying to do (did someone rootkit the bios?), and what we can do about it. Trying to contain it will likely break the BIOS and causes silent hangs with no usable bug report left.

Ingo

#13 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 7 lines · Ingo Molnar
Quoted 4 lines · H. Peter Anvin
Quoted 2 lines · Avi Kivity

kvm might help detecting these issues, but not in fixing them. If you isolate the BIOS, then you've prevented corruption, but you've also prevented it from doing whatever it is it was supposed to do. If you give it access to memory and the rest of the system, then whatever evil it has wrought affects the system.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

You could try to allow the BIOS access to selected pieces of memory and hardware, virtualizing the rest, but it seems to me it would be more like a recipe for a giant headache that a solution.

The main thing you could do is drop or virtualize memory accesses to RAM it should never access in the first place, like some BIOSes which scribble over random locations in low memory.

it would be enough to get the information out. That way we could see (from the access patterns) what the heck it is trying to do (did someone rootkit the bios?), and what we can do about it. Trying to contain it will likely break the BIOS and causes silent hangs with no usable bug report left.

Hmm, it's doable with the 1:1 mode; Andrea did some work on this.

However if the bios tries to do anything clever (like using SMM) things will fail pretty badly.

Signature · 1 line
error compiling committee.c: too many arguments to function
#14 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to H. Peter Anvin
Quoted 4 lines · H. Peter Anvin

The main thing you could do is drop or virtualize memory accesses to RAM it should never access in the first place, like some BIOSes which scribble over random locations in low memory.

Please don't.

This discussion is just taking us down a rat-hole of more complexity, and _way_ more fragility.

I'm absolutely willing to bet that trying to do the BIOS calls will break way more than it will fix. Sure, it will probably work for 99.9% of all BIOSes, but then it will break horribly for some BIOS that tries to do something "clever". SMM has already been mentioned as an example of something that simply isn't virtualizable.

Timing is another, very traditional, one. There used to be video BIOSes that simply didn't work in a dosbox-like environment because they had tight timing loops that were coupled to hardware. I can pretty much guarantee that that has gone away as far as the video BIOS is concerned, but the main BIOS? Who the hell knows.

Sure, none of the calls we do to the BIOS from the kernel should need anything fancy at all, and maybe I'm pessimistic. But at the same time, I really don't think the BIOS calls are worth that kind of infrastructure.

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Linus

#15 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 3 lines · Linus Torvalds

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Yeah. I only brought up the virtualization thing as a hypothetical:
"if" corrupting the main OS ever became a widespread problem. Then i made the argument that this is unlikely to happen, because Windows will be affected by it just as much. (while register state corruptions might go unnoticed much more easily, just via the random call-environment clobbering of registers by Windows itself.)

The only case where i could see virtualization to be useful is the low memory RAM corruption pattern that some people have observed.

The problem with it, it happens on s2ram transitions, and that is driven by SMM mainly - which is a hypervisor sitting on top of all the other would-be-hypervisors and thus not virtualizable.

Which leaves us without a single practical case. So it's not going to happen.

Ingo

#16 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 7 lines · Ingo Molnar
Quoted 2 lines

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Yeah. I only brought up the virtualization thing as a hypothetical: "if" corrupting the main OS ever became a widespread problem. Then i made the argument that this is unlikely to happen, because Windows will be affected by it just as much. (while register state corruptions might go unnoticed much more easily, just via the random call-environment clobbering of registers by Windows itself.)

The only case where i could see virtualization to be useful is the low memory RAM corruption pattern that some people have observed.

You could easily check that by checksumming pages (or actually copying them to high memory) before the call, and verifying after the call.

Quoted 2 lines

The problem with it, it happens on s2ram transitions, and that is driven by SMM mainly - which is a hypervisor sitting on top of all the other would-be-hypervisors and thus not virtualizable.

AMD in fact has a chapter called "Containerizing Platform SMM" or words to the effect, which describes how to take a running system and drop its SMM mode into a virtualization container. I made a point of skipping over those pages with my eyes closed so I can't tell you how incredibly complex it is.

It's probably even doable on Intel, though much more difficult, due to Intel not supporting big real mode in a guest, and most SMM code using it to access memory. You'd end up running most of the code in the emulator, and performing the transitions by hand.

Of course, the VMM has to be careful not to trigger SMM itself, or much merriment ensues.

Quoted 2 lines

Which leaves us without a single practical case. So it's not going to happen.

I don't think the effort is worth the benefit in this case, but there actually is an interesting use case for this. SMM is known to be harmful to deterministic replay games and to real time response. If we can virtualize SMM, we can increase the range of hardware on which the real time kernel is able to deliver real time guarantees.

Signature · 1 line
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
#17 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 14 lines · Avi Kivity
Quoted 13 lines · Ingo Molnar
Quoted 4 lines

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Yeah. I only brought up the virtualization thing as a
hypothetical: "if" corrupting the main OS ever became a widespread problem. Then i made the argument that this is unlikely to happen, because Windows will be affected by it just as much. (while register state corruptions might go unnoticed much more easily, just via the random call-environment clobbering of registers by Windows itself.)

Quoted 7 lines
Quoted 3 lines

The only case where i could see virtualization to be useful is the low memory RAM corruption pattern that some people have observed.

You could easily check that by checksumming pages (or actually copying them to high memory) before the call, and verifying after the call.

Yes, we could do memory checks, and ... hey, we already do that:

bb577f9: x86: add periodic corruption check
5394f80: x86: check for and defend against BIOS memory corruption

... and i seem to be the one who implemented it! ;-)

That check resulted in logs showing the BIOS corrupting Linux memory across s2ram cycles or HDMI plug/unplug events on certain boxes (are Hollywood rootkits in the BIOS now?), and resulted in some head-scratching but not much more.

See:

"corrupt PMD after resume"

http://bugzilla.kernel.org/show_bug.cgi?id=11237

Quoted 21 lines
Quoted 3 lines

The problem with it, it happens on s2ram transitions, and that is driven by SMM mainly - which is a hypervisor sitting on top of all the other would-be-hypervisors and thus not virtualizable.

AMD in fact has a chapter called "Containerizing Platform SMM" or words to the effect, which describes how to take a running system and drop its SMM mode into a virtualization container. I made a point of skipping over those pages with my eyes closed so I can't tell you how incredibly complex it is.

It's probably even doable on Intel, though much more difficult, due to Intel not supporting big real mode in a guest, and most SMM code using it to access memory. You'd end up running most of the code in the emulator, and performing the transitions by hand.

Of course, the VMM has to be careful not to trigger SMM itself, or much merriment ensues.

Quoted 2 lines

Which leaves us without a single practical case. So it's not going to happen.

Quoted 6 lines

I don't think the effort is worth the benefit in this case, but there actually is an interesting use case for this. SMM is known to be harmful to deterministic replay games and to real time response. If we can virtualize SMM, we can increase the range of hardware on which the real time kernel is able to deliver real time guarantees.

Hey, i do have a real sweet spot for deterministic execution - but SMM, while not problem-free (like most of firmware), also has a very real role in not letting various hardware melt. So SMM should be thought of as a flexible extended arm of hardware - not some sw bit.

So i think that the memory of that SMM virtualization chapter you've almost read should be quickly erased from your mind. (Via forceful means if prompt corrective self-action is not forthcoming.)

The determinism issue can IMHO be solved via a simpler measure: by making sure the owner of the box always knows when SMMs happened. Real-time folks are very picky about their hardware and there's many suppliers, so it would have a real market effect. I know about one case where a BIOS was modified to lessen its SMM latency impact.

Ingo

#18 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 25 lines · Ingo Molnar
Quoted 14 lines · Avi Kivity
Quoted 13 lines · Ingo Molnar
Quoted 4 lines

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Yeah. I only brought up the virtualization thing as a
hypothetical: "if" corrupting the main OS ever became a widespread problem. Then i made the argument that this is unlikely to happen, because Windows will be affected by it just as much. (while register state corruptions might go unnoticed much more easily, just via the random call-environment clobbering of registers by Windows itself.)

Quoted 7 lines
Quoted 3 lines

The only case where i could see virtualization to be useful is the low memory RAM corruption pattern that some people have observed.

You could easily check that by checksumming pages (or actually copying them to high memory) before the call, and verifying after the call.

Quoted 6 lines

Yes, we could do memory checks, and ... hey, we already do that:

bb577f9: x86: add periodic corruption check
5394f80: x86: check for and defend against BIOS memory corruption

... and i seem to be the one who implemented it! ;-)

s/implemented/merged+fixed :-)

Ingo

author reviewer
#19 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 8 lines · Ingo Molnar
Quoted 6 lines

Yes, we could do memory checks, and ... hey, we already do that:

bb577f9: x86: add periodic corruption check
5394f80: x86: check for and defend against BIOS memory corruption

... and i seem to be the one who implemented it! ;-)

s/implemented/merged+fixed :-)

Actually, what would probably be more productive than trying to track corruption would be to drop the low 1 MB of memory before suspend to RAM
- make sure that it is as close to completely unused as possible.

All *known* cases of low memory corruption are either boot time or due to s2ram.

I don't know how realistic it is to make the low 1 MB completely unused over the s2ram cycle. The trivial way of doing it is to simply not use it -- it's only some 600K after all; a more sophisticated way would be to explicitly constrain it to transient uses that would be dead at s2ram.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#20 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 14 lines · H. Peter Anvin
Quoted 8 lines · Ingo Molnar
Quoted 6 lines

Yes, we could do memory checks, and ... hey, we already do that:

bb577f9: x86: add periodic corruption check
5394f80: x86: check for and defend against BIOS memory corruption

... and i seem to be the one who implemented it! ;-)

s/implemented/merged+fixed :-)

Actually, what would probably be more productive than trying to track corruption would be to drop the low 1 MB of memory before suspend to RAM
- make sure that it is as close to completely unused as possible.

Quoted 7 lines

All *known* cases of low memory corruption are either boot time or due to s2ram.

I don't know how realistic it is to make the low 1 MB completely unused over the s2ram cycle. The trivial way of doing it is to simply not use it -- it's only some 600K after all; a more sophisticated way would be to explicitly constrain it to transient uses that would be dead at s2ram.

That should be doable... with memory hotplug support etc, eventually.

OTOH all known corruption is within 64K IIRC, and reserving that is rather easy.
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
author reviewer
#21 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 4 lines · Pavel Machek

OTOH all known corruption is within 64K IIRC, and reserving that is rather easy.
Pavel

Sadly, not so.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#22 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to H. Peter Anvin
Quoted 8 lines · H. Peter Anvin
Quoted 7 lines · Ingo Molnar
Quoted 6 lines

Yes, we could do memory checks, and ... hey, we already do that:

bb577f9: x86: add periodic corruption check
5394f80: x86: check for and defend against BIOS memory corruption

... and i seem to be the one who implemented it! ;-)

Quoted 8 lines
Quoted 1 line

s/implemented/merged+fixed :-)

Actually, what would probably be more productive than trying to track corruption would be to drop the low 1 MB of memory before suspend to RAM
- make sure that it is as close to completely unused as possible.

All *known* cases of low memory corruption are either boot time or due to s2ram.

IIRC, the first person to report the issue found that it triggered when hotplugging a HDMI cable.

#23 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 2 lines · Alan Jenkins

IIRC, the first person to report the issue found that it triggered when hotplugging a HDMI cable.

Oh, that's right. Either we were invoking the video BIOS from the kernel (which we do actually do sometimes) -- in which case we have control over when it happens -- or there is commingling of the video BIOS and mainboard BIOS combined with SMM crap. Joy.

-hpa

#24 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 8 lines · H. Peter Anvin
Quoted 2 lines · Alan Jenkins

IIRC, the first person to report the issue found that it triggered when hotplugging a HDMI cable.

Oh, that's right. Either we were invoking the video BIOS from the kernel (which we do actually do sometimes) -- in which case we have control over when it happens -- or there is commingling of the video BIOS and mainboard BIOS combined with SMM crap. Joy.

The corruption pattern in the bugzilla:

    http://bugzilla.kernel.org/show_bug.cgi?id=11237

... looks like an x86 descriptor table. Does the pattern below make any sense to anyone? I've attached the relevant bits of one of the reports below.

Ingo

[   28.414367] Corrupted low memory at c000c000 (c000 phys) = 02062004
[   28.414367] Corrupted low memory at c000c004 (c004 phys) = 0000003a
[   28.414367] Corrupted low memory at c000c008 (c008 phys) = 00208000
[   28.414367] Corrupted low memory at c000c00c (c00c phys) = 3e88c6fd
[   28.414367] Corrupted low memory at c000c018 (c018 phys) = 0000004a
[   28.414367] Corrupted low memory at c000c01c (c01c phys) = aaaaaa00
[   28.414367] Corrupted low memory at c000c020 (c020 phys) = 00000644
[   28.414367] Corrupted low memory at c000c024 (c024 phys) = 00000140
[   28.414367] Corrupted low memory at c000c028 (c028 phys) = ffffffff
[   28.414367] Corrupted low memory at c000c02c (c02c phys) = ffffffff
[   28.414367] Corrupted low memory at c000c030 (c030 phys) = ffffffff
[   28.414367] Corrupted low memory at c000c034 (c034 phys) = ffffffff
[   28.414367] Corrupted low memory at c000c038 (c038 phys) = ffffffff
[   28.414367] Corrupted low memory at c000c03c (c03c phys) = ffffffff
[   28.414367] Corrupted low memory at c000c040 (c040 phys) = 00fffbff
[   28.414367] Corrupted low memory at c000c044 (c044 phys) = fd9035c3
[   28.414367] Corrupted low memory at c000c048 (c048 phys) = a9fe7bf8
[   28.414367] Corrupted low memory at c000c04c (c04c phys) = 3f00ff0f
[   28.414367] Corrupted low memory at c000c050 (c050 phys) = c7ffdffe
[   28.414367] Corrupted low memory at c000c054 (c054 phys) = 3c03bc1e
[   28.414367] Corrupted low memory at c000c058 (c058 phys) = 00d62480
[   28.414367] Corrupted low memory at c000c05c (c05c phys) = fffffe14
[   28.414367] Corrupted low memory at c000c060 (c060 phys) = eb1fe1fe
[   28.414367] Corrupted low memory at c000c064 (c064 phys) = ff3cf64c
[   28.414367] Corrupted low memory at c000c068 (c068 phys) = 807f879f
[   28.414367] Corrupted low memory at c000c06c (c06c phys) = f0266027
[   28.414367] Corrupted low memory at c000c070 (c070 phys) = 18fe1d74
[   28.414367] Corrupted low memory at c000c074 (c074 phys) = 6b122000
[   28.414367] Corrupted low memory at c000c078 (c078 phys) = e7fffbcf
[   28.414367] Corrupted low memory at c000c07c (c07c phys) = 0ff0f3f0
[   28.414367] Corrupted low memory at c000c080 (c080 phys) = 9fffee3f
[   28.414367] Corrupted low memory at c000c084 (c084 phys) = 1bc3e440
[   28.414367] Corrupted low memory at c000c088 (c088 phys) = 07fc01fe
[   28.414367] Corrupted low memory at c000c08c (c08c phys) = ff0dfe00
[   28.414367] Corrupted low memory at c000c090 (c090 phys) = ebe00035
[   28.414367] Corrupted low memory at c000c094 (c094 phys) = 3fe00ff0
[   28.414367] Corrupted low memory at c000c098 (c098 phys) = f86ff007
[   28.414367] Corrupted low memory at c000c09c (c09c phys) = ff803fc0
[   28.414367] Corrupted low memory at c000c0a0 (c0a0 phys) = e1bfc01f
[   28.414367] Corrupted low memory at c000c0a4 (c0a4 phys) = fe00ff03
[   28.414367] Corrupted low memory at c000c0a8 (c0a8 phys) = 86ff007f
[   28.414367] Corrupted low memory at c000c0ac (c0ac phys) = 78001a30
[   28.414367] Corrupted low memory at c000c0b0 (c0b0 phys) = f007f81f
[   28.414367] Corrupted low memory at c000c0b4 (c0b4 phys) = 37f803fc
[   28.414367] Corrupted low memory at c000c0b8 (c0b8 phys) = c01fe07f
[   28.414367] Corrupted low memory at c000c0bc (c0bc phys) = dfe00ff0
[   28.414367] Corrupted low memory at c000c0c0 (c0c0 phys) = 007f81ff
[   28.414367] Corrupted low memory at c000c0c4 (c0c4 phys) = 7f803fc3
[   28.414367] Corrupted low memory at c000c0c8 (c0c8 phys) = 000f7ffc
[   28.414367] Corrupted low memory at c000c0cc (c0cc phys) = 03fc0ff8
[   28.414367] Corrupted low memory at c000c0d0 (c0d0 phys) = fc01fe1b
[   28.414367] Corrupted low memory at c000c0d4 (c0d4 phys) = 0ff03fe0
[   28.414367] Corrupted low memory at c000c0d8 (c0d8 phys) = f007f86f
[   28.414367] Corrupted low memory at c000c0dc (c0dc phys) = 3fc0ff80
[   28.414367] Corrupted low memory at c000c0e0 (c0e0 phys) = c01fe1bf
[   28.414367] Corrupted low memory at c000c0e4 (c0e4 phys) = 07bffe00
[   28.414367] Corrupted low memory at c000c0e8 (c0e8 phys) = fe07fc01
[   28.414367] Corrupted low memory at c000c0ec (c0ec phys) = 00ff0dfe
[   28.414367] Corrupted low memory at c000c0f0 (c0f0 phys) = f81ff007
[   28.414367] Corrupted low memory at c000c0f4 (c0f4 phys) = 03fc37f8
[   28.414367] Corrupted low memory at c000c0f8 (c0f8 phys) = e07fc01f
[   28.414367] Corrupted low memory at c000c0fc (c0fc phys) = 0ff0dfe0
[   28.414367] Corrupted low memory at c000c100 (c100 phys) = dfff0003
[   28.414367] Corrupted low memory at c000c104 (c104 phys) = 03fe00ff
[   28.414367] Corrupted low memory at c000c108 (c108 phys) = 7f86ff00
[   28.414367] Corrupted low memory at c000c10c (c10c phys) = 0ff803fc
[   28.414367] Corrupted low memory at c000c110 (c110 phys) = fe1bfc01
[   28.414367] Corrupted low memory at c000c114 (c114 phys) = 3fe00ff0
[   28.414367] Corrupted low memory at c000c118 (c118 phys) = f86ff007
[   28.414367] Corrupted low memory at c000c11c (c11c phys) = ff8001ef
[   28.414367] Corrupted low memory at c000c120 (c120 phys) = ff007f81
[   28.414367] Corrupted low memory at c000c124 (c124 phys) = c37f803f
[   28.414367] Corrupted low memory at c000c128 (c128 phys) = fc01fe07
[   28.414367] Corrupted low memory at c000c12c (c12c phys) = 0dfe00ff
[   28.414367] Corrupted low memory at c000c130 (c130 phys) = f007f81f
[   28.414367] Corrupted low memory at c000c134 (c134 phys) = 37f803fc
[   28.414367] Corrupted low memory at c000c138 (c138 phys) = c000f7ff
[   28.414367] Corrupted low memory at c000c13c (c13c phys) = 803fc0ff
[   28.414367] Corrupted low memory at c000c140 (c140 phys) = bfc01fe1
[   28.414367] Corrupted low memory at c000c144 (c144 phys) = 00ff03fe
[   28.414367] Corrupted low memory at c000c148 (c148 phys) = ff007f86
[   28.414367] Corrupted low memory at c000c14c (c14c phys) = 03fc0ff8
[   28.414367] Corrupted low memory at c000c150 (c150 phys) = fc01fe1b
[   28.414367] Corrupted low memory at c000c154 (c154 phys) = 007bffe0
[   28.414367] Corrupted low memory at c000c158 (c158 phys) = 1fe07fc0
[   28.414367] Corrupted low memory at c000c15c (c15c phys) = e00ff0df
[   28.414367] Corrupted low memory at c000c160 (c160 phys) = 7f81ff00
[   28.414367] Corrupted low memory at c000c164 (c164 phys) = 803fc37f
[   28.414367] Corrupted low memory at c000c168 (c168 phys) = fe07fc01
[   28.414367] Corrupted low memory at c000c16c (c16c phys) = 00ff0dfe
[   28.414367] Corrupted low memory at c000c170 (c170 phys) = 3dfff000
[   28.414367] Corrupted low memory at c000c174 (c174 phys) = f03fe00f
[   28.414367] Corrupted low memory at c000c178 (c178 phys) = 07f86ff0
[   28.414367] Corrupted low memory at c000c17c (c17c phys) = c0ff803f
[   28.414367] Corrupted low memory at c000c180 (c180 phys) = 1fe1bfc0
[   28.414367] Corrupted low memory at c000c184 (c184 phys) = 03fe00ff
[   28.414367] Corrupted low memory at c000c188 (c188 phys) = 7f86ff00
[   28.414367] Corrupted low memory at c000c18c (c18c phys) = fff8001e
[   28.414367] Corrupted low memory at c000c190 (c190 phys) = 1ff007f8
[   28.414367] Corrupted low memory at c000c194 (c194 phys) = fc37f803
[   28.414367] Corrupted low memory at c000c198 (c198 phys) = 7fc01fe0
[   28.414367] Corrupted low memory at c000c19c (c19c phys) = f0dfe00f
[   28.414367] Corrupted low memory at c000c1a0 (c1a0 phys) = ff007f81
[   28.414367] Corrupted low memory at c000c1a4 (c1a4 phys) = c37f803f
[   28.414367] Corrupted low memory at c000c1a8 (c1a8 phys) = fc000f7f
[   28.414367] Corrupted low memory at c000c1ac (c1ac phys) = f803fc0f
[   28.414367] Corrupted low memory at c000c1b0 (c1b0 phys) = 1bfc01fe
[   28.414367] Corrupted low memory at c000c1b4 (c1b4 phys) = e00ff03f
[   28.414367] Corrupted low memory at c000c1b8 (c1b8 phys) = 6ff007f8
[   28.414367] Corrupted low memory at c000c1bc (c1bc phys) = 803fc0ff
[   28.414367] Corrupted low memory at c000c1c0 (c1c0 phys) = bfc01fe1
[   28.414367] Corrupted low memory at c000c1c4 (c1c4 phys) = 0007bffe
[   28.414367] Corrupted low memory at c000c1c8 (c1c8 phys) = 01fe07fc
[   28.414367] Corrupted low memory at c000c1cc (c1cc phys) = fe00ff0d
[   28.414367] Corrupted low memory at c000c1d0 (c1d0 phys) = 07f81ff0
[   28.414367] Corrupted low memory at c000c1d4 (c1d4 phys) = f803fc37
[   28.414367] Corrupted low memory at c000c1d8 (c1d8 phys) = 1fe07fc0
[   28.414367] Corrupted low memory at c000c1dc (c1dc phys) = e00ff0df
[   28.414367] Corrupted low memory at c000c1e0 (c1e0 phys) = 03dfff00
[   28.414367] Corrupted low memory at c000c1e4 (c1e4 phys) = ff03fe00
[   28.414367] Corrupted low memory at c000c1e8 (c1e8 phys) = 007f86ff
[   28.414367] Corrupted low memory at c000c1ec (c1ec phys) = fc0ff803
[   28.414367] Corrupted low memory at c000c1f0 (c1f0 phys) = 01fe1bfc
[   28.414367] Corrupted low memory at c000c1f4 (c1f4 phys) = f03fe00f
[   28.414367] Corrupted low memory at c000c1f8 (c1f8 phys) = 07f86ff0
[   28.414367] Corrupted low memory at c000c1fc (c1fc phys) = efff8001
[   28.414367] Corrupted low memory at c000c200 (c200 phys) = 81ff007f
[   28.414367] Corrupted low memory at c000c204 (c204 phys) = 3fc37f80
[   28.414367] Corrupted low memory at c000c208 (c208 phys) = 07fc01fe
[   28.414367] Corrupted low memory at c000c20c (c20c phys) = ff0dfe00
[   28.414367] Corrupted low memory at c000c210 (c210 phys) = 1ff007f8
[   28.414367] Corrupted low memory at c000c214 (c214 phys) = fc37f803
[   28.414367] Corrupted low memory at c000c218 (c218 phys) = ffc000f7
[   28.414367] Corrupted low memory at c000c21c (c21c phys) = ff803fc0
[   28.414367] Corrupted low memory at c000c220 (c220 phys) = e1bfc01f
[   28.414367] Corrupted low memory at c000c224 (c224 phys) = fe00ff03
[   28.414367] Corrupted low memory at c000c228 (c228 phys) = 86ff007f
[   28.414367] Corrupted low memory at c000c22c (c22c phys) = f803fc0f
[   28.414367] Corrupted low memory at c000c230 (c230 phys) = 1bfc01fe
[   28.414367] Corrupted low memory at c000c234 (c234 phys) = e0007bff
[   28.414367] Corrupted low memory at c000c238 (c238 phys) = c01fe07f
[   28.414367] Corrupted low memory at c000c23c (c23c phys) = dfe00ff0
[   28.414367] Corrupted low memory at c000c240 (c240 phys) = 007f81ff
[   28.414367] Corrupted low memory at c000c244 (c244 phys) = 7f803fc3
[   28.414367] Corrupted low memory at c000c248 (c248 phys) = 01fe07fc
[   28.414367] Corrupted low memory at c000c24c (c24c phys) = fe00ff0d
[   28.414367] Corrupted low memory at c000c250 (c250 phys) = 003dfff0
[   28.414367] Corrupted low memory at c000c254 (c254 phys) = 0ff03fe0
[   28.414367] Corrupted low memory at c000c258 (c258 phys) = f007f86f
[   28.414367] Corrupted low memory at c000c25c (c25c phys) = 3fc0ff80
[   28.414367] Corrupted low memory at c000c260 (c260 phys) = c01fe1bf
[   28.414367] Corrupted low memory at c000c264 (c264 phys) = ff03fe00
[   28.414367] Corrupted low memory at c000c268 (c268 phys) = 007f86ff
[   28.414367] Corrupted low memory at c000c26c (c26c phys) = 1efff800
[   28.414367] Corrupted low memory at c000c270 (c270 phys) = f81ff007
[   28.414367] Corrupted low memory at c000c274 (c274 phys) = 03fc37f8
[   28.414367] Corrupted low memory at c000c278 (c278 phys) = e07fc01f
[   28.414367] Corrupted low memory at c000c27c (c27c phys) = 0ff0dfe0
[   28.414367] Corrupted low memory at c000c280 (c280 phys) = 81ff007f
[   28.414367] Corrupted low memory at c000c284 (c284 phys) = 3fc37f80
[   28.414367] Corrupted low memory at c000c288 (c288 phys) = 7ffc000f
[   28.414367] Corrupted low memory at c000c28c (c28c phys) = 0ff803fc
[   28.414367] Corrupted low memory at c000c290 (c290 phys) = fe1bfc01
[   28.414367] Corrupted low memory at c000c294 (c294 phys) = 3fe00ff0
[   28.414367] Corrupted low memory at c000c298 (c298 phys) = f86ff007
[   28.414367] Corrupted low memory at c000c29c (c29c phys) = ff803fc0
[   28.414367] Corrupted low memory at c000c2a0 (c2a0 phys) = e1bfc01f
[   28.414367] Corrupted low memory at c000c2a4 (c2a4 phys) = fe0007bf
[   28.414367] Corrupted low memory at c000c2a8 (c2a8 phys) = fc01fe07
[   28.414367] Corrupted low memory at c000c2ac (c2ac phys) = 0dfe00ff
[   28.414367] Corrupted low memory at c000c2b0 (c2b0 phys) = f007f81f
[   28.414367] Corrupted low memory at c000c2b4 (c2b4 phys) = 37f803fc
[   28.414367] Corrupted low memory at c000c2b8 (c2b8 phys) = c01fe07f
[   28.414367] Corrupted low memory at c000c2bc (c2bc phys) = dfe00ff0
[   28.414367] Corrupted low memory at c000c2c0 (c2c0 phys) = 0003dfff
[   28.414367] Corrupted low memory at c000c2c4 (c2c4 phys) = 00ff03fe
[   28.414367] Corrupted low memory at c000c2c8 (c2c8 phys) = ff007f86
[   28.414367] Corrupted low memory at c000c2cc (c2cc phys) = 03fc0ff8
[   28.414367] Corrupted low memory at c000c2d0 (c2d0 phys) = fc01fe1b
[   28.414367] Corrupted low memory at c000c2d4 (c2d4 phys) = 0ff03fe0
[   28.414367] Corrupted low memory at c000c2d8 (c2d8 phys) = f007f86f
[   28.414367] Corrupted low memory at c000c2dc (c2dc phys) = 01efff80
[   28.414367] Corrupted low memory at c000c2e0 (c2e0 phys) = 7f81ff00
[   28.414367] Corrupted low memory at c000c2e4 (c2e4 phys) = 803fc37f
[   28.414367] Corrupted low memory at c000c2e8 (c2e8 phys) = fe07fc01
[   28.414367] Corrupted low memory at c000c2ec (c2ec phys) = 00ff0dfe
[   28.414367] Corrupted low memory at c000c2f0 (c2f0 phys) = f81ff007
[   28.414367] Corrupted low memory at c000c2f4 (c2f4 phys) = 03fc37f8
[   28.414367] Corrupted low memory at c000c2f8 (c2f8 phys) = f7ffc000
[   28.414367] Corrupted low memory at c000c2fc (c2fc phys) = c0ff803f
[   28.414367] Corrupted low memory at c000c300 (c300 phys) = 1fe1bfc0
[   28.414367] Corrupted low memory at c000c304 (c304 phys) = 03fe00ff
[   28.414367] Corrupted low memory at c000c308 (c308 phys) = 7f86ff00
[   28.414367] Corrupted low memory at c000c30c (c30c phys) = 0ff803fc
[   28.414367] Corrupted low memory at c000c310 (c310 phys) = fe1bfc01
[   28.414367] Corrupted low memory at c000c314 (c314 phys) = ffe0007b
[   28.414367] Corrupted low memory at c000c318 (c318 phys) = 7fc01fe0
[   28.414367] Corrupted low memory at c000c31c (c31c phys) = f0dfe00f
[   28.414367] Corrupted low memory at c000c320 (c320 phys) = ff007f81
[   28.414367] Corrupted low memory at c000c324 (c324 phys) = c37f803f
[   28.414367] Corrupted low memory at c000c328 (c328 phys) = fc01fe07
[   28.414367] Corrupted low memory at c000c32c (c32c phys) = 0dfe00ff
[   28.414367] Corrupted low memory at c000c330 (c330 phys) = f0003dff
[   28.414367] Corrupted low memory at c000c334 (c334 phys) = e00ff03f
[   28.414367] Corrupted low memory at c000c338 (c338 phys) = 6ff007f8
[   28.414367] Corrupted low memory at c000c33c (c33c phys) = 803fc0ff
[   28.414367] Corrupted low memory at c000c340 (c340 phys) = bfc01fe1
[   28.414367] Corrupted low memory at c000c344 (c344 phys) = 00ff03fe
[   28.414367] Corrupted low memory at c000c348 (c348 phys) = ff007f86
[   28.414367] Corrupted low memory at c000c34c (c34c phys) = 001efff8
[   28.414367] Corrupted low memory at c000c350 (c350 phys) = 07f81ff0
[   28.414367] Corrupted low memory at c000c354 (c354 phys) = f803fc37
[   28.414367] Corrupted low memory at c000c358 (c358 phys) = 1fe07fc0
[   28.414367] Corrupted low memory at c000c35c (c35c phys) = e00ff0df
[   28.414367] Corrupted low memory at c000c360 (c360 phys) = 7f81ff00
[   28.414367] Corrupted low memory at c000c364 (c364 phys) = 803fc37f
[   28.414367] Corrupted low memory at c000c368 (c368 phys) = 0f7ffc00
[   28.414367] Corrupted low memory at c000c36c (c36c phys) = fc0ff803
[   28.414367] Corrupted low memory at c000c370 (c370 phys) = 01fe1bfc
[   28.414367] Corrupted low memory at c000c374 (c374 phys) = f03fe00f
[   28.414367] Corrupted low memory at c000c378 (c378 phys) = 07f86ff0
[   28.414367] Corrupted low memory at c000c37c (c37c phys) = c0ff803f
[   28.414367] Corrupted low memory at c000c380 (c380 phys) = 1fe1bfc0
[   28.414367] Corrupted low memory at c000c384 (c384 phys) = bffe0007
[   28.414367] Corrupted low memory at c000c388 (c388 phys) = 07fc01fe
[   28.414367] Corrupted low memory at c000c38c (c38c phys) = ff0dfe00
[   28.414367] Corrupted low memory at c000c390 (c390 phys) = 1ff007f8
[   28.414367] Corrupted low memory at c000c394 (c394 phys) = fc37f803
[   28.414367] Corrupted low memory at c000c398 (c398 phys) = 7fc01fe0
[   28.414367] Corrupted low memory at c000c39c (c39c phys) = f0dfe00f
[   28.414367] Corrupted low memory at c000c3a0 (c3a0 phys) = ff0003df
[   28.414367] Corrupted low memory at c000c3a4 (c3a4 phys) = fe00ff03
[   28.414367] Corrupted low memory at c000c3a8 (c3a8 phys) = 86ff007f
[   28.414367] Corrupted low memory at c000c3ac (c3ac phys) = f803fc0f
[   28.414367] Corrupted low memory at c000c3b0 (c3b0 phys) = 1bfc01fe
[   28.414367] Corrupted low memory at c000c3b4 (c3b4 phys) = e00ff03f
[   28.414367] Corrupted low memory at c000c3b8 (c3b8 phys) = 6ff007f8
[   28.414367] Corrupted low memory at c000c3bc (c3bc phys) = 8001efff
[   28.414367] Pid: 2217, comm: suspend-steph Not tainted 2.6.27-rc6 #2
[   28.414367]  [<c02485eb>] dpm_power_up+0x33/0x96
[   28.414367]  [<c01431e1>] suspend_devices_and_enter+0xc3/0x11c
[   28.414367]  [<c014333c>] enter_state+0xc3/0x113
[   28.414367]  [<c0143413>] state_store+0x87/0x9a
[   28.414367]  [<c014338c>] state_store+0x0/0x9a
[   28.414367]  [<c01e6687>] kobj_attr_store+0x18/0x1c
[   28.414367]  [<c01b3fc6>] sysfs_write_file+0xb0/0xdd
[   28.414367]  [<c01b3f16>] sysfs_write_file+0x0/0xdd
[   28.414367]  [<c017a87f>] vfs_write+0x84/0x121
[   28.414367]  [<c017a9b4>] sys_write+0x3c/0x63
[   28.414367]  [<c01038a3>] sysenter_do_call+0x12/0x2f
[   28.414367]  =======================
[   28.416720] ACPI: Waking up from system sleep state S3
author reviewer
#25 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 5 lines · Ingo Molnar

... looks like an x86 descriptor table. Does the pattern below make any sense to anyone? I've attached the relevant bits of one of the reports below.

It's weird... it's clearly not random, but the pattern is shifting all over the place. Almost makes me want to guess some kind of bitmask (the 0xaaaaaa00 bit and the stretches of 00 and ff kind of hint that way) but even then it doesn't really seem to make a whole lot of sense. Perhaps it's a data segment of some code which is barfing on memory.

960 bytes at 0xc000 (48K)... almost makes one wonder if someone confused address 0xc000 with segment 0xc000 (the VGA BIOS)...

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#26 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 6 lines · H. Peter Anvin
Quoted 3 lines · Ingo Molnar

... looks like an x86 descriptor table. Does the pattern below make any sense to anyone? I've attached the relevant bits of one of the reports below.

Quoted 9 lines

It's weird... it's clearly not random, but the pattern is shifting all over the place. Almost makes me want to guess some kind of bitmask (the 0xaaaaaa00 bit and the stretches of 00 and ff kind of hint that way) but even then it doesn't really seem to make a whole lot of sense. Perhaps it's a data segment of some code which is barfing on memory.

960 bytes at 0xc000 (48K)... almost makes one wonder if someone confused address 0xc000 with segment 0xc000 (the VGA BIOS)...

(I wonder if its a bunch of super-secret HDMI crypto keys ;)

J

author reviewer
#27 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

Quoted 3 lines · Jeremy Fitzhardinge

(I wonder if its a bunch of super-secret HDMI crypto keys ;)

It's too long to be an EDID block (128 bytes), but it could be part of it.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#28 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to Ingo Molnar
Quoted 15 lines · Ingo Molnar
Quoted 11 lines · Avi Kivity
Quoted 7 lines · Ingo Molnar
Quoted 3 lines

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Yeah. I only brought up the virtualization thing as a hypothetical: "if" corrupting the main OS ever became a widespread problem. Then i made the argument that this is unlikely to happen, because Windows will be affected by it just as much. (while register state corruptions might go unnoticed much more easily, just via the random call-environment clobbering of registers by Windows itself.)

The only case where i could see virtualization to be useful is the low memory RAM corruption pattern that some people have observed.

You could easily check that by checksumming pages (or actually copying them to high memory) before the call, and verifying after the call.

Quoted 9 lines

Yes, we could do memory checks, and ... hey, we already do that:

bb577f9: x86: add periodic corruption check
5394f80: x86: check for and defend against BIOS memory corruption

... and i seem to be the one who implemented it! ;-)

That check resulted in logs showing the BIOS corrupting Linux memory across s2ram cycles or HDMI plug/unplug events on certain boxes (are Hollywood rootkits in the BIOS now?), and resulted in some head-scratching but not much more.

Then there's definitely no point in putting it into a container, is there? I mean, we could track down the exact instruction which caused the corruption, but how would it help us?

Quoted 7 lines
Quoted 2 lines

I don't think the effort is worth the benefit in this case, but there actually is an interesting use case for this. SMM is known to be harmful to deterministic replay games and to real time response. If we can virtualize SMM, we can increase the range of hardware on which the real time kernel is able to deliver real time guarantees.

Hey, i do have a real sweet spot for deterministic execution - but SMM, while not problem-free (like most of firmware), also has a very real role in not letting various hardware melt. So SMM should be thought of as a flexible extended arm of hardware - not some sw bit.

So i think that the memory of that SMM virtualization chapter you've almost read should be quickly erased from your mind. (Via forceful means if prompt corrective self-action is not forthcoming.)

I'll keep my remaining neurons, thanks.

Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
author reviewer
#29 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to Linus Torvalds
Quoted 16 lines · Linus Torvalds

This discussion is just taking us down a rat-hole of more complexity, and _way_ more fragility.

I'm absolutely willing to bet that trying to do the BIOS calls will break way more than it will fix. Sure, it will probably work for 99.9% of all BIOSes, but then it will break horribly for some BIOS that tries to do something "clever". SMM has already been mentioned as an example of something that simply isn't virtualizable.

Timing is another, very traditional, one. There used to be video BIOSes that simply didn't work in a dosbox-like environment because they had tight timing loops that were coupled to hardware. I can pretty much guarantee that that has gone away as far as the video BIOS is concerned, but the main BIOS? Who the hell knows.

Quoted 8 lines

Sure, none of the calls we do to the BIOS from the kernel should need anything fancy at all, and maybe I'm pessimistic. But at the same time, I really don't think the BIOS calls are worth that kind of infrastructure.

Sure, go ahead and wrap them in some kind of "save and restore all registers" wrapping, but nothing fancier than that. It would just be overkill, and likely to break more than it fixes.

Agreed completely.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
author reviewer
#30 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to Pavel Machek
Quoted 8 lines · Pavel Machek
Quoted 5 lines

+/*
+ * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes
+ * touching memory they shouldn't be.
+ */

Touching memory? AFAICT it only prevents touching registers.

Ah yes. -EBUGGYCOMMENT. ;)

-hpa

author reviewer
#31 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS calls -- infrastructure

In reply to Pavel Machek
Quoted 18 lines · Pavel Machek

arch/x86/boot/bioscall.S line 26

Quoted 12 lines
arch/x86/boot/bioscall.S new file +11 -0
+	.code16
+	.text
+	.globl	intcall
+	.type	intcall, @function
+intcall:
+	/* Self-modify the INT instruction.  Ugly, but works. */
+	cmpb	%al, 3f
+	je	1f
+	movb	%al, 3f
+	jmp	1f		/* Synchronize pipeline */
+1:

There are various CPU bugs with self-modifying code, but I guess we are not using it heavily enough. Also we are single-threaded so that should be ok.
Pavel

This case is extremely straightforward, so I'm not worried about it. The final JMP is actually not required (there is a LOOP instruction between the modify and the invocation point) but is there for extra safety.

FWIW, we already do SMC during the transfer to protected mode (pmjump.S), and hopefully got the issues worked out there.

-hpa

#32 lore raw

[tip:x86/setup] x86, setup: "glove box" BIOS interrupts in the EDD code

In reply to H. Peter Anvin
Commit-ID:  3435d3476c5ed955d56a6216ed2d156847b3a575
Gitweb:     http://git.kernel.org/tip/3435d3476c5ed955d56a6216ed2d156847b3a575
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:17:17 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:11 -0700

x86, setup: "glove box" BIOS interrupts in the EDD code

Impact: BIOS proofing

"Glove box" off BIOS interrupts in the EDD code.

LKML-Reference: <[email protected]>

---
 arch/x86/boot/edd.c |   71 ++++++++++++++++++++++----------------------------
 1 files changed, 31 insertions(+), 40 deletions(-)
arch/x86/boot/edd.c +31 -40
index 1aae8f3..c501a5b 100644
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -22,17 +23,17 @@
  */
 static int read_mbr(u8 devno, void *buf)
 {
-	u16 ax, bx, cx, dx;
+	struct biosregs ireg, oreg;
 
-	ax = 0x0201;		/* Legacy Read, one sector */
-	cx = 0x0001;		/* Sector 0-0-1 */
-	dx = devno;
-	bx = (size_t)buf;
-	asm volatile("pushfl; stc; int $0x13; setc %%al; popfl"
-		     : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
-		     : : "esi", "edi", "memory");
+	initregs(&ireg);
+	ireg.ax = 0x0201;		/* Legacy Read, one sector */
+	ireg.cx = 0x0001;		/* Sector 0-0-1 */
+	ireg.dl = devno;
+	ireg.bx = (size_t)buf;
 
-	return -(u8)ax;		/* 0 or -1 */
+	intcall(0x13, &ireg, &oreg);
+
+	return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
 }
 
 static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig)
@@ -72,56 +73,46 @@ static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig)
 
 static int get_edd_info(u8 devno, struct edd_info *ei)
 {
-	u16 ax, bx, cx, dx, di;
+	struct biosregs ireg, oreg;
 
 	memset(ei, 0, sizeof *ei);
 
 	/* Check Extensions Present */
 
-	ax = 0x4100;
-	bx = EDDMAGIC1;
-	dx = devno;
-	asm("pushfl; stc; int $0x13; setc %%al; popfl"
-	    : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
-	    : : "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x41;
+	ireg.bx = EDDMAGIC1;
+	ireg.dl = devno;
+	intcall(0x13, &ireg, &oreg);
 
-	if ((u8)ax)
+	if (oreg.eflags & X86_EFLAGS_CF)
 		return -1;	/* No extended information */
 
-	if (bx != EDDMAGIC2)
+	if (oreg.bx != EDDMAGIC2)
 		return -1;
 
 	ei->device  = devno;
-	ei->version = ax >> 8;	/* EDD version number */
-	ei->interface_support = cx; /* EDD functionality subsets */
+	ei->version = oreg.ah;		 /* EDD version number */
+	ei->interface_support = oreg.cx; /* EDD functionality subsets */
 
 	/* Extended Get Device Parameters */
 
 	ei->params.length = sizeof(ei->params);
-	ax = 0x4800;
-	dx = devno;
-	asm("pushfl; int $0x13; popfl"
-	    : "+a" (ax), "+d" (dx), "=m" (ei->params)
-	    : "S" (&ei->params)
-	    : "ebx", "ecx", "edi");
+	ireg.ah = 0x48;
+	ireg.si = (size_t)&ei->params;
+	intcall(0x13, &ireg, &oreg);
 
 	/* Get legacy CHS parameters */
 
 	/* Ralf Brown recommends setting ES:DI to 0:0 */
-	ax = 0x0800;
-	dx = devno;
-	di = 0;
-	asm("pushw %%es; "
-	    "movw %%di,%%es; "
-	    "pushfl; stc; int $0x13; setc %%al; popfl; "
-	    "popw %%es"
-	    : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
-	    : : "esi");
-
-	if ((u8)ax == 0) {
-		ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2);
-		ei->legacy_max_head = dx >> 8;
-		ei->legacy_sectors_per_track = cx & 0x3f;
+	ireg.ah = 0x08;
+	ireg.es = 0;
+	intcall(0x13, &ireg, &oreg);
+
+	if (!(oreg.eflags & X86_EFLAGS_CF)) {
+		ei->legacy_max_cylinder = oreg.ch + ((oreg.cl & 0xc0) << 2);
+		ei->legacy_max_head = oreg.dh;
+		ei->legacy_sectors_per_track = oreg.cl & 0x3f;
 	}
 
 	return 0;
#33 lore raw

[tip:x86/setup] x86, setup: "glove box" BIOS interrupts in the MCA code

In reply to H. Peter Anvin
Commit-ID:  0a706db320768f8f6e43bbf73b58d2aabdc93354
Gitweb:     http://git.kernel.org/tip/0a706db320768f8f6e43bbf73b58d2aabdc93354
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:19:00 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:11 -0700

x86, setup: "glove box" BIOS interrupts in the MCA code

Impact: BIOS proofing

"Glove box" off BIOS interrupts in the MCA code.

LKML-Reference: <[email protected]>

---
 arch/x86/boot/mca.c |   27 ++++++++++++---------------
 1 files changed, 12 insertions(+), 15 deletions(-)
arch/x86/boot/mca.c +12 -15
index 911eaae..a95a531 100644
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -16,26 +17,22 @@
 
 int query_mca(void)
 {
-	u8 err;
-	u16 es, bx, len;
-
-	asm("pushw %%es ; "
-	    "int $0x15 ; "
-	    "setc %0 ; "
-	    "movw %%es, %1 ; "
-	    "popw %%es"
-	    : "=acd" (err), "=acdSD" (es), "=b" (bx)
-	    : "a" (0xc000));
-
-	if (err)
+	struct biosregs ireg, oreg;
+	u16 len;
+
+	initregs(&ireg);
+	ireg.ah = 0xc0;
+	intcall(0x15, &ireg, &oreg);
+
+	if (oreg.eflags & X86_EFLAGS_CF)
 		return -1;	/* No MCA present */
 
-	set_fs(es);
-	len = rdfs16(bx);
+	set_fs(oreg.es);
+	len = rdfs16(oreg.bx);
 
 	if (len > sizeof(boot_params.sys_desc_table))
 		len = sizeof(boot_params.sys_desc_table);
 
-	copy_from_fs(&boot_params.sys_desc_table, bx, len);
+	copy_from_fs(&boot_params.sys_desc_table, oreg.bx, len);
 	return 0;
 }
#34 lore raw

[tip:x86/setup] x86, setup: "glove box" BIOS interrupts in the video code

In reply to H. Peter Anvin
Commit-ID:  cf06de7b9cdd3efee7a59dced1977b3c21d43732
Gitweb:     http://git.kernel.org/tip/cf06de7b9cdd3efee7a59dced1977b3c21d43732
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:20:11 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:12 -0700

x86, setup: "glove box" BIOS interrupts in the video code

Impact: BIOS proofing

"Glove box" off BIOS interrupts in the video code.

LKML-Reference: <[email protected]>

Cc Pavel Machek <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
---
 arch/x86/boot/video-bios.c |   27 ++++-----
 arch/x86/boot/video-vesa.c |  137 +++++++++++++++++++-------------------------
 arch/x86/boot/video-vga.c  |   95 +++++++++++++++++++------------
 arch/x86/boot/video.c      |   42 ++++++-------
 arch/x86/boot/video.h      |   14 -----
 5 files changed, 151 insertions(+), 164 deletions(-)
arch/x86/boot/video-bios.c +13 -14
index 3fa979c..d660be4 100644
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -29,21 +30,21 @@ static int bios_set_mode(struct mode_info *mi)
 
 static int set_bios_mode(u8 mode)
 {
-	u16 ax;
+	struct biosregs ireg, oreg;
 	u8 new_mode;
 
-	ax = mode;		/* AH=0x00 Set Video Mode */
-	asm volatile(INT10
-		     : "+a" (ax)
-		     : : "ebx", "ecx", "edx", "esi", "edi");
+	initregs(&ireg);
+	ireg.al = mode;		/* AH=0x00 Set Video Mode */
+	intcall(0x10, &ireg, NULL);
 
-	ax = 0x0f00;		/* Get Current Video Mode */
-	asm volatile(INT10
-		     : "+a" (ax)
-		     : : "ebx", "ecx", "edx", "esi", "edi");
+
+	ireg.ah = 0x0f;		/* Get Current Video Mode */
+	intcall(0x10, &ireg, &oreg);
 
 	do_restore = 1;		/* Assume video contents were lost */
-	new_mode = ax & 0x7f;	/* Not all BIOSes are clean with the top bit */
+
+	/* Not all BIOSes are clean with the top bit */
+	new_mode = ireg.al & 0x7f;
 
 	if (new_mode == mode)
 		return 0;	/* Mode change OK */
@@ -53,10 +54,8 @@ static int set_bios_mode(u8 mode)
 		/* Mode setting failed, but we didn't end up where we
 		   started.  That's bad.  Try to revert to the original
 		   video mode. */
-		ax = boot_params.screen_info.orig_video_mode;
-		asm volatile(INT10
-			     : "+a" (ax)
-			     : : "ebx", "ecx", "edx", "esi", "edi");
+		ireg.ax = boot_params.screen_info.orig_video_mode;
+		intcall(0x10, &ireg, NULL);
 	}
 #endif
 	return -1;
arch/x86/boot/video-vesa.c +60 -77

224 lines not on this page · raw message

arch/x86/boot/video-vga.c +59 -36

182 lines not on this page · raw message

arch/x86/boot/video.c +19 -23

77 lines not on this page · raw message

arch/x86/boot/video.h +0 -14
index ee63f5d..5bb174a 100644
@@ -112,20 +112,6 @@ extern int force_x, force_y;	/* Don't query the BIOS for cols/rows */
 extern int do_restore;		/* Restore screen contents */
 extern int graphic_mode;	/* Graphics mode with linear frame buffer */
 
-/*
- * int $0x10 is notorious for touching registers it shouldn't.
- * gcc doesn't like %ebp being clobbered, so define it as a push/pop
- * sequence here.
- *
- * A number of systems, including the original PC can clobber %bp in
- * certain circumstances, like when scrolling.  There exists at least
- * one Trident video card which could clobber DS under a set of
- * circumstances that we are unlikely to encounter (scrolling when
- * using an extended graphics mode of more than 800x600 pixels), but
- * it's cheap insurance to deal with that here.
- */
-#define INT10 "pushl %%ebp; pushw %%ds; int $0x10; popw %%ds; popl %%ebp"
-
 /* Accessing VGA indexed registers */
 static inline u8 in_idx(u16 port, u8 index)
 {
Acked-by
#35 lore raw

Re: [tip:x86/setup] x86, setup: "glove box" BIOS interrupts in the video code

Quoted 9 lines · H. Peter Anvin
Commit-ID:  cf06de7b9cdd3efee7a59dced1977b3c21d43732
Gitweb:     http://git.kernel.org/tip/cf06de7b9cdd3efee7a59dced1977b3c21d43732
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Wed, 1 Apr 2009 18:20:11 -0700
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 9 Apr 2009 16:08:12 -0700

x86, setup: "glove box" BIOS interrupts in the video code

Quoted 7 lines

Impact: BIOS proofing

"Glove box" off BIOS interrupts in the video code.

LKML-Reference: <[email protected]>

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#36 lore raw
In reply to H. Peter Anvin
Quoted 9 lines · H. Peter Anvin

This is a patchset to "glove box" off BIOS interrupts in the x86 setup code, thus hopefully dealing once and for all with the problems of BIOSes touching registers they shouldn't.

The concept is simple: we manipulate a register image in memory, then swap it in immediately before calling the BIOS, and then switch the register file back. All BIOS interrupts are channeled through this path.

The increase in size is about 8% or ~1.3K in the maximal case.

FWIW, I like the approach.

Thanks,
Rafael