domain_unpause(d);
}
+/*
+ * This function is used to update the IRTE for posted-interrupt
+ * when guest changes MSI/MSI-X information.
+ */
+static int cf_check vmx_pi_update_irte(const struct vcpu *v,
+ const struct pirq *pirq, uint8_t gvec)
+{
+ const struct pi_desc *pi_desc = v ? &v->arch.hvm.vmx.pi_desc : NULL;
+ struct irq_desc *desc;
+ struct msi_desc *msi_desc;
+ int rc;
+
+ desc = pirq_spin_lock_irq_desc(pirq, NULL);
+ if ( !desc )
+ return -EINVAL;
+
+ msi_desc = desc->msi_desc;
+ if ( !msi_desc )
+ {
+ rc = -ENODEV;
+ goto unlock_out;
+ }
+ msi_desc->pi_desc = pi_desc;
+ msi_desc->gvec = gvec;
+
+ spin_unlock_irq(&desc->lock);
+
+ ASSERT(pcidevs_locked());
+
+ return iommu_update_ire_from_msi(msi_desc, &msi_desc->msg);
+
+ unlock_out:
+ spin_unlock_irq(&desc->lock);
+
+ return rc;
+}
+
static const struct lbr_info {
u32 base, count;
} p4_lbr[] = {
{
alloc_direct_apic_vector(&posted_intr_vector, pi_notification_interrupt);
if ( iommu_intpost )
+ {
alloc_direct_apic_vector(&pi_wakeup_vector, pi_wakeup_interrupt);
+ vmx_function_table.pi_update_irte = vmx_pi_update_irte;
+ }
+
vmx_function_table.deliver_posted_intr = vmx_deliver_posted_intr;
vmx_function_table.sync_pir_to_irr = vmx_sync_pir_to_irr;
vmx_function_table.test_pir = vmx_test_pir;
#include <asm/x86_emulate.h>
#include <asm/hvm/asid.h>
+struct pirq; /* needed by pi_update_irte */
+
#ifdef CONFIG_HVM_FEP
/* Permit use of the Forced Emulation Prefix in HVM guests */
extern bool_t opt_hvm_fep;
void (*sync_pir_to_irr)(struct vcpu *v);
bool (*test_pir)(const struct vcpu *v, uint8_t vector);
void (*handle_eoi)(uint8_t vector, int isr);
+ int (*pi_update_irte)(const struct vcpu *v, const struct pirq *pirq,
+ uint8_t gvec);
/*Walk nested p2m */
int (*nhvm_hap_walk_L1_p2m)(struct vcpu *v, paddr_t L2_gpa,
alternative_vcall(hvm_funcs.set_nonreg_state, v, nrs);
}
+static inline int hvm_pi_update_irte(const struct vcpu *v,
+ const struct pirq *pirq, uint8_t gvec)
+{
+ return alternative_call(hvm_funcs.pi_update_irte, v, pirq, gvec);
+}
+
#else /* CONFIG_HVM */
#define hvm_enabled false
#include <asm/apicdef.h>
#include <asm/cache.h>
#include <asm/processor.h>
-#include <asm/hvm/vmx/vmcs.h>
#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
extern bool untrusted_msi;
-int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
- const uint8_t gvec);
-
extern bool iommu_non_coherent, iommu_superpages;
static inline void iommu_sync_cache(const void *addr, unsigned int size)
for_each_drhd_unit ( drhd )
disable_qinval(drhd->iommu);
}
-
-/*
- * This function is used to update the IRTE for posted-interrupt
- * when guest changes MSI/MSI-X information.
- */
-int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
- const uint8_t gvec)
-{
- struct irq_desc *desc;
- struct msi_desc *msi_desc;
- int rc;
-
- desc = pirq_spin_lock_irq_desc(pirq, NULL);
- if ( !desc )
- return -EINVAL;
-
- msi_desc = desc->msi_desc;
- if ( !msi_desc )
- {
- rc = -ENODEV;
- goto unlock_out;
- }
- msi_desc->pi_desc = pi_desc;
- msi_desc->gvec = gvec;
-
- spin_unlock_irq(&desc->lock);
-
- ASSERT(pcidevs_locked());
-
- return msi_msg_write_remap_rte(msi_desc, &msi_desc->msg);
-
- unlock_out:
- spin_unlock_irq(&desc->lock);
-
- return rc;
-}
/* Use interrupt posting if it is supported. */
if ( iommu_intpost )
- pi_update_irte(vcpu ? &vcpu->arch.hvm.vmx.pi_desc : NULL,
- info, pirq_dpci->gmsi.gvec);
+ hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
if ( pt_irq_bind->u.msi.gflags & XEN_DOMCTL_VMSI_X86_UNMASKED )
{
what = "bogus";
}
else if ( pirq_dpci && pirq_dpci->gmsi.posted )
- pi_update_irte(NULL, pirq, 0);
+ hvm_pi_update_irte(NULL, pirq, 0);
if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) &&
list_empty(&pirq_dpci->digl_list) )