# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1173272832 0
# Node ID fbbf1f07fefe38807c21a4b8398dd1b5341a1260
# Parent dad3d143c3b0319ed6265a89879c3e11308b1c1f
[HVM] Disallow soft resets in the BIOS.
They aren't safe if the guest has brought up PV device drivers.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
tools/firmware/rombios/rombios.c | 102 ++++++++++++++++++++++++---------------
1 files changed, 65 insertions(+), 37 deletions(-)
diff -r dad3d143c3b0 -r fbbf1f07fefe tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c Wed Mar 07 11:17:03 2007 +0000
+++ b/tools/firmware/rombios/rombios.c Wed Mar 07 13:07:12 2007 +0000
@@ -890,7 +890,7 @@ static void int15_function();
static void int15_function();
static void int16_function();
static void int17_function();
-static void int19_function();
+static void int18_function();
static void int1a_function();
static void int70_function();
static void int74_function();
@@ -1837,6 +1837,38 @@ keyboard_panic(status)
}
//--------------------------------------------------------------------------
+// machine_reset
+//--------------------------------------------------------------------------
+ void
+machine_reset()
+{
+ /* Frob the keyboard reset line to reset the processor */
+ outb(0x64, 0x60); /* Map the flags register at data port (0x60) */
+ outb(0x60, 0x14); /* Set the flags to system|disable */
+ outb(0x64, 0xfe); /* Pulse output 0 (system reset) low */
+ BX_PANIC("Couldn't reset the machine\n");
+}
+
+//--------------------------------------------------------------------------
+// clobber_entry_point
+// Because PV drivers in HVM guests detach some of the emulated devices,
+// it is not safe to do a soft reboot by just dropping to real mode and
+// jumping at ffff:0000. -- the boot drives might have disappeared!
+// This rather foul function overwrites(!) the BIOS entry point
+// to point at machine-reset, which will cause the Xen tools to
+// rebuild the whole machine from scratch.
+//--------------------------------------------------------------------------
+ void
+clobber_entry_point()
+{
+ /* The instruction at the entry point is one byte (0xea) for the
+ * jump opcode, then two bytes of address, then two of segment.
+ * Overwrite the address bytes.*/
+ write_word(0xffff, 0x0001, machine_reset);
+}
+
+
+//--------------------------------------------------------------------------
// shutdown_status_panic
// called when the shutdown statsu is not implemented, displays the status
//--------------------------------------------------------------------------
@@ -7626,7 +7658,7 @@ int17_function(regs, ds, iret_addr)
}
void
-int19_function(seq_nr)
+int18_function(seq_nr)
Bit16u seq_nr;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
@@ -7702,8 +7734,8 @@ ASM_START
push cx
push dx
- mov dl, _int19_function.bootdrv + 2[bp]
- mov ax, _int19_function.bootseg + 2[bp]
+ mov dl, _int18_function.bootdrv + 2[bp]
+ mov ax, _int18_function.bootseg + 2[bp]
mov es, ax ;; segment
mov bx, #0x0000 ;; offset
mov ah, #0x02 ;; function 2, read diskette sector
@@ -7714,7 +7746,7 @@ ASM_START
int #0x13 ;; read sector
jnc int19_load_done
mov ax, #0x0001
- mov _int19_function.status + 2[bp], ax
+ mov _int18_function.status + 2[bp], ax
int19_load_done:
pop dx
@@ -7789,13 +7821,13 @@ ASM_START
;; Build an iret stack frame that will take us to the boot vector.
;; iret pops ip, then cs, then flags, so push them in the opposite order.
pushf
- mov ax, _int19_function.bootseg + 0[bp]
+ mov ax, _int18_function.bootseg + 0[bp]
push ax
- mov ax, _int19_function.bootip + 0[bp]
+ mov ax, _int18_function.bootip + 0[bp]
push ax
;; Set the magic number in ax and the boot drive in dl.
mov ax, #0xaa55
- mov dl, _int19_function.bootdrv + 0[bp]
+ mov dl, _int18_function.bootdrv + 0[bp]
;; Zero some of the other registers.
xor bx, bx
mov ds, bx
@@ -8272,6 +8304,8 @@ int18_handler: ;; Boot Failure recovery:
mov ss, ax
;; Get the boot sequence number out of the IPL memory
+ ;; The first time we do this it will have been set to -1 so
+ ;; we will start from device 0.
mov bx, #IPL_SEG
mov ds, bx ;; Set segment
mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number
@@ -8279,43 +8313,33 @@ int18_handler: ;; Boot Failure recovery:
mov IPL_SEQUENCE_OFFSET, bx ;; Write it back
mov ds, ax ;; and reset the segment to zero.
- ;; Carry on in the INT 19h handler, using the new sequence number
+ ;; Call the C code for the next boot device
push bx
-
- jmp int19_next_boot
+ call _int18_function
+
+ ;; Boot failed: invoke the boot recovery function...
+ int #0x18
;----------
;- INT19h -
;----------
int19_relocated: ;; Boot function, relocated
-
- ;; int19 was beginning to be really complex, so now it
- ;; just calls a C function that does the work
-
- push bp
- mov bp, sp
-
- ;; Reset SS and SP
+ ;;
+ ;; *** Warning: INT 19h resets the whole machine ***
+ ;;
+ ;; Because PV drivers in HVM guests detach some of the emulated devices,
+ ;; it is not safe to do a soft reboot by just dropping to real mode and
+ ;; invoking INT 19h -- the boot drives might have disappeared!
+ ;; If the user asks for a soft reboot, the only thing we can do is
+ ;; reset the whole machine. When it comes back up, the normal BIOS
+ ;; boot sequence will start, which is more or less the required behaviour.
+ ;;
+ ;; Reset SP and SS
mov ax, #0xfffe
mov sp, ax
xor ax, ax
mov ss, ax
-
- ;; Start from the first boot device (0, in AX)
- mov bx, #IPL_SEG
- mov ds, bx ;; Set segment to write to the IPL memory
- mov IPL_SEQUENCE_OFFSET, ax ;; Save the sequence number
- mov ds, ax ;; and reset the segment.
-
- push ax
-
-int19_next_boot:
-
- ;; Call the C code for the next boot device
- call _int19_function
-
- ;; Boot failed: invoke the boot recovery function
- int #0x18
+ call _machine_reset
;----------
;- INT1Ch -
@@ -9609,6 +9633,8 @@ normal_post:
call _log_bios_start
+ call _clobber_entry_point
+
;; set all interrupts to default handler
mov bx, #0x0000 ;; offset index
mov cx, #0x0100 ;; counter (256 interrupts)
@@ -9857,8 +9883,10 @@ post_default_ints:
call _tcpa_calling_int19h /* specs: 8.2.3 step 1 */
call _tcpa_add_event_separators /* specs: 8.2.3 step 2 */
#endif
- int #0x19
- //JMP_EP(0x0064) ; INT 19h location
+
+ ;; Start the boot sequence. See the comments in int19_relocated
+ ;; for why we use INT 18h instead of INT 19h here.
+ int #0x18
#if BX_TCGBIOS
call _tcpa_returned_int19h /* specs: 8.2.3 step 3/7 */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|