ia64/xen-unstable

changeset 13848:e825954d4179

[HVM] Save/restore: tidy up IRQs
- don't save PV state
- recalculate IRQ assert counts instead of saving them

Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Mon Feb 05 15:08:18 2007 +0000 (2007-02-05)
parents 7a7509570af9
children 8bc64a3a5054
files xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/vioapic.c xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/irq.h xen/include/public/hvm/save.h
line diff
     1.1 --- a/xen/arch/x86/hvm/irq.c	Mon Feb 05 11:38:22 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/irq.c	Mon Feb 05 15:08:18 2007 +0000
     1.3 @@ -24,16 +24,17 @@
     1.4  #include <xen/event.h>
     1.5  #include <xen/sched.h>
     1.6  #include <asm/hvm/domain.h>
     1.7 +#include <asm/hvm/support.h>
     1.8  
     1.9  static void __hvm_pci_intx_assert(
    1.10      struct domain *d, unsigned int device, unsigned int intx)
    1.11  {
    1.12 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.13 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.14      unsigned int gsi, link, isa_irq;
    1.15  
    1.16      ASSERT((device <= 31) && (intx <= 3));
    1.17  
    1.18 -    if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx) )
    1.19 +    if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx.i) )
    1.20          return;
    1.21  
    1.22      gsi = hvm_pci_intx_gsi(device, intx);
    1.23 @@ -41,7 +42,7 @@ static void __hvm_pci_intx_assert(
    1.24          vioapic_irq_positive_edge(d, gsi);
    1.25  
    1.26      link    = hvm_pci_intx_link(device, intx);
    1.27 -    isa_irq = hvm_irq->pci_link_route[link];
    1.28 +    isa_irq = hvm_irq->pci_link.route[link];
    1.29      if ( (hvm_irq->pci_link_assert_count[link]++ == 0) && isa_irq &&
    1.30           (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
    1.31      {
    1.32 @@ -61,19 +62,19 @@ void hvm_pci_intx_assert(
    1.33  static void __hvm_pci_intx_deassert(
    1.34      struct domain *d, unsigned int device, unsigned int intx)
    1.35  {
    1.36 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.37 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.38      unsigned int gsi, link, isa_irq;
    1.39  
    1.40      ASSERT((device <= 31) && (intx <= 3));
    1.41  
    1.42 -    if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx) )
    1.43 +    if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx.i) )
    1.44          return;
    1.45  
    1.46      gsi = hvm_pci_intx_gsi(device, intx);
    1.47      --hvm_irq->gsi_assert_count[gsi];
    1.48  
    1.49      link    = hvm_pci_intx_link(device, intx);
    1.50 -    isa_irq = hvm_irq->pci_link_route[link];
    1.51 +    isa_irq = hvm_irq->pci_link.route[link];
    1.52      if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq &&
    1.53           (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
    1.54          vpic_irq_negative_edge(d, isa_irq);
    1.55 @@ -90,14 +91,14 @@ void hvm_pci_intx_deassert(
    1.56  void hvm_isa_irq_assert(
    1.57      struct domain *d, unsigned int isa_irq)
    1.58  {
    1.59 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.60 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.61      unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
    1.62  
    1.63      ASSERT(isa_irq <= 15);
    1.64  
    1.65      spin_lock(&d->arch.hvm_domain.irq_lock);
    1.66  
    1.67 -    if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq) &&
    1.68 +    if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq.i) &&
    1.69           (hvm_irq->gsi_assert_count[gsi]++ == 0) )
    1.70      {
    1.71          vioapic_irq_positive_edge(d, gsi);
    1.72 @@ -110,14 +111,14 @@ void hvm_isa_irq_assert(
    1.73  void hvm_isa_irq_deassert(
    1.74      struct domain *d, unsigned int isa_irq)
    1.75  {
    1.76 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.77 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.78      unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
    1.79  
    1.80      ASSERT(isa_irq <= 15);
    1.81  
    1.82      spin_lock(&d->arch.hvm_domain.irq_lock);
    1.83  
    1.84 -    if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq) &&
    1.85 +    if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq.i) &&
    1.86           (--hvm_irq->gsi_assert_count[gsi] == 0) )
    1.87          vpic_irq_negative_edge(d, isa_irq);
    1.88  
    1.89 @@ -128,7 +129,7 @@ void hvm_set_callback_irq_level(void)
    1.90  {
    1.91      struct vcpu *v = current;
    1.92      struct domain *d = v->domain;
    1.93 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.94 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.95      unsigned int gsi, pdev, pintx, asserted;
    1.96  
    1.97      /* Fast lock-free tests. */
    1.98 @@ -178,17 +179,17 @@ void hvm_set_callback_irq_level(void)
    1.99  
   1.100  void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
   1.101  {
   1.102 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.103 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.104      u8 old_isa_irq;
   1.105  
   1.106      ASSERT((link <= 3) && (isa_irq <= 15));
   1.107  
   1.108      spin_lock(&d->arch.hvm_domain.irq_lock);
   1.109  
   1.110 -    old_isa_irq = hvm_irq->pci_link_route[link];
   1.111 +    old_isa_irq = hvm_irq->pci_link.route[link];
   1.112      if ( old_isa_irq == isa_irq )
   1.113          goto out;
   1.114 -    hvm_irq->pci_link_route[link] = isa_irq;
   1.115 +    hvm_irq->pci_link.route[link] = isa_irq;
   1.116  
   1.117      if ( hvm_irq->pci_link_assert_count[link] == 0 )
   1.118          goto out;
   1.119 @@ -211,7 +212,7 @@ void hvm_set_pci_link_route(struct domai
   1.120  
   1.121  void hvm_set_callback_via(struct domain *d, uint64_t via)
   1.122  {
   1.123 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.124 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.125      unsigned int gsi=0, pdev=0, pintx=0;
   1.126      uint8_t via_type;
   1.127  
   1.128 @@ -335,3 +336,150 @@ int is_isa_irq_masked(struct vcpu *v, in
   1.129               (1 << (isa_irq & 7))) &&
   1.130              domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
   1.131  }
   1.132 +
   1.133 +#if 0 /* Keep for debugging */
   1.134 +static void irq_dump(struct domain *d)
   1.135 +{
   1.136 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.137 +    int i; 
   1.138 +    printk("PCI 0x%16.16"PRIx64"%16.16"PRIx64
   1.139 +           " ISA 0x%8.8"PRIx32" ROUTE %u %u %u %u\n",
   1.140 +           hvm_irq->pci_intx.pad[0],  hvm_irq->pci_intx.pad[1],
   1.141 +           (uint32_t) hvm_irq->isa_irq.pad[0], 
   1.142 +           hvm_irq->pci_link.route[0], hvm_irq->pci_link.route[1],
   1.143 +           hvm_irq->pci_link.route[2], hvm_irq->pci_link.route[3]);
   1.144 +    for ( i = 0 ; i < VIOAPIC_NUM_PINS; i += 8 )
   1.145 +        printk("GSI  %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8
   1.146 +               " %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8"\n",
   1.147 +               hvm_irq->gsi_assert_count[i+0],
   1.148 +               hvm_irq->gsi_assert_count[i+1],
   1.149 +               hvm_irq->gsi_assert_count[i+2],
   1.150 +               hvm_irq->gsi_assert_count[i+3],
   1.151 +               hvm_irq->gsi_assert_count[i+4],
   1.152 +               hvm_irq->gsi_assert_count[i+5],
   1.153 +               hvm_irq->gsi_assert_count[i+6],
   1.154 +               hvm_irq->gsi_assert_count[i+7]);
   1.155 +    printk("Link %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8"\n",
   1.156 +           hvm_irq->pci_link_assert_count[0],
   1.157 +           hvm_irq->pci_link_assert_count[1],
   1.158 +           hvm_irq->pci_link_assert_count[2],
   1.159 +           hvm_irq->pci_link_assert_count[3]);
   1.160 +    printk("Callback via %i:0x%"PRIx32",%s asserted\n", 
   1.161 +           hvm_irq->callback_via_type, hvm_irq->callback_via.gsi, 
   1.162 +           hvm_irq->callback_via_asserted ? "" : " not");
   1.163 +}
   1.164 +#endif
   1.165 +
   1.166 +static int irq_save_pci(struct domain *d, hvm_domain_context_t *h)
   1.167 +{
   1.168 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.169 +
   1.170 +    /* Save PCI IRQ lines */
   1.171 +    return ( hvm_save_entry(PCI_IRQ, 0, h, &hvm_irq->pci_intx) );
   1.172 +}
   1.173 +
   1.174 +static int irq_save_isa(struct domain *d, hvm_domain_context_t *h)
   1.175 +{
   1.176 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.177 +
   1.178 +    /* Save ISA IRQ lines */
   1.179 +    return ( hvm_save_entry(ISA_IRQ, 0, h, &hvm_irq->isa_irq) );
   1.180 +}
   1.181 +
   1.182 +static int irq_save_link(struct domain *d, hvm_domain_context_t *h)
   1.183 +{
   1.184 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.185 +
   1.186 +    /* Save PCI-ISA link state */
   1.187 +    return ( hvm_save_entry(PCI_LINK, 0, h, &hvm_irq->pci_link) );
   1.188 +}
   1.189 +
   1.190 +static int irq_load_pci(struct domain *d, hvm_domain_context_t *h)
   1.191 +{
   1.192 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.193 +    int link, dev, intx, gsi;
   1.194 +
   1.195 +    /* Load the PCI IRQ lines */
   1.196 +    if ( hvm_load_entry(PCI_IRQ, h, &hvm_irq->pci_intx) != 0 )
   1.197 +        return -EINVAL;
   1.198 +
   1.199 +    /* Clear the PCI link assert counts */
   1.200 +    for ( link = 0; link < 4; link++ )
   1.201 +        hvm_irq->pci_link_assert_count[link] = 0;
   1.202 +    
   1.203 +    /* Clear the GSI link assert counts */
   1.204 +    for ( gsi = 0; gsi < VIOAPIC_NUM_PINS; gsi++ )
   1.205 +        hvm_irq->gsi_assert_count[gsi] = 0;
   1.206 +
   1.207 +    /* Recalculate the counts from the IRQ line state */
   1.208 +    for ( dev = 0; dev < 32; dev++ )
   1.209 +        for ( intx = 0; intx < 4; intx++ )
   1.210 +            if ( test_bit(dev*4 + intx, &hvm_irq->pci_intx.i) )
   1.211 +            {
   1.212 +                /* Direct GSI assert */
   1.213 +                gsi = hvm_pci_intx_gsi(dev, intx);
   1.214 +                hvm_irq->gsi_assert_count[gsi]++;
   1.215 +                /* PCI-ISA bridge assert */
   1.216 +                link = hvm_pci_intx_link(dev, intx);
   1.217 +                hvm_irq->pci_link_assert_count[link]++;
   1.218 +            }
   1.219 +
   1.220 +    return 0;
   1.221 +}
   1.222 +
   1.223 +static int irq_load_isa(struct domain *d, hvm_domain_context_t *h)
   1.224 +{
   1.225 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.226 +    int irq;
   1.227 +
   1.228 +    /* Load the ISA IRQ lines */
   1.229 +    if ( hvm_load_entry(ISA_IRQ, h, &hvm_irq->isa_irq) != 0 )
   1.230 +        return -EINVAL;
   1.231 +
   1.232 +    /* Adjust the GSI assert counts for the ISA IRQ line state.
   1.233 +     * This relies on the PCI IRQ state being loaded first. */
   1.234 +    for ( irq = 0; irq < 16; irq++ )
   1.235 +        if ( test_bit(irq, &hvm_irq->isa_irq.i) )
   1.236 +            hvm_irq->gsi_assert_count[hvm_isa_irq_to_gsi(irq)]++;
   1.237 +
   1.238 +    return 0;
   1.239 +}
   1.240 +
   1.241 +
   1.242 +static int irq_load_link(struct domain *d, hvm_domain_context_t *h)
   1.243 +{
   1.244 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
   1.245 +    int link, gsi;
   1.246 +
   1.247 +    /* Load the PCI-ISA IRQ link routing table */
   1.248 +    if ( hvm_load_entry(PCI_LINK, h, &hvm_irq->pci_link) != 0 )
   1.249 +        return -EINVAL;
   1.250 +
   1.251 +    /* Sanity check */
   1.252 +    for ( link = 0; link < 4; link++ )
   1.253 +        if ( hvm_irq->pci_link.route[link] > 15 )
   1.254 +        {
   1.255 +            gdprintk(XENLOG_ERR, 
   1.256 +                     "HVM restore: PCI-ISA link %u out of range (%u)\n",
   1.257 +                     link, hvm_irq->pci_link.route[link]);
   1.258 +            return -EINVAL;
   1.259 +        }
   1.260 +
   1.261 +    /* Adjust the GSI assert counts for the link outputs.
   1.262 +     * This relies on the PCI and ISA IRQ state being loaded first */
   1.263 +    for ( link = 0; link < 4; link++ )
   1.264 +    {
   1.265 +        if ( hvm_irq->pci_link_assert_count[link] != 0 )
   1.266 +        {
   1.267 +            gsi = hvm_irq->pci_link.route[link];
   1.268 +            if ( gsi != 0 )
   1.269 +                hvm_irq->gsi_assert_count[gsi]++;
   1.270 +        }
   1.271 +    }
   1.272 +
   1.273 +    return 0;
   1.274 +}
   1.275 +
   1.276 +HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci);
   1.277 +HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa);
   1.278 +HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link);
     2.1 --- a/xen/arch/x86/hvm/vioapic.c	Mon Feb 05 11:38:22 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/vioapic.c	Mon Feb 05 15:08:18 2007 +0000
     2.3 @@ -125,7 +125,7 @@ static void vioapic_write_redirent(
     2.4      struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t val)
     2.5  {
     2.6      struct domain *d = vioapic_domain(vioapic);
     2.7 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
     2.8 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     2.9      union vioapic_redir_entry *pent, ent;
    2.10  
    2.11      spin_lock(&d->arch.hvm_domain.irq_lock);
    2.12 @@ -446,7 +446,7 @@ static int get_eoi_gsi(struct hvm_hw_vio
    2.13  void vioapic_update_EOI(struct domain *d, int vector)
    2.14  {
    2.15      struct hvm_hw_vioapic *vioapic = domain_vioapic(d);
    2.16 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    2.17 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    2.18      union vioapic_redir_entry *ent;
    2.19      int gsi;
    2.20  
    2.21 @@ -486,41 +486,10 @@ static void ioapic_info(struct hvm_hw_vi
    2.22      }
    2.23  
    2.24  }
    2.25 -static void hvmirq_info(struct hvm_hw_irq *hvm_irq)
    2.26 -{
    2.27 -    int i;
    2.28 -    printk("*****hvmirq state:*****\n");
    2.29 -    for (i = 0; i < BITS_TO_LONGS(32*4); i++)
    2.30 -        printk("hvmirq pci_intx[%d]:0x%lx.\n", i, hvm_irq->pci_intx[i]);
    2.31 -
    2.32 -    for (i = 0; i < BITS_TO_LONGS(16); i++)
    2.33 -        printk("hvmirq isa_irq[%d]:0x%lx.\n", i, hvm_irq->isa_irq[i]);
    2.34 -
    2.35 -    for (i = 0; i < BITS_TO_LONGS(1); i++)
    2.36 -        printk("hvmirq callback_irq_wire[%d]:0x%lx.\n", i, hvm_irq->callback_irq_wire[i]);
    2.37 -
    2.38 -    printk("hvmirq callback_via_type:0x%x.\n", hvm_irq->callback_via_type);
    2.39 -    printk("hvmirq callback_via:0x%x.\n", hvm_irq->callback_via.gsi);
    2.40 -    
    2.41 -
    2.42 -    for (i = 0; i < 4; i++)
    2.43 -        printk("hvmirq pci_link_route[%d]:0x%"PRIx8".\n", i, hvm_irq->pci_link_route[i]);
    2.44 -
    2.45 -    for (i = 0; i < 4; i++)
    2.46 -        printk("hvmirq pci_link_assert_count[%d]:0x%"PRIx8".\n", i, hvm_irq->pci_link_assert_count[i]);
    2.47 -
    2.48 -    for (i = 0; i < VIOAPIC_NUM_PINS; i++)
    2.49 -        printk("hvmirq gsi_assert_count[%d]:0x%"PRIx8".\n", i, hvm_irq->gsi_assert_count[i]);
    2.50 -
    2.51 -    printk("hvmirq round_robin_prev_vcpu:0x%"PRIx8".\n", hvm_irq->round_robin_prev_vcpu);
    2.52 -}
    2.53  #else
    2.54  static void ioapic_info(struct hvm_hw_vioapic *s)
    2.55  {
    2.56  }
    2.57 -static void hvmirq_info(struct hvm_hw_irq *hvm_irq)
    2.58 -{
    2.59 -}
    2.60  #endif
    2.61  
    2.62  
    2.63 @@ -533,16 +502,6 @@ static int ioapic_save(struct domain *d,
    2.64      return ( hvm_save_entry(IOAPIC, 0, h, s) );
    2.65  }
    2.66  
    2.67 -static int ioapic_save_irqs(struct domain *d, hvm_domain_context_t *h)
    2.68 -{
    2.69 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    2.70 -    hvmirq_info(hvm_irq);
    2.71 -
    2.72 -    /* save IRQ state*/
    2.73 -    return ( hvm_save_entry(IRQ, 0, h, hvm_irq) );    
    2.74 -}
    2.75 -
    2.76 -
    2.77  static int ioapic_load(struct domain *d, hvm_domain_context_t *h)
    2.78  {
    2.79      struct hvm_hw_vioapic *s = domain_vioapic(d);
    2.80 @@ -555,20 +514,7 @@ static int ioapic_load(struct domain *d,
    2.81      return 0;
    2.82  }
    2.83  
    2.84 -static int ioapic_load_irqs(struct domain *d, hvm_domain_context_t *h)
    2.85 -{
    2.86 -    struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
    2.87 -
    2.88 -    /* restore irq state */
    2.89 -    if ( hvm_load_entry(IRQ, h, hvm_irq) != 0 )
    2.90 -        return -EINVAL;
    2.91 -
    2.92 -    hvmirq_info(hvm_irq);
    2.93 -    return 0;
    2.94 -}
    2.95 -
    2.96  HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load);
    2.97 -HVM_REGISTER_SAVE_RESTORE(IRQ, ioapic_save_irqs, ioapic_load_irqs);
    2.98  
    2.99  void vioapic_init(struct domain *d)
   2.100  {
     3.1 --- a/xen/include/asm-x86/hvm/domain.h	Mon Feb 05 11:38:22 2007 +0000
     3.2 +++ b/xen/include/asm-x86/hvm/domain.h	Mon Feb 05 15:08:18 2007 +0000
     3.3 @@ -39,7 +39,7 @@ struct hvm_domain {
     3.4  
     3.5      /* Lock protects access to irq, vpic and vioapic. */
     3.6      spinlock_t             irq_lock;
     3.7 -    struct hvm_hw_irq      irq;
     3.8 +    struct hvm_irq         irq;
     3.9      struct hvm_hw_vpic     vpic[2]; /* 0=master; 1=slave */
    3.10      struct hvm_hw_vioapic  vioapic;
    3.11  
     4.1 --- a/xen/include/asm-x86/hvm/irq.h	Mon Feb 05 11:38:22 2007 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/irq.h	Mon Feb 05 15:08:18 2007 +0000
     4.3 @@ -28,6 +28,69 @@
     4.4  #include <asm/hvm/vioapic.h>
     4.5  #include <public/hvm/save.h>
     4.6  
     4.7 +
     4.8 +struct hvm_irq {
     4.9 +    /*
    4.10 +     * Virtual interrupt wires for a single PCI bus.
    4.11 +     * Indexed by: device*4 + INTx#.
    4.12 +     */
    4.13 +    struct hvm_hw_pci_irqs pci_intx;
    4.14 +
    4.15 +    /*
    4.16 +     * Virtual interrupt wires for ISA devices.
    4.17 +     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
    4.18 +     */
    4.19 +    struct hvm_hw_isa_irqs isa_irq;
    4.20 +
    4.21 +    /*
    4.22 +     * PCI-ISA interrupt router.
    4.23 +     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
    4.24 +     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
    4.25 +     * The router provides a programmable mapping from each link to a GSI.
    4.26 +     */
    4.27 +    struct hvm_hw_pci_link pci_link;
    4.28 +
    4.29 +    /* Virtual interrupt and via-link for paravirtual platform driver. */
    4.30 +    uint32_t callback_via_asserted;
    4.31 +    union {
    4.32 +        enum {
    4.33 +            HVMIRQ_callback_none,
    4.34 +            HVMIRQ_callback_gsi,
    4.35 +            HVMIRQ_callback_pci_intx
    4.36 +        } callback_via_type;
    4.37 +        uint32_t pad; /* So the next field will be aligned */
    4.38 +    };
    4.39 +    union {
    4.40 +        uint32_t gsi;
    4.41 +        struct { uint8_t dev, intx; } pci;
    4.42 +    } callback_via;
    4.43 +
    4.44 +    /* Number of INTx wires asserting each PCI-ISA link. */
    4.45 +    u8 pci_link_assert_count[4];
    4.46 +
    4.47 +    /*
    4.48 +     * Number of wires asserting each GSI.
    4.49 +     * 
    4.50 +     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
    4.51 +     * except ISA IRQ 0, which is connected to GSI 2.
    4.52 +     * PCI links map into this space via the PCI-ISA bridge.
    4.53 +     * 
    4.54 +     * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
    4.55 +     * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
    4.56 +     */
    4.57 +    u8 gsi_assert_count[VIOAPIC_NUM_PINS];
    4.58 +
    4.59 +    /*
    4.60 +     * GSIs map onto PIC/IO-APIC in the usual way:
    4.61 +     *  0-7:  Master 8259 PIC, IO-APIC pins 0-7
    4.62 +     *  8-15: Slave  8259 PIC, IO-APIC pins 8-15
    4.63 +     *  16+ : IO-APIC pins 16+
    4.64 +     */
    4.65 +
    4.66 +    /* Last VCPU that was delivered a LowestPrio interrupt. */
    4.67 +    u8 round_robin_prev_vcpu;
    4.68 +};
    4.69 +
    4.70  #define hvm_pci_intx_gsi(dev, intx)  \
    4.71      (((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16)
    4.72  #define hvm_pci_intx_link(dev, intx) \
     5.1 --- a/xen/include/public/hvm/save.h	Mon Feb 05 11:38:22 2007 +0000
     5.2 +++ b/xen/include/public/hvm/save.h	Mon Feb 05 15:08:18 2007 +0000
     5.3 @@ -270,72 +270,46 @@ DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, str
     5.4  
     5.5  
     5.6  /*
     5.7 - * IRQ
     5.8 + * IRQs
     5.9   */
    5.10  
    5.11 -struct hvm_hw_irq {
    5.12 +struct hvm_hw_pci_irqs {
    5.13      /*
    5.14       * Virtual interrupt wires for a single PCI bus.
    5.15       * Indexed by: device*4 + INTx#.
    5.16       */
    5.17 -    DECLARE_BITMAP(pci_intx, 32*4);
    5.18 +    union {
    5.19 +        DECLARE_BITMAP(i, 32*4);
    5.20 +        uint64_t pad[2];
    5.21 +    };
    5.22 +};
    5.23  
    5.24 +DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
    5.25 +
    5.26 +struct hvm_hw_isa_irqs {
    5.27      /*
    5.28       * Virtual interrupt wires for ISA devices.
    5.29       * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
    5.30       */
    5.31 -    DECLARE_BITMAP(isa_irq, 16);
    5.32 -
    5.33 -    /* Virtual interrupt and via-link for paravirtual platform driver. */
    5.34 -    uint32_t callback_via_asserted;
    5.35      union {
    5.36 -        enum {
    5.37 -            HVMIRQ_callback_none,
    5.38 -            HVMIRQ_callback_gsi,
    5.39 -            HVMIRQ_callback_pci_intx
    5.40 -        } callback_via_type;
    5.41 -        uint32_t pad; /* So the next field will be aligned */
    5.42 +        DECLARE_BITMAP(i, 16);
    5.43 +        uint64_t pad[1];
    5.44      };
    5.45 -    union {
    5.46 -        uint32_t gsi;
    5.47 -        struct { uint8_t dev, intx; } pci;
    5.48 -    } callback_via;
    5.49 +};
    5.50  
    5.51 +DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
    5.52 +
    5.53 +struct hvm_hw_pci_link {
    5.54      /*
    5.55       * PCI-ISA interrupt router.
    5.56       * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
    5.57       * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
    5.58       * The router provides a programmable mapping from each link to a GSI.
    5.59       */
    5.60 -    u8 pci_link_route[4];
    5.61 -
    5.62 -    /* Number of INTx wires asserting each PCI-ISA link. */
    5.63 -    u8 pci_link_assert_count[4];
    5.64 -
    5.65 -    /*
    5.66 -     * Number of wires asserting each GSI.
    5.67 -     * 
    5.68 -     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
    5.69 -     * except ISA IRQ 0, which is connected to GSI 2.
    5.70 -     * PCI links map into this space via the PCI-ISA bridge.
    5.71 -     * 
    5.72 -     * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
    5.73 -     * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
    5.74 -     */
    5.75 -    u8 gsi_assert_count[VIOAPIC_NUM_PINS];
    5.76 -
    5.77 -    /*
    5.78 -     * GSIs map onto PIC/IO-APIC in the usual way:
    5.79 -     *  0-7:  Master 8259 PIC, IO-APIC pins 0-7
    5.80 -     *  8-15: Slave  8259 PIC, IO-APIC pins 8-15
    5.81 -     *  16+ : IO-APIC pins 16+
    5.82 -     */
    5.83 -
    5.84 -    /* Last VCPU that was delivered a LowestPrio interrupt. */
    5.85 -    u8 round_robin_prev_vcpu;
    5.86 +    u8 route[4];
    5.87  };
    5.88  
    5.89 -DECLARE_HVM_SAVE_TYPE(IRQ, 7, struct hvm_hw_irq);
    5.90 +DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
    5.91  
    5.92  
    5.93  /* 
    5.94 @@ -360,7 +334,7 @@ struct hvm_hw_pit {
    5.95      uint32_t speaker_data_on;
    5.96  };
    5.97  
    5.98 -DECLARE_HVM_SAVE_TYPE(PIT, 8, struct hvm_hw_pit);
    5.99 +DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
   5.100  
   5.101  
   5.102  /* 
   5.103 @@ -375,7 +349,7 @@ struct hvm_hw_rtc {
   5.104      uint8_t cmos_index;
   5.105  };
   5.106  
   5.107 -DECLARE_HVM_SAVE_TYPE(RTC, 9, struct hvm_hw_rtc);
   5.108 +DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
   5.109  
   5.110  
   5.111  /*
   5.112 @@ -405,13 +379,13 @@ struct hvm_hw_hpet {
   5.113      uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
   5.114  };
   5.115  
   5.116 -DECLARE_HVM_SAVE_TYPE(HPET, 10, struct hvm_hw_hpet);
   5.117 +DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
   5.118  
   5.119  
   5.120  /* 
   5.121   * Largest type-code in use
   5.122   */
   5.123 -#define HVM_SAVE_CODE_MAX 10
   5.124 +#define HVM_SAVE_CODE_MAX 12
   5.125  
   5.126  
   5.127  /*