aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-03-17 18:33:05 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-03-17 18:33:05 +0000
commitd649689a8ecb2e276cc20d3af6d416e3c299cb17 (patch)
tree0e95f648151a0d24a2b44a07e2588d1f10809e96 /target
parentcc818a2148c5f321bdeb8e5564bdb2914e824600 (diff)
parent32b9523ad5b44dea87792d5d8f71a87e8cc5803b (diff)
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* Bugfixes all over the place * get/set_uint cleanups (Felipe) * Lock guard support (Stefan) * MemoryRegion ownership cleanup (Philippe) * AVX512 optimization for buffer_is_zero (Robert) # gpg: Signature made Tue 17 Mar 2020 15:01:54 GMT # gpg: using RSA key BFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (62 commits) hw/arm: Let devices own the MemoryRegion they create hw/arm: Remove unnecessary memory_region_set_readonly() on ROM alias hw/ppc/ppc405: Use memory_region_init_rom() with read-only regions hw/arm/stm32: Use memory_region_init_rom() with read-only regions hw/char: Let devices own the MemoryRegion they create hw/riscv: Let devices own the MemoryRegion they create hw/dma: Let devices own the MemoryRegion they create hw/display: Let devices own the MemoryRegion they create hw/core: Let devices own the MemoryRegion they create scripts/cocci: Patch to let devices own their MemoryRegions scripts/cocci: Patch to remove unnecessary memory_region_set_readonly() scripts/cocci: Patch to detect potential use of memory_region_init_rom hw/sparc: Use memory_region_init_rom() with read-only regions hw/sh4: Use memory_region_init_rom() with read-only regions hw/riscv: Use memory_region_init_rom() with read-only regions hw/ppc: Use memory_region_init_rom() with read-only regions hw/pci-host: Use memory_region_init_rom() with read-only regions hw/net: Use memory_region_init_rom() with read-only regions hw/m68k: Use memory_region_init_rom() with read-only regions hw/display: Use memory_region_init_rom() with read-only regions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/cpu.c22
-rw-r--r--target/i386/hax-posix.c33
-rw-r--r--target/i386/hax-windows.c33
-rw-r--r--target/i386/sev.c106
-rw-r--r--target/i386/whp-dispatch.h9
-rw-r--r--target/i386/whpx-all.c162
-rw-r--r--target/s390x/ioinst.c2
7 files changed, 145 insertions, 222 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3623ecefbd..7fe367078c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1153,22 +1153,6 @@ static void arm_set_pmu(Object *obj, bool value, Error **errp)
cpu->has_pmu = value;
}
-static void arm_get_init_svtor(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- ARMCPU *cpu = ARM_CPU(obj);
-
- visit_type_uint32(v, name, &cpu->init_svtor, errp);
-}
-
-static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- ARMCPU *cpu = ARM_CPU(obj);
-
- visit_type_uint32(v, name, &cpu->init_svtor, errp);
-}
-
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
{
/*
@@ -1288,9 +1272,9 @@ void arm_cpu_post_init(Object *obj)
* a simple DEFINE_PROP_UINT32 for this because we want to permit
* the property to be set after realize.
*/
- object_property_add(obj, "init-svtor", "uint32",
- arm_get_init_svtor, arm_set_init_svtor,
- NULL, NULL, &error_abort);
+ object_property_add_uint32_ptr(obj, "init-svtor",
+ &cpu->init_svtor,
+ OBJ_PROP_FLAG_READWRITE, &error_abort);
}
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property);
diff --git a/target/i386/hax-posix.c b/target/i386/hax-posix.c
index a5426a6dac..3bad89f133 100644
--- a/target/i386/hax-posix.c
+++ b/target/i386/hax-posix.c
@@ -108,41 +108,12 @@ int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
static char *hax_vm_devfs_string(int vm_id)
{
- char *name;
-
- if (vm_id > MAX_VM_ID) {
- fprintf(stderr, "Too big VM id\n");
- return NULL;
- }
-
-#define HAX_VM_DEVFS "/dev/hax_vm/vmxx"
- name = g_strdup(HAX_VM_DEVFS);
- if (!name) {
- return NULL;
- }
-
- snprintf(name, sizeof HAX_VM_DEVFS, "/dev/hax_vm/vm%02d", vm_id);
- return name;
+ return g_strdup_printf("/dev/hax_vm/vm%02d", vm_id);
}
static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
{
- char *name;
-
- if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
- fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
- return NULL;
- }
-
-#define HAX_VCPU_DEVFS "/dev/hax_vmxx/vcpuxx"
- name = g_strdup(HAX_VCPU_DEVFS);
- if (!name) {
- return NULL;
- }
-
- snprintf(name, sizeof HAX_VCPU_DEVFS, "/dev/hax_vm%02d/vcpu%02d",
- vm_id, vcpu_id);
- return name;
+ return g_strdup_printf("/dev/hax_vm%02d/vcpu%02d", vm_id, vcpu_id);
}
int hax_host_create_vm(struct hax_state *hax, int *vmid)
diff --git a/target/i386/hax-windows.c b/target/i386/hax-windows.c
index 5729ad9b48..0ba488c468 100644
--- a/target/i386/hax-windows.c
+++ b/target/i386/hax-windows.c
@@ -185,41 +185,12 @@ int hax_mod_version(struct hax_state *hax, struct hax_module_version *version)
static char *hax_vm_devfs_string(int vm_id)
{
- char *name;
-
- if (vm_id > MAX_VM_ID) {
- fprintf(stderr, "Too big VM id\n");
- return NULL;
- }
-
-#define HAX_VM_DEVFS "\\\\.\\hax_vmxx"
- name = g_strdup(HAX_VM_DEVFS);
- if (!name) {
- return NULL;
- }
-
- snprintf(name, sizeof HAX_VM_DEVFS, "\\\\.\\hax_vm%02d", vm_id);
- return name;
+ return g_strdup_printf("/dev/hax_vm/vm%02d", vm_id);
}
static char *hax_vcpu_devfs_string(int vm_id, int vcpu_id)
{
- char *name;
-
- if (vm_id > MAX_VM_ID || vcpu_id > MAX_VCPU_ID) {
- fprintf(stderr, "Too big vm id %x or vcpu id %x\n", vm_id, vcpu_id);
- return NULL;
- }
-
-#define HAX_VCPU_DEVFS "\\\\.\\hax_vmxx_vcpuxx"
- name = g_strdup(HAX_VCPU_DEVFS);
- if (!name) {
- return NULL;
- }
-
- snprintf(name, sizeof HAX_VCPU_DEVFS, "\\\\.\\hax_vm%02d_vcpu%02d",
- vm_id, vcpu_id);
- return name;
+ return g_strdup_printf("/dev/hax_vm%02d/vcpu%02d", vm_id, vcpu_id);
}
int hax_host_create_vm(struct hax_state *hax, int *vmid)
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 024bb24e51..846018a12d 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -267,109 +267,21 @@ qsev_guest_class_init(ObjectClass *oc, void *data)
}
static void
-qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
- uint32_t value;
-
- visit_type_uint32(v, name, &value, errp);
- sev->handle = value;
-}
-
-static void
-qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
- uint32_t value;
-
- visit_type_uint32(v, name, &value, errp);
- sev->policy = value;
-}
-
-static void
-qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
- uint32_t value;
-
- visit_type_uint32(v, name, &value, errp);
- sev->cbitpos = value;
-}
-
-static void
-qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
- uint32_t value;
-
- visit_type_uint32(v, name, &value, errp);
- sev->reduced_phys_bits = value;
-}
-
-static void
-qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- uint32_t value;
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
-
- value = sev->policy;
- visit_type_uint32(v, name, &value, errp);
-}
-
-static void
-qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- uint32_t value;
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
-
- value = sev->handle;
- visit_type_uint32(v, name, &value, errp);
-}
-
-static void
-qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- uint32_t value;
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
-
- value = sev->cbitpos;
- visit_type_uint32(v, name, &value, errp);
-}
-
-static void
-qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- uint32_t value;
- QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
-
- value = sev->reduced_phys_bits;
- visit_type_uint32(v, name, &value, errp);
-}
-
-static void
qsev_guest_init(Object *obj)
{
QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
sev->policy = DEFAULT_GUEST_POLICY;
- object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
- qsev_guest_set_policy, NULL, NULL, NULL);
- object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
- qsev_guest_set_handle, NULL, NULL, NULL);
- object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos,
- qsev_guest_set_cbitpos, NULL, NULL, NULL);
- object_property_add(obj, "reduced-phys-bits", "uint32",
- qsev_guest_get_reduced_phys_bits,
- qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL);
+ object_property_add_uint32_ptr(obj, "policy", &sev->policy,
+ OBJ_PROP_FLAG_READWRITE, NULL);
+ object_property_add_uint32_ptr(obj, "handle", &sev->handle,
+ OBJ_PROP_FLAG_READWRITE, NULL);
+ object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
+ OBJ_PROP_FLAG_READWRITE, NULL);
+ object_property_add_uint32_ptr(obj, "reduced-phys-bits",
+ &sev->reduced_phys_bits,
+ OBJ_PROP_FLAG_READWRITE, NULL);
}
/* sev guest info */
diff --git a/target/i386/whp-dispatch.h b/target/i386/whp-dispatch.h
index 87d049ceab..e4695c349f 100644
--- a/target/i386/whp-dispatch.h
+++ b/target/i386/whp-dispatch.h
@@ -23,6 +23,12 @@
X(HRESULT, WHvGetVirtualProcessorRegisters, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, WHV_REGISTER_VALUE* RegisterValues)) \
X(HRESULT, WHvSetVirtualProcessorRegisters, (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, const WHV_REGISTER_NAME* RegisterNames, UINT32 RegisterCount, const WHV_REGISTER_VALUE* RegisterValues)) \
+/*
+ * These are supplemental functions that may not be present
+ * on all versions and are not critical for basic functionality.
+ */
+#define LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(X) \
+ X(HRESULT, WHvSuspendPartitionTime, (WHV_PARTITION_HANDLE Partition)) \
#define LIST_WINHVEMULATION_FUNCTIONS(X) \
X(HRESULT, WHvEmulatorCreateEmulator, (const WHV_EMULATOR_CALLBACKS* Callbacks, WHV_EMULATOR_HANDLE* Emulator)) \
@@ -40,10 +46,12 @@
/* Define function typedef */
LIST_WINHVPLATFORM_FUNCTIONS(WHP_DEFINE_TYPE)
LIST_WINHVEMULATION_FUNCTIONS(WHP_DEFINE_TYPE)
+LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DEFINE_TYPE)
struct WHPDispatch {
LIST_WINHVPLATFORM_FUNCTIONS(WHP_DECLARE_MEMBER)
LIST_WINHVEMULATION_FUNCTIONS(WHP_DECLARE_MEMBER)
+ LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DECLARE_MEMBER)
};
extern struct WHPDispatch whp_dispatch;
@@ -53,6 +61,7 @@ bool init_whp_dispatch(void);
typedef enum WHPFunctionList {
WINHV_PLATFORM_FNS_DEFAULT,
WINHV_EMULATION_FNS_DEFAULT,
+ WINHV_PLATFORM_FNS_SUPPLEMENTAL
} WHPFunctionList;
#endif /* WHP_DISPATCH_H */
diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c
index 683d49d217..c78baac6df 100644
--- a/target/i386/whpx-all.c
+++ b/target/i386/whpx-all.c
@@ -114,7 +114,6 @@ static const WHV_REGISTER_NAME whpx_register_names[] = {
WHvX64RegisterXmmControlStatus,
/* X64 MSRs */
- WHvX64RegisterTsc,
WHvX64RegisterEfer,
#ifdef TARGET_X86_64
WHvX64RegisterKernelGsBase,
@@ -215,7 +214,44 @@ static SegmentCache whpx_seg_h2q(const WHV_X64_SEGMENT_REGISTER *hs)
return qs;
}
-static void whpx_set_registers(CPUState *cpu)
+static int whpx_set_tsc(CPUState *cpu)
+{
+ struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ WHV_REGISTER_NAME tsc_reg = WHvX64RegisterTsc;
+ WHV_REGISTER_VALUE tsc_val;
+ HRESULT hr;
+ struct whpx_state *whpx = &whpx_global;
+
+ /*
+ * Suspend the partition prior to setting the TSC to reduce the variance
+ * in TSC across vCPUs. When the first vCPU runs post suspend, the
+ * partition is automatically resumed.
+ */
+ if (whp_dispatch.WHvSuspendPartitionTime) {
+
+ /*
+ * Unable to suspend partition while setting TSC is not a fatal
+ * error. It just increases the likelihood of TSC variance between
+ * vCPUs and some guest OS are able to handle that just fine.
+ */
+ hr = whp_dispatch.WHvSuspendPartitionTime(whpx->partition);
+ if (FAILED(hr)) {
+ warn_report("WHPX: Failed to suspend partition, hr=%08lx", hr);
+ }
+ }
+
+ tsc_val.Reg64 = env->tsc;
+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
+ whpx->partition, cpu->cpu_index, &tsc_reg, 1, &tsc_val);
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to set TSC, hr=%08lx", hr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void whpx_set_registers(CPUState *cpu, int level)
{
struct whpx_state *whpx = &whpx_global;
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
@@ -230,6 +266,14 @@ static void whpx_set_registers(CPUState *cpu)
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
+ /*
+ * Following MSRs have side effects on the guest or are too heavy for
+ * runtime. Limit them to full state update.
+ */
+ if (level >= WHPX_SET_RESET_STATE) {
+ whpx_set_tsc(cpu);
+ }
+
memset(&vcxt, 0, sizeof(struct whpx_register_set));
v86 = (env->eflags & VM_MASK);
@@ -330,8 +374,6 @@ static void whpx_set_registers(CPUState *cpu)
idx += 1;
/* MSRs */
- assert(whpx_register_names[idx] == WHvX64RegisterTsc);
- vcxt.values[idx++].Reg64 = env->tsc;
assert(whpx_register_names[idx] == WHvX64RegisterEfer);
vcxt.values[idx++].Reg64 = env->efer;
#ifdef TARGET_X86_64
@@ -379,6 +421,25 @@ static void whpx_set_registers(CPUState *cpu)
return;
}
+static int whpx_get_tsc(CPUState *cpu)
+{
+ struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ WHV_REGISTER_NAME tsc_reg = WHvX64RegisterTsc;
+ WHV_REGISTER_VALUE tsc_val;
+ HRESULT hr;
+ struct whpx_state *whpx = &whpx_global;
+
+ hr = whp_dispatch.WHvGetVirtualProcessorRegisters(
+ whpx->partition, cpu->cpu_index, &tsc_reg, 1, &tsc_val);
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to get TSC, hr=%08lx", hr);
+ return -1;
+ }
+
+ env->tsc = tsc_val.Reg64;
+ return 0;
+}
+
static void whpx_get_registers(CPUState *cpu)
{
struct whpx_state *whpx = &whpx_global;
@@ -394,6 +455,11 @@ static void whpx_get_registers(CPUState *cpu)
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
+ if (!env->tsc_valid) {
+ whpx_get_tsc(cpu);
+ env->tsc_valid = !runstate_is_running();
+ }
+
hr = whp_dispatch.WHvGetVirtualProcessorRegisters(
whpx->partition, cpu->cpu_index,
whpx_register_names,
@@ -492,8 +558,6 @@ static void whpx_get_registers(CPUState *cpu)
idx += 1;
/* MSRs */
- assert(whpx_register_names[idx] == WHvX64RegisterTsc);
- env->tsc = vcxt.values[idx++].Reg64;
assert(whpx_register_names[idx] == WHvX64RegisterEfer);
env->efer = vcxt.values[idx++].Reg64;
#ifdef TARGET_X86_64
@@ -841,9 +905,8 @@ static void whpx_vcpu_process_async_events(CPUState *cpu)
if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) &&
!(env->hflags & HF_SMM_MASK)) {
-
+ whpx_cpu_synchronize_state(cpu);
do_cpu_init(x86_cpu);
- cpu->vcpu_dirty = true;
vcpu->interruptable = true;
}
@@ -859,17 +922,13 @@ static void whpx_vcpu_process_async_events(CPUState *cpu)
}
if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) {
- if (!cpu->vcpu_dirty) {
- whpx_get_registers(cpu);
- }
+ whpx_cpu_synchronize_state(cpu);
do_cpu_sipi(x86_cpu);
}
if (cpu->interrupt_request & CPU_INTERRUPT_TPR) {
cpu->interrupt_request &= ~CPU_INTERRUPT_TPR;
- if (!cpu->vcpu_dirty) {
- whpx_get_registers(cpu);
- }
+ whpx_cpu_synchronize_state(cpu);
apic_handle_tpr_access_report(x86_cpu->apic_state, env->eip,
env->tpr_access_type);
}
@@ -896,7 +955,7 @@ static int whpx_vcpu_run(CPUState *cpu)
do {
if (cpu->vcpu_dirty) {
- whpx_set_registers(cpu);
+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
cpu->vcpu_dirty = false;
}
@@ -980,38 +1039,32 @@ static int whpx_vcpu_run(CPUState *cpu)
WHV_REGISTER_VALUE reg_values[5];
WHV_REGISTER_NAME reg_names[5];
UINT32 reg_count = 5;
- UINT64 rip, rax, rcx, rdx, rbx;
+ UINT64 cpuid_fn, rip = 0, rax = 0, rcx = 0, rdx = 0, rbx = 0;
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
memset(reg_values, 0, sizeof(reg_values));
rip = vcpu->exit_ctx.VpContext.Rip +
vcpu->exit_ctx.VpContext.InstructionLength;
- switch (vcpu->exit_ctx.CpuidAccess.Rax) {
- case 1:
- rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
- /* Advertise that we are running on a hypervisor */
- rcx =
- vcpu->exit_ctx.CpuidAccess.DefaultResultRcx |
- CPUID_EXT_HYPERVISOR;
-
- rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
- rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
- break;
+ cpuid_fn = vcpu->exit_ctx.CpuidAccess.Rax;
+
+ /*
+ * Ideally, these should be supplied to the hypervisor during VCPU
+ * initialization and it should be able to satisfy this request.
+ * But, currently, WHPX doesn't support setting CPUID values in the
+ * hypervisor once the partition has been setup, which is too late
+ * since VCPUs are realized later. For now, use the values from
+ * QEMU to satisfy these requests, until WHPX adds support for
+ * being able to set these values in the hypervisor at runtime.
+ */
+ cpu_x86_cpuid(env, cpuid_fn, 0, (UINT32 *)&rax, (UINT32 *)&rbx,
+ (UINT32 *)&rcx, (UINT32 *)&rdx);
+ switch (cpuid_fn) {
case 0x80000001:
- rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
/* Remove any support of OSVW */
- rcx =
- vcpu->exit_ctx.CpuidAccess.DefaultResultRcx &
- ~CPUID_EXT3_OSVW;
-
- rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
- rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
+ rcx &= ~CPUID_EXT3_OSVW;
break;
- default:
- rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
- rcx = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;
- rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
- rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
}
reg_names[0] = WHvX64RegisterRip;
@@ -1067,21 +1120,23 @@ static int whpx_vcpu_run(CPUState *cpu)
static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
{
- whpx_get_registers(cpu);
- cpu->vcpu_dirty = true;
+ if (!cpu->vcpu_dirty) {
+ whpx_get_registers(cpu);
+ cpu->vcpu_dirty = true;
+ }
}
static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu,
run_on_cpu_data arg)
{
- whpx_set_registers(cpu);
+ whpx_set_registers(cpu, WHPX_SET_RESET_STATE);
cpu->vcpu_dirty = false;
}
static void do_whpx_cpu_synchronize_post_init(CPUState *cpu,
run_on_cpu_data arg)
{
- whpx_set_registers(cpu);
+ whpx_set_registers(cpu, WHPX_SET_FULL_STATE);
cpu->vcpu_dirty = false;
}
@@ -1123,6 +1178,15 @@ void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)
static Error *whpx_migration_blocker;
+static void whpx_cpu_update_state(void *opaque, int running, RunState state)
+{
+ CPUX86State *env = opaque;
+
+ if (running) {
+ env->tsc_valid = false;
+ }
+}
+
int whpx_init_vcpu(CPUState *cpu)
{
HRESULT hr;
@@ -1178,6 +1242,7 @@ int whpx_init_vcpu(CPUState *cpu)
cpu->vcpu_dirty = true;
cpu->hax_vcpu = (struct hax_vcpu_state *)vcpu;
+ qemu_add_vm_change_state_handler(whpx_cpu_update_state, cpu->env_ptr);
return 0;
}
@@ -1367,6 +1432,10 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
#define WINHV_PLATFORM_DLL "WinHvPlatform.dll"
#define WINHV_EMULATION_DLL "WinHvEmulation.dll"
+ #define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \
+ whp_dispatch.function_name = \
+ (function_name ## _t)GetProcAddress(hLib, #function_name); \
+
#define WHP_LOAD_FIELD(return_type, function_name, signature) \
whp_dispatch.function_name = \
(function_name ## _t)GetProcAddress(hLib, #function_name); \
@@ -1394,6 +1463,11 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)
LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
break;
+
+ case WINHV_PLATFORM_FNS_SUPPLEMENTAL:
+ WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
+ LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL)
+ break;
}
*handle = hLib;
@@ -1554,6 +1628,8 @@ bool init_whp_dispatch(void)
goto error;
}
+ assert(load_whp_dispatch_fns(&hWinHvPlatform,
+ WINHV_PLATFORM_FNS_SUPPLEMENTAL));
whp_dispatch_initialized = true;
return true;
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index c437a1d8c6..0e840cc579 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -347,7 +347,7 @@ typedef struct ChscResp {
uint16_t len;
uint16_t code;
uint32_t param;
- char data[0];
+ char data[];
} QEMU_PACKED ChscResp;
#define CHSC_MIN_RESP_LEN 0x0008