mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
viridian: add implementation of the HvSendSyntheticClusterIpi hypercall
This patch adds an implementation of the hypercall as documented in the specification [1], section 10.5.2. This enlightenment, as with others, is advertised by CPUID leaf 0x40000004 and is under control of a new 'hcall_ipi' option in libxl. If used, this enlightenment should mean the guest only takes a single VMEXIT to issue IPIs to multiple vCPUs rather than the multiple VMEXITs that would result from using the emulated local APIC. [1] https://github.com/MicrosoftDocs/Virtualization-Documentation/raw/live/tlfs/Hypervisor%20Top%20Level%20Functional%20Specification%20v5.0C.pdf Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Acked-by: Wei Liu <wei.liu2@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
26fba3c855
commit
fda96b7382
6 files changed
+85
-1
No files matched your search
@@ -2175,6 +2175,12 @@ ticks and hence enabling this group will ensure that ticks will be
|
||||
consistent with use of an enlightened time source (B<time_ref_count> or
|
||||
B<reference_tsc>).
|
||||
|
||||
=item B<hcall_ipi>
|
||||
|
||||
This set incorporates use of a hypercall for interprocessor interrupts.
|
||||
This enlightenment may improve performance of Windows guests with multiple
|
||||
virtual CPUs.
|
||||
|
||||
=item B<defaults>
|
||||
|
||||
This is a special value that enables the default set of groups, which
|
||||
|
||||
@@ -330,6 +330,12 @@
|
||||
*/
|
||||
#define LIBXL_HAVE_VIRIDIAN_STIMER 1
|
||||
|
||||
/*
|
||||
* LIBXL_HAVE_VIRIDIAN_HCALL_IPI indicates that the 'hcall_ipi' value
|
||||
* is present in the viridian enlightenment enumeration.
|
||||
*/
|
||||
#define LIBXL_HAVE_VIRIDIAN_HCALL_IPI 1
|
||||
|
||||
/*
|
||||
* LIBXL_HAVE_BUILDINFO_HVM_ACPI_LAPTOP_SLATE indicates that
|
||||
* libxl_domain_build_info has the u.hvm.acpi_laptop_slate field.
|
||||
|
||||
@@ -324,6 +324,9 @@ static int hvm_set_viridian_features(libxl__gc *gc, uint32_t domid,
|
||||
if (libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_STIMER))
|
||||
mask |= HVMPV_time_ref_count | HVMPV_synic | HVMPV_stimer;
|
||||
|
||||
if (libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_IPI))
|
||||
mask |= HVMPV_hcall_ipi;
|
||||
|
||||
if (mask != 0 &&
|
||||
xc_hvm_param_set(CTX->xch,
|
||||
domid,
|
||||
|
||||
@@ -237,6 +237,7 @@ libxl_viridian_enlightenment = Enumeration("viridian_enlightenment", [
|
||||
(6, "crash_ctl"),
|
||||
(7, "synic"),
|
||||
(8, "stimer"),
|
||||
(9, "hcall_ipi"),
|
||||
])
|
||||
|
||||
libxl_hdtype = Enumeration("hdtype", [
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define HvFlushVirtualAddressSpace 0x0002
|
||||
#define HvFlushVirtualAddressList 0x0003
|
||||
#define HvNotifyLongSpinWait 0x0008
|
||||
#define HvSendSyntheticClusterIpi 0x000b
|
||||
#define HvGetPartitionId 0x0046
|
||||
#define HvExtCallQueryCapabilities 0x8001
|
||||
|
||||
@@ -95,6 +96,7 @@ typedef union _HV_CRASH_CTL_REG_CONTENTS
|
||||
#define CPUID4A_HCALL_REMOTE_TLB_FLUSH (1 << 2)
|
||||
#define CPUID4A_MSR_BASED_APIC (1 << 3)
|
||||
#define CPUID4A_RELAX_TIMER_INT (1 << 5)
|
||||
#define CPUID4A_SYNTHETIC_CLUSTER_IPI (1 << 10)
|
||||
|
||||
/* Viridian CPUID leaf 6: Implementation HW features detected and in use */
|
||||
#define CPUID6A_APIC_OVERLAY (1 << 0)
|
||||
@@ -206,6 +208,8 @@ void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
|
||||
res->a |= CPUID4A_HCALL_REMOTE_TLB_FLUSH;
|
||||
if ( !cpu_has_vmx_apic_reg_virt )
|
||||
res->a |= CPUID4A_MSR_BASED_APIC;
|
||||
if ( viridian_feature_mask(d) & HVMPV_hcall_ipi )
|
||||
res->a |= CPUID4A_SYNTHETIC_CLUSTER_IPI;
|
||||
|
||||
/*
|
||||
* This value is the recommended number of attempts to try to
|
||||
@@ -628,6 +632,65 @@ int viridian_hypercall(struct cpu_user_regs *regs)
|
||||
break;
|
||||
}
|
||||
|
||||
case HvSendSyntheticClusterIpi:
|
||||
{
|
||||
struct vcpu *v;
|
||||
uint32_t vector;
|
||||
uint64_t vcpu_mask;
|
||||
|
||||
status = HV_STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Get input parameters. */
|
||||
if ( input.fast )
|
||||
{
|
||||
if ( input_params_gpa >> 32 )
|
||||
break;
|
||||
|
||||
vector = input_params_gpa;
|
||||
vcpu_mask = output_params_gpa;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct {
|
||||
uint32_t vector;
|
||||
uint8_t target_vtl;
|
||||
uint8_t reserved_zero[3];
|
||||
uint64_t vcpu_mask;
|
||||
} input_params;
|
||||
|
||||
if ( hvm_copy_from_guest_phys(&input_params, input_params_gpa,
|
||||
sizeof(input_params)) !=
|
||||
HVMTRANS_okay )
|
||||
break;
|
||||
|
||||
if ( input_params.target_vtl ||
|
||||
input_params.reserved_zero[0] ||
|
||||
input_params.reserved_zero[1] ||
|
||||
input_params.reserved_zero[2] )
|
||||
break;
|
||||
|
||||
vector = input_params.vector;
|
||||
vcpu_mask = input_params.vcpu_mask;
|
||||
}
|
||||
|
||||
if ( vector < 0x10 || vector > 0xff )
|
||||
break;
|
||||
|
||||
for_each_vcpu ( currd, v )
|
||||
{
|
||||
if ( v->vcpu_id >= (sizeof(vcpu_mask) * 8) )
|
||||
break;
|
||||
|
||||
if ( !(vcpu_mask & (1ul << v->vcpu_id)) )
|
||||
continue;
|
||||
|
||||
vlapic_set_irq(vcpu_vlapic(v), vector, 0);
|
||||
}
|
||||
|
||||
status = HV_STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
gprintk(XENLOG_WARNING, "unimplemented hypercall %04x\n",
|
||||
input.call_code);
|
||||
|
||||
@@ -154,6 +154,10 @@
|
||||
#define _HVMPV_stimer 8
|
||||
#define HVMPV_stimer (1 << _HVMPV_stimer)
|
||||
|
||||
/* Use Synthetic Cluster IPI Hypercall */
|
||||
#define _HVMPV_hcall_ipi 9
|
||||
#define HVMPV_hcall_ipi (1 << _HVMPV_hcall_ipi)
|
||||
|
||||
#define HVMPV_feature_mask \
|
||||
(HVMPV_base_freq | \
|
||||
HVMPV_no_freq | \
|
||||
@@ -163,7 +167,8 @@
|
||||
HVMPV_apic_assist | \
|
||||
HVMPV_crash_ctl | \
|
||||
HVMPV_synic | \
|
||||
HVMPV_stimer)
|
||||
HVMPV_stimer | \
|
||||
HVMPV_hcall_ipi)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||