ia64/xen-unstable

changeset 14289:fbbf1f07fefe

[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@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Wed Mar 07 13:07:12 2007 +0000 (2007-03-07)
parents dad3d143c3b0
children 42b29f084c31
files tools/firmware/rombios/rombios.c
line diff
     1.1 --- a/tools/firmware/rombios/rombios.c	Wed Mar 07 11:17:03 2007 +0000
     1.2 +++ b/tools/firmware/rombios/rombios.c	Wed Mar 07 13:07:12 2007 +0000
     1.3 @@ -890,7 +890,7 @@ static void           int14_function();
     1.4  static void           int15_function();
     1.5  static void           int16_function();
     1.6  static void           int17_function();
     1.7 -static void           int19_function();
     1.8 +static void           int18_function();
     1.9  static void           int1a_function();
    1.10  static void           int70_function();
    1.11  static void           int74_function();
    1.12 @@ -1837,6 +1837,38 @@ keyboard_panic(status)
    1.13  }
    1.14  
    1.15  //--------------------------------------------------------------------------
    1.16 +// machine_reset
    1.17 +//--------------------------------------------------------------------------
    1.18 +  void
    1.19 +machine_reset()
    1.20 +{
    1.21 +  /* Frob the keyboard reset line to reset the processor */
    1.22 +  outb(0x64, 0x60); /* Map the flags register at data port (0x60) */
    1.23 +  outb(0x60, 0x14); /* Set the flags to system|disable */
    1.24 +  outb(0x64, 0xfe); /* Pulse output 0 (system reset) low */
    1.25 +  BX_PANIC("Couldn't reset the machine\n");
    1.26 +}
    1.27 +
    1.28 +//--------------------------------------------------------------------------
    1.29 +// clobber_entry_point
    1.30 +//    Because PV drivers in HVM guests detach some of the emulated devices, 
    1.31 +//    it is not safe to do a soft reboot by just dropping to real mode and
    1.32 +//    jumping at ffff:0000. -- the boot drives might have disappeared!
    1.33 +//    This rather foul function overwrites(!) the BIOS entry point 
    1.34 +//    to point at machine-reset, which will cause the Xen tools to
    1.35 +//    rebuild the whole machine from scratch.
    1.36 +//--------------------------------------------------------------------------
    1.37 +  void 
    1.38 +clobber_entry_point() 
    1.39 +{
    1.40 +    /* The instruction at the entry point is one byte (0xea) for the
    1.41 +     * jump opcode, then two bytes of address, then two of segment. 
    1.42 +     * Overwrite the address bytes.*/
    1.43 +    write_word(0xffff, 0x0001, machine_reset); 
    1.44 +}
    1.45 +
    1.46 +
    1.47 +//--------------------------------------------------------------------------
    1.48  // shutdown_status_panic
    1.49  //   called when the shutdown statsu is not implemented, displays the status
    1.50  //--------------------------------------------------------------------------
    1.51 @@ -7626,7 +7658,7 @@ int17_function(regs, ds, iret_addr)
    1.52  }
    1.53  
    1.54  void
    1.55 -int19_function(seq_nr)
    1.56 +int18_function(seq_nr)
    1.57  Bit16u seq_nr;
    1.58  {
    1.59    Bit16u ebda_seg=read_word(0x0040,0x000E);
    1.60 @@ -7702,8 +7734,8 @@ ASM_START
    1.61      push cx
    1.62      push dx
    1.63  
    1.64 -    mov  dl, _int19_function.bootdrv + 2[bp]
    1.65 -    mov  ax, _int19_function.bootseg + 2[bp]
    1.66 +    mov  dl, _int18_function.bootdrv + 2[bp]
    1.67 +    mov  ax, _int18_function.bootseg + 2[bp]
    1.68      mov  es, ax         ;; segment
    1.69      mov  bx, #0x0000    ;; offset
    1.70      mov  ah, #0x02      ;; function 2, read diskette sector
    1.71 @@ -7714,7 +7746,7 @@ ASM_START
    1.72      int  #0x13          ;; read sector
    1.73      jnc  int19_load_done
    1.74      mov  ax, #0x0001
    1.75 -    mov  _int19_function.status + 2[bp], ax
    1.76 +    mov  _int18_function.status + 2[bp], ax
    1.77  
    1.78  int19_load_done:
    1.79      pop  dx
    1.80 @@ -7789,13 +7821,13 @@ ASM_START
    1.81      ;; Build an iret stack frame that will take us to the boot vector.
    1.82      ;; iret pops ip, then cs, then flags, so push them in the opposite order.
    1.83      pushf
    1.84 -    mov  ax, _int19_function.bootseg + 0[bp] 
    1.85 +    mov  ax, _int18_function.bootseg + 0[bp] 
    1.86      push ax
    1.87 -    mov  ax, _int19_function.bootip + 0[bp] 
    1.88 +    mov  ax, _int18_function.bootip + 0[bp] 
    1.89      push ax
    1.90      ;; Set the magic number in ax and the boot drive in dl.
    1.91      mov  ax, #0xaa55
    1.92 -    mov  dl, _int19_function.bootdrv + 0[bp]
    1.93 +    mov  dl, _int18_function.bootdrv + 0[bp]
    1.94      ;; Zero some of the other registers.
    1.95      xor  bx, bx
    1.96      mov  ds, bx
    1.97 @@ -8272,6 +8304,8 @@ int18_handler: ;; Boot Failure recovery:
    1.98    mov  ss, ax
    1.99  
   1.100    ;; Get the boot sequence number out of the IPL memory
   1.101 +  ;; The first time we do this it will have been set to -1 so 
   1.102 +  ;; we will start from device 0.
   1.103    mov  bx, #IPL_SEG 
   1.104    mov  ds, bx                     ;; Set segment
   1.105    mov  bx, IPL_SEQUENCE_OFFSET    ;; BX is now the sequence number
   1.106 @@ -8279,43 +8313,33 @@ int18_handler: ;; Boot Failure recovery:
   1.107    mov  IPL_SEQUENCE_OFFSET, bx    ;; Write it back
   1.108    mov  ds, ax                     ;; and reset the segment to zero. 
   1.109  
   1.110 -  ;; Carry on in the INT 19h handler, using the new sequence number
   1.111 +  ;; Call the C code for the next boot device
   1.112    push bx
   1.113 -
   1.114 -  jmp  int19_next_boot
   1.115 +  call _int18_function
   1.116 +
   1.117 +  ;; Boot failed: invoke the boot recovery function...
   1.118 +  int  #0x18
   1.119  
   1.120  ;----------
   1.121  ;- INT19h -
   1.122  ;----------
   1.123  int19_relocated: ;; Boot function, relocated
   1.124 -
   1.125 -  ;; int19 was beginning to be really complex, so now it
   1.126 -  ;; just calls a C function that does the work
   1.127 -
   1.128 -  push bp
   1.129 -  mov  bp, sp
   1.130 -  
   1.131 -  ;; Reset SS and SP
   1.132 +  ;;
   1.133 +  ;; *** Warning: INT 19h resets the whole machine *** 
   1.134 +  ;;
   1.135 +  ;; Because PV drivers in HVM guests detach some of the emulated devices, 
   1.136 +  ;; it is not safe to do a soft reboot by just dropping to real mode and
   1.137 +  ;; invoking INT 19h -- the boot drives might have disappeared!
   1.138 +  ;; If the user asks for a soft reboot, the only thing we can do is 
   1.139 +  ;; reset the whole machine.  When it comes back up, the normal BIOS 
   1.140 +  ;; boot sequence will start, which is more or less the required behaviour.
   1.141 +  ;; 
   1.142 +  ;; Reset SP and SS
   1.143    mov  ax, #0xfffe
   1.144    mov  sp, ax
   1.145    xor  ax, ax
   1.146    mov  ss, ax
   1.147 -
   1.148 -  ;; Start from the first boot device (0, in AX)
   1.149 -  mov  bx, #IPL_SEG 
   1.150 -  mov  ds, bx                     ;; Set segment to write to the IPL memory
   1.151 -  mov  IPL_SEQUENCE_OFFSET, ax    ;; Save the sequence number 
   1.152 -  mov  ds, ax                     ;; and reset the segment.
   1.153 -
   1.154 -  push ax
   1.155 -
   1.156 -int19_next_boot:
   1.157 -
   1.158 -  ;; Call the C code for the next boot device
   1.159 -  call _int19_function
   1.160 -
   1.161 -  ;; Boot failed: invoke the boot recovery function
   1.162 -  int  #0x18
   1.163 +  call _machine_reset
   1.164  
   1.165  ;----------
   1.166  ;- INT1Ch -
   1.167 @@ -9609,6 +9633,8 @@ normal_post:
   1.168  
   1.169    call _log_bios_start
   1.170  
   1.171 +  call _clobber_entry_point
   1.172 +
   1.173    ;; set all interrupts to default handler
   1.174    mov  bx, #0x0000    ;; offset index
   1.175    mov  cx, #0x0100    ;; counter (256 interrupts)
   1.176 @@ -9857,8 +9883,10 @@ post_default_ints:
   1.177    call _tcpa_calling_int19h          /* specs: 8.2.3 step 1 */
   1.178    call _tcpa_add_event_separators    /* specs: 8.2.3 step 2 */
   1.179  #endif
   1.180 -  int  #0x19
   1.181 -  //JMP_EP(0x0064) ; INT 19h location
   1.182 +
   1.183 +  ;; Start the boot sequence.   See the comments in int19_relocated 
   1.184 +  ;; for why we use INT 18h instead of INT 19h here.
   1.185 +  int  #0x18
   1.186  
   1.187  #if BX_TCGBIOS
   1.188    call _tcpa_returned_int19h         /* specs: 8.2.3 step 3/7 */