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:
Paul Durrant authored and Jan Beulich committed 2019-04-05 10:32:57 +02:00
1 parent 26fba3c855
commit fda96b7382
6 files changed
+85 -1

No files matched your search

+6
View File
@@ -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
+6
View File
@@ -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.
+3
View File
@@ -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,
+1
View File
@@ -237,6 +237,7 @@ libxl_viridian_enlightenment = Enumeration("viridian_enlightenment", [
(6, "crash_ctl"),
(7, "synic"),
(8, "stimer"),
(9, "hcall_ipi"),
])
libxl_hdtype = Enumeration("hdtype", [
+63
View File
@@ -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);
+6 -1
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.