|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH V3] x86/HVM: Introduce struct hvm_pi_ops
The current function pointers in struct vmx_domain for managing hvm
posted interrupt can be used also by SVM AVIC. Therefore, this patch
introduces the struct hvm_pi_ops in the struct hvm_domain to hold them.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Kevin Tian <kevin.tian@xxxxxxxxx>
Cc: Jun Nakajima <jun.nakajima@xxxxxxxxx>
---
Changes from V2:
* Remove "pi_" prefix from the function pointers.
* Reword and move VMX-specific description.
NOTE: I have separated this patch out from the AMD AVIC patch series
since this mainly affects HVM and VMX code.
xen/arch/x86/hvm/vmx/vmx.c | 73 +++++++++++++++++++++++++++++---------
xen/include/asm-x86/hvm/domain.h | 34 ++++++++++++++++++
xen/include/asm-x86/hvm/hvm.h | 4 +--
xen/include/asm-x86/hvm/vmx/vmcs.h | 59 ------------------------------
4 files changed, 93 insertions(+), 77 deletions(-)
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 7b2c50c..0854e17 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -103,6 +103,47 @@ void vmx_pi_per_cpu_init(unsigned int cpu)
spin_lock_init(&per_cpu(vmx_pi_blocking, cpu).lock);
}
+/*
+ * To handle posted interrupts correctly, we need to set the following
+ * state:
+ *
+ * * The PI notification vector (NV)
+ * * The PI notification destination processor (NDST)
+ * * The PI "suppress notification" bit (SN)
+ * * The vcpu pi "blocked" list
+ *
+ * VMX implements the runstate transitions as the following:
+ *
+ * A: runnable -> running
+ * - SN = 0
+ * - NDST = v->processor
+ * If a VM is currently running, we want the PI delivered to the guest vcpu
+ * on the proper pcpu.
+ *
+ * B: running -> runnable
+ * - SN = 1
+ *
+ * C: running -> blocked
+ * - SN = 0
+ * - NV = pi_wakeup_vector
+ * - Add vcpu to blocked list
+ * If the vm is blocked, we want the PI delivered to Xen so that it can
+ * wake it up.
+ *
+ * D: blocked -> runnable
+ * - SN = 0
+ * - NV = posted_intr_vector
+ * - Take vcpu off blocked list
+ * If the VM is currently either preempted or offline (i.e., not running
+ * because of some reason other than blocking waiting for an interrupt),
+ * there's nothing Xen can do -- we want the interrupt pending bit set in
+ * the guest, but we don't want to bother Xen with an interrupt (SN clear).
+ *
+ * There's a brief window of time between vmx_intr_assist() and checking
+ * softirqs where if an interrupt comes in it may be lost; so we need Xen
+ * to get an interrupt and raise a softirq so that it will go through the
+ * vmx_intr_assist() path again (SN clear, NV = posted_interrupt).
+ */
static void vmx_vcpu_block(struct vcpu *v)
{
unsigned long flags;
@@ -204,12 +245,12 @@ void vmx_pi_hooks_assign(struct domain *d)
if ( !iommu_intpost || !has_hvm_container_domain(d) )
return;
- ASSERT(!d->arch.hvm_domain.vmx.vcpu_block);
+ ASSERT(!d->arch.hvm_domain.pi_ops.vcpu_block);
- d->arch.hvm_domain.vmx.vcpu_block = vmx_vcpu_block;
- d->arch.hvm_domain.vmx.pi_switch_from = vmx_pi_switch_from;
- d->arch.hvm_domain.vmx.pi_switch_to = vmx_pi_switch_to;
- d->arch.hvm_domain.vmx.pi_do_resume = vmx_pi_do_resume;
+ d->arch.hvm_domain.pi_ops.vcpu_block = vmx_vcpu_block;
+ d->arch.hvm_domain.pi_ops.switch_from = vmx_pi_switch_from;
+ d->arch.hvm_domain.pi_ops.switch_to = vmx_pi_switch_to;
+ d->arch.hvm_domain.pi_ops.do_resume = vmx_pi_do_resume;
}
/* This function is called when pcidevs_lock is held */
@@ -218,12 +259,12 @@ void vmx_pi_hooks_deassign(struct domain *d)
if ( !iommu_intpost || !has_hvm_container_domain(d) )
return;
- ASSERT(d->arch.hvm_domain.vmx.vcpu_block);
+ ASSERT(d->arch.hvm_domain.pi_ops.vcpu_block);
- d->arch.hvm_domain.vmx.vcpu_block = NULL;
- d->arch.hvm_domain.vmx.pi_switch_from = NULL;
- d->arch.hvm_domain.vmx.pi_switch_to = NULL;
- d->arch.hvm_domain.vmx.pi_do_resume = NULL;
+ d->arch.hvm_domain.pi_ops.vcpu_block = NULL;
+ d->arch.hvm_domain.pi_ops.switch_from = NULL;
+ d->arch.hvm_domain.pi_ops.switch_to = NULL;
+ d->arch.hvm_domain.pi_ops.do_resume = NULL;
}
static int vmx_domain_initialise(struct domain *d)
@@ -901,8 +942,8 @@ static void vmx_ctxt_switch_from(struct vcpu *v)
vmx_restore_host_msrs();
vmx_save_dr(v);
- if ( v->domain->arch.hvm_domain.vmx.pi_switch_from )
- v->domain->arch.hvm_domain.vmx.pi_switch_from(v);
+ if ( v->domain->arch.hvm_domain.pi_ops.switch_from )
+ v->domain->arch.hvm_domain.pi_ops.switch_from(v);
}
static void vmx_ctxt_switch_to(struct vcpu *v)
@@ -916,8 +957,8 @@ static void vmx_ctxt_switch_to(struct vcpu *v)
vmx_restore_guest_msrs(v);
vmx_restore_dr(v);
- if ( v->domain->arch.hvm_domain.vmx.pi_switch_to )
- v->domain->arch.hvm_domain.vmx.pi_switch_to(v);
+ if ( v->domain->arch.hvm_domain.pi_ops.switch_to )
+ v->domain->arch.hvm_domain.pi_ops.switch_to(v);
}
@@ -3963,8 +4004,8 @@ void vmx_vmenter_helper(const struct cpu_user_regs *regs)
struct hvm_vcpu_asid *p_asid;
bool_t need_flush;
- if ( curr->domain->arch.hvm_domain.vmx.pi_do_resume )
- curr->domain->arch.hvm_domain.vmx.pi_do_resume(curr);
+ if ( curr->domain->arch.hvm_domain.pi_ops.do_resume )
+ curr->domain->arch.hvm_domain.pi_ops.do_resume(curr);
if ( !cpu_has_vmx_vpid )
goto out;
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index f34d784..f7674cd 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -72,6 +72,38 @@ struct hvm_ioreq_server {
bool_t bufioreq_atomic;
};
+/*
+ * This structure defines function hooks to support hardware-assisted
+ * virtual interrupt delivery to guest. (e.g. VMX PI and SVM AVIC).
+ *
+ * The way we implement this now is by looking at what needs to happen on
+ * the following runstate transitions:
+ *
+ * A: runnable -> running : switch_to
+ * B: running -> runnable : switch_from
+ * C: running -> blocked : vcpu_block
+ * D: blocked -> runnable : do_resume
+ *
+ * For transitions A and B, we add hooks into ctx_switch_{to,from} paths.
+ *
+ * For transition C, we add a new arch hook, arch_vcpu_block(), which is
+ * called from vcpu_block() and vcpu_do_poll().
+ *
+ * For transition D, rather than add an extra arch hook on vcpu_wake, we
+ * add a hook on the vmentry path which checks to see if either of the two
+ * actions need to be taken.
+ *
+ * These hooks only need to be called when the domain in question actually
+ * has a physical device assigned to it, so we set and clear the callbacks
+ * as appropriate when device assignment changes.
+ */
+struct hvm_pi_ops {
+ void (*vcpu_block) (struct vcpu *);
+ void (*switch_from) (struct vcpu *v);
+ void (*switch_to) (struct vcpu *v);
+ void (*do_resume) (struct vcpu *v);
+};
+
struct hvm_domain {
/* Guest page range used for non-default ioreq servers */
struct {
@@ -148,6 +180,8 @@ struct hvm_domain {
struct list_head list;
} write_map;
+ struct hvm_pi_ops pi_ops;
+
union {
struct vmx_domain vmx;
struct svm_domain svm;
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 7e7462e..b1e4c75 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -638,8 +638,8 @@ unsigned long hvm_cr4_guest_reserved_bits(const struct vcpu
*v, bool_t restore);
struct vcpu *v_ = (v); \
struct domain *d_ = v_->domain; \
if ( has_hvm_container_domain(d_) && \
- (cpu_has_vmx && d_->arch.hvm_domain.vmx.vcpu_block) ) \
- d_->arch.hvm_domain.vmx.vcpu_block(v_); \
+ (d_->arch.hvm_domain.pi_ops.vcpu_block) ) \
+ d_->arch.hvm_domain.pi_ops.vcpu_block(v_); \
})
#endif /* __ASM_X86_HVM_HVM_H__ */
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h
b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 997f4f5..4ec8b08 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -77,65 +77,6 @@ struct vmx_domain {
unsigned long apic_access_mfn;
/* VMX_DOMAIN_* */
unsigned int status;
-
- /*
- * To handle posted interrupts correctly, we need to set the following
- * state:
- *
- * * The PI notification vector (NV)
- * * The PI notification destination processor (NDST)
- * * The PI "suppress notification" bit (SN)
- * * The vcpu pi "blocked" list
- *
- * If a VM is currently running, we want the PI delivered to the guest vcpu
- * on the proper pcpu (NDST = v->processor, SN clear).
- *
- * If the vm is blocked, we want the PI delivered to Xen so that it can
- * wake it up (SN clear, NV = pi_wakeup_vector, vcpu on block list).
- *
- * If the VM is currently either preempted or offline (i.e., not running
- * because of some reason other than blocking waiting for an interrupt),
- * there's nothing Xen can do -- we want the interrupt pending bit set in
- * the guest, but we don't want to bother Xen with an interrupt (SN clear).
- *
- * There's a brief window of time between vmx_intr_assist() and checking
- * softirqs where if an interrupt comes in it may be lost; so we need Xen
- * to get an interrupt and raise a softirq so that it will go through the
- * vmx_intr_assist() path again (SN clear, NV = posted_interrupt).
- *
- * The way we implement this now is by looking at what needs to happen on
- * the following runstate transitions:
- *
- * A: runnable -> running
- * - SN = 0
- * - NDST = v->processor
- * B: running -> runnable
- * - SN = 1
- * C: running -> blocked
- * - NV = pi_wakeup_vector
- * - Add vcpu to blocked list
- * D: blocked -> runnable
- * - NV = posted_intr_vector
- * - Take vcpu off blocked list
- *
- * For transitions A and B, we add hooks into vmx_ctxt_switch_{from,to}
- * paths.
- *
- * For transition C, we add a new arch hook, arch_vcpu_block(), which is
- * called from vcpu_block() and vcpu_do_poll().
- *
- * For transition D, rather than add an extra arch hook on vcpu_wake, we
- * add a hook on the vmentry path which checks to see if either of the two
- * actions need to be taken.
- *
- * These hooks only need to be called when the domain in question actually
- * has a physical device assigned to it, so we set and clear the callbacks
- * as appropriate when device assignment changes.
- */
- void (*vcpu_block) (struct vcpu *);
- void (*pi_switch_from) (struct vcpu *v);
- void (*pi_switch_to) (struct vcpu *v);
- void (*pi_do_resume) (struct vcpu *v);
};
struct pi_desc {
--
1.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |