aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/hpet.c5
-rw-r--r--xen/arch/x86/hvm/hvm.c2
-rw-r--r--xen/arch/x86/hvm/irq.c52
-rw-r--r--xen/arch/x86/hvm/svm/svm.c2
-rw-r--r--xen/arch/x86/hvm/vioapic.c113
-rw-r--r--xen/arch/x86/hvm/vlapic.c89
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c2
-rw-r--r--xen/arch/x86/hvm/vpic.c84
-rw-r--r--xen/include/asm-x86/hvm/domain.h7
-rw-r--r--xen/include/asm-x86/hvm/irq.h65
-rw-r--r--xen/include/asm-x86/hvm/vioapic.h41
-rw-r--r--xen/include/asm-x86/hvm/vlapic.h25
-rw-r--r--xen/include/asm-x86/hvm/vpic.h46
-rw-r--r--xen/include/public/hvm/save.h178
14 files changed, 326 insertions, 385 deletions
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index e86df4e735..b0f6413669 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -314,7 +314,6 @@ static void hpet_route_interrupt(HPETState *h, unsigned int tn)
{
unsigned int tn_int_route = timer_int_route(h, tn);
struct domain *d = h->vcpu->domain;
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) )
{
@@ -336,9 +335,9 @@ static void hpet_route_interrupt(HPETState *h, unsigned int tn)
}
/* We only support edge-triggered interrupt now */
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
vioapic_irq_positive_edge(d, tn_int_route);
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
static void hpet_timer_fn(void *opaque)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 9fa0186d43..1c294ca236 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -135,7 +135,7 @@ int hvm_domain_initialise(struct domain *d)
spin_lock_init(&d->arch.hvm_domain.pbuf_lock);
spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
- spin_lock_init(&d->arch.hvm_domain.irq.lock);
+ spin_lock_init(&d->arch.hvm_domain.irq_lock);
rc = shadow_enable(d, SHM2_refcounts|SHM2_translate|SHM2_external);
if ( rc != 0 )
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 72f8419d46..7644fe338d 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -28,7 +28,7 @@
static void __hvm_pci_intx_assert(
struct domain *d, unsigned int device, unsigned int intx)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi, link, isa_irq;
ASSERT((device <= 31) && (intx <= 3));
@@ -53,17 +53,15 @@ static void __hvm_pci_intx_assert(
void hvm_pci_intx_assert(
struct domain *d, unsigned int device, unsigned int intx)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
__hvm_pci_intx_assert(d, device, intx);
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
static void __hvm_pci_intx_deassert(
struct domain *d, unsigned int device, unsigned int intx)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi, link, isa_irq;
ASSERT((device <= 31) && (intx <= 3));
@@ -84,22 +82,20 @@ static void __hvm_pci_intx_deassert(
void hvm_pci_intx_deassert(
struct domain *d, unsigned int device, unsigned int intx)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
__hvm_pci_intx_deassert(d, device, intx);
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
void hvm_isa_irq_assert(
struct domain *d, unsigned int isa_irq)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
ASSERT(isa_irq <= 15);
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq) &&
(hvm_irq->gsi_assert_count[gsi]++ == 0) )
@@ -108,31 +104,31 @@ void hvm_isa_irq_assert(
vpic_irq_positive_edge(d, isa_irq);
}
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
void hvm_isa_irq_deassert(
struct domain *d, unsigned int isa_irq)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
ASSERT(isa_irq <= 15);
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq) &&
(--hvm_irq->gsi_assert_count[gsi] == 0) )
vpic_irq_negative_edge(d, isa_irq);
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
void hvm_set_callback_irq_level(void)
{
struct vcpu *v = current;
struct domain *d = v->domain;
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi, pdev, pintx, asserted;
/* Fast lock-free tests. */
@@ -140,7 +136,7 @@ void hvm_set_callback_irq_level(void)
(hvm_irq->callback_via_type == HVMIRQ_callback_none) )
return;
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
/* NB. Do not check the evtchn_upcall_mask. It is not used in HVM mode. */
asserted = !!vcpu_info(v, evtchn_upcall_pending);
@@ -177,17 +173,17 @@ void hvm_set_callback_irq_level(void)
}
out:
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
u8 old_isa_irq;
ASSERT((link <= 3) && (isa_irq <= 15));
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
old_isa_irq = hvm_irq->pci_link_route[link];
if ( old_isa_irq == isa_irq )
@@ -207,7 +203,7 @@ void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
}
out:
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
dprintk(XENLOG_G_INFO, "Dom%u PCI link %u changed %u -> %u\n",
d->domain_id, link, old_isa_irq, isa_irq);
@@ -215,7 +211,7 @@ void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
void hvm_set_callback_via(struct domain *d, uint64_t via)
{
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi=0, pdev=0, pintx=0;
uint8_t via_type;
@@ -224,7 +220,7 @@ void hvm_set_callback_via(struct domain *d, uint64_t via)
(via_type > HVMIRQ_callback_pci_intx) )
via_type = HVMIRQ_callback_none;
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
/* Tear down old callback via. */
if ( hvm_irq->callback_via_asserted )
@@ -271,7 +267,7 @@ void hvm_set_callback_via(struct domain *d, uint64_t via)
break;
}
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
dprintk(XENLOG_G_INFO, "Dom%u callback via changed to ", d->domain_id);
switch ( via_type )
@@ -300,7 +296,7 @@ int cpu_has_pending_irq(struct vcpu *v)
if ( !vlapic_accept_pic_intr(v) )
return 0;
- return plat->irq.vpic[0].int_output;
+ return plat->vpic[0].int_output;
}
int cpu_get_interrupt(struct vcpu *v, int *type)
@@ -322,7 +318,7 @@ int get_isa_irq_vector(struct vcpu *v, int isa_irq, int type)
unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
if ( type == APIC_DM_EXTINT )
- return (v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].irq_base
+ return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
+ (isa_irq & 7));
return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
@@ -335,7 +331,7 @@ int is_isa_irq_masked(struct vcpu *v, int isa_irq)
if ( is_lvtt(v, isa_irq) )
return !is_lvtt_enabled(v);
- return ((v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].imr &
+ return ((v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr &
(1 << (isa_irq & 7))) &&
domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
}
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index ba3121618e..fcb08ee5f6 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1960,7 +1960,7 @@ static inline void svm_do_msr_access(
msr_content = vmcb->sysenter_eip;
break;
case MSR_IA32_APICBASE:
- msr_content = vcpu_vlapic(v)->apic_base_msr;
+ msr_content = vcpu_vlapic(v)->hw.apic_base_msr;
break;
default:
if (long_mode_do_msr_read(regs))
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 120693ef09..3efe1286cd 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -47,9 +47,9 @@
#define opt_hvm_debug_level opt_vmx_debug_level
#endif
-static void vioapic_deliver(struct vioapic *vioapic, int irq);
+static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq);
-static unsigned long vioapic_read_indirect(struct vioapic *vioapic,
+static unsigned long vioapic_read_indirect(struct hvm_hw_vioapic *vioapic,
unsigned long addr,
unsigned long length)
{
@@ -96,7 +96,7 @@ static unsigned long vioapic_read(struct vcpu *v,
unsigned long addr,
unsigned long length)
{
- struct vioapic *vioapic = domain_vioapic(v->domain);
+ struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain);
uint32_t result;
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_read addr %lx\n", addr);
@@ -122,13 +122,13 @@ static unsigned long vioapic_read(struct vcpu *v,
}
static void vioapic_write_redirent(
- struct vioapic *vioapic, unsigned int idx, int top_word, uint32_t val)
+ struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t val)
{
struct domain *d = vioapic_domain(vioapic);
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
union vioapic_redir_entry *pent, ent;
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
pent = &vioapic->redirtbl[idx];
ent = *pent;
@@ -157,11 +157,11 @@ static void vioapic_write_redirent(
vioapic_deliver(vioapic, idx);
}
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
static void vioapic_write_indirect(
- struct vioapic *vioapic, unsigned long addr,
+ struct hvm_hw_vioapic *vioapic, unsigned long addr,
unsigned long length, unsigned long val)
{
switch ( vioapic->ioregsel )
@@ -206,7 +206,7 @@ static void vioapic_write(struct vcpu *v,
unsigned long length,
unsigned long val)
{
- struct vioapic *vioapic = domain_vioapic(v->domain);
+ struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain);
addr &= 0xff;
@@ -233,7 +233,7 @@ static void vioapic_write(struct vcpu *v,
static int vioapic_range(struct vcpu *v, unsigned long addr)
{
- struct vioapic *vioapic = domain_vioapic(v->domain);
+ struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain);
return ((addr >= vioapic->base_address &&
(addr < vioapic->base_address + VIOAPIC_MEM_LENGTH)));
@@ -246,7 +246,7 @@ struct hvm_mmio_handler vioapic_mmio_handler = {
};
static void ioapic_inj_irq(
- struct vioapic *vioapic,
+ struct hvm_hw_vioapic *vioapic,
struct vlapic *target,
uint8_t vector,
uint8_t trig_mode,
@@ -270,7 +270,7 @@ static void ioapic_inj_irq(
}
static uint32_t ioapic_get_delivery_bitmask(
- struct vioapic *vioapic, uint16_t dest, uint8_t dest_mode)
+ struct hvm_hw_vioapic *vioapic, uint16_t dest, uint8_t dest_mode)
{
uint32_t mask = 0;
struct vcpu *v;
@@ -316,7 +316,7 @@ static inline int pit_channel0_enabled(void)
return pt->enabled;
}
-static void vioapic_deliver(struct vioapic *vioapic, int irq)
+static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
{
uint16_t dest = vioapic->redirtbl[irq].fields.dest_id;
uint8_t dest_mode = vioapic->redirtbl[irq].fields.dest_mode;
@@ -327,7 +327,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
struct vlapic *target;
struct vcpu *v;
- ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq.lock));
+ ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq_lock));
HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
"dest=%x dest_mode=%x delivery_mode=%x "
@@ -409,13 +409,13 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
void vioapic_irq_positive_edge(struct domain *d, unsigned int irq)
{
- struct vioapic *vioapic = domain_vioapic(d);
+ struct hvm_hw_vioapic *vioapic = domain_vioapic(d);
union vioapic_redir_entry *ent;
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_irq_positive_edge irq %x", irq);
ASSERT(irq < VIOAPIC_NUM_PINS);
- ASSERT(spin_is_locked(&d->arch.hvm_domain.irq.lock));
+ ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
ent = &vioapic->redirtbl[irq];
if ( ent->fields.mask )
@@ -432,7 +432,7 @@ void vioapic_irq_positive_edge(struct domain *d, unsigned int irq)
}
}
-static int get_eoi_gsi(struct vioapic *vioapic, int vector)
+static int get_eoi_gsi(struct hvm_hw_vioapic *vioapic, int vector)
{
int i;
@@ -445,12 +445,12 @@ static int get_eoi_gsi(struct vioapic *vioapic, int vector)
void vioapic_update_EOI(struct domain *d, int vector)
{
- struct vioapic *vioapic = domain_vioapic(d);
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_vioapic *vioapic = domain_vioapic(d);
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
union vioapic_redir_entry *ent;
int gsi;
- spin_lock(&hvm_irq->lock);
+ spin_lock(&d->arch.hvm_domain.irq_lock);
if ( (gsi = get_eoi_gsi(vioapic, vector)) == -1 )
{
@@ -470,11 +470,11 @@ void vioapic_update_EOI(struct domain *d, int vector)
}
out:
- spin_unlock(&hvm_irq->lock);
+ spin_unlock(&d->arch.hvm_domain.irq_lock);
}
#ifdef HVM_DEBUG_SUSPEND
-static void ioapic_info(struct vioapic *s)
+static void ioapic_info(struct hvm_hw_vioapic *s)
{
int i;
printk("*****ioapic state:*****\n");
@@ -486,7 +486,7 @@ static void ioapic_info(struct vioapic *s)
}
}
-static void hvmirq_info(struct hvm_irq *hvm_irq)
+static void hvmirq_info(struct hvm_hw_irq *hvm_irq)
{
int i;
printk("*****hvmirq state:*****\n");
@@ -515,87 +515,44 @@ static void hvmirq_info(struct hvm_irq *hvm_irq)
printk("hvmirq round_robin_prev_vcpu:0x%"PRIx8".\n", hvm_irq->round_robin_prev_vcpu);
}
#else
-static void ioapic_info(struct vioapic *s)
+static void ioapic_info(struct hvm_hw_vioapic *s)
{
}
-static void hvmirq_info(struct hvm_irq *hvm_irq)
+static void hvmirq_info(struct hvm_hw_irq *hvm_irq)
{
}
#endif
static void ioapic_save(hvm_domain_context_t *h, void *opaque)
{
- int i;
struct domain *d = opaque;
- struct vioapic *s = domain_vioapic(d);
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_vioapic *s = domain_vioapic(d);
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
ioapic_info(s);
hvmirq_info(hvm_irq);
- /* save iopaic state*/
- hvm_put_32u(h, s->ioregsel);
- hvm_put_32u(h, s->id);
- hvm_put_64u(h, s->base_address);
- for (i = 0; i < VIOAPIC_NUM_PINS; i++) {
- hvm_put_64u(h, s->redirtbl[i].bits);
- }
+ /* save io-apic state*/
+ hvm_put_struct(h, s);
/* save hvm irq state */
- hvm_put_buffer(h, (char*)hvm_irq->pci_intx, 16);
- hvm_put_buffer(h, (char*)hvm_irq->isa_irq, 2);
- hvm_put_32u(h, hvm_irq->callback_via_asserted);
- hvm_put_32u(h, hvm_irq->callback_via_type);
- hvm_put_32u(h, hvm_irq->callback_via.gsi);
-
- for (i = 0; i < 4; i++)
- hvm_put_8u(h, hvm_irq->pci_link_route[i]);
-
- for (i = 0; i < 4; i++)
- hvm_put_8u(h, hvm_irq->pci_link_assert_count[i]);
-
- for (i = 0; i < VIOAPIC_NUM_PINS; i++)
- hvm_put_8u(h, hvm_irq->gsi_assert_count[i]);
-
- hvm_put_8u(h, hvm_irq->round_robin_prev_vcpu);
-
+ hvm_put_struct(h, hvm_irq);
}
static int ioapic_load(hvm_domain_context_t *h, void *opaque, int version_id)
{
- int i;
struct domain *d = opaque;
- struct vioapic *s = domain_vioapic(d);
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct hvm_hw_vioapic *s = domain_vioapic(d);
+ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq;
if (version_id != 1)
return -EINVAL;
/* restore ioapic state */
- s->ioregsel = hvm_get_32u(h);
- s->id = hvm_get_32u(h);
- s->base_address = hvm_get_64u(h);
- for (i = 0; i < VIOAPIC_NUM_PINS; i++) {
- s->redirtbl[i].bits = hvm_get_64u(h);
- }
+ hvm_get_struct(h, s);
/* restore irq state */
- hvm_get_buffer(h, (char*)hvm_irq->pci_intx, 16);
- hvm_get_buffer(h, (char*)hvm_irq->isa_irq, 2);
- hvm_irq->callback_via_asserted = hvm_get_32u(h);
- hvm_irq->callback_via_type = hvm_get_32u(h);
- hvm_irq->callback_via.gsi = hvm_get_32u(h);
-
- for (i = 0; i < 4; i++)
- hvm_irq->pci_link_route[i] = hvm_get_8u(h);
-
- for (i = 0; i < 4; i++)
- hvm_irq->pci_link_assert_count[i] = hvm_get_8u(h);
-
- for (i = 0; i < VIOAPIC_NUM_PINS; i++)
- hvm_irq->gsi_assert_count[i] = hvm_get_8u(h);
-
- hvm_irq->round_robin_prev_vcpu = hvm_get_8u(h);
+ hvm_get_struct(h, hvm_irq);
ioapic_info(s);
hvmirq_info(hvm_irq);
@@ -605,7 +562,7 @@ static int ioapic_load(hvm_domain_context_t *h, void *opaque, int version_id)
void vioapic_init(struct domain *d)
{
- struct vioapic *vioapic = domain_vioapic(d);
+ struct hvm_hw_vioapic *vioapic = domain_vioapic(d);
int i;
hvm_register_savevm(d, "xen_hvm_ioapic", 0, 1, ioapic_save, ioapic_load, d);
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 4be3f55e1e..e3456f391a 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -81,7 +81,7 @@ static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
(vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
#define vlapic_base_address(vlapic) \
- (vlapic->apic_base_msr & MSR_IA32_APICBASE_BASE)
+ (vlapic->hw.apic_base_msr & MSR_IA32_APICBASE_BASE)
static int vlapic_reset(struct vlapic *vlapic);
@@ -100,15 +100,16 @@ static int vlapic_reset(struct vlapic *vlapic);
#define vlapic_clear_vector(vec, bitmap) \
clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
-static int vlapic_find_highest_vector(u32 *bitmap)
+static int vlapic_find_highest_vector(void *bitmap)
{
+ uint32_t *word = bitmap;
int word_offset = MAX_VECTOR / 32;
/* Work backwards through the bitmap (first 32-bit word in every four). */
- while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) )
+ while ( (word_offset != 0) && (word[(--word_offset)*4] == 0) )
continue;
- return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32);
+ return (fls(word[word_offset*4]) - 1) + (word_offset * 32);
}
@@ -118,19 +119,19 @@ static int vlapic_find_highest_vector(u32 *bitmap)
static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
{
- return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
+ return vlapic_test_and_set_vector(vector, &vlapic->regs->data[APIC_IRR]);
}
static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
{
- vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
+ vlapic_clear_vector(vector, &vlapic->regs->data[APIC_IRR]);
}
int vlapic_find_highest_irr(struct vlapic *vlapic)
{
int result;
- result = vlapic_find_highest_vector(vlapic->regs + APIC_IRR);
+ result = vlapic_find_highest_vector(&vlapic->regs->data[APIC_IRR]);
ASSERT((result == -1) || (result >= 16));
return result;
@@ -142,7 +143,7 @@ int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig)
ret = !vlapic_test_and_set_irr(vec, vlapic);
if ( trig )
- vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
+ vlapic_set_vector(vec, &vlapic->regs->data[APIC_TMR]);
/* We may need to wake up target vcpu, besides set pending bit here */
return ret;
@@ -152,7 +153,7 @@ int vlapic_find_highest_isr(struct vlapic *vlapic)
{
int result;
- result = vlapic_find_highest_vector(vlapic->regs + APIC_ISR);
+ result = vlapic_find_highest_vector(&vlapic->regs->data[APIC_ISR]);
ASSERT((result == -1) || (result >= 16));
return result;
@@ -279,7 +280,7 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
{
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"level trig mode for vector %d\n", vector);
- vlapic_set_vector(vector, vlapic->regs + APIC_TMR);
+ vlapic_set_vector(vector, &vlapic->regs->data[APIC_TMR]);
}
vcpu_kick(v);
@@ -375,9 +376,9 @@ void vlapic_EOI_set(struct vlapic *vlapic)
if ( vector == -1 )
return;
- vlapic_clear_vector(vector, vlapic->regs + APIC_ISR);
+ vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]);
- if ( vlapic_test_and_clear_vector(vector, vlapic->regs + APIC_TMR) )
+ if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) )
vioapic_update_EOI(vlapic_domain(vlapic), vector);
}
@@ -433,7 +434,7 @@ static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
counter_passed = (hvm_get_guest_time(v) - vlapic->pt.last_plt_gtime) // TSC
* 1000000000ULL / ticks_per_sec(v) // NS
- / APIC_BUS_CYCLE_NS / vlapic->timer_divisor;
+ / APIC_BUS_CYCLE_NS / vlapic->hw.timer_divisor;
tmcct = tmict - counter_passed;
HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
@@ -450,12 +451,12 @@ static void vlapic_set_tdcr(struct vlapic *vlapic, unsigned int val)
val &= 0xb;
vlapic_set_reg(vlapic, APIC_TDCR, val);
- /* Update the demangled timer_divisor. */
+ /* Update the demangled hw.timer_divisor. */
val = ((val & 3) | ((val & 8) >> 1)) + 1;
- vlapic->timer_divisor = 1 << (val & 7);
+ vlapic->hw.timer_divisor = 1 << (val & 7);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
- "vlapic_set_tdcr timer_divisor: %d.", vlapic->timer_divisor);
+ "vlapic_set_tdcr timer_divisor: %d.", vlapic->hw.timer_divisor);
}
static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
@@ -614,7 +615,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
int i;
uint32_t lvt_val;
- vlapic->disabled |= VLAPIC_SW_DISABLED;
+ vlapic->hw.disabled |= VLAPIC_SW_DISABLED;
for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
{
@@ -624,7 +625,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
}
}
else
- vlapic->disabled &= ~VLAPIC_SW_DISABLED;
+ vlapic->hw.disabled &= ~VLAPIC_SW_DISABLED;
break;
case APIC_ESR:
@@ -656,7 +657,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
case APIC_TMICT:
{
- uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->timer_divisor;
+ uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->hw.timer_divisor;
vlapic_set_reg(vlapic, APIC_TMICT, val);
create_periodic_time(current, &vlapic->pt, period, vlapic->pt.irq,
@@ -672,7 +673,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
case APIC_TDCR:
vlapic_set_tdcr(vlapic, val & 0xb);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divisor is 0x%x",
- vlapic->timer_divisor);
+ vlapic->hw.timer_divisor);
break;
default:
@@ -697,23 +698,23 @@ struct hvm_mmio_handler vlapic_mmio_handler = {
void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
{
- if ( (vlapic->apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE )
+ if ( (vlapic->hw.apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE )
{
if ( value & MSR_IA32_APICBASE_ENABLE )
{
vlapic_reset(vlapic);
- vlapic->disabled &= ~VLAPIC_HW_DISABLED;
+ vlapic->hw.disabled &= ~VLAPIC_HW_DISABLED;
}
else
{
- vlapic->disabled |= VLAPIC_HW_DISABLED;
+ vlapic->hw.disabled |= VLAPIC_HW_DISABLED;
}
}
- vlapic->apic_base_msr = value;
+ vlapic->hw.apic_base_msr = value;
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
- "apic base msr is 0x%016"PRIx64".", vlapic->apic_base_msr);
+ "apic base msr is 0x%016"PRIx64".", vlapic->hw.apic_base_msr);
}
int vlapic_accept_pic_intr(struct vcpu *v)
@@ -754,7 +755,7 @@ int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
if ( vector == -1 )
return -1;
- vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
+ vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]);
vlapic_clear_irr(vector, vlapic);
*mode = APIC_DM_FIXED;
@@ -790,7 +791,7 @@ static int vlapic_reset(struct vlapic *vlapic)
vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
vlapic_set_reg(vlapic, APIC_SPIV, 0xff);
- vlapic->disabled |= VLAPIC_SW_DISABLED;
+ vlapic->hw.disabled |= VLAPIC_SW_DISABLED;
return 1;
}
@@ -799,10 +800,9 @@ static int vlapic_reset(struct vlapic *vlapic)
static void lapic_info(struct vlapic *s)
{
printk("*****lapic state:*****\n");
- printk("lapic 0x%"PRIx64".\n", s->apic_base_msr);
- printk("lapic 0x%x.\n", s->disabled);
- printk("lapic 0x%x.\n", s->timer_divisor);
- printk("lapic 0x%x.\n", s->timer_pending_count);
+ printk("lapic 0x%"PRIx64".\n", s->hw.apic_base_msr);
+ printk("lapic 0x%x.\n", s->hw.disabled);
+ printk("lapic 0x%x.\n", s->hw.timer_divisor);
}
#else
static void lapic_info(struct vlapic *s)
@@ -816,15 +816,8 @@ static void lapic_save(hvm_domain_context_t *h, void *opaque)
lapic_info(s);
- hvm_put_64u(h, s->apic_base_msr);
- hvm_put_32u(h, s->disabled);
- hvm_put_32u(h, s->timer_divisor);
-
- /*XXX: need this?*/
- hvm_put_32u(h, s->timer_pending_count);
-
- hvm_put_buffer(h, (char*)s->regs, 0x3f0);
-
+ hvm_put_struct(h, &s->hw);
+ hvm_put_struct(h, s->regs);
}
static int lapic_load(hvm_domain_context_t *h, void *opaque, int version_id)
@@ -836,19 +829,13 @@ static int lapic_load(hvm_domain_context_t *h, void *opaque, int version_id)
if (version_id != 1)
return -EINVAL;
- s->apic_base_msr = hvm_get_64u(h);
- s->disabled = hvm_get_32u(h);
- s->timer_divisor = hvm_get_32u(h);
-
- /*XXX: need this?*/
- s->timer_pending_count = hvm_get_32u(h);
-
- hvm_get_buffer(h, (char*)s->regs, 0x3f0);
+ hvm_get_struct(h, &s->hw);
+ hvm_get_struct(h, s->regs);
/* rearm the actiemr if needed */
tmict = vlapic_get_reg(s, APIC_TMICT);
if (tmict > 0) {
- uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->timer_divisor;
+ uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->hw.timer_divisor;
create_periodic_time(v, &s->pt, period, s->pt.irq,
vlapic_lvtt_period(s), NULL, s);
@@ -887,9 +874,9 @@ int vlapic_init(struct vcpu *v)
hvm_register_savevm(v->domain, "xen_hvm_lapic", v->vcpu_id, 1, lapic_save, lapic_load, vlapic);
vlapic_reset(vlapic);
- vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+ vlapic->hw.apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
if ( v->vcpu_id == 0 )
- vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
+ vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP;
init_timer(&vlapic->pt.timer, pt_timer_fn, &vlapic->pt, v->processor);
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 6f62f40528..9d8a3c64a6 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2309,7 +2309,7 @@ static inline int vmx_do_msr_read(struct cpu_user_regs *regs)
msr_content = __vmread(GUEST_SYSENTER_EIP);
break;
case MSR_IA32_APICBASE:
- msr_content = vcpu_vlapic(v)->apic_base_msr;
+ msr_content = vcpu_vlapic(v)->hw.apic_base_msr;
break;
default:
if ( long_mode_do_msr_read(regs) )
diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c
index 4f36dd3bdf..290b5f3129 100644
--- a/xen/arch/x86/hvm/vpic.c
+++ b/xen/arch/x86/hvm/vpic.c
@@ -35,9 +35,9 @@
#include <asm/hvm/support.h>
#define vpic_domain(v) (container_of((v), struct domain, \
- arch.hvm_domain.irq.vpic[!vpic->is_master]))
-#define __vpic_lock(v) &container_of((v), struct hvm_irq, \
- vpic[!(v)->is_master])->lock
+ arch.hvm_domain.vpic[!vpic->is_master]))
+#define __vpic_lock(v) &container_of((v), struct hvm_domain, \
+ vpic[!(v)->is_master])->irq_lock
#define vpic_lock(v) spin_lock(__vpic_lock(v))
#define vpic_unlock(v) spin_unlock(__vpic_lock(v))
#define vpic_is_locked(v) spin_is_locked(__vpic_lock(v))
@@ -45,7 +45,7 @@
/* Return the highest priority found in mask. Return 8 if none. */
#define VPIC_PRIO_NONE 8
-static int vpic_get_priority(struct vpic *vpic, uint8_t mask)
+static int vpic_get_priority(struct hvm_hw_vpic *vpic, uint8_t mask)
{
int prio;
@@ -61,7 +61,7 @@ static int vpic_get_priority(struct vpic *vpic, uint8_t mask)
}
/* Return the PIC's highest priority pending interrupt. Return -1 if none. */
-static int vpic_get_highest_priority_irq(struct vpic *vpic)
+static int vpic_get_highest_priority_irq(struct hvm_hw_vpic *vpic)
{
int cur_priority, priority, irq;
uint8_t mask;
@@ -92,7 +92,7 @@ static int vpic_get_highest_priority_irq(struct vpic *vpic)
return (priority < cur_priority) ? irq : -1;
}
-static void vpic_update_int_output(struct vpic *vpic)
+static void vpic_update_int_output(struct hvm_hw_vpic *vpic)
{
int irq;
@@ -129,7 +129,7 @@ static void vpic_update_int_output(struct vpic *vpic)
}
}
-static void __vpic_intack(struct vpic *vpic, int irq)
+static void __vpic_intack(struct hvm_hw_vpic *vpic, int irq)
{
uint8_t mask = 1 << irq;
@@ -147,7 +147,7 @@ static void __vpic_intack(struct vpic *vpic, int irq)
vpic_update_int_output(vpic);
}
-static int vpic_intack(struct vpic *vpic)
+static int vpic_intack(struct hvm_hw_vpic *vpic)
{
int irq = -1;
@@ -174,7 +174,7 @@ static int vpic_intack(struct vpic *vpic)
return irq;
}
-static void vpic_ioport_write(struct vpic *vpic, uint32_t addr, uint32_t val)
+static void vpic_ioport_write(struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t val)
{
int priority, cmd, irq;
uint8_t mask;
@@ -291,7 +291,7 @@ static void vpic_ioport_write(struct vpic *vpic, uint32_t addr, uint32_t val)
vpic_unlock(vpic);
}
-static uint32_t vpic_ioport_read(struct vpic *vpic, uint32_t addr)
+static uint32_t vpic_ioport_read(struct hvm_hw_vpic *vpic, uint32_t addr)
{
if ( vpic->poll )
{
@@ -307,7 +307,7 @@ static uint32_t vpic_ioport_read(struct vpic *vpic, uint32_t addr)
static int vpic_intercept_pic_io(ioreq_t *p)
{
- struct vpic *vpic;
+ struct hvm_hw_vpic *vpic;
uint32_t data;
if ( (p->size != 1) || (p->count != 1) )
@@ -316,7 +316,7 @@ static int vpic_intercept_pic_io(ioreq_t *p)
return 1;
}
- vpic = &current->domain->arch.hvm_domain.irq.vpic[p->addr >> 7];
+ vpic = &current->domain->arch.hvm_domain.vpic[p->addr >> 7];
if ( p->dir == IOREQ_WRITE )
{
@@ -340,7 +340,7 @@ static int vpic_intercept_pic_io(ioreq_t *p)
static int vpic_intercept_elcr_io(ioreq_t *p)
{
- struct vpic *vpic;
+ struct hvm_hw_vpic *vpic;
uint32_t data;
if ( (p->size != 1) || (p->count != 1) )
@@ -349,7 +349,7 @@ static int vpic_intercept_elcr_io(ioreq_t *p)
return 1;
}
- vpic = &current->domain->arch.hvm_domain.irq.vpic[p->addr & 1];
+ vpic = &current->domain->arch.hvm_domain.vpic[p->addr & 1];
if ( p->dir == IOREQ_WRITE )
{
@@ -379,7 +379,7 @@ static int vpic_intercept_elcr_io(ioreq_t *p)
}
#ifdef HVM_DEBUG_SUSPEND
-static void vpic_info(struct vpic *s)
+static void vpic_info(struct hvm_hw_vpic *s)
{
printk("*****pic state:*****\n");
printk("pic 0x%x.\n", s->irr);
@@ -399,61 +399,27 @@ static void vpic_info(struct vpic *s)
printk("pic 0x%x.\n", s->is_master);
}
#else
-static void vpic_info(struct vpic *s)
+static void vpic_info(struct hvm_hw_vpic *s)
{
}
#endif
static void vpic_save(hvm_domain_context_t *h, void *opaque)
{
- struct vpic *s = opaque;
+ struct hvm_hw_vpic *s = opaque;
vpic_info(s);
-
- hvm_put_8u(h, s->irr);
- hvm_put_8u(h, s->imr);
- hvm_put_8u(h, s->isr);
- hvm_put_8u(h, s->irq_base);
- hvm_put_8u(h, s->init_state);
- hvm_put_8u(h, s->priority_add);
- hvm_put_8u(h, s->readsel_isr);
-
- hvm_put_8u(h, s->poll);
- hvm_put_8u(h, s->auto_eoi);
-
- hvm_put_8u(h, s->rotate_on_auto_eoi);
- hvm_put_8u(h, s->special_fully_nested_mode);
- hvm_put_8u(h, s->special_mask_mode);
-
- hvm_put_8u(h, s->elcr);
- hvm_put_8u(h, s->int_output);
+ hvm_put_struct(h, s);
}
static int vpic_load(hvm_domain_context_t *h, void *opaque, int version_id)
{
- struct vpic *s = opaque;
+ struct hvm_hw_vpic *s = opaque;
if (version_id != 1)
return -EINVAL;
- s->irr = hvm_get_8u(h);
- s->imr = hvm_get_8u(h);
- s->isr = hvm_get_8u(h);
- s->irq_base = hvm_get_8u(h);
- s->init_state = hvm_get_8u(h);
- s->priority_add = hvm_get_8u(h);
- s->readsel_isr = hvm_get_8u(h);
-
- s->poll = hvm_get_8u(h);
- s->auto_eoi = hvm_get_8u(h);
-
- s->rotate_on_auto_eoi = hvm_get_8u(h);
- s->special_fully_nested_mode = hvm_get_8u(h);
- s->special_mask_mode = hvm_get_8u(h);
-
- s->elcr = hvm_get_8u(h);
- s->int_output = hvm_get_8u(h);
-
+ hvm_get_struct(h, s);
vpic_info(s);
return 0;
@@ -461,10 +427,10 @@ static int vpic_load(hvm_domain_context_t *h, void *opaque, int version_id)
void vpic_init(struct domain *d)
{
- struct vpic *vpic;
+ struct hvm_hw_vpic *vpic;
/* Master PIC. */
- vpic = &d->arch.hvm_domain.irq.vpic[0];
+ vpic = &d->arch.hvm_domain.vpic[0];
memset(vpic, 0, sizeof(*vpic));
vpic->is_master = 1;
vpic->elcr = 1 << 2;
@@ -482,7 +448,7 @@ void vpic_init(struct domain *d)
void vpic_irq_positive_edge(struct domain *d, int irq)
{
- struct vpic *vpic = &d->arch.hvm_domain.irq.vpic[irq >> 3];
+ struct hvm_hw_vpic *vpic = &d->arch.hvm_domain.vpic[irq >> 3];
uint8_t mask = 1 << (irq & 7);
ASSERT(irq <= 15);
@@ -498,7 +464,7 @@ void vpic_irq_positive_edge(struct domain *d, int irq)
void vpic_irq_negative_edge(struct domain *d, int irq)
{
- struct vpic *vpic = &d->arch.hvm_domain.irq.vpic[irq >> 3];
+ struct hvm_hw_vpic *vpic = &d->arch.hvm_domain.vpic[irq >> 3];
uint8_t mask = 1 << (irq & 7);
ASSERT(irq <= 15);
@@ -515,7 +481,7 @@ void vpic_irq_negative_edge(struct domain *d, int irq)
int cpu_get_pic_interrupt(struct vcpu *v, int *type)
{
int irq, vector;
- struct vpic *vpic = &v->domain->arch.hvm_domain.irq.vpic[0];
+ struct hvm_hw_vpic *vpic = &v->domain->arch.hvm_domain.vpic[0];
if ( !vlapic_accept_pic_intr(v) || !vpic->int_output )
return -1;
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index 35cc998585..eda4a3d028 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -26,6 +26,7 @@
#include <asm/hvm/vlapic.h>
#include <asm/hvm/io.h>
#include <public/hvm/params.h>
+#include <public/hvm/save.h>
typedef void SaveStateHandler(hvm_domain_context_t *h, void *opaque);
typedef int LoadStateHandler(hvm_domain_context_t *h, void *opaque, int version_id);
@@ -50,7 +51,11 @@ struct hvm_domain {
struct hvm_io_handler io_handler;
- struct hvm_irq irq;
+ /* Lock protects access to irq, vpic and vioapic. */
+ spinlock_t irq_lock;
+ struct hvm_hw_irq irq;
+ struct hvm_hw_vpic vpic[2]; /* 0=master; 1=slave */
+ struct hvm_hw_vioapic vioapic;
/* hvm_print_line() logging. */
char pbuf[80];
diff --git a/xen/include/asm-x86/hvm/irq.h b/xen/include/asm-x86/hvm/irq.h
index 44e9ab1cf5..7ac0f5b579 100644
--- a/xen/include/asm-x86/hvm/irq.h
+++ b/xen/include/asm-x86/hvm/irq.h
@@ -26,70 +26,7 @@
#include <xen/spinlock.h>
#include <asm/hvm/vpic.h>
#include <asm/hvm/vioapic.h>
-
-struct hvm_irq {
- /* Lock protects access to all other fields. */
- spinlock_t lock;
-
- /*
- * Virtual interrupt wires for a single PCI bus.
- * Indexed by: device*4 + INTx#.
- */
- DECLARE_BITMAP(pci_intx, 32*4);
-
- /*
- * Virtual interrupt wires for ISA devices.
- * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
- */
- DECLARE_BITMAP(isa_irq, 16);
-
- /* Virtual interrupt and via-link for paravirtual platform driver. */
- unsigned int callback_via_asserted;
- enum {
- HVMIRQ_callback_none,
- HVMIRQ_callback_gsi,
- HVMIRQ_callback_pci_intx
- } callback_via_type;
- union {
- unsigned int gsi;
- struct { uint8_t dev, intx; } pci;
- } callback_via;
-
- /*
- * PCI-ISA interrupt router.
- * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
- * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
- * The router provides a programmable mapping from each link to a GSI.
- */
- u8 pci_link_route[4];
-
- /* Number of INTx wires asserting each PCI-ISA link. */
- u8 pci_link_assert_count[4];
-
- /*
- * Number of wires asserting each GSI.
- *
- * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
- * except ISA IRQ 0, which is connected to GSI 2.
- * PCI links map into this space via the PCI-ISA bridge.
- *
- * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
- * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
- */
- u8 gsi_assert_count[VIOAPIC_NUM_PINS];
-
- /*
- * GSIs map onto PIC/IO-APIC in the usual way:
- * 0-7: Master 8259 PIC, IO-APIC pins 0-7
- * 8-15: Slave 8259 PIC, IO-APIC pins 8-15
- * 16+ : IO-APIC pins 16+
- */
- struct vpic vpic[2]; /* 0=master; 1=slave */
- struct vioapic vioapic;
-
- /* Last VCPU that was delivered a LowestPrio interrupt. */
- u8 round_robin_prev_vcpu;
-};
+#include <public/hvm/save.h>
#define hvm_pci_intx_gsi(dev, intx) \
(((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16)
diff --git a/xen/include/asm-x86/hvm/vioapic.h b/xen/include/asm-x86/hvm/vioapic.h
index 6a934b7b39..701bbdf36b 100644
--- a/xen/include/asm-x86/hvm/vioapic.h
+++ b/xen/include/asm-x86/hvm/vioapic.h
@@ -28,13 +28,7 @@
#include <xen/config.h>
#include <xen/types.h>
#include <xen/smp.h>
-
-#ifdef __ia64__
-#define VIOAPIC_IS_IOSAPIC 1
-#define VIOAPIC_NUM_PINS 24
-#else
-#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
-#endif
+#include <public/hvm/save.h>
#if !VIOAPIC_IS_IOSAPIC
#define VIOAPIC_VERSION_ID 0x11 /* IOAPIC version */
@@ -58,38 +52,9 @@
#define VIOAPIC_REG_VERSION 0x01
#define VIOAPIC_REG_ARB_ID 0x02 /* x86 IOAPIC only */
-#define domain_vioapic(d) (&(d)->arch.hvm_domain.irq.vioapic)
+#define domain_vioapic(d) (&(d)->arch.hvm_domain.vioapic)
#define vioapic_domain(v) (container_of((v), struct domain, \
- arch.hvm_domain.irq.vioapic))
-
-union vioapic_redir_entry
-{
- uint64_t bits;
- struct {
- uint8_t vector;
- uint8_t delivery_mode:3;
- uint8_t dest_mode:1;
- uint8_t delivery_status:1;
- uint8_t polarity:1;
- uint8_t remote_irr:1;
- uint8_t trig_mode:1;
- uint8_t mask:1;
- uint8_t reserve:7;
-#if !VIOAPIC_IS_IOSAPIC
- uint8_t reserved[4];
- uint8_t dest_id;
-#else
- uint8_t reserved[3];
- uint16_t dest_id;
-#endif
- } fields;
-};
-
-struct vioapic {
- uint32_t ioregsel, id;
- unsigned long base_address;
- union vioapic_redir_entry redirtbl[VIOAPIC_NUM_PINS];
-};
+ arch.hvm_domain.vioapic))
void vioapic_init(struct domain *d);
void vioapic_irq_positive_edge(struct domain *d, unsigned int irq);
diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index 0137b34515..4700f63fb5 100644
--- a/xen/include/asm-x86/hvm/vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -44,31 +44,28 @@
*/
#define VLAPIC_HW_DISABLED 0x1
#define VLAPIC_SW_DISABLED 0x2
-#define vlapic_sw_disabled(vlapic) ((vlapic)->disabled & VLAPIC_SW_DISABLED)
-#define vlapic_hw_disabled(vlapic) ((vlapic)->disabled & VLAPIC_HW_DISABLED)
-#define vlapic_disabled(vlapic) ((vlapic)->disabled)
-#define vlapic_enabled(vlapic) (!vlapic_disabled(vlapic))
+#define vlapic_sw_disabled(vlapic) ((vlapic)->hw.disabled & VLAPIC_SW_DISABLED)
+#define vlapic_hw_disabled(vlapic) ((vlapic)->hw.disabled & VLAPIC_HW_DISABLED)
+#define vlapic_disabled(vlapic) ((vlapic)->hw.disabled)
+#define vlapic_enabled(vlapic) (!vlapic_disabled(vlapic))
struct vlapic {
- uint64_t apic_base_msr;
- uint32_t disabled; /* VLAPIC_xx_DISABLED */
- uint32_t timer_divisor;
- struct periodic_time pt;
- int timer_pending_count;
- s_time_t timer_last_update;
- struct page_info *regs_page;
- void *regs;
+ struct hvm_hw_lapic hw;
+ struct hvm_hw_lapic_regs *regs;
+ struct periodic_time pt;
+ s_time_t timer_last_update;
+ struct page_info *regs_page;
};
static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
{
- return *((uint32_t *)(vlapic->regs + reg));
+ return *((uint32_t *)(&vlapic->regs->data[reg]));
}
static inline void vlapic_set_reg(
struct vlapic *vlapic, uint32_t reg, uint32_t val)
{
- *((uint32_t *)(vlapic->regs + reg)) = val;
+ *((uint32_t *)(&vlapic->regs->data[reg])) = val;
}
int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
diff --git a/xen/include/asm-x86/hvm/vpic.h b/xen/include/asm-x86/hvm/vpic.h
index 2195529df6..6bb9bb35ea 100644
--- a/xen/include/asm-x86/hvm/vpic.h
+++ b/xen/include/asm-x86/hvm/vpic.h
@@ -27,51 +27,7 @@
#ifndef __ASM_X86_HVM_VPIC_H__
#define __ASM_X86_HVM_VPIC_H__
-struct vpic {
- /* IR line bitmasks. */
- uint8_t irr, imr, isr;
-
- /* Line IRx maps to IRQ irq_base+x */
- uint8_t irq_base;
-
- /*
- * Where are we in ICW2-4 initialisation (0 means no init in progress)?
- * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
- * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence)
- * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
- */
- uint8_t init_state:4;
-
- /* IR line with highest priority. */
- uint8_t priority_add:4;
-
- /* Reads from A=0 obtain ISR or IRR? */
- uint8_t readsel_isr:1;
-
- /* Reads perform a polling read? */
- uint8_t poll:1;
-
- /* Automatically clear IRQs from the ISR during INTA? */
- uint8_t auto_eoi:1;
-
- /* Automatically rotate IRQ priorities during AEOI? */
- uint8_t rotate_on_auto_eoi:1;
-
- /* Exclude slave inputs when considering in-service IRQs? */
- uint8_t special_fully_nested_mode:1;
-
- /* Special mask mode excludes masked IRs from AEOI and priority checks. */
- uint8_t special_mask_mode:1;
-
- /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
- uint8_t is_master:1;
-
- /* Edge/trigger selection. */
- uint8_t elcr;
-
- /* Virtual INT output. */
- uint8_t int_output;
-};
+#include <public/hvm/save.h>
void vpic_irq_positive_edge(struct domain *d, int irq);
void vpic_irq_negative_edge(struct domain *d, int irq);
diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h
index e8a2e52f5a..367b3ec0a7 100644
--- a/xen/include/public/hvm/save.h
+++ b/xen/include/public/hvm/save.h
@@ -84,7 +84,6 @@ struct hvm_hw_cpu {
uint64_t idtr_base;
uint64_t gdtr_base;
-
uint32_t cs_arbytes;
uint32_t ds_arbytes;
uint32_t es_arbytes;
@@ -137,5 +136,182 @@ struct hvm_hw_pit {
};
+/*
+ * PIC
+ */
+#define HVM_SAVE_TYPE_PIC 3
+struct hvm_hw_vpic {
+ /* IR line bitmasks. */
+ uint8_t irr;
+ uint8_t imr;
+ uint8_t isr;
+
+ /* Line IRx maps to IRQ irq_base+x */
+ uint8_t irq_base;
+
+ /*
+ * Where are we in ICW2-4 initialisation (0 means no init in progress)?
+ * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
+ * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence)
+ * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
+ */
+ uint8_t init_state:4;
+
+ /* IR line with highest priority. */
+ uint8_t priority_add:4;
+
+ /* Reads from A=0 obtain ISR or IRR? */
+ uint8_t readsel_isr:1;
+
+ /* Reads perform a polling read? */
+ uint8_t poll:1;
+
+ /* Automatically clear IRQs from the ISR during INTA? */
+ uint8_t auto_eoi:1;
+
+ /* Automatically rotate IRQ priorities during AEOI? */
+ uint8_t rotate_on_auto_eoi:1;
+
+ /* Exclude slave inputs when considering in-service IRQs? */
+ uint8_t special_fully_nested_mode:1;
+
+ /* Special mask mode excludes masked IRs from AEOI and priority checks. */
+ uint8_t special_mask_mode:1;
+
+ /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
+ uint8_t is_master:1;
+
+ /* Edge/trigger selection. */
+ uint8_t elcr;
+
+ /* Virtual INT output. */
+ uint8_t int_output;
+};
+
+
+/*
+ * IO-APIC
+ */
+#define HVM_SAVE_TYPE_IOAPIC 4
+
+#ifdef __ia64__
+#define VIOAPIC_IS_IOSAPIC 1
+#define VIOAPIC_NUM_PINS 24
+#else
+#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
+#endif
+
+struct hvm_hw_vioapic {
+ uint64_t base_address;
+ uint32_t ioregsel;
+ uint32_t id;
+ union vioapic_redir_entry
+ {
+ uint64_t bits;
+ struct {
+ uint8_t vector;
+ uint8_t delivery_mode:3;
+ uint8_t dest_mode:1;
+ uint8_t delivery_status:1;
+ uint8_t polarity:1;
+ uint8_t remote_irr:1;
+ uint8_t trig_mode:1;
+ uint8_t mask:1;
+ uint8_t reserve:7;
+#if !VIOAPIC_IS_IOSAPIC
+ uint8_t reserved[4];
+ uint8_t dest_id;
+#else
+ uint8_t reserved[3];
+ uint16_t dest_id;
+#endif
+ } fields;
+ } redirtbl[VIOAPIC_NUM_PINS];
+};
+
+
+/*
+ * IRQ
+ */
+#define HVM_SAVE_TYPE_IRQ 5
+struct hvm_hw_irq {
+ /*
+ * Virtual interrupt wires for a single PCI bus.
+ * Indexed by: device*4 + INTx#.
+ */
+ DECLARE_BITMAP(pci_intx, 32*4);
+
+ /*
+ * Virtual interrupt wires for ISA devices.
+ * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
+ */
+ DECLARE_BITMAP(isa_irq, 16);
+
+ /* Virtual interrupt and via-link for paravirtual platform driver. */
+ uint32_t callback_via_asserted;
+ union {
+ enum {
+ HVMIRQ_callback_none,
+ HVMIRQ_callback_gsi,
+ HVMIRQ_callback_pci_intx
+ } callback_via_type;
+ uint32_t pad; /* So the next field will be aligned */
+ };
+ union {
+ uint32_t gsi;
+ struct { uint8_t dev, intx; } pci;
+ } callback_via;
+
+ /*
+ * PCI-ISA interrupt router.
+ * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
+ * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
+ * The router provides a programmable mapping from each link to a GSI.
+ */
+ u8 pci_link_route[4];
+
+ /* Number of INTx wires asserting each PCI-ISA link. */
+ u8 pci_link_assert_count[4];
+
+ /*
+ * Number of wires asserting each GSI.
+ *
+ * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
+ * except ISA IRQ 0, which is connected to GSI 2.
+ * PCI links map into this space via the PCI-ISA bridge.
+ *
+ * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
+ * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16
+ */
+ u8 gsi_assert_count[VIOAPIC_NUM_PINS];
+
+ /*
+ * GSIs map onto PIC/IO-APIC in the usual way:
+ * 0-7: Master 8259 PIC, IO-APIC pins 0-7
+ * 8-15: Slave 8259 PIC, IO-APIC pins 8-15
+ * 16+ : IO-APIC pins 16+
+ */
+
+ /* Last VCPU that was delivered a LowestPrio interrupt. */
+ u8 round_robin_prev_vcpu;
+};
+
+
+/*
+ * LAPIC
+ */
+#define HVM_SAVE_TYPE_LAPIC 6
+struct hvm_hw_lapic {
+ uint64_t apic_base_msr;
+ uint32_t disabled; /* VLAPIC_xx_DISABLED */
+ uint32_t timer_divisor;
+};
+
+#define HVM_SAVE_TYPE_LAPIC_REGS 7
+
+struct hvm_hw_lapic_regs {
+ /* A 4k page of register state */
+ uint8_t data[0x400];
+};
#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */