ia64/xen-unstable

changeset 16802:2633dc4f55d4

vt-d: Clean up and bug fixes to ioapic handling.
Signed-off-by: Allen Kay <allen.m.kay@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 18 13:41:33 2008 +0000 (2008-01-18)
parents 4a6282589b90
children 62fc84adc8ed
files xen/arch/x86/hvm/vmx/vtd/dmar.c xen/arch/x86/hvm/vmx/vtd/dmar.h xen/arch/x86/hvm/vmx/vtd/utils.c xen/include/asm-x86/hvm/vmx/intel-iommu.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vtd/dmar.c	Fri Jan 18 13:40:22 2008 +0000
     1.2 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c	Fri Jan 18 13:41:33 2008 +0000
     1.3 @@ -43,7 +43,6 @@ boolean_param("vtd", vtd_enabled);
     1.4  LIST_HEAD(acpi_drhd_units);
     1.5  LIST_HEAD(acpi_rmrr_units);
     1.6  LIST_HEAD(acpi_atsr_units);
     1.7 -LIST_HEAD(acpi_ioapic_units);
     1.8  
     1.9  u8 dmar_host_address_width;
    1.10  
    1.11 @@ -66,6 +65,47 @@ static int __init acpi_register_rmrr_uni
    1.12      return 0;
    1.13  }
    1.14  
    1.15 +static int acpi_ioapic_device_match(
    1.16 +    struct list_head *ioapic_list, unsigned int apic_id)
    1.17 +{
    1.18 +    struct acpi_ioapic_unit *ioapic;
    1.19 +    list_for_each_entry( ioapic, ioapic_list, list ) {
    1.20 +        if (ioapic->apic_id == apic_id)
    1.21 +            return 1;
    1.22 +    }
    1.23 +    return 0;
    1.24 +}
    1.25 +
    1.26 +struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id)
    1.27 +{
    1.28 +    struct acpi_drhd_unit *drhd;
    1.29 +    list_for_each_entry( drhd, &acpi_drhd_units, list ) {
    1.30 +        if ( acpi_ioapic_device_match(&drhd->ioapic_list, apic_id) ) {
    1.31 +            dprintk(XENLOG_INFO VTDPREFIX,
    1.32 +                    "ioapic_to_drhd: drhd->address = %lx\n",
    1.33 +                    drhd->address);
    1.34 +            return drhd;
    1.35 +        }
    1.36 +    }
    1.37 +    return NULL;
    1.38 +}
    1.39 +
    1.40 +struct iommu * ioapic_to_iommu(unsigned int apic_id)
    1.41 +{
    1.42 +    struct acpi_drhd_unit *drhd;
    1.43 +
    1.44 +    list_for_each_entry( drhd, &acpi_drhd_units, list ) {
    1.45 +        if ( acpi_ioapic_device_match(&drhd->ioapic_list, apic_id) ) {
    1.46 +            dprintk(XENLOG_INFO VTDPREFIX,
    1.47 +                    "ioapic_to_iommu: drhd->address = %lx\n",
    1.48 +                    drhd->address);
    1.49 +            return drhd->iommu;
    1.50 +        }
    1.51 +    }
    1.52 +    dprintk(XENLOG_WARNING VTDPREFIX, "returning NULL\n");
    1.53 +    return NULL;
    1.54 +}
    1.55 +
    1.56  static int acpi_pci_device_match(struct pci_dev *devices, int cnt,
    1.57                                   struct pci_dev *dev)
    1.58  {
    1.59 @@ -111,18 +151,18 @@ struct acpi_drhd_unit * acpi_find_matche
    1.60          if ( acpi_pci_device_match(drhd->devices,
    1.61                                     drhd->devices_cnt, dev) )
    1.62          {
    1.63 -            gdprintk(XENLOG_INFO VTDPREFIX, 
    1.64 -                     "acpi_find_matched_drhd_unit: drhd->address = %lx\n",
    1.65 -                     drhd->address);
    1.66 +            dprintk(XENLOG_INFO VTDPREFIX, 
    1.67 +                    "acpi_find_matched_drhd_unit: drhd->address = %lx\n",
    1.68 +                    drhd->address);
    1.69              return drhd;
    1.70          }
    1.71      }
    1.72  
    1.73      if ( include_all_drhd )
    1.74      {
    1.75 -        gdprintk(XENLOG_INFO VTDPREFIX, 
    1.76 -                 "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
    1.77 -                 include_all_drhd->address);
    1.78 +        dprintk(XENLOG_INFO VTDPREFIX, 
    1.79 +                "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
    1.80 +                include_all_drhd->address);
    1.81          return include_all_drhd;
    1.82      }
    1.83  
    1.84 @@ -160,8 +200,8 @@ struct acpi_atsr_unit * acpi_find_matche
    1.85  
    1.86      if ( all_ports_atsru )
    1.87      {
    1.88 -        gdprintk(XENLOG_INFO VTDPREFIX,
    1.89 -                 "acpi_find_matched_atsr_unit: all_ports_atsru\n");
    1.90 +        dprintk(XENLOG_INFO VTDPREFIX,
    1.91 +                "acpi_find_matched_atsr_unit: all_ports_atsru\n");
    1.92          return all_ports_atsru;;
    1.93      }
    1.94  
    1.95 @@ -180,9 +220,10 @@ static int scope_device_count(void *star
    1.96      while ( start < end )
    1.97      {
    1.98          scope = start;
    1.99 -        if ( scope->length < MIN_SCOPE_LEN )
   1.100 +        if ( (scope->length < MIN_SCOPE_LEN) ||
   1.101 +             (scope->dev_type >= ACPI_DEV_ENTRY_COUNT) )
   1.102          {
   1.103 -            printk(KERN_WARNING PREFIX "Invalid device scope\n");
   1.104 +            dprintk(XENLOG_WARNING VTDPREFIX, "Invalid device scope\n");
   1.105              return -EINVAL;
   1.106          }
   1.107  
   1.108 @@ -199,16 +240,16 @@ static int scope_device_count(void *star
   1.109  
   1.110          if ( scope->dev_type == ACPI_DEV_ENDPOINT )
   1.111          {
   1.112 -            printk(KERN_INFO PREFIX
   1.113 -                   "found endpoint: bdf = %x:%x:%x\n",
   1.114 -                   bus, path->dev, path->fn);
   1.115 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.116 +                    "found endpoint: bdf = %x:%x:%x\n",
   1.117 +                    bus, path->dev, path->fn);
   1.118              count++;
   1.119          }
   1.120          else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
   1.121          {
   1.122 -            printk(KERN_INFO PREFIX
   1.123 -                   "found bridge: bdf = %x:%x:%x\n",
   1.124 -                   bus, path->dev, path->fn);
   1.125 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.126 +                    "found bridge: bdf = %x:%x:%x\n",
   1.127 +                    bus, path->dev, path->fn);
   1.128              sec_bus = read_pci_config_byte(
   1.129                  bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.130              sub_bus = read_pci_config_byte(
   1.131 @@ -237,16 +278,16 @@ static int scope_device_count(void *star
   1.132          }
   1.133          else if ( scope->dev_type == ACPI_DEV_IOAPIC )
   1.134          {
   1.135 -            printk(KERN_INFO PREFIX
   1.136 -                   "found IOAPIC: bdf = %x:%x:%x\n",
   1.137 -                   bus, path->dev, path->fn);
   1.138 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.139 +                    "found IOAPIC: bdf = %x:%x:%x\n",
   1.140 +                    bus, path->dev, path->fn);
   1.141              count++;
   1.142          }
   1.143          else
   1.144          {
   1.145 -            printk(KERN_INFO PREFIX
   1.146 -                   "found MSI HPET: bdf = %x:%x:%x\n",
   1.147 -                   bus, path->dev, path->fn);
   1.148 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.149 +                    "found MSI HPET: bdf = %x:%x:%x\n",
   1.150 +                    bus, path->dev, path->fn);
   1.151              count++;
   1.152          }
   1.153  
   1.154 @@ -256,8 +297,8 @@ static int scope_device_count(void *star
   1.155      return count;
   1.156  }
   1.157  
   1.158 -static int __init acpi_parse_dev_scope(void *start, void *end, int *cnt,
   1.159 -                                       struct pci_dev **devices)
   1.160 +static int __init acpi_parse_dev_scope(
   1.161 +    void *start, void *end, void *acpi_entry, int type)
   1.162  {
   1.163      struct acpi_dev_scope *scope;
   1.164      u8 bus, sub_bus, sec_bus;
   1.165 @@ -268,10 +309,33 @@ static int __init acpi_parse_dev_scope(v
   1.166      u8 dev, func;
   1.167      u32 l;
   1.168  
   1.169 +    int *cnt = NULL;
   1.170 +    struct pci_dev **devices = NULL;
   1.171 +    struct acpi_drhd_unit *dmaru = (struct acpi_drhd_unit *) acpi_entry;
   1.172 +    struct acpi_rmrr_unit *rmrru = (struct acpi_rmrr_unit *) acpi_entry;
   1.173 +    struct acpi_atsr_unit *atsru = (struct acpi_atsr_unit *) acpi_entry;
   1.174 +
   1.175 +    switch (type) {
   1.176 +        case DMAR_TYPE:
   1.177 +            cnt = &(dmaru->devices_cnt);
   1.178 +            devices = &(dmaru->devices);
   1.179 +            break;
   1.180 +        case RMRR_TYPE:
   1.181 +            cnt = &(rmrru->devices_cnt);
   1.182 +            devices = &(rmrru->devices);
   1.183 +            break;
   1.184 +        case ATSR_TYPE:
   1.185 +            cnt = &(atsru->devices_cnt);
   1.186 +            devices = &(atsru->devices);
   1.187 +            break;
   1.188 +        default:
   1.189 +            dprintk(XENLOG_ERR VTDPREFIX, "invalid vt-d acpi entry type\n");
   1.190 +    }
   1.191 +
   1.192      *cnt = scope_device_count(start, end);
   1.193      if ( *cnt == 0 )
   1.194      {
   1.195 -        printk(KERN_INFO PREFIX "acpi_parse_dev_scope: no device\n");
   1.196 +        dprintk(XENLOG_INFO VTDPREFIX, "acpi_parse_dev_scope: no device\n");
   1.197          return 0;
   1.198      }
   1.199  
   1.200 @@ -298,18 +362,18 @@ static int __init acpi_parse_dev_scope(v
   1.201  
   1.202          if ( scope->dev_type == ACPI_DEV_ENDPOINT )
   1.203          {
   1.204 -            printk(KERN_INFO PREFIX
   1.205 -                   "found endpoint: bdf = %x:%x:%x\n",
   1.206 -                   bus, path->dev, path->fn);
   1.207 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.208 +                    "found endpoint: bdf = %x:%x:%x\n",
   1.209 +                    bus, path->dev, path->fn);
   1.210              pdev->bus = bus;
   1.211              pdev->devfn = PCI_DEVFN(path->dev, path->fn);
   1.212              pdev++;
   1.213          }
   1.214          else if ( scope->dev_type == ACPI_DEV_P2PBRIDGE )
   1.215          {
   1.216 -            printk(KERN_INFO PREFIX
   1.217 -                   "found bridge: bus = %x dev = %x func = %x\n",
   1.218 -                   bus, path->dev, path->fn);
   1.219 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.220 +                    "found bridge: bus = %x dev = %x func = %x\n",
   1.221 +                    bus, path->dev, path->fn);
   1.222              sec_bus = read_pci_config_byte(
   1.223                  bus, path->dev, path->fn, PCI_SECONDARY_BUS);
   1.224              sub_bus = read_pci_config_byte(
   1.225 @@ -348,16 +412,15 @@ static int __init acpi_parse_dev_scope(v
   1.226              acpi_ioapic_unit->ioapic.bdf.bus = bus;
   1.227              acpi_ioapic_unit->ioapic.bdf.dev = path->dev;
   1.228              acpi_ioapic_unit->ioapic.bdf.func = path->fn;
   1.229 -            list_add(&acpi_ioapic_unit->list, &acpi_ioapic_units);
   1.230 -            printk(KERN_INFO PREFIX
   1.231 -                   "found IOAPIC: bus = %x dev = %x func = %x\n",
   1.232 -                   bus, path->dev, path->fn);
   1.233 +            list_add(&acpi_ioapic_unit->list, &dmaru->ioapic_list);
   1.234 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.235 +                    "found IOAPIC: bus = %x dev = %x func = %x\n",
   1.236 +                    bus, path->dev, path->fn);
   1.237          }
   1.238          else
   1.239 -            printk(KERN_INFO PREFIX
   1.240 -                   "found MSI HPET: bus = %x dev = %x func = %x\n",
   1.241 -                   bus, path->dev, path->fn);
   1.242 -        
   1.243 +            dprintk(XENLOG_INFO VTDPREFIX,
   1.244 +                    "found MSI HPET: bus = %x dev = %x func = %x\n",
   1.245 +                    bus, path->dev, path->fn);
   1.246          start += scope->length;
   1.247      }
   1.248  
   1.249 @@ -371,6 +434,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
   1.250      struct acpi_drhd_unit *dmaru;
   1.251      int ret = 0;
   1.252      static int include_all;
   1.253 +    void *dev_scope_start, *dev_scope_end;
   1.254  
   1.255      dmaru = xmalloc(struct acpi_drhd_unit);
   1.256      if ( !dmaru )
   1.257 @@ -379,21 +443,22 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
   1.258  
   1.259      dmaru->address = drhd->address;
   1.260      dmaru->include_all = drhd->flags & 1; /* BIT0: INCLUDE_ALL */
   1.261 -    printk(KERN_INFO PREFIX "dmaru->address = %lx\n", dmaru->address);
   1.262 +    INIT_LIST_HEAD(&dmaru->ioapic_list);
   1.263 +    dprintk(XENLOG_INFO VTDPREFIX, "dmaru->address = %lx\n", dmaru->address);
   1.264  
   1.265 -    if ( !dmaru->include_all )
   1.266 -        ret = acpi_parse_dev_scope(
   1.267 -            (void *)(drhd + 1),
   1.268 -            ((void *)drhd) + header->length,
   1.269 -            &dmaru->devices_cnt, &dmaru->devices);
   1.270 -    else
   1.271 +    dev_scope_start = (void *)(drhd + 1);
   1.272 +    dev_scope_end   = ((void *)drhd) + header->length;
   1.273 +    ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
   1.274 +                               dmaru, DMAR_TYPE);
   1.275 +
   1.276 +    if ( dmaru->include_all )
   1.277      {
   1.278 -        printk(KERN_INFO PREFIX "found INCLUDE_ALL\n");
   1.279 +        dprintk(XENLOG_INFO VTDPREFIX, "found INCLUDE_ALL\n");
   1.280          /* Only allow one INCLUDE_ALL */
   1.281          if ( include_all )
   1.282          {
   1.283 -            printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
   1.284 -                   "device scope is allowed\n");
   1.285 +            dprintk(XENLOG_WARNING VTDPREFIX,
   1.286 +                    "Only one INCLUDE_ALL device scope is allowed\n");
   1.287              ret = -EINVAL;
   1.288          }
   1.289          include_all = 1;
   1.290 @@ -411,6 +476,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
   1.291  {
   1.292      struct acpi_table_rmrr *rmrr = (struct acpi_table_rmrr *)header;
   1.293      struct acpi_rmrr_unit *rmrru;
   1.294 +    void *dev_scope_start, *dev_scope_end;
   1.295      int ret = 0;
   1.296  
   1.297      rmrru = xmalloc(struct acpi_rmrr_unit);
   1.298 @@ -420,15 +486,10 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
   1.299  
   1.300      rmrru->base_address = rmrr->base_address;
   1.301      rmrru->end_address = rmrr->end_address;
   1.302 -    printk(KERN_INFO PREFIX
   1.303 -           "acpi_parse_one_rmrr: base=%"PRIx64" end=%"PRIx64"\n",
   1.304 -           rmrr->base_address, rmrr->end_address);
   1.305 -
   1.306 -    ret = acpi_parse_dev_scope(
   1.307 -        (void *)(rmrr + 1),
   1.308 -        ((void*)rmrr) + header->length,
   1.309 -        &rmrru->devices_cnt, &rmrru->devices);
   1.310 -
   1.311 +    dev_scope_start = (void *)(rmrr + 1);
   1.312 +    dev_scope_end   = ((void *)rmrr) + header->length;
   1.313 +    ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
   1.314 +                               rmrru, RMRR_TYPE);
   1.315      if ( ret || (rmrru->devices_cnt == 0) )
   1.316          xfree(rmrru);
   1.317      else
   1.318 @@ -443,6 +504,7 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
   1.319      struct acpi_atsr_unit *atsru;
   1.320      int ret = 0;
   1.321      static int all_ports;
   1.322 +    void *dev_scope_start, *dev_scope_end;
   1.323  
   1.324      atsru = xmalloc(struct acpi_atsr_unit);
   1.325      if ( !atsru )
   1.326 @@ -451,18 +513,19 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
   1.327  
   1.328      atsru->all_ports = atsr->flags & 1; /* BIT0: ALL_PORTS */
   1.329      if ( !atsru->all_ports )
   1.330 -        ret = acpi_parse_dev_scope(
   1.331 -            (void *)(atsr + 1),
   1.332 -            ((void *)atsr) + header->length,
   1.333 -            &atsru->devices_cnt, &atsru->devices);
   1.334 -    else
   1.335      {
   1.336 -        printk(KERN_INFO PREFIX "found ALL_PORTS\n");
   1.337 +        dev_scope_start = (void *)(atsr + 1);
   1.338 +        dev_scope_end   = ((void *)atsr) + header->length;
   1.339 +        ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
   1.340 +                                   atsru, ATSR_TYPE);
   1.341 +    }
   1.342 +    else {
   1.343 +        dprintk(XENLOG_INFO VTDPREFIX, "found ALL_PORTS\n");
   1.344          /* Only allow one ALL_PORTS */
   1.345          if ( all_ports )
   1.346          {
   1.347 -            printk(KERN_WARNING PREFIX "Only one ALL_PORTS "
   1.348 -                   "device scope is allowed\n");
   1.349 +            dprintk(XENLOG_WARNING VTDPREFIX,
   1.350 +                    "Only one ALL_PORTS device scope is allowed\n");
   1.351              ret = -EINVAL;
   1.352          }
   1.353          all_ports = 1;
   1.354 @@ -488,19 +551,19 @@ static int __init acpi_parse_dmar(unsign
   1.355      dmar = (struct acpi_table_dmar *)__acpi_map_table(phys_addr, size);
   1.356      if ( !dmar )
   1.357      {
   1.358 -        printk(KERN_WARNING PREFIX "Unable to map DMAR\n");
   1.359 +        dprintk(XENLOG_WARNING VTDPREFIX, "Unable to map DMAR\n");
   1.360          return -ENODEV;
   1.361      }
   1.362  
   1.363      if ( !dmar->haw )
   1.364      {
   1.365 -        printk(KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
   1.366 +        dprintk(XENLOG_WARNING VTDPREFIX, "Zero: Invalid DMAR haw\n");
   1.367          return -EINVAL;
   1.368      }
   1.369  
   1.370      dmar_host_address_width = dmar->haw;
   1.371 -    printk(KERN_INFO PREFIX "Host address width %d\n",
   1.372 -           dmar_host_address_width);
   1.373 +    dprintk(XENLOG_INFO VTDPREFIX, "Host address width %d\n",
   1.374 +            dmar_host_address_width);
   1.375  
   1.376      entry_header = (struct acpi_dmar_entry_header *)(dmar + 1);
   1.377      while ( ((unsigned long)entry_header) <
   1.378 @@ -509,19 +572,19 @@ static int __init acpi_parse_dmar(unsign
   1.379          switch ( entry_header->type )
   1.380          {
   1.381          case ACPI_DMAR_DRHD:
   1.382 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_DRHD\n");
   1.383 +            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_DRHD\n");
   1.384              ret = acpi_parse_one_drhd(entry_header);
   1.385              break;
   1.386          case ACPI_DMAR_RMRR:
   1.387 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_RMRR\n");
   1.388 +            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_RMRR\n");
   1.389              ret = acpi_parse_one_rmrr(entry_header);
   1.390              break;
   1.391          case ACPI_DMAR_ATSR:
   1.392 -            printk(KERN_INFO PREFIX "found ACPI_DMAR_ATSR\n");
   1.393 +            dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_ATSR\n");
   1.394              ret = acpi_parse_one_atsr(entry_header);
   1.395              break;
   1.396          default:
   1.397 -            printk(KERN_WARNING PREFIX "Unknown DMAR structure type\n");
   1.398 +            dprintk(XENLOG_WARNING VTDPREFIX, "Unknown DMAR structure type\n");
   1.399              ret = -EINVAL;
   1.400              break;
   1.401          }
   1.402 @@ -551,7 +614,7 @@ int acpi_dmar_init(void)
   1.403  
   1.404      if ( list_empty(&acpi_drhd_units) )
   1.405      {
   1.406 -        printk(KERN_ERR PREFIX "No DMAR devices found\n");
   1.407 +        dprintk(XENLOG_ERR VTDPREFIX, "No DMAR devices found\n");
   1.408          vtd_enabled = 0;
   1.409          return -ENODEV;
   1.410      }
     2.1 --- a/xen/arch/x86/hvm/vmx/vtd/dmar.h	Fri Jan 18 13:40:22 2008 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.h	Fri Jan 18 13:41:33 2008 +0000
     2.3 @@ -26,6 +26,20 @@
     2.4  
     2.5  extern u8 dmar_host_address_width;
     2.6  
     2.7 +/* This one is for interrupt remapping */
     2.8 +struct acpi_ioapic_unit {
     2.9 +    struct list_head list;
    2.10 +    int apic_id;
    2.11 +    union {
    2.12 +        u16 info;
    2.13 +        struct {
    2.14 +            u16 func: 3,
    2.15 +                dev:  5,
    2.16 +                bus:  8;
    2.17 +        }bdf;
    2.18 +    }ioapic;
    2.19 +};
    2.20 +
    2.21  struct acpi_drhd_unit {
    2.22      struct list_head list;
    2.23      unsigned long    address; /* register base address of the unit */
    2.24 @@ -33,6 +47,7 @@ struct acpi_drhd_unit {
    2.25      int    devices_cnt;
    2.26      u8    include_all:1;
    2.27      struct iommu *iommu;
    2.28 +    struct list_head ioapic_list;
    2.29  };
    2.30  
    2.31  struct acpi_rmrr_unit {
    2.32 @@ -73,19 +88,9 @@ struct acpi_atsr_unit {
    2.33  struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev);
    2.34  struct acpi_rmrr_unit * acpi_find_matched_rmrr_unit(struct pci_dev *dev);
    2.35  
    2.36 -/* This one is for interrupt remapping */
    2.37 -struct acpi_ioapic_unit {
    2.38 -    struct list_head list;
    2.39 -    int apic_id;
    2.40 -    union {
    2.41 -        u16 info;
    2.42 -        struct {
    2.43 -            u16 bus: 8,
    2.44 -                dev: 5,
    2.45 -                func: 3;
    2.46 -        }bdf;
    2.47 -    }ioapic;
    2.48 -};
    2.49 +#define DMAR_TYPE 1
    2.50 +#define RMRR_TYPE 2
    2.51 +#define ATSR_TYPE 3
    2.52  
    2.53  #define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */
    2.54  #define time_after(a,b)         \
     3.1 --- a/xen/arch/x86/hvm/vmx/vtd/utils.c	Fri Jan 18 13:40:22 2008 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/vtd/utils.c	Fri Jan 18 13:41:33 2008 +0000
     3.3 @@ -146,12 +146,14 @@ u32 get_level_index(unsigned long gmfn, 
     3.4      return gmfn & LEVEL_MASK;
     3.5  }
     3.6  
     3.7 -void print_vtd_entries(struct domain *d, int bus, int devfn,
     3.8 -                       unsigned long gmfn)
     3.9 +void print_vtd_entries(
    3.10 +    struct domain *d, 
    3.11 +    struct iommu *iommu,
    3.12 +    int bus, int devfn,
    3.13 +    unsigned long gmfn)
    3.14  {
    3.15      struct hvm_iommu *hd = domain_hvm_iommu(d);
    3.16      struct acpi_drhd_unit *drhd;
    3.17 -    struct iommu *iommu;
    3.18      struct context_entry *ctxt_entry;
    3.19      struct root_entry *root_entry;
    3.20      struct dma_pte pte;
    3.21 @@ -175,7 +177,6 @@ void print_vtd_entries(struct domain *d,
    3.22      {
    3.23          printk("---- print_vtd_entries %d ----\n", i++);
    3.24  
    3.25 -        iommu = drhd->iommu;
    3.26          root_entry = iommu->root_entry;
    3.27          if ( root_entry == NULL )
    3.28          {
     4.1 --- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h	Fri Jan 18 13:40:22 2008 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h	Fri Jan 18 13:41:33 2008 +0000
     4.3 @@ -127,32 +127,34 @@
     4.4  #define DMA_TLB_IVA_HINT(x) ((((u64)x) & 1) << 6)
     4.5  
     4.6  /* GCMD_REG */
     4.7 -#define DMA_GCMD_TE (((u64)1) << 31)
     4.8 -#define DMA_GCMD_SRTP (((u64)1) << 30)
     4.9 -#define DMA_GCMD_SFL (((u64)1) << 29)
    4.10 -#define DMA_GCMD_EAFL (((u64)1) << 28)
    4.11 -#define DMA_GCMD_WBF (((u64)1) << 27)
    4.12 -#define DMA_GCMD_QIE (((u64)1) << 26)
    4.13 -#define DMA_GCMD_IRE (((u64)1) << 25)
    4.14 -#define DMA_GCMD_SIRTP (((u64)1) << 24)
    4.15 +#define DMA_GCMD_TE     (((u64)1) << 31)
    4.16 +#define DMA_GCMD_SRTP   (((u64)1) << 30)
    4.17 +#define DMA_GCMD_SFL    (((u64)1) << 29)
    4.18 +#define DMA_GCMD_EAFL   (((u64)1) << 28)
    4.19 +#define DMA_GCMD_WBF    (((u64)1) << 27)
    4.20 +#define DMA_GCMD_QIE    (((u64)1) << 26)
    4.21 +#define DMA_GCMD_IRE    (((u64)1) << 25)
    4.22 +#define DMA_GCMD_SIRTP  (((u64)1) << 24)
    4.23 +#define DMA_GCMD_CFI    (((u64)1) << 23)
    4.24  
    4.25  /* GSTS_REG */
    4.26 -#define DMA_GSTS_TES (((u64)1) << 31)
    4.27 -#define DMA_GSTS_RTPS (((u64)1) << 30)
    4.28 -#define DMA_GSTS_FLS (((u64)1) << 29)
    4.29 -#define DMA_GSTS_AFLS (((u64)1) << 28)
    4.30 -#define DMA_GSTS_WBFS (((u64)1) << 27)
    4.31 -#define DMA_GSTS_IRTPS (((u64)1) << 24)
    4.32 +#define DMA_GSTS_TES    (((u64)1) << 31)
    4.33 +#define DMA_GSTS_RTPS   (((u64)1) << 30)
    4.34 +#define DMA_GSTS_FLS    (((u64)1) << 29)
    4.35 +#define DMA_GSTS_AFLS   (((u64)1) << 28)
    4.36 +#define DMA_GSTS_WBFS   (((u64)1) << 27)
    4.37  #define DMA_GSTS_QIES   (((u64)1) <<26)
    4.38  #define DMA_GSTS_IRES   (((u64)1) <<25)
    4.39 +#define DMA_GSTS_SIRTPS (((u64)1) << 24)
    4.40 +#define DMA_GSTS_CFIS   (((u64)1) <<23)
    4.41  
    4.42  /* PMEN_REG */
    4.43 -#define DMA_PMEN_EPM   (((u32)1) << 31)
    4.44 -#define DMA_PMEN_PRS   (((u32)1) << 0)
    4.45 +#define DMA_PMEN_EPM    (((u32)1) << 31)
    4.46 +#define DMA_PMEN_PRS    (((u32)1) << 0)
    4.47  
    4.48  /* CCMD_REG */
    4.49  #define DMA_CCMD_INVL_GRANU_OFFSET  61
    4.50 -#define DMA_CCMD_ICC (((u64)1) << 63)
    4.51 +#define DMA_CCMD_ICC   (((u64)1) << 63)
    4.52  #define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
    4.53  #define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
    4.54  #define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
    4.55 @@ -171,8 +173,14 @@
    4.56  #define DMA_FECTL_IM (((u64)1) << 31)
    4.57  
    4.58  /* FSTS_REG */
    4.59 -#define DMA_FSTS_PPF ((u64)2)
    4.60 -#define DMA_FSTS_PFO ((u64)1)
    4.61 +#define DMA_FSTS_PFO ((u64)1 << 0)
    4.62 +#define DMA_FSTS_PPF ((u64)1 << 1)
    4.63 +#define DMA_FSTS_AFO ((u64)1 << 2)
    4.64 +#define DMA_FSTS_APF ((u64)1 << 3)
    4.65 +#define DMA_FSTS_IQE ((u64)1 << 4)
    4.66 +#define DMA_FSTS_ICE ((u64)1 << 5)
    4.67 +#define DMA_FSTS_ITE ((u64)1 << 6)
    4.68 +#define DMA_FSTS_FAULTS    DMA_FSTS_PFO | DMA_FSTS_PPF | DMA_FSTS_AFO | DMA_FSTS_APF | DMA_FSTS_IQE | DMA_FSTS_ICE | DMA_FSTS_ITE
    4.69  #define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
    4.70  
    4.71  /* FRCD_REG, 32 bits access */
    4.72 @@ -266,8 +274,10 @@ struct dma_pte {
    4.73  
    4.74  /* interrupt remap entry */
    4.75  struct iremap_entry {
    4.76 +  union {
    4.77 +    u64 lo_val;
    4.78      struct {
    4.79 -        u64 present : 1,
    4.80 +        u64 p       : 1,
    4.81              fpd     : 1,
    4.82              dm      : 1,
    4.83              rh      : 1,
    4.84 @@ -279,12 +289,16 @@ struct iremap_entry {
    4.85              res_2   : 8,
    4.86              dst     : 32;
    4.87      }lo;
    4.88 +  };
    4.89 +  union {
    4.90 +    u64 hi_val;
    4.91      struct {
    4.92          u64 sid     : 16,
    4.93              sq      : 2,
    4.94              svt     : 2,
    4.95              res_1   : 44;
    4.96      }hi;
    4.97 +  };
    4.98  };
    4.99  #define IREMAP_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct iremap_entry))
   4.100  #define iremap_present(v) ((v).lo & 1)
   4.101 @@ -386,11 +400,11 @@ struct poll_info {
   4.102  
   4.103  #define RESERVED_VAL        0
   4.104  
   4.105 -#define TYPE_INVAL_CONTEXT  1
   4.106 -#define TYPE_INVAL_IOTLB    2
   4.107 -#define TYPE_INVAL_DEVICE_IOTLB 3
   4.108 -#define TYPE_INVAL_IEC          4
   4.109 -#define TYPE_INVAL_WAIT         5
   4.110 +#define TYPE_INVAL_CONTEXT      0x1
   4.111 +#define TYPE_INVAL_IOTLB        0x2
   4.112 +#define TYPE_INVAL_DEVICE_IOTLB 0x3
   4.113 +#define TYPE_INVAL_IEC          0x4
   4.114 +#define TYPE_INVAL_WAIT         0x5
   4.115  
   4.116  #define NOTIFY_TYPE_POLL        1
   4.117  #define NOTIFY_TYPE_INTR        1
   4.118 @@ -400,6 +414,10 @@ struct poll_info {
   4.119  
   4.120  #define IEC_GLOBAL_INVL         0
   4.121  #define IEC_INDEX_INVL          1
   4.122 +#define IRTA_REG_EIME_SHIFT     11
   4.123 +#define IRTA_REG_TABLE_SIZE     7    // 4k page = 256 * 16 byte entries
   4.124 +                                     // 2^^(IRTA_REG_TABLE_SIZE + 1) = 256
   4.125 +                                     // IRTA_REG_TABLE_SIZE = 7
   4.126  
   4.127  #define VTD_PAGE_TABLE_LEVEL_3  3
   4.128  #define VTD_PAGE_TABLE_LEVEL_4  4
   4.129 @@ -414,4 +432,29 @@ extern struct list_head acpi_drhd_units;
   4.130  extern struct list_head acpi_rmrr_units;
   4.131  extern struct list_head acpi_ioapic_units;
   4.132  
   4.133 +struct qi_ctrl {
   4.134 +    struct qinval_entry *qinval;         /* queue invalidation page */
   4.135 +    int qinval_index;                    /* queue invalidation index */
   4.136 +    spinlock_t qinval_lock;      /* lock for queue invalidation page */
   4.137 +    spinlock_t qinval_poll_lock; /* lock for queue invalidation poll addr */
   4.138 +    volatile u32 qinval_poll_status;     /* used by poll methord to sync */
   4.139 +};
   4.140 +
   4.141 +struct ir_ctrl {
   4.142 +    struct iremap_entry *iremap;         /* interrupt remap table */
   4.143 +    int iremap_index;                    /* interrupt remap index */
   4.144 +    spinlock_t iremap_lock;      /* lock for irq remappping table */
   4.145 +};
   4.146 +
   4.147 +struct iommu_flush {
   4.148 +    int (*context)(void *iommu, u16 did, u16 source_id, u8 function_mask, u64 type, int non_present_entry_flush);
   4.149 +    int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order, u64 type, int non_present_entry_flush);
   4.150 +};
   4.151 +
   4.152 +struct intel_iommu {
   4.153 +    struct qi_ctrl qi_ctrl;
   4.154 +    struct ir_ctrl ir_ctrl;
   4.155 +    struct iommu_flush flush; 
   4.156 +};
   4.157 +
   4.158  #endif