ia64/xen-unstable

changeset 15683:36caf6f84072

Merge with ppc/xen-unstable.hg.
author kfraser@localhost.localdomain
date Wed Aug 01 08:59:03 2007 +0100 (2007-08-01)
parents 553f64e4f6ef 43836c2b595b
children 425c3d6f7557
files
line diff
     1.1 --- a/tools/firmware/hvmloader/smbios.c	Mon Jul 30 17:10:45 2007 -0500
     1.2 +++ b/tools/firmware/hvmloader/smbios.c	Wed Aug 01 08:59:03 2007 +0100
     1.3 @@ -169,7 +169,7 @@ hvm_write_smbios_tables(void)
     1.4      /* temporary variables used to build up Xen version string */
     1.5      char *p = NULL; /* points to next point of insertion */
     1.6      unsigned len = 0; /* length of string already composed */
     1.7 -    char *tmp = NULL; /* holds result of itoa() */
     1.8 +    char tmp[16]; /* holds result of itoa() */
     1.9      unsigned tmp_len; /* length of next string to add */
    1.10  
    1.11      hypercall_xen_version(XENVER_guest_handle, uuid);
     2.1 --- a/tools/libxc/ia64/Makefile	Mon Jul 30 17:10:45 2007 -0500
     2.2 +++ b/tools/libxc/ia64/Makefile	Wed Aug 01 08:59:03 2007 +0100
     2.3 @@ -5,6 +5,8 @@ GUEST_SRCS-y += ia64/xc_ia64_linux_save.
     2.4  GUEST_SRCS-y += ia64/xc_ia64_linux_restore.c
     2.5  
     2.6  GUEST_SRCS-y += ia64/xc_dom_ia64_util.c
     2.7 +GUEST_SRCS-y += ia64/dom_fw_acpi.c
     2.8 +
     2.9  DOMFW_SRCS_BASE := dom_fw_common.c dom_fw_domu.c dom_fw_asm.S
    2.10  DOMFW_SRCS := $(addprefix ia64/, $(DOMFW_SRCS_BASE))
    2.11  $(DOMFW_SRCS):
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/ia64/dom_fw_acpi.c	Wed Aug 01 08:59:03 2007 +0100
     3.3 @@ -0,0 +1,13 @@
     3.4 +#include <inttypes.h>
     3.5 +#include <xen/acpi.h>
     3.6 +
     3.7 +uint8_t
     3.8 +generate_acpi_checksum(void *tbl, unsigned long len)
     3.9 +{
    3.10 +    uint8_t *ptr, sum = 0;
    3.11 +
    3.12 +    for ( ptr = tbl; len > 0 ; len--, ptr++ )
    3.13 +        sum += *ptr;
    3.14 +
    3.15 +    return 0 - sum;
    3.16 +}
     4.1 --- a/tools/python/xen/util/acmpolicy.py	Mon Jul 30 17:10:45 2007 -0500
     4.2 +++ b/tools/python/xen/util/acmpolicy.py	Wed Aug 01 08:59:03 2007 +0100
     4.3 @@ -818,12 +818,13 @@ class ACMPolicy(XSPolicy):
     4.4              if successful,the policy's flags will indicate that the
     4.5              policy is the one loaded into the hypervisor
     4.6          """
     4.7 -        (ret, output) = commands.getstatusoutput(
     4.8 +        if not self.isloaded():
     4.9 +            (ret, output) = commands.getstatusoutput(
    4.10                                     security.xensec_tool +
    4.11                                     " loadpolicy " +
    4.12                                     self.get_filename(".bin"))
    4.13 -        if ret != 0:
    4.14 -            return -xsconstants.XSERR_POLICY_LOAD_FAILED
    4.15 +            if ret != 0:
    4.16 +                return -xsconstants.XSERR_POLICY_LOAD_FAILED
    4.17          return xsconstants.XSERR_SUCCESS
    4.18  
    4.19      def isloaded(self):
     5.1 --- a/tools/xm-test/lib/XmTestLib/acm.py	Mon Jul 30 17:10:45 2007 -0500
     5.2 +++ b/tools/xm-test/lib/XmTestLib/acm.py	Wed Aug 01 08:59:03 2007 +0100
     5.3 @@ -67,6 +67,10 @@ def ACMLoadPolicy(policy='xm-test'):
     5.4      if main.serverType == main.SERVER_XEN_API:
     5.5          ACMLoadPolicy_XenAPI()
     5.6      else:
     5.7 +        cmd='xm dumppolicy | grep -E "^POLICY REFERENCE = ' + policy + '.$"'
     5.8 +        s, o = traceCommand(cmd)
     5.9 +        if o != "":
    5.10 +            return
    5.11          s, o = traceCommand("xm makepolicy %s" % (policy))
    5.12          if s != 0:
    5.13              FAIL("Need to be able to do 'xm makepolicy %s' but could not" %
     6.1 --- a/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py	Mon Jul 30 17:10:45 2007 -0500
     6.2 +++ b/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py	Wed Aug 01 08:59:03 2007 +0100
     6.3 @@ -12,11 +12,20 @@ from xen.xend import XendAPIConstants
     6.4  from xen.util import acmpolicy, security, xsconstants
     6.5  from xen.util.acmpolicy import ACMPolicy
     6.6  from xen.xend.XendDomain import DOM0_UUID
     6.7 +from XmTestLib.acm import *
     6.8  
     6.9  import commands
    6.10  import os
    6.11  import base64
    6.12  
    6.13 +if not isACMEnabled():
    6.14 +    SKIP("Not running this test since ACM not enabled.")
    6.15 +
    6.16 +try:
    6.17 +    session = xapi.connect()
    6.18 +except:
    6.19 +    SKIP("Skipping this test since xm is not using the Xen-API.")
    6.20 +
    6.21  xm_test = {}
    6.22  xm_test['policyname'] = "xm-test"
    6.23  xm_test['date'] = "Fri Sep 29 14:44:38 2006"
     7.1 --- a/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py	Mon Jul 30 17:10:45 2007 -0500
     7.2 +++ b/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py	Wed Aug 01 08:59:03 2007 +0100
     7.3 @@ -7,6 +7,7 @@
     7.4  
     7.5  from XmTestLib import xapi
     7.6  from XmTestLib.XenAPIDomain import XmTestAPIDomain
     7.7 +from XmTestLib.acm import *
     7.8  from XmTestLib import *
     7.9  from xen.xend import XendAPIConstants
    7.10  from xen.util import security, xsconstants
    7.11 @@ -16,6 +17,14 @@ import base64
    7.12  import struct
    7.13  import time
    7.14  
    7.15 +if not isACMEnabled():
    7.16 +    SKIP("Not running this test since ACM not enabled.")
    7.17 +
    7.18 +try:
    7.19 +    session = xapi.connect()
    7.20 +except:
    7.21 +    SKIP("Skipping this test since xm is not using the Xen-API.")
    7.22 +
    7.23  def typestoxml(types):
    7.24      res = ""
    7.25      for t in types:
     8.1 --- a/xen/arch/ia64/xen/dom_fw_common.c	Mon Jul 30 17:10:45 2007 -0500
     8.2 +++ b/xen/arch/ia64/xen/dom_fw_common.c	Wed Aug 01 08:59:03 2007 +0100
     8.3 @@ -207,17 +207,6 @@ print_md(efi_memory_desc_t *md)
     8.4  		printk("(%luKB)\n", size >> 10);
     8.5  }
     8.6  
     8.7 -uint8_t
     8.8 -generate_acpi_checksum(void *tbl, unsigned long len)
     8.9 -{
    8.10 -	uint8_t *ptr, sum = 0;
    8.11 -
    8.12 -	for (ptr = tbl; len > 0 ; len--, ptr++)
    8.13 -		sum += *ptr;
    8.14 -
    8.15 -	return 0 - sum;
    8.16 -}
    8.17 -
    8.18  struct fake_acpi_tables {
    8.19  	struct acpi20_table_rsdp rsdp;
    8.20  	struct xsdt_descriptor_rev2 xsdt;
     9.1 --- a/xen/arch/ia64/xen/dom_fw_dom0.c	Mon Jul 30 17:10:45 2007 -0500
     9.2 +++ b/xen/arch/ia64/xen/dom_fw_dom0.c	Wed Aug 01 08:59:03 2007 +0100
     9.3 @@ -103,6 +103,7 @@ acpi_update_madt_checksum(unsigned long 
     9.4  /* base is physical address of acpi table */
     9.5  static void __init touch_acpi_table(void)
     9.6  {
     9.7 +	int result;
     9.8  	lsapic_nbr = 0;
     9.9  
    9.10  	if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_update_lsapic, 0) < 0)
    9.11 @@ -111,6 +112,18 @@ static void __init touch_acpi_table(void
    9.12  				  acpi_patch_plat_int_src, 0) < 0)
    9.13  		printk("Error parsing MADT - no PLAT_INT_SRC entries\n");
    9.14  
    9.15 +	result = acpi_table_disable(ACPI_SRAT);
    9.16 +	if ( result == 0 )
    9.17 +		printk("Success Disabling SRAT\n");
    9.18 +	else if ( result != -ENOENT )
    9.19 +		printk("ERROR: Failed Disabling SRAT\n");
    9.20 +
    9.21 +	result = acpi_table_disable(ACPI_SLIT);
    9.22 +	if ( result == 0 )
    9.23 +		printk("Success Disabling SLIT\n");
    9.24 +	else if ( result != -ENOENT )
    9.25 +		printk("ERROR: Failed Disabling SLIT\n");
    9.26 +
    9.27  	acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum);
    9.28  
    9.29  	return;
    10.1 --- a/xen/arch/x86/acpi/boot.c	Mon Jul 30 17:10:45 2007 -0500
    10.2 +++ b/xen/arch/x86/acpi/boot.c	Wed Aug 01 08:59:03 2007 +0100
    10.3 @@ -371,12 +371,19 @@ extern u32 pmtmr_ioport;
    10.4  
    10.5  #ifdef CONFIG_ACPI_SLEEP
    10.6  /* Get pm1x_cnt and pm1x_evt information for ACPI sleep */
    10.7 -static int __init
    10.8 +static void __init
    10.9  acpi_fadt_parse_sleep_info(struct fadt_descriptor_rev2 *fadt)
   10.10  {
   10.11 +	struct acpi_table_rsdp *rsdp;
   10.12 +	unsigned long rsdp_phys;
   10.13  	struct facs_descriptor_rev2 *facs = NULL;
   10.14  	uint64_t facs_pa;
   10.15  
   10.16 +	rsdp_phys = acpi_find_rsdp();
   10.17 +	if (!rsdp_phys || acpi_disabled)
   10.18 +		goto bad;
   10.19 +	rsdp = __va(rsdp_phys);
   10.20 +
   10.21  	if (fadt->revision >= FADT2_REVISION_ID) {
   10.22  		/* Sanity check on FADT Rev. 2 */
   10.23  		if ((fadt->xpm1a_cnt_blk.address_space_id !=
   10.24 @@ -432,8 +439,7 @@ acpi_fadt_parse_sleep_info(struct fadt_d
   10.25  			"FACS is shorter than ACPI spec allow: 0x%x",
   10.26  			facs->length);
   10.27  
   10.28 -	if ((acpi_rsdp_rev < 2) ||
   10.29 -	    (facs->length < 32)) {
   10.30 +	if ((rsdp->revision < 2) || (facs->length < 32)) {
   10.31  		acpi_sinfo.wakeup_vector = facs_pa + 
   10.32  			offsetof(struct facs_descriptor_rev2,
   10.33  				 firmware_waking_vector);
   10.34 @@ -451,10 +457,9 @@ acpi_fadt_parse_sleep_info(struct fadt_d
   10.35  		acpi_sinfo.pm1a_cnt, acpi_sinfo.pm1b_cnt,
   10.36  		acpi_sinfo.pm1a_evt, acpi_sinfo.pm1b_cnt,
   10.37  		acpi_sinfo.wakeup_vector, acpi_sinfo.vector_width);
   10.38 -	return 0;
   10.39 +	return;
   10.40  bad:
   10.41  	memset(&acpi_sinfo, 0, sizeof(acpi_sinfo));
   10.42 -	return 0;
   10.43  }
   10.44  #endif
   10.45  
    11.1 --- a/xen/arch/x86/hvm/instrlen.c	Mon Jul 30 17:10:45 2007 -0500
    11.2 +++ b/xen/arch/x86/hvm/instrlen.c	Wed Aug 01 08:59:03 2007 +0100
    11.3 @@ -9,14 +9,6 @@
    11.4   * x86_emulate.c.  Used for MMIO.
    11.5   */
    11.6  
    11.7 -/*
    11.8 - * TODO: The way in which we use hvm_instruction_length is very inefficient as
    11.9 - * it now stands. It will be worthwhile to return the actual instruction buffer
   11.10 - * along with the instruction length since one of the reasons we are getting
   11.11 - * the instruction length is to know how many instruction bytes we need to
   11.12 - * fetch.
   11.13 - */
   11.14 -
   11.15  #include <xen/config.h>
   11.16  #include <xen/sched.h>
   11.17  #include <xen/mm.h>
   11.18 @@ -194,31 +186,51 @@ static uint8_t twobyte_table[256] = {
   11.19  /* 
   11.20   * insn_fetch - fetch the next byte from instruction stream
   11.21   */
   11.22 -#define insn_fetch()                                                    \
   11.23 -({ uint8_t _x;                                                          \
   11.24 -   if ( length >= 15 )                                                  \
   11.25 -       return -1;                                                       \
   11.26 -   if ( inst_copy_from_guest(&_x, pc, 1) != 1 ) {                       \
   11.27 -       gdprintk(XENLOG_WARNING,                                         \
   11.28 -                "Cannot read from address %lx (eip %lx, mode %d)\n",    \
   11.29 -                pc, org_pc, address_bytes);                             \
   11.30 -       return -1;                                                       \
   11.31 -   }                                                                    \
   11.32 -   pc += 1;                                                             \
   11.33 -   length += 1;                                                         \
   11.34 -   _x;                                                                  \
   11.35 +#define insn_fetch()                                                      \
   11.36 +({ uint8_t _x;                                                            \
   11.37 +   if ( length >= 15 )                                                    \
   11.38 +       return -1;                                                         \
   11.39 +   if ( inst_copy_from_guest(&_x, pc, 1) != 1 ) {                         \
   11.40 +       unsigned long err;                                                 \
   11.41 +       struct segment_register cs;                                        \
   11.42 +       gdprintk(XENLOG_WARNING,                                           \
   11.43 +                "Cannot read from address %lx (eip %lx, mode %d)\n",      \
   11.44 +                pc, org_pc, address_bytes);                               \
   11.45 +       err = 0; /* Must be not-present: we don't enforce reserved bits */ \
   11.46 +       if ( hvm_nx_enabled(current) )                                     \
   11.47 +           err |= PFEC_insn_fetch;                                        \
   11.48 +       hvm_get_segment_register(current, x86_seg_cs, &cs);                \
   11.49 +       if ( cs.attr.fields.dpl != 0 )                                     \
   11.50 +           err |= PFEC_user_mode;                                         \
   11.51 +       hvm_inject_exception(TRAP_page_fault, err, pc);                    \
   11.52 +       return -1;                                                         \
   11.53 +   }                                                                      \
   11.54 +   if ( buf )                                                             \
   11.55 +       buf[length] = _x;                                                  \
   11.56 +   length += 1;                                                           \
   11.57 +   pc += 1;                                                               \
   11.58 +   _x;                                                                    \
   11.59  })
   11.60  
   11.61 +#define insn_skip(_n) do {                      \
   11.62 +    int _i;                                     \
   11.63 +    for ( _i = 0; _i < (_n); _i++) {            \
   11.64 +        (void) insn_fetch();                    \
   11.65 +    }                                           \
   11.66 +} while (0)
   11.67 +
   11.68  /**
   11.69 - * hvm_instruction_length - returns the current instructions length
   11.70 + * hvm_instruction_fetch - read the current instruction and return its length
   11.71   *
   11.72   * @org_pc: guest instruction pointer
   11.73 - * @mode: guest operating mode
   11.74 + * @address_bytes: guest address width
   11.75 + * @buf: (optional) buffer to load actual instruction bytes into
   11.76   *
   11.77 - * EXTERNAL this routine calculates the length of the current instruction
   11.78 - * pointed to by org_pc.  The guest state is _not_ changed by this routine.
   11.79 + * Doesn't increment the guest's instruction pointer, but may
   11.80 + * issue faults to the guest.  Returns -1 on failure.
   11.81   */
   11.82 -int hvm_instruction_length(unsigned long org_pc, int address_bytes)
   11.83 +int hvm_instruction_fetch(unsigned long org_pc, int address_bytes,
   11.84 +                          unsigned char *buf)
   11.85  {
   11.86      uint8_t b, d, twobyte = 0, rex_prefix = 0, modrm_reg = 0;
   11.87      unsigned int op_default, op_bytes, ad_default, ad_bytes, tmp;
   11.88 @@ -317,18 +329,13 @@ done_prefixes:
   11.89              {
   11.90              case 0:
   11.91                  if ( modrm_rm == 6 ) 
   11.92 -                {
   11.93 -                    length += 2;
   11.94 -                    pc += 2; /* skip disp16 */
   11.95 -                }
   11.96 +                    insn_skip(2); /* skip disp16 */
   11.97                  break;
   11.98              case 1:
   11.99 -                length += 1;
  11.100 -                pc += 1; /* skip disp8 */
  11.101 +                insn_skip(1); /* skip disp8 */
  11.102                  break;
  11.103              case 2:
  11.104 -                length += 2;
  11.105 -                pc += 2; /* skip disp16 */
  11.106 +                insn_skip(2); /* skip disp16 */
  11.107                  break;
  11.108              }
  11.109          }
  11.110 @@ -340,33 +347,19 @@ done_prefixes:
  11.111              case 0:
  11.112                  if ( (modrm_rm == 4) && 
  11.113                       ((insn_fetch() & 7) == 5) )
  11.114 -                {
  11.115 -                    length += 4;
  11.116 -                    pc += 4; /* skip disp32 specified by SIB.base */
  11.117 -                }
  11.118 +                    insn_skip(4); /* skip disp32 specified by SIB.base */
  11.119                  else if ( modrm_rm == 5 )
  11.120 -                {
  11.121 -                    length += 4;
  11.122 -                    pc += 4; /* skip disp32 */
  11.123 -                }
  11.124 +                    insn_skip(4); /* skip disp32 */
  11.125                  break;
  11.126              case 1:
  11.127                  if ( modrm_rm == 4 )
  11.128 -                {
  11.129 -                    length += 1;
  11.130 -                    pc += 1;
  11.131 -                }
  11.132 -                length += 1;
  11.133 -                pc += 1; /* skip disp8 */
  11.134 +                    insn_skip(1);
  11.135 +                insn_skip(1); /* skip disp8 */
  11.136                  break;
  11.137              case 2:
  11.138                  if ( modrm_rm == 4 )
  11.139 -                {
  11.140 -                    length += 1;
  11.141 -                    pc += 1;
  11.142 -                }
  11.143 -                length += 4;
  11.144 -                pc += 4; /* skip disp32 */
  11.145 +                    insn_skip(1);
  11.146 +                insn_skip(4); /* skip disp32 */
  11.147                  break;
  11.148              }
  11.149          }
  11.150 @@ -387,12 +380,10 @@ done_prefixes:
  11.151          tmp = (d & ByteOp) ? 1 : op_bytes;
  11.152          if ( tmp == 8 ) tmp = 4;
  11.153          /* NB. Immediates are sign-extended as necessary. */
  11.154 -        length += tmp;
  11.155 -        pc += tmp;
  11.156 +        insn_skip(tmp);
  11.157          break;
  11.158      case SrcImmByte:
  11.159 -        length += 1;
  11.160 -        pc += 1;
  11.161 +        insn_skip(1);
  11.162          break;
  11.163      }
  11.164  
  11.165 @@ -402,8 +393,7 @@ done_prefixes:
  11.166      switch ( b )
  11.167      {
  11.168      case 0xa0 ... 0xa3: /* mov */
  11.169 -        length += ad_bytes;
  11.170 -        pc += ad_bytes; /* skip src/dst displacement */
  11.171 +        insn_skip(ad_bytes); /* skip src/dst displacement */
  11.172          break;
  11.173      case 0xf6 ... 0xf7: /* Grp3 */
  11.174          switch ( modrm_reg )
  11.175 @@ -412,8 +402,7 @@ done_prefixes:
  11.176              /* Special case in Grp3: test has an immediate source operand. */
  11.177              tmp = (d & ByteOp) ? 1 : op_bytes;
  11.178              if ( tmp == 8 ) tmp = 4;
  11.179 -            length += tmp;
  11.180 -            pc += tmp;
  11.181 +            insn_skip(tmp);
  11.182              break;
  11.183          }
  11.184          break;
    12.1 --- a/xen/arch/x86/hvm/platform.c	Mon Jul 30 17:10:45 2007 -0500
    12.2 +++ b/xen/arch/x86/hvm/platform.c	Wed Aug 01 08:59:03 2007 +0100
    12.3 @@ -1041,17 +1041,13 @@ void handle_mmio(unsigned long gpa)
    12.4          /* real or vm86 modes */
    12.5          address_bytes = 2;
    12.6      inst_addr = hvm_get_segment_base(v, x86_seg_cs) + regs->eip;
    12.7 -    inst_len = hvm_instruction_length(inst_addr, address_bytes);
    12.8 +    memset(inst, 0, MAX_INST_LEN);
    12.9 +    inst_len = hvm_instruction_fetch(inst_addr, address_bytes, inst);
   12.10      if ( inst_len <= 0 )
   12.11      {
   12.12 -        printk("handle_mmio: failed to get instruction length\n");
   12.13 -        domain_crash_synchronous();
   12.14 -    }
   12.15 -
   12.16 -    memset(inst, 0, MAX_INST_LEN);
   12.17 -    if ( inst_copy_from_guest(inst, inst_addr, inst_len) != inst_len ) {
   12.18 -        printk("handle_mmio: failed to copy instruction\n");
   12.19 -        domain_crash_synchronous();
   12.20 +        gdprintk(XENLOG_DEBUG, "handle_mmio: failed to get instruction\n");
   12.21 +        /* hvm_instruction_fetch() will have injected a #PF; get out now */
   12.22 +        return;
   12.23      }
   12.24  
   12.25      if ( mmio_decode(address_bytes, inst, mmio_op, &ad_size,
    13.1 --- a/xen/arch/x86/hvm/svm/intr.c	Mon Jul 30 17:10:45 2007 -0500
    13.2 +++ b/xen/arch/x86/hvm/svm/intr.c	Wed Aug 01 08:59:03 2007 +0100
    13.3 @@ -58,7 +58,7 @@ static void svm_inject_nmi(struct vcpu *
    13.4  
    13.5      event.bytes = 0;
    13.6      event.fields.v = 1;
    13.7 -    event.fields.type = EVENTTYPE_NMI;
    13.8 +    event.fields.type = X86_EVENTTYPE_NMI;
    13.9      event.fields.vector = 2;
   13.10  
   13.11      ASSERT(vmcb->eventinj.fields.v == 0);
   13.12 @@ -72,13 +72,33 @@ static void svm_inject_extint(struct vcp
   13.13  
   13.14      event.bytes = 0;
   13.15      event.fields.v = 1;
   13.16 -    event.fields.type = EVENTTYPE_INTR;
   13.17 +    event.fields.type = X86_EVENTTYPE_EXT_INTR;
   13.18      event.fields.vector = vector;
   13.19  
   13.20      ASSERT(vmcb->eventinj.fields.v == 0);
   13.21      vmcb->eventinj = event;
   13.22  }
   13.23      
   13.24 +static void enable_intr_window(struct vcpu *v, enum hvm_intack intr_source)
   13.25 +{
   13.26 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
   13.27 +
   13.28 +    ASSERT(intr_source != hvm_intack_none);
   13.29 +
   13.30 +    /*
   13.31 +     * Create a dummy virtual interrupt to intercept as soon as the
   13.32 +     * guest can accept the real interrupt.
   13.33 +     *
   13.34 +     * TODO: Better NMI handling. We need a way to skip a MOV SS interrupt
   13.35 +     * shadow. This is hard to do without hardware support. We should also
   13.36 +     * track 'NMI blocking' from NMI injection until IRET. This can be done
   13.37 +     * quite easily in software by intercepting the unblocking IRET.
   13.38 +     */
   13.39 +    vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
   13.40 +    HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
   13.41 +    svm_inject_dummy_vintr(v);
   13.42 +}
   13.43 +
   13.44  asmlinkage void svm_intr_assist(void) 
   13.45  {
   13.46      struct vcpu *v = current;
   13.47 @@ -86,21 +106,6 @@ asmlinkage void svm_intr_assist(void)
   13.48      enum hvm_intack intr_source;
   13.49      int intr_vector;
   13.50  
   13.51 -    /*
   13.52 -     * Previous event delivery caused this intercept?
   13.53 -     * This will happen if the injection is latched by the processor (hence
   13.54 -     * clearing vintr.fields.irq or eventinj.v) but then subsequently a fault
   13.55 -     * occurs (e.g., due to lack of shadow mapping of guest IDT or guest-kernel
   13.56 -     * stack).
   13.57 -     */
   13.58 -    if ( vmcb->exitintinfo.fields.v )
   13.59 -    {
   13.60 -        vmcb->eventinj = vmcb->exitintinfo;
   13.61 -        vmcb->exitintinfo.bytes = 0;
   13.62 -        HVMTRACE_1D(REINJ_VIRQ, v, intr_vector);
   13.63 -        return;
   13.64 -    }
   13.65 -
   13.66      /* Crank the handle on interrupt state. */
   13.67      pt_update_irq(v);
   13.68      hvm_set_callback_irq_level();
   13.69 @@ -111,32 +116,23 @@ asmlinkage void svm_intr_assist(void)
   13.70              return;
   13.71  
   13.72          /*
   13.73 -         * If the guest can't take an interrupt right now, create a 'fake'
   13.74 -         * virtual interrupt on to intercept as soon as the guest _can_ take
   13.75 -         * interrupts.  Do not obtain the next interrupt from the vlapic/pic
   13.76 -         * if unable to inject.
   13.77 -         *
   13.78 -         * Also do this if there is an injection already pending. This is
   13.79 -         * because the event delivery can arbitrarily delay the injection
   13.80 -         * of the vintr (for example, if the exception is handled via an
   13.81 -         * interrupt gate, hence zeroing RFLAGS.IF). In the meantime:
   13.82 -         * - the vTPR could be modified upwards, so we need to wait until the
   13.83 -         *   exception is delivered before we can safely decide that an
   13.84 -         *   interrupt is deliverable; and
   13.85 -         * - the guest might look at the APIC/PIC state, so we ought not to
   13.86 -         *   have cleared the interrupt out of the IRR.
   13.87 -         *
   13.88 -         * TODO: Better NMI handling. We need a way to skip a MOV SS interrupt
   13.89 -         * shadow. This is hard to do without hardware support. We should also
   13.90 -         * track 'NMI blocking' from NMI injection until IRET. This can be done
   13.91 -         * quite easily in software by intercepting the unblocking IRET.
   13.92 +         * Pending IRQs must be delayed if:
   13.93 +         * 1. An event is already pending. This is despite the fact that SVM
   13.94 +         *    provides a VINTR delivery method quite separate from the EVENTINJ
   13.95 +         *    mechanism. The event delivery can arbitrarily delay the injection
   13.96 +         *    of the vintr (for example, if the exception is handled via an
   13.97 +         *    interrupt gate, hence zeroing RFLAGS.IF). In the meantime:
   13.98 +         *    - the vTPR could be modified upwards, so we need to wait until
   13.99 +         *      the exception is delivered before we can safely decide that an
  13.100 +         *      interrupt is deliverable; and
  13.101 +         *    - the guest might look at the APIC/PIC state, so we ought not to
  13.102 +         *      have cleared the interrupt out of the IRR.
  13.103 +         * 2. The IRQ is masked.
  13.104           */
  13.105 -        if ( !hvm_interrupts_enabled(v, intr_source) ||
  13.106 -             vmcb->eventinj.fields.v )
  13.107 +        if ( unlikely(vmcb->eventinj.fields.v) ||
  13.108 +             !hvm_interrupts_enabled(v, intr_source) )
  13.109          {
  13.110 -            vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
  13.111 -            HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
  13.112 -            svm_inject_dummy_vintr(v);
  13.113 +            enable_intr_window(v, intr_source);
  13.114              return;
  13.115          }
  13.116      } while ( !hvm_vcpu_ack_pending_irq(v, intr_source, &intr_vector) );
  13.117 @@ -151,6 +147,11 @@ asmlinkage void svm_intr_assist(void)
  13.118          svm_inject_extint(v, intr_vector);
  13.119          pt_intr_post(v, intr_vector, intr_source);
  13.120      }
  13.121 +
  13.122 +    /* Is there another IRQ to queue up behind this one? */
  13.123 +    intr_source = hvm_vcpu_has_pending_irq(v);
  13.124 +    if ( unlikely(intr_source != hvm_intack_none) )
  13.125 +        enable_intr_window(v, intr_source);
  13.126  }
  13.127  
  13.128  /*
    14.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Jul 30 17:10:45 2007 -0500
    14.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Aug 01 08:59:03 2007 +0100
    14.3 @@ -71,8 +71,8 @@ static void *root_vmcb[NR_CPUS] __read_m
    14.4  /* hardware assisted paging bits */
    14.5  extern int opt_hap_enabled;
    14.6  
    14.7 -static void svm_inject_exception(struct vcpu *v, int trap, 
    14.8 -                                        int ev, int error_code)
    14.9 +static void svm_inject_exception(
   14.10 +    struct vcpu *v, int trap, int ev, int error_code)
   14.11  {
   14.12      eventinj_t event;
   14.13      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
   14.14 @@ -84,13 +84,11 @@ static void svm_inject_exception(struct 
   14.15  
   14.16      event.bytes = 0;            
   14.17      event.fields.v = 1;
   14.18 -    event.fields.type = EVENTTYPE_EXCEPTION;
   14.19 +    event.fields.type = X86_EVENTTYPE_HW_EXCEPTION;
   14.20      event.fields.vector = trap;
   14.21      event.fields.ev = ev;
   14.22      event.fields.errorcode = error_code;
   14.23  
   14.24 -    ASSERT(vmcb->eventinj.fields.v == 0);
   14.25 -    
   14.26      vmcb->eventinj = event;
   14.27  }
   14.28  
   14.29 @@ -362,22 +360,15 @@ int svm_vmcb_save(struct vcpu *v, struct
   14.30      c->sysenter_esp = vmcb->sysenter_esp;
   14.31      c->sysenter_eip = vmcb->sysenter_eip;
   14.32  
   14.33 -    /* Save any event/interrupt that was being injected when we last exited. */
   14.34 -    if ( vmcb->exitintinfo.fields.v )
   14.35 +    c->pending_event = 0;
   14.36 +    c->error_code = 0;
   14.37 +    if ( vmcb->eventinj.fields.v &&
   14.38 +         hvm_event_needs_reinjection(vmcb->eventinj.fields.type,
   14.39 +                                     vmcb->eventinj.fields.vector) )
   14.40      {
   14.41 -        c->pending_event = vmcb->exitintinfo.bytes & 0xffffffff;
   14.42 -        c->error_code = vmcb->exitintinfo.fields.errorcode;
   14.43 -    }
   14.44 -    else if ( vmcb->eventinj.fields.v ) 
   14.45 -    {
   14.46 -        c->pending_event = vmcb->eventinj.bytes & 0xffffffff;
   14.47 +        c->pending_event = (uint32_t)vmcb->eventinj.bytes;
   14.48          c->error_code = vmcb->eventinj.fields.errorcode;
   14.49      }
   14.50 -    else 
   14.51 -    {
   14.52 -        c->pending_event = 0;
   14.53 -        c->error_code = 0;
   14.54 -    }
   14.55  
   14.56      return 1;
   14.57  }
   14.58 @@ -495,11 +486,11 @@ int svm_vmcb_restore(struct vcpu *v, str
   14.59      vmcb->sysenter_esp = c->sysenter_esp;
   14.60      vmcb->sysenter_eip = c->sysenter_eip;
   14.61  
   14.62 -    /* update VMCB for nested paging restore */
   14.63 -    if ( paging_mode_hap(v->domain) ) {
   14.64 +    if ( paging_mode_hap(v->domain) )
   14.65 +    {
   14.66          vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
   14.67 -        vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4 |
   14.68 -                    (HVM_CR4_HOST_MASK & ~X86_CR4_PAE);
   14.69 +        vmcb->cr4 = (v->arch.hvm_svm.cpu_shadow_cr4 |
   14.70 +                     (HVM_CR4_HOST_MASK & ~X86_CR4_PAE));
   14.71          vmcb->cr3 = c->cr3;
   14.72          vmcb->np_enable = 1;
   14.73          vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
   14.74 @@ -514,26 +505,23 @@ int svm_vmcb_restore(struct vcpu *v, str
   14.75          gdprintk(XENLOG_INFO, "Re-injecting 0x%"PRIx32", 0x%"PRIx32"\n",
   14.76                   c->pending_event, c->error_code);
   14.77  
   14.78 -        /* VMX uses a different type for #OF and #BP; fold into "Exception"  */
   14.79 -        if ( c->pending_type == 6 ) 
   14.80 -            c->pending_type = 3;
   14.81 -        /* Sanity check */
   14.82 -        if ( c->pending_type == 1 || c->pending_type > 4 
   14.83 -             || c->pending_reserved != 0 )
   14.84 +        if ( (c->pending_type == 1) || (c->pending_type > 6) ||
   14.85 +             (c->pending_reserved != 0) )
   14.86          {
   14.87              gdprintk(XENLOG_ERR, "Invalid pending event 0x%"PRIx32"\n", 
   14.88                       c->pending_event);
   14.89              return -EINVAL;
   14.90          }
   14.91 -        /* Put this pending event in exitintinfo and svm_intr_assist()
   14.92 -         * will reinject it when we return to the guest. */
   14.93 -        vmcb->exitintinfo.bytes = c->pending_event;
   14.94 -        vmcb->exitintinfo.fields.errorcode = c->error_code;
   14.95 +
   14.96 +        if ( hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
   14.97 +        {
   14.98 +            vmcb->eventinj.bytes = c->pending_event;
   14.99 +            vmcb->eventinj.fields.errorcode = c->error_code;
  14.100 +        }
  14.101      }
  14.102  
  14.103      paging_update_paging_modes(v);
  14.104 -    /* signal paging update to ASID handler */
  14.105 -    svm_asid_g_update_paging (v);
  14.106 +    svm_asid_g_update_paging(v);
  14.107  
  14.108      return 0;
  14.109   
  14.110 @@ -965,10 +953,10 @@ static void svm_hvm_inject_exception(
  14.111      svm_inject_exception(v, trapnr, (errcode != -1), errcode);
  14.112  }
  14.113  
  14.114 -static int svm_event_injection_faulted(struct vcpu *v)
  14.115 +static int svm_event_pending(struct vcpu *v)
  14.116  {
  14.117      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  14.118 -    return vmcb->exitintinfo.fields.v;
  14.119 +    return vmcb->eventinj.fields.v;
  14.120  }
  14.121  
  14.122  static struct hvm_function_table svm_function_table = {
  14.123 @@ -1000,7 +988,7 @@ static struct hvm_function_table svm_fun
  14.124      .inject_exception     = svm_hvm_inject_exception,
  14.125      .init_ap_context      = svm_init_ap_context,
  14.126      .init_hypercall_page  = svm_init_hypercall_page,
  14.127 -    .event_injection_faulted = svm_event_injection_faulted
  14.128 +    .event_pending        = svm_event_pending
  14.129  };
  14.130  
  14.131  static void svm_npt_detect(void)
  14.132 @@ -1668,6 +1656,17 @@ static int svm_set_cr0(unsigned long val
  14.133    
  14.134      HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
  14.135  
  14.136 +    if ( (u32)value != value )
  14.137 +    {
  14.138 +        HVM_DBG_LOG(DBG_LEVEL_1,
  14.139 +                    "Guest attempts to set upper 32 bits in CR0: %lx",
  14.140 +                    value);
  14.141 +        svm_inject_exception(v, TRAP_gp_fault, 1, 0);
  14.142 +        return 0;
  14.143 +    }
  14.144 +
  14.145 +    value &= ~HVM_CR0_GUEST_RESERVED_BITS;
  14.146 +
  14.147      /* ET is reserved and should be always be 1. */
  14.148      value |= X86_CR0_ET;
  14.149  
  14.150 @@ -2420,6 +2419,7 @@ asmlinkage void svm_vmexit_handler(struc
  14.151      unsigned long eip;
  14.152      struct vcpu *v = current;
  14.153      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  14.154 +    eventinj_t eventinj;
  14.155      int inst_len, rc;
  14.156  
  14.157      exit_reason = vmcb->exitcode;
  14.158 @@ -2435,6 +2435,13 @@ asmlinkage void svm_vmexit_handler(struc
  14.159      perfc_incra(svmexits, exit_reason);
  14.160      eip = vmcb->rip;
  14.161  
  14.162 +    /* Event delivery caused this intercept? Queue for redelivery. */
  14.163 +    eventinj = vmcb->exitintinfo;
  14.164 +    if ( unlikely(eventinj.fields.v) &&
  14.165 +         hvm_event_needs_reinjection(eventinj.fields.type,
  14.166 +                                     eventinj.fields.vector) )
  14.167 +        vmcb->eventinj = eventinj;
  14.168 +
  14.169      switch ( exit_reason )
  14.170      {
  14.171      case VMEXIT_INTR:
    15.1 --- a/xen/arch/x86/hvm/vmx/intr.c	Mon Jul 30 17:10:45 2007 -0500
    15.2 +++ b/xen/arch/x86/hvm/vmx/intr.c	Wed Aug 01 08:59:03 2007 +0100
    15.3 @@ -76,10 +76,9 @@ static void enable_intr_window(struct vc
    15.4      u32 *cpu_exec_control = &v->arch.hvm_vmx.exec_control;
    15.5      u32 ctl = CPU_BASED_VIRTUAL_INTR_PENDING;
    15.6  
    15.7 -    if ( unlikely(intr_source == hvm_intack_none) )
    15.8 -        return;
    15.9 +    ASSERT(intr_source != hvm_intack_none);
   15.10  
   15.11 -    if ( unlikely(intr_source == hvm_intack_nmi) && cpu_has_vmx_vnmi )
   15.12 +    if ( (intr_source == hvm_intack_nmi) && cpu_has_vmx_vnmi )
   15.13      {
   15.14          /*
   15.15           * We set MOV-SS blocking in lieu of STI blocking when delivering an
   15.16 @@ -131,68 +130,27 @@ asmlinkage void vmx_intr_assist(void)
   15.17      int intr_vector;
   15.18      enum hvm_intack intr_source;
   15.19      struct vcpu *v = current;
   15.20 -    unsigned int idtv_info_field;
   15.21 -    unsigned long inst_len;
   15.22 +    unsigned int intr_info;
   15.23  
   15.24 +    /* Crank the handle on interrupt state. */
   15.25      pt_update_irq(v);
   15.26 -
   15.27      hvm_set_callback_irq_level();
   15.28  
   15.29 -    update_tpr_threshold(vcpu_vlapic(v));
   15.30 -
   15.31      do {
   15.32          intr_source = hvm_vcpu_has_pending_irq(v);
   15.33 -
   15.34 -        if ( unlikely(v->arch.hvm_vmx.vector_injected) )
   15.35 -        {
   15.36 -            v->arch.hvm_vmx.vector_injected = 0;
   15.37 -            enable_intr_window(v, intr_source);
   15.38 -            return;
   15.39 -        }
   15.40 -
   15.41 -        /* This could be moved earlier in the VMX resume sequence. */
   15.42 -        idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
   15.43 -        if ( unlikely(idtv_info_field & INTR_INFO_VALID_MASK) )
   15.44 -        {
   15.45 -            /* See SDM 3B 25.7.1.1 and .2 for info about masking resvd bits. */
   15.46 -            __vmwrite(VM_ENTRY_INTR_INFO_FIELD,
   15.47 -                      idtv_info_field & ~INTR_INFO_RESVD_BITS_MASK);
   15.48 +        if ( likely(intr_source == hvm_intack_none) )
   15.49 +            goto out;
   15.50  
   15.51 -            /*
   15.52 -             * Safe: the length will only be interpreted for software
   15.53 -             * exceptions and interrupts. If we get here then delivery of some
   15.54 -             * event caused a fault, and this always results in defined
   15.55 -             * VM_EXIT_INSTRUCTION_LEN.
   15.56 -             */
   15.57 -            inst_len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe */
   15.58 -            __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
   15.59 -
   15.60 -            if ( unlikely(idtv_info_field & 0x800) ) /* valid error code */
   15.61 -                __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE,
   15.62 -                          __vmread(IDT_VECTORING_ERROR_CODE));
   15.63 -
   15.64 -            /*
   15.65 -             * Clear NMI-blocking interruptibility info if an NMI delivery
   15.66 -             * faulted. Re-delivery will re-set it (see SDM 3B 25.7.1.2).
   15.67 -             */
   15.68 -            if ( (idtv_info_field&INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI )
   15.69 -                __vmwrite(GUEST_INTERRUPTIBILITY_INFO,
   15.70 -                          __vmread(GUEST_INTERRUPTIBILITY_INFO) &
   15.71 -                          ~VMX_INTR_SHADOW_NMI);
   15.72 -
   15.73 -            enable_intr_window(v, intr_source);
   15.74 -
   15.75 -            HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
   15.76 -            return;
   15.77 -        }
   15.78 -
   15.79 -        if ( likely(intr_source == hvm_intack_none) )
   15.80 -            return;
   15.81 -
   15.82 -        if ( !hvm_interrupts_enabled(v, intr_source) )
   15.83 +        /*
   15.84 +         * An event is already pending or the pending interrupt is masked?
   15.85 +         * Then the pending interrupt must be delayed.
   15.86 +         */
   15.87 +        intr_info = __vmread(VM_ENTRY_INTR_INFO);
   15.88 +        if ( unlikely(intr_info & INTR_INFO_VALID_MASK) ||
   15.89 +             !hvm_interrupts_enabled(v, intr_source) )
   15.90          {
   15.91              enable_intr_window(v, intr_source);
   15.92 -            return;
   15.93 +            goto out;
   15.94          }
   15.95      } while ( !hvm_vcpu_ack_pending_irq(v, intr_source, &intr_vector) );
   15.96  
   15.97 @@ -206,6 +164,14 @@ asmlinkage void vmx_intr_assist(void)
   15.98          vmx_inject_extint(v, intr_vector);
   15.99          pt_intr_post(v, intr_vector, intr_source);
  15.100      }
  15.101 +
  15.102 +    /* Is there another IRQ to queue up behind this one? */
  15.103 +    intr_source = hvm_vcpu_has_pending_irq(v);
  15.104 +    if ( unlikely(intr_source != hvm_intack_none) )
  15.105 +        enable_intr_window(v, intr_source);
  15.106 +
  15.107 + out:
  15.108 +    update_tpr_threshold(vcpu_vlapic(v));
  15.109  }
  15.110  
  15.111  /*
    16.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Mon Jul 30 17:10:45 2007 -0500
    16.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Wed Aug 01 08:59:03 2007 +0100
    16.3 @@ -240,9 +240,24 @@ int vmx_cpu_up(void)
    16.4  {
    16.5      u32 eax, edx;
    16.6      int cpu = smp_processor_id();
    16.7 +    u64 cr0, vmx_cr0_fixed0, vmx_cr0_fixed1;
    16.8  
    16.9      BUG_ON(!(read_cr4() & X86_CR4_VMXE));
   16.10  
   16.11 +    /* 
   16.12 +     * Ensure the current processor operating mode meets 
   16.13 +     * the requred CRO fixed bits in VMX operation. 
   16.14 +     */
   16.15 +    cr0 = read_cr0();
   16.16 +    rdmsrl(MSR_IA32_VMX_CR0_FIXED0, vmx_cr0_fixed0);
   16.17 +    rdmsrl(MSR_IA32_VMX_CR0_FIXED1, vmx_cr0_fixed1);
   16.18 +    if ( (~cr0 & vmx_cr0_fixed0) || (cr0 & ~vmx_cr0_fixed1) )
   16.19 +    {
   16.20 +        printk("CPU%d: some settings of host CR0 are " 
   16.21 +               "not allowed in VMX operation.\n", cpu);
   16.22 +        return 0;
   16.23 +    }
   16.24 +
   16.25      rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
   16.26  
   16.27      if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
   16.28 @@ -418,7 +433,7 @@ static void construct_vmcs(struct vcpu *
   16.29      __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
   16.30      __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
   16.31  
   16.32 -    __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
   16.33 +    __vmwrite(VM_ENTRY_INTR_INFO, 0);
   16.34  
   16.35      __vmwrite(CR0_GUEST_HOST_MASK, ~0UL);
   16.36      __vmwrite(CR4_GUEST_HOST_MASK, ~0UL);
    17.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Mon Jul 30 17:10:45 2007 -0500
    17.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Aug 01 08:59:03 2007 +0100
    17.3 @@ -613,29 +613,14 @@ void vmx_vmcs_save(struct vcpu *v, struc
    17.4      c->sysenter_esp = __vmread(GUEST_SYSENTER_ESP);
    17.5      c->sysenter_eip = __vmread(GUEST_SYSENTER_EIP);
    17.6  
    17.7 -    /*
    17.8 -     * Save any event/interrupt that was being injected when we last
    17.9 -     * exited. IDT_VECTORING_INFO_FIELD has priority, as anything in
   17.10 -     * VM_ENTRY_INTR_INFO_FIELD is either a fault caused by the first
   17.11 -     * event, which will happen the next time, or an interrupt, which we
   17.12 -     * never inject when IDT_VECTORING_INFO_FIELD is valid.
   17.13 -     */
   17.14 -    if ( (ev = __vmread(IDT_VECTORING_INFO_FIELD)) & INTR_INFO_VALID_MASK )
   17.15 -    {
   17.16 -        c->pending_event = ev;
   17.17 -        c->error_code = __vmread(IDT_VECTORING_ERROR_CODE);
   17.18 -    }
   17.19 -    else if ( (ev = __vmread(VM_ENTRY_INTR_INFO_FIELD)) &
   17.20 -              INTR_INFO_VALID_MASK )
   17.21 +    c->pending_event = 0;
   17.22 +    c->error_code = 0;
   17.23 +    if ( ((ev = __vmread(VM_ENTRY_INTR_INFO)) & INTR_INFO_VALID_MASK) &&
   17.24 +         hvm_event_needs_reinjection((ev >> 8) & 7, ev & 0xff) )
   17.25      {
   17.26          c->pending_event = ev;
   17.27          c->error_code = __vmread(VM_ENTRY_EXCEPTION_ERROR_CODE);
   17.28      }
   17.29 -    else
   17.30 -    {
   17.31 -        c->pending_event = 0;
   17.32 -        c->error_code = 0;
   17.33 -    }
   17.34  
   17.35      vmx_vmcs_exit(v);
   17.36  }
   17.37 @@ -754,34 +739,9 @@ int vmx_vmcs_restore(struct vcpu *v, str
   17.38  
   17.39      if ( c->pending_valid )
   17.40      {
   17.41 -        vmx_vmcs_enter(v);
   17.42 -
   17.43          gdprintk(XENLOG_INFO, "Re-injecting 0x%"PRIx32", 0x%"PRIx32"\n",
   17.44                   c->pending_event, c->error_code);
   17.45  
   17.46 -        /* SVM uses type 3 ("Exception") for #OF and #BP; VMX uses type 6 */
   17.47 -        if ( (c->pending_type == 3) &&
   17.48 -             ((c->pending_vector == 3) || (c->pending_vector == 4)) )
   17.49 -            c->pending_type = 6;
   17.50 -
   17.51 -        /* For software exceptions, we need to tell the hardware the
   17.52 -         * instruction length as well (hmmm). */
   17.53 -        if ( c->pending_type > 4 )
   17.54 -        {
   17.55 -            int addrbytes, ilen;
   17.56 -            if ( (c->cs_arbytes & X86_SEG_AR_CS_LM_ACTIVE) &&
   17.57 -                 (c->msr_efer & EFER_LMA) )
   17.58 -                addrbytes = 8;
   17.59 -            else if ( c->cs_arbytes & X86_SEG_AR_DEF_OP_SIZE )
   17.60 -                addrbytes = 4;
   17.61 -            else
   17.62 -                addrbytes = 2;
   17.63 -
   17.64 -            ilen = hvm_instruction_length(c->rip, addrbytes);
   17.65 -            __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen);
   17.66 -        }
   17.67 -
   17.68 -        /* Sanity check */
   17.69          if ( (c->pending_type == 1) || (c->pending_type > 6) ||
   17.70               (c->pending_reserved != 0) )
   17.71          {
   17.72 @@ -790,12 +750,13 @@ int vmx_vmcs_restore(struct vcpu *v, str
   17.73              return -EINVAL;
   17.74          }
   17.75  
   17.76 -        /* Re-inject the exception */
   17.77 -        __vmwrite(VM_ENTRY_INTR_INFO_FIELD, c->pending_event);
   17.78 -        __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, c->error_code);
   17.79 -        v->arch.hvm_vmx.vector_injected = 1;
   17.80 -
   17.81 -        vmx_vmcs_exit(v);
   17.82 +        if ( hvm_event_needs_reinjection(c->pending_type, c->pending_vector) )
   17.83 +        {
   17.84 +            vmx_vmcs_enter(v);
   17.85 +            __vmwrite(VM_ENTRY_INTR_INFO, c->pending_event);
   17.86 +            __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, c->error_code);
   17.87 +            vmx_vmcs_exit(v);
   17.88 +        }
   17.89      }
   17.90  
   17.91      return 0;
   17.92 @@ -1203,14 +1164,10 @@ static void vmx_update_vtpr(struct vcpu 
   17.93      /* VMX doesn't have a V_TPR field */
   17.94  }
   17.95  
   17.96 -static int vmx_event_injection_faulted(struct vcpu *v)
   17.97 +static int vmx_event_pending(struct vcpu *v)
   17.98  {
   17.99 -    unsigned int idtv_info_field;
  17.100 -
  17.101      ASSERT(v == current);
  17.102 -
  17.103 -    idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
  17.104 -    return (idtv_info_field & INTR_INFO_VALID_MASK);
  17.105 +    return (__vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK);
  17.106  }
  17.107  
  17.108  static void disable_intercept_for_msr(u32 msr)
  17.109 @@ -1261,7 +1218,7 @@ static struct hvm_function_table vmx_fun
  17.110      .inject_exception     = vmx_inject_exception,
  17.111      .init_ap_context      = vmx_init_ap_context,
  17.112      .init_hypercall_page  = vmx_init_hypercall_page,
  17.113 -    .event_injection_faulted = vmx_event_injection_faulted,
  17.114 +    .event_pending        = vmx_event_pending,
  17.115      .cpu_up               = vmx_cpu_up,
  17.116      .cpu_down             = vmx_cpu_down,
  17.117  };
  17.118 @@ -2200,6 +2157,17 @@ static int vmx_set_cr0(unsigned long val
  17.119  
  17.120      HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
  17.121  
  17.122 +    if ( (u32)value != value )
  17.123 +    {
  17.124 +        HVM_DBG_LOG(DBG_LEVEL_1,
  17.125 +                    "Guest attempts to set upper 32 bits in CR0: %lx",
  17.126 +                    value);
  17.127 +        vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
  17.128 +        return 0;
  17.129 +    }
  17.130 +
  17.131 +    value &= ~HVM_CR0_GUEST_RESERVED_BITS;
  17.132 +
  17.133      /* ET is reserved and should be always be 1. */
  17.134      value |= X86_CR0_ET;
  17.135  
  17.136 @@ -2842,47 +2810,6 @@ static void vmx_do_extint(struct cpu_use
  17.137      }
  17.138  }
  17.139  
  17.140 -static void vmx_reflect_exception(struct vcpu *v)
  17.141 -{
  17.142 -    int error_code, intr_info, vector;
  17.143 -
  17.144 -    intr_info = __vmread(VM_EXIT_INTR_INFO);
  17.145 -    vector = intr_info & 0xff;
  17.146 -    if ( intr_info & INTR_INFO_DELIVER_CODE_MASK )
  17.147 -        error_code = __vmread(VM_EXIT_INTR_ERROR_CODE);
  17.148 -    else
  17.149 -        error_code = VMX_DELIVER_NO_ERROR_CODE;
  17.150 -
  17.151 -#ifndef NDEBUG
  17.152 -    {
  17.153 -        unsigned long rip;
  17.154 -
  17.155 -        rip = __vmread(GUEST_RIP);
  17.156 -        HVM_DBG_LOG(DBG_LEVEL_1, "rip = %lx, error_code = %x",
  17.157 -                    rip, error_code);
  17.158 -    }
  17.159 -#endif /* NDEBUG */
  17.160 -
  17.161 -    /*
  17.162 -     * According to Intel Virtualization Technology Specification for
  17.163 -     * the IA-32 Intel Architecture (C97063-002 April 2005), section
  17.164 -     * 2.8.3, SW_EXCEPTION should be used for #BP and #OV, and
  17.165 -     * HW_EXCEPTION used for everything else.  The main difference
  17.166 -     * appears to be that for SW_EXCEPTION, the EIP/RIP is incremented
  17.167 -     * by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION,
  17.168 -     * it is not.
  17.169 -     */
  17.170 -    if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION )
  17.171 -    {
  17.172 -        int ilen = __get_instruction_length(); /* Safe: software exception */
  17.173 -        vmx_inject_sw_exception(v, vector, ilen);
  17.174 -    }
  17.175 -    else
  17.176 -    {
  17.177 -        vmx_inject_hw_exception(v, vector, error_code);
  17.178 -    }
  17.179 -}
  17.180 -
  17.181  static void vmx_failed_vmentry(unsigned int exit_reason,
  17.182                                 struct cpu_user_regs *regs)
  17.183  {
  17.184 @@ -2919,7 +2846,7 @@ static void vmx_failed_vmentry(unsigned 
  17.185  
  17.186  asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
  17.187  {
  17.188 -    unsigned int exit_reason;
  17.189 +    unsigned int exit_reason, idtv_info;
  17.190      unsigned long exit_qualification, inst_len = 0;
  17.191      struct vcpu *v = current;
  17.192  
  17.193 @@ -2935,6 +2862,30 @@ asmlinkage void vmx_vmexit_handler(struc
  17.194      if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
  17.195          return vmx_failed_vmentry(exit_reason, regs);
  17.196  
  17.197 +    /* Event delivery caused this intercept? Queue for redelivery. */
  17.198 +    idtv_info = __vmread(IDT_VECTORING_INFO);
  17.199 +    if ( unlikely(idtv_info & INTR_INFO_VALID_MASK) )
  17.200 +    {
  17.201 +        if ( hvm_event_needs_reinjection((idtv_info>>8)&7, idtv_info&0xff) )
  17.202 +        {
  17.203 +            /* See SDM 3B 25.7.1.1 and .2 for info about masking resvd bits. */
  17.204 +            __vmwrite(VM_ENTRY_INTR_INFO,
  17.205 +                      idtv_info & ~INTR_INFO_RESVD_BITS_MASK);
  17.206 +            if ( idtv_info & INTR_INFO_DELIVER_CODE_MASK )
  17.207 +                __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE,
  17.208 +                          __vmread(IDT_VECTORING_ERROR_CODE));
  17.209 +        }
  17.210 +
  17.211 +        /*
  17.212 +         * Clear NMI-blocking interruptibility info if an NMI delivery faulted.
  17.213 +         * Re-delivery will re-set it (see SDM 3B 25.7.1.2).
  17.214 +         */
  17.215 +        if ( (idtv_info & INTR_INFO_INTR_TYPE_MASK) == (X86_EVENTTYPE_NMI<<8) )
  17.216 +            __vmwrite(GUEST_INTERRUPTIBILITY_INFO,
  17.217 +                      __vmread(GUEST_INTERRUPTIBILITY_INFO) &
  17.218 +                      ~VMX_INTR_SHADOW_NMI);
  17.219 +    }
  17.220 +
  17.221      switch ( exit_reason )
  17.222      {
  17.223      case EXIT_REASON_EXCEPTION_NMI:
  17.224 @@ -2957,7 +2908,7 @@ asmlinkage void vmx_vmexit_handler(struc
  17.225           * (NB. If we emulate this IRET for any reason, we should re-clear!)
  17.226           */
  17.227          if ( unlikely(intr_info & INTR_INFO_NMI_UNBLOCKED_BY_IRET) &&
  17.228 -             !(__vmread(IDT_VECTORING_INFO_FIELD) & INTR_INFO_VALID_MASK) &&
  17.229 +             !(__vmread(IDT_VECTORING_INFO) & INTR_INFO_VALID_MASK) &&
  17.230               (vector != TRAP_double_fault) )
  17.231              __vmwrite(GUEST_INTERRUPTIBILITY_INFO,
  17.232                      __vmread(GUEST_INTERRUPTIBILITY_INFO)|VMX_INTR_SHADOW_NMI);
  17.233 @@ -2995,14 +2946,12 @@ asmlinkage void vmx_vmexit_handler(struc
  17.234              vmx_inject_hw_exception(v, TRAP_page_fault, regs->error_code);
  17.235              break;
  17.236          case TRAP_nmi:
  17.237 -            if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI )
  17.238 -            {
  17.239 -                HVMTRACE_0D(NMI, v);
  17.240 -                vmx_store_cpu_guest_regs(v, regs, NULL);
  17.241 -                do_nmi(regs); /* Real NMI, vector 2: normal processing. */
  17.242 -            }
  17.243 -            else
  17.244 -                vmx_reflect_exception(v);
  17.245 +            if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) !=
  17.246 +                 (X86_EVENTTYPE_NMI << 8) )
  17.247 +                goto exit_and_crash;
  17.248 +            HVMTRACE_0D(NMI, v);
  17.249 +            vmx_store_cpu_guest_regs(v, regs, NULL);
  17.250 +            do_nmi(regs); /* Real NMI, vector 2: normal processing. */
  17.251              break;
  17.252          case TRAP_machine_check:
  17.253              HVMTRACE_0D(MCE, v);
    18.1 --- a/xen/arch/x86/mm/shadow/multi.c	Mon Jul 30 17:10:45 2007 -0500
    18.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Wed Aug 01 08:59:03 2007 +0100
    18.3 @@ -2905,7 +2905,7 @@ static int sh_page_fault(struct vcpu *v,
    18.4           * stack is currently considered to be a page table, so we should
    18.5           * unshadow the faulting page before exiting.
    18.6           */
    18.7 -        if ( unlikely(hvm_event_injection_faulted(v)) )
    18.8 +        if ( unlikely(hvm_event_pending(v)) )
    18.9          {
   18.10              gdprintk(XENLOG_DEBUG, "write to pagetable during event "
   18.11                       "injection: cr2=%#lx, mfn=%#lx\n", 
    19.1 --- a/xen/drivers/acpi/tables.c	Mon Jul 30 17:10:45 2007 -0500
    19.2 +++ b/xen/drivers/acpi/tables.c	Wed Aug 01 08:59:03 2007 +0100
    19.3 @@ -73,7 +73,6 @@ struct acpi_table_sdt {
    19.4  
    19.5  static unsigned long sdt_pa;	/* Physical Address */
    19.6  static unsigned long sdt_count;	/* Table count */
    19.7 -unsigned char acpi_rsdp_rev;
    19.8  
    19.9  static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata;
   19.10  
   19.11 @@ -227,6 +226,17 @@ void acpi_table_print_madt_entry(acpi_ta
   19.12  	}
   19.13  }
   19.14  
   19.15 +uint8_t
   19.16 +generate_acpi_checksum(void *tbl, unsigned long len)
   19.17 +{
   19.18 +	uint8_t *ptr, sum = 0;
   19.19 +
   19.20 +	for (ptr = tbl; len > 0 ; len--, ptr++)
   19.21 +		sum += *ptr;
   19.22 +
   19.23 +	return 0 - sum;
   19.24 +}
   19.25 +
   19.26  static int
   19.27  acpi_table_compute_checksum(void *table_pointer, unsigned long length)
   19.28  {
   19.29 @@ -599,8 +609,6 @@ int __init acpi_table_init(void)
   19.30  	       "RSDP (v%3.3d %6.6s                                ) @ 0x%p\n",
   19.31  	       rsdp->revision, rsdp->oem_id, (void *)rsdp_phys);
   19.32  
   19.33 -	acpi_rsdp_rev = rsdp->revision;
   19.34 -
   19.35  	if (rsdp->revision < 2)
   19.36  		result =
   19.37  		    acpi_table_compute_checksum(rsdp,
   19.38 @@ -623,3 +631,143 @@ int __init acpi_table_init(void)
   19.39  
   19.40  	return 0;
   19.41  }
   19.42 +
   19.43 +int __init
   19.44 +acpi_table_disable(enum acpi_table_id table_id)
   19.45 +{
   19.46 +	struct acpi_table_header *header = NULL;
   19.47 +	struct acpi_table_rsdp *rsdp;
   19.48 +	unsigned long rsdp_phys;
   19.49 +	char *table_name;
   19.50 +	int id;
   19.51 +
   19.52 +	rsdp_phys = acpi_find_rsdp();
   19.53 +	if (!rsdp_phys)
   19.54 +		return -ENODEV;
   19.55 +
   19.56 +	rsdp = (struct acpi_table_rsdp *)__acpi_map_table(rsdp_phys,
   19.57 +		sizeof(struct acpi_table_rsdp));
   19.58 +	if (!rsdp)
   19.59 +		return -ENODEV;
   19.60 +
   19.61 +	for (id = 0; id < sdt_count; id++)
   19.62 +		if (sdt_entry[id].id == table_id)
   19.63 +			break;
   19.64 +
   19.65 +	if (id == sdt_count)
   19.66 +		return -ENOENT;
   19.67 +
   19.68 +	table_name = acpi_table_signatures[table_id];
   19.69 +
   19.70 +	/* First check XSDT (but only on ACPI 2.0-compatible systems) */
   19.71 +
   19.72 +	if ((rsdp->revision >= 2) &&
   19.73 +	    (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) {
   19.74 +
   19.75 +		struct acpi_table_xsdt *mapped_xsdt = NULL;
   19.76 +
   19.77 +		sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address;
   19.78 +
   19.79 +		/* map in just the header */
   19.80 +		header = (struct acpi_table_header *)
   19.81 +		    __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
   19.82 +
   19.83 +		if (!header) {
   19.84 +			printk(KERN_WARNING PREFIX
   19.85 +			       "Unable to map XSDT header\n");
   19.86 +			return -ENODEV;
   19.87 +		}
   19.88 +
   19.89 +		/* remap in the entire table before processing */
   19.90 +		mapped_xsdt = (struct acpi_table_xsdt *)
   19.91 +		    __acpi_map_table(sdt_pa, header->length);
   19.92 +		if (!mapped_xsdt) {
   19.93 +			printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
   19.94 +			return -ENODEV;
   19.95 +		}
   19.96 +		header = &mapped_xsdt->header;
   19.97 +
   19.98 +		if (strncmp(header->signature, "XSDT", 4)) {
   19.99 +			printk(KERN_WARNING PREFIX
  19.100 +			       "XSDT signature incorrect\n");
  19.101 +			return -ENODEV;
  19.102 +		}
  19.103 +
  19.104 +		if (acpi_table_compute_checksum(header, header->length)) {
  19.105 +			printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n");
  19.106 +			return -ENODEV;
  19.107 +		}
  19.108 +
  19.109 +		if (id < sdt_count) {
  19.110 +			header = (struct acpi_table_header *)
  19.111 +			   __acpi_map_table(mapped_xsdt->entry[id], sizeof(struct acpi_table_header));
  19.112 +		} else {
  19.113 +			printk(KERN_WARNING PREFIX
  19.114 +			       "Unable to disable entry %d\n",
  19.115 +			       id);
  19.116 +			return -ENODEV;
  19.117 +		}
  19.118 +	}
  19.119 +
  19.120 +	/* Then check RSDT */
  19.121 +
  19.122 +	else if (rsdp->rsdt_address) {
  19.123 +
  19.124 +		struct acpi_table_rsdt *mapped_rsdt = NULL;
  19.125 +
  19.126 +		sdt_pa = rsdp->rsdt_address;
  19.127 +
  19.128 +		/* map in just the header */
  19.129 +		header = (struct acpi_table_header *)
  19.130 +		    __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
  19.131 +		if (!header) {
  19.132 +			printk(KERN_WARNING PREFIX
  19.133 +			       "Unable to map RSDT header\n");
  19.134 +			return -ENODEV;
  19.135 +		}
  19.136 +
  19.137 +		/* remap in the entire table before processing */
  19.138 +		mapped_rsdt = (struct acpi_table_rsdt *)
  19.139 +		    __acpi_map_table(sdt_pa, header->length);
  19.140 +		if (!mapped_rsdt) {
  19.141 +			printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
  19.142 +			return -ENODEV;
  19.143 +		}
  19.144 +		header = &mapped_rsdt->header;
  19.145 +
  19.146 +		if (strncmp(header->signature, "RSDT", 4)) {
  19.147 +			printk(KERN_WARNING PREFIX
  19.148 +			       "RSDT signature incorrect\n");
  19.149 +			return -ENODEV;
  19.150 +		}
  19.151 +
  19.152 +		if (acpi_table_compute_checksum(header, header->length)) {
  19.153 +			printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n");
  19.154 +			return -ENODEV;
  19.155 +		}
  19.156 +		if (id < sdt_count) {
  19.157 +			header = (struct acpi_table_header *)
  19.158 +			   __acpi_map_table(mapped_rsdt->entry[id], sizeof(struct acpi_table_header));
  19.159 +		} else {
  19.160 +			printk(KERN_WARNING PREFIX
  19.161 +			       "Unable to disable entry %d\n",
  19.162 +			       id);
  19.163 +			return -ENODEV;
  19.164 +		}
  19.165 +	}
  19.166 +
  19.167 +	else {
  19.168 +		printk(KERN_WARNING PREFIX
  19.169 +		       "No System Description Table (RSDT/XSDT) specified in RSDP\n");
  19.170 +		return -ENODEV;
  19.171 +	}
  19.172 +
  19.173 +	memcpy(header->signature, "OEMx", 4);
  19.174 +	memcpy(header->oem_id, "xxxxxx", 6);
  19.175 +	memcpy(header->oem_id+1, table_name, 4);
  19.176 +	memcpy(header->oem_table_id, "Xen     ", 8);
  19.177 +	header->checksum = 0;
  19.178 +	header->checksum = generate_acpi_checksum(header, header->length);
  19.179 +
  19.180 +	return 0;
  19.181 +}
    20.1 --- a/xen/include/asm-ia64/dom_fw_common.h	Mon Jul 30 17:10:45 2007 -0500
    20.2 +++ b/xen/include/asm-ia64/dom_fw_common.h	Wed Aug 01 08:59:03 2007 +0100
    20.3 @@ -85,7 +85,6 @@ void
    20.4  xen_ia64_efi_make_md(efi_memory_desc_t *md,
    20.5                       uint32_t type, uint64_t attr, 
    20.6                       uint64_t start, uint64_t end);
    20.7 -uint8_t generate_acpi_checksum(void *tbl, unsigned long len);
    20.8  struct fake_acpi_tables;
    20.9  void dom_fw_fake_acpi(domain_t *d, struct fake_acpi_tables *tables);
   20.10  int efi_mdt_cmp(const void *a, const void *b); 
    21.1 --- a/xen/include/asm-x86/hvm/hvm.h	Mon Jul 30 17:10:45 2007 -0500
    21.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Wed Aug 01 08:59:03 2007 +0100
    21.3 @@ -154,7 +154,7 @@ struct hvm_function_table {
    21.4  
    21.5      void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
    21.6  
    21.7 -    int  (*event_injection_faulted)(struct vcpu *v);
    21.8 +    int  (*event_pending)(struct vcpu *v);
    21.9  
   21.10      int  (*cpu_up)(void);
   21.11      void (*cpu_down)(void);
   21.12 @@ -229,7 +229,8 @@ hvm_guest_x86_mode(struct vcpu *v)
   21.13      return hvm_funcs.guest_x86_mode(v);
   21.14  }
   21.15  
   21.16 -int hvm_instruction_length(unsigned long pc, int address_bytes);
   21.17 +int hvm_instruction_fetch(unsigned long pc, int address_bytes,
   21.18 +                          unsigned char *buf);
   21.19  
   21.20  static inline void
   21.21  hvm_update_host_cr3(struct vcpu *v)
   21.22 @@ -295,25 +296,72 @@ hvm_inject_exception(unsigned int trapnr
   21.23  
   21.24  int hvm_bringup_ap(int vcpuid, int trampoline_vector);
   21.25  
   21.26 -static inline int hvm_event_injection_faulted(struct vcpu *v)
   21.27 +static inline int hvm_event_pending(struct vcpu *v)
   21.28  {
   21.29 -    return hvm_funcs.event_injection_faulted(v);
   21.30 +    return hvm_funcs.event_pending(v);
   21.31  }
   21.32  
   21.33 +/* These reserved bits in lower 32 remain 0 after any load of CR0 */
   21.34 +#define HVM_CR0_GUEST_RESERVED_BITS             \
   21.35 +    (~((unsigned long)                          \
   21.36 +       (X86_CR0_PE | X86_CR0_MP | X86_CR0_EM |  \
   21.37 +        X86_CR0_TS | X86_CR0_ET | X86_CR0_NE |  \
   21.38 +        X86_CR0_WP | X86_CR0_AM | X86_CR0_NW |  \
   21.39 +        X86_CR0_CD | X86_CR0_PG)))
   21.40 +
   21.41  /* These bits in CR4 are owned by the host. */
   21.42  #define HVM_CR4_HOST_MASK (mmu_cr4_features & \
   21.43      (X86_CR4_VMXE | X86_CR4_PAE | X86_CR4_MCE))
   21.44  
   21.45  /* These bits in CR4 cannot be set by the guest. */
   21.46 -#define HVM_CR4_GUEST_RESERVED_BITS \
   21.47 -    ~(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | \
   21.48 -      X86_CR4_DE  | X86_CR4_PSE | X86_CR4_PAE | \
   21.49 -      X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE | \
   21.50 -      X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT)
   21.51 +#define HVM_CR4_GUEST_RESERVED_BITS                     \
   21.52 +    (~((unsigned long)                                  \
   21.53 +       (X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD |       \
   21.54 +        X86_CR4_DE  | X86_CR4_PSE | X86_CR4_PAE |       \
   21.55 +        X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE |       \
   21.56 +        X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT)))
   21.57  
   21.58  /* These exceptions must always be intercepted. */
   21.59  #define HVM_TRAP_MASK (1U << TRAP_machine_check)
   21.60  
   21.61 +/*
   21.62 + * x86 event types. This enumeration is valid for:
   21.63 + *  Intel VMX: {VM_ENTRY,VM_EXIT,IDT_VECTORING}_INTR_INFO[10:8]
   21.64 + *  AMD SVM: eventinj[10:8] and exitintinfo[10:8] (types 0-4 only)
   21.65 + */
   21.66 +#define X86_EVENTTYPE_EXT_INTR              0    /* external interrupt */
   21.67 +#define X86_EVENTTYPE_NMI                   2    /* NMI                */
   21.68 +#define X86_EVENTTYPE_HW_EXCEPTION          3    /* hardware exception */
   21.69 +#define X86_EVENTTYPE_SW_INTERRUPT          4    /* software interrupt */
   21.70 +#define X86_EVENTTYPE_SW_EXCEPTION          6    /* software exception */
   21.71 +
   21.72 +/*
   21.73 + * Need to re-inject a given event? We avoid re-injecting software exceptions
   21.74 + * and interrupts because the faulting/trapping instruction can simply be
   21.75 + * re-executed (neither VMX nor SVM update RIP when they VMEXIT during
   21.76 + * INT3/INTO/INTn).
   21.77 + */
   21.78 +static inline int hvm_event_needs_reinjection(uint8_t type, uint8_t vector)
   21.79 +{
   21.80 +    switch ( type )
   21.81 +    {
   21.82 +    case X86_EVENTTYPE_EXT_INTR:
   21.83 +    case X86_EVENTTYPE_NMI:
   21.84 +        return 1;
   21.85 +    case X86_EVENTTYPE_HW_EXCEPTION:
   21.86 +        /*
   21.87 +         * SVM uses type 3 ("HW Exception") for #OF and #BP. We explicitly
   21.88 +         * check for these vectors, as they are really SW Exceptions. SVM has
   21.89 +         * not updated RIP to point after the trapping instruction (INT3/INTO).
   21.90 +         */
   21.91 +        return (vector != 3) && (vector != 4);
   21.92 +    default:
   21.93 +        /* Software exceptions/interrupts can be re-executed (e.g., INT n). */
   21.94 +        break;
   21.95 +    }
   21.96 +    return 0;
   21.97 +}
   21.98 +
   21.99  static inline int hvm_cpu_up(void)
  21.100  {
  21.101      if ( hvm_funcs.cpu_up )
    22.1 --- a/xen/include/asm-x86/hvm/svm/vmcb.h	Mon Jul 30 17:10:45 2007 -0500
    22.2 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h	Wed Aug 01 08:59:03 2007 +0100
    22.3 @@ -320,14 +320,6 @@ typedef union
    22.4      } fields;
    22.5  } __attribute__ ((packed)) eventinj_t;
    22.6  
    22.7 -enum EVENTTYPES
    22.8 -{
    22.9 -    EVENTTYPE_INTR = 0,
   22.10 -    EVENTTYPE_NMI = 2,
   22.11 -    EVENTTYPE_EXCEPTION = 3,
   22.12 -    EVENTTYPE_SWINT = 4,
   22.13 -};
   22.14 -
   22.15  typedef union 
   22.16  {
   22.17      u64 bytes;
    23.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Mon Jul 30 17:10:45 2007 -0500
    23.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Wed Aug 01 08:59:03 2007 +0100
    23.3 @@ -67,9 +67,6 @@ struct arch_vmx_struct {
    23.4      /* Cache of cpu execution control. */
    23.5      u32                  exec_control;
    23.6  
    23.7 -    /* If there is vector installed in the INTR_INFO_FIELD. */
    23.8 -    u32                  vector_injected;
    23.9 -
   23.10      unsigned long        cpu_cr0; /* copy of guest CR0 */
   23.11      unsigned long        cpu_shadow_cr0; /* copy of guest read shadow CR0 */
   23.12      unsigned long        cpu_shadow_cr4; /* copy of guest read shadow CR4 */
   23.13 @@ -198,7 +195,7 @@ enum vmcs_field {
   23.14      VM_EXIT_MSR_LOAD_COUNT          = 0x00004010,
   23.15      VM_ENTRY_CONTROLS               = 0x00004012,
   23.16      VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
   23.17 -    VM_ENTRY_INTR_INFO_FIELD        = 0x00004016,
   23.18 +    VM_ENTRY_INTR_INFO              = 0x00004016,
   23.19      VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
   23.20      VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
   23.21      TPR_THRESHOLD                   = 0x0000401c,
   23.22 @@ -207,7 +204,7 @@ enum vmcs_field {
   23.23      VM_EXIT_REASON                  = 0x00004402,
   23.24      VM_EXIT_INTR_INFO               = 0x00004404,
   23.25      VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
   23.26 -    IDT_VECTORING_INFO_FIELD        = 0x00004408,
   23.27 +    IDT_VECTORING_INFO              = 0x00004408,
   23.28      IDT_VECTORING_ERROR_CODE        = 0x0000440a,
   23.29      VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
   23.30      VMX_INSTRUCTION_INFO            = 0x0000440e,
    24.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Mon Jul 30 17:10:45 2007 -0500
    24.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Wed Aug 01 08:59:03 2007 +0100
    24.3 @@ -94,11 +94,6 @@ void vmx_vlapic_msr_changed(struct vcpu 
    24.4  #define INTR_INFO_VALID_MASK            0x80000000      /* 31 */
    24.5  #define INTR_INFO_RESVD_BITS_MASK       0x7ffff000
    24.6  
    24.7 -#define INTR_TYPE_EXT_INTR              (0 << 8)    /* external interrupt */
    24.8 -#define INTR_TYPE_NMI                   (2 << 8)    /* NMI                */
    24.9 -#define INTR_TYPE_HW_EXCEPTION          (3 << 8)    /* hardware exception */
   24.10 -#define INTR_TYPE_SW_EXCEPTION          (6 << 8)    /* software exception */
   24.11 -
   24.12  /*
   24.13   * Exit Qualifications for MOV for Control Register Access
   24.14   */
   24.15 @@ -263,8 +258,8 @@ static inline int __vmxon (u64 addr)
   24.16      return rc;
   24.17  }
   24.18  
   24.19 -static inline void __vmx_inject_exception(struct vcpu *v, int trap, int type,
   24.20 -                                         int error_code, int ilen)
   24.21 +static inline void __vmx_inject_exception(
   24.22 +    struct vcpu *v, int trap, int type, int error_code)
   24.23  {
   24.24      unsigned long intr_fields;
   24.25  
   24.26 @@ -276,16 +271,13 @@ static inline void __vmx_inject_exceptio
   24.27       *   VM entry]", PRM Vol. 3, 22.6.1 (Interruptibility State).
   24.28       */
   24.29  
   24.30 -    intr_fields = (INTR_INFO_VALID_MASK | type | trap);
   24.31 +    intr_fields = (INTR_INFO_VALID_MASK | (type<<8) | trap);
   24.32      if ( error_code != VMX_DELIVER_NO_ERROR_CODE ) {
   24.33          __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
   24.34          intr_fields |= INTR_INFO_DELIVER_CODE_MASK;
   24.35      }
   24.36  
   24.37 -    if ( ilen )
   24.38 -      __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen);
   24.39 -
   24.40 -    __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
   24.41 +    __vmwrite(VM_ENTRY_INTR_INFO, intr_fields);
   24.42  
   24.43      if (trap == TRAP_page_fault)
   24.44          HVMTRACE_2D(PF_INJECT, v, v->arch.hvm_vmx.cpu_cr2, error_code);
   24.45 @@ -296,29 +288,19 @@ static inline void __vmx_inject_exceptio
   24.46  static inline void vmx_inject_hw_exception(
   24.47      struct vcpu *v, int trap, int error_code)
   24.48  {
   24.49 -    v->arch.hvm_vmx.vector_injected = 1;
   24.50 -    __vmx_inject_exception(v, trap, INTR_TYPE_HW_EXCEPTION, error_code, 0);
   24.51 -}
   24.52 -
   24.53 -static inline void vmx_inject_sw_exception(
   24.54 -    struct vcpu *v, int trap, int instruction_len)
   24.55 -{
   24.56 -    v->arch.hvm_vmx.vector_injected = 1;
   24.57 -    __vmx_inject_exception(v, trap, INTR_TYPE_SW_EXCEPTION,
   24.58 -                           VMX_DELIVER_NO_ERROR_CODE,
   24.59 -                           instruction_len);
   24.60 +    __vmx_inject_exception(v, trap, X86_EVENTTYPE_HW_EXCEPTION, error_code);
   24.61  }
   24.62  
   24.63  static inline void vmx_inject_extint(struct vcpu *v, int trap)
   24.64  {
   24.65 -    __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR,
   24.66 -                           VMX_DELIVER_NO_ERROR_CODE, 0);
   24.67 +    __vmx_inject_exception(v, trap, X86_EVENTTYPE_EXT_INTR,
   24.68 +                           VMX_DELIVER_NO_ERROR_CODE);
   24.69  }
   24.70  
   24.71  static inline void vmx_inject_nmi(struct vcpu *v)
   24.72  {
   24.73 -    __vmx_inject_exception(v, 2, INTR_TYPE_NMI,
   24.74 -                           VMX_DELIVER_NO_ERROR_CODE, 0);
   24.75 +    __vmx_inject_exception(v, 2, X86_EVENTTYPE_NMI,
   24.76 +                           VMX_DELIVER_NO_ERROR_CODE);
   24.77  }
   24.78  
   24.79  #endif /* __ASM_X86_HVM_VMX_VMX_H__ */
    25.1 --- a/xen/include/xen/acpi.h	Mon Jul 30 17:10:45 2007 -0500
    25.2 +++ b/xen/include/xen/acpi.h	Wed Aug 01 08:59:03 2007 +0100
    25.3 @@ -383,6 +383,7 @@ int acpi_boot_table_init (void);
    25.4  int acpi_numa_init (void);
    25.5  
    25.6  int acpi_table_init (void);
    25.7 +int acpi_table_disable(enum acpi_table_id table_id);
    25.8  int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler);
    25.9  int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header);
   25.10  int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
   25.11 @@ -390,6 +391,7 @@ int acpi_table_parse_srat (enum acpi_sra
   25.12  void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr);
   25.13  void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
   25.14  void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
   25.15 +uint8_t generate_acpi_checksum(void *tbl, unsigned long len);
   25.16  
   25.17  /* the following four functions are architecture-dependent */
   25.18  void acpi_numa_slit_init (struct acpi_table_slit *slit);
   25.19 @@ -534,6 +536,5 @@ static inline int acpi_get_pxm(acpi_hand
   25.20  #endif
   25.21  
   25.22  extern int pnpacpi_disabled;
   25.23 -extern unsigned char acpi_rsdp_rev;
   25.24  
   25.25  #endif /*_LINUX_ACPI_H*/