All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] target/i386/hvf: add vmware-cpuid-freq cpu feature
@ 2021-01-13 20:52 yaroshchuk2000
  2021-01-13 21:25 ` no-reply
  2021-01-14 19:47 ` [PATCH v2] " yaroshchuk2000
  0 siblings, 2 replies; 11+ messages in thread
From: yaroshchuk2000 @ 2021-01-13 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-trivial, r.bolshakov, Vladislav Yaroshchuk

From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>

For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
add paravirtualization cpuid leaf 0x40000010
https://lkml.org/lkml/2008/10/1/246

Leaf 0x40000010, Timing Information:
EAX: (Virtual) TSC frequency in kHz.
EBX: (Virtual) Bus (local apic timer) frequency in kHz.
ECX, EDX: RESERVED (Per above, reserved fields are set to zero).

On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
names `machdep.tsc.frequency` and `hw.busfrequency`

This options is required for Darwin-XNU guest to be synchronized with
host

Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
---
 target/i386/hvf/hvf.c | 92 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ed9356565c..0873e4969e 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -65,6 +65,7 @@
 
 #include <Hypervisor/hv.h>
 #include <Hypervisor/hv_vmx.h>
+#include <sys/sysctl.h>
 
 #include "exec/address-spaces.h"
 #include "hw/i386/apic_internal.h"
@@ -456,6 +457,50 @@ static void dummy_signal(int sig)
 {
 }
 
+static void init_tsc_freq(CPUX86State *env)
+{
+    size_t length;
+    uint64_t tsc_freq;
+
+    if (env->tsc_khz != 0) {
+        return;
+    }
+
+    length = sizeof(uint64_t);
+    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL, 0)) {
+        /* fprintf(stderr, "%s: sysctl machdep.tsc.frequency errored\n", __func__); */
+        return;
+    }
+    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
+}
+
+static void init_apic_bus_freq(CPUX86State *env)
+{
+    size_t length;
+    uint64_t bus_freq;
+
+    if (env->apic_bus_freq != 0) {
+        return;
+    }
+
+    length = sizeof(uint64_t);
+    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
+        /* fprintf(stderr, "%s: sysctl hw.busfrequency errored\n", __func__); */
+        return;
+    }
+    env->apic_bus_freq = bus_freq;
+}
+
+static inline bool tsc_is_known(CPUX86State *env)
+{
+    return env->tsc_khz != 0;
+}
+
+static inline bool apic_bus_freq_is_known(CPUX86State *env)
+{
+    return env->apic_bus_freq != 0;
+}
+
 int hvf_init_vcpu(CPUState *cpu)
 {
 
@@ -480,6 +525,15 @@ int hvf_init_vcpu(CPUState *cpu)
     hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
     env->hvf_mmio_buf = g_new(char, 4096);
 
+    if (x86cpu->vmware_cpuid_freq) {
+        init_tsc_freq(env);
+        init_apic_bus_freq(env);
+
+        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
+            error_report("vmware-cpuid-freq: feature couldn't be enabled");
+        }
+    }
+
     r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
     cpu->vcpu_dirty = 1;
     assert_hvf_ok(r);
@@ -597,6 +651,42 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
     }
 }
 
+static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+                              uint32_t *eax, uint32_t *ebx,
+                              uint32_t *ecx, uint32_t *edx)
+{
+    /*
+     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010 leafs
+     * Provides vmware-cpuid-freq support to hvf
+     */
+
+    uint32_t signature[3];
+
+    if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
+        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
+        return;
+    }
+
+    switch (index) {
+        case 0x40000000:
+            memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */
+            *eax = 0x40000010;                     /* Max available cpuid leaf */
+            *ebx = signature[0];
+            *ecx = signature[1];
+            *edx = signature[2];
+            break;
+        case 0x40000010:
+            *eax = env->tsc_khz;
+            *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
+            *ecx = 0;
+            *edx = 0;
+            break;
+        default:
+            cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
+            break;
+    }
+}
+
 int hvf_vcpu_exec(CPUState *cpu)
 {
     X86CPU *x86_cpu = X86_CPU(cpu);
@@ -734,7 +824,7 @@ int hvf_vcpu_exec(CPUState *cpu)
             uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
             uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
 
-            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
+            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
 
             wreg(cpu->hvf_fd, HV_X86_RAX, rax);
             wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-13 20:52 [PATCH] target/i386/hvf: add vmware-cpuid-freq cpu feature yaroshchuk2000
@ 2021-01-13 21:25 ` no-reply
  2021-01-14 19:47 ` [PATCH v2] " yaroshchuk2000
  1 sibling, 0 replies; 11+ messages in thread
From: no-reply @ 2021-01-13 21:25 UTC (permalink / raw)
  To: yaroshchuk2000; +Cc: qemu-trivial, r.bolshakov, qemu-devel, yaroshchuk2000

Patchew URL: https://patchew.org/QEMU/20210113205221.32308-1-yaroshchuk2000@gmail.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210113205221.32308-1-yaroshchuk2000@gmail.com
Subject: [PATCH] target/i386/hvf: add vmware-cpuid-freq cpu feature

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
f4f6e29 target/i386/hvf: add vmware-cpuid-freq cpu feature

=== OUTPUT BEGIN ===
WARNING: line over 80 characters
#52: FILE: target/i386/hvf/hvf.c:471:
+        /* fprintf(stderr, "%s: sysctl machdep.tsc.frequency errored\n", __func__); */

ERROR: switch and case should be at the same indent
#124: FILE: target/i386/hvf/hvf.c:670:
+    switch (index) {
+        case 0x40000000:
[...]
+        case 0x40000010:
[...]
+        default:

WARNING: line over 80 characters
#127: FILE: target/i386/hvf/hvf.c:673:
+            *eax = 0x40000010;                     /* Max available cpuid leaf */

total: 1 errors, 2 warnings, 122 lines checked

Commit f4f6e29c5d8c (target/i386/hvf: add vmware-cpuid-freq cpu feature) has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210113205221.32308-1-yaroshchuk2000@gmail.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-13 20:52 [PATCH] target/i386/hvf: add vmware-cpuid-freq cpu feature yaroshchuk2000
  2021-01-13 21:25 ` no-reply
@ 2021-01-14 19:47 ` yaroshchuk2000
  2021-01-19 18:01   ` Roman Bolshakov
                     ` (2 more replies)
  1 sibling, 3 replies; 11+ messages in thread
From: yaroshchuk2000 @ 2021-01-14 19:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-trivial, r.bolshakov, Vladislav Yaroshchuk

From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>

For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
add paravirtualization cpuid leaf 0x40000010
https://lkml.org/lkml/2008/10/1/246

Leaf 0x40000010, Timing Information:
EAX: (Virtual) TSC frequency in kHz.
EBX: (Virtual) Bus (local apic timer) frequency in kHz.
ECX, EDX: RESERVED (Per above, reserved fields are set to zero).

On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
names `machdep.tsc.frequency` and `hw.busfrequency`

This options is required for Darwin-XNU guest to be synchronized with
host

Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
---
 target/i386/hvf/hvf.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ed9356565c..a5daafe202 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -65,6 +65,7 @@
 
 #include <Hypervisor/hv.h>
 #include <Hypervisor/hv_vmx.h>
+#include <sys/sysctl.h>
 
 #include "exec/address-spaces.h"
 #include "hw/i386/apic_internal.h"
@@ -456,6 +457,48 @@ static void dummy_signal(int sig)
 {
 }
 
+static void init_tsc_freq(CPUX86State *env)
+{
+    size_t length;
+    uint64_t tsc_freq;
+
+    if (env->tsc_khz != 0) {
+        return;
+    }
+
+    length = sizeof(uint64_t);
+    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL, 0)) {
+        return;
+    }
+    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
+}
+
+static void init_apic_bus_freq(CPUX86State *env)
+{
+    size_t length;
+    uint64_t bus_freq;
+
+    if (env->apic_bus_freq != 0) {
+        return;
+    }
+
+    length = sizeof(uint64_t);
+    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
+        return;
+    }
+    env->apic_bus_freq = bus_freq;
+}
+
+static inline bool tsc_is_known(CPUX86State *env)
+{
+    return env->tsc_khz != 0;
+}
+
+static inline bool apic_bus_freq_is_known(CPUX86State *env)
+{
+    return env->apic_bus_freq != 0;
+}
+
 int hvf_init_vcpu(CPUState *cpu)
 {
 
@@ -480,6 +523,15 @@ int hvf_init_vcpu(CPUState *cpu)
     hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
     env->hvf_mmio_buf = g_new(char, 4096);
 
+    if (x86cpu->vmware_cpuid_freq) {
+        init_tsc_freq(env);
+        init_apic_bus_freq(env);
+
+        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
+            error_report("vmware-cpuid-freq: feature couldn't be enabled");
+        }
+    }
+
     r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
     cpu->vcpu_dirty = 1;
     assert_hvf_ok(r);
@@ -597,6 +649,42 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
     }
 }
 
+static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+                              uint32_t *eax, uint32_t *ebx,
+                              uint32_t *ecx, uint32_t *edx)
+{
+    /*
+     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010 leafs
+     * Provides vmware-cpuid-freq support to hvf
+     */
+
+    uint32_t signature[3];
+
+    if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
+        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
+        return;
+    }
+
+    switch (index) {
+    case 0x40000000:
+        memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */
+        *eax = 0x40000010;                     /* Max available cpuid leaf */
+        *ebx = signature[0];
+        *ecx = signature[1];
+        *edx = signature[2];
+        break;
+    case 0x40000010:
+        *eax = env->tsc_khz;
+        *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
+        *ecx = 0;
+        *edx = 0;
+        break;
+    default:
+        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
+        break;
+    }
+}
+
 int hvf_vcpu_exec(CPUState *cpu)
 {
     X86CPU *x86_cpu = X86_CPU(cpu);
@@ -734,7 +822,7 @@ int hvf_vcpu_exec(CPUState *cpu)
             uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
             uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
 
-            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
+            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
 
             wreg(cpu->hvf_fd, HV_X86_RAX, rax);
             wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-14 19:47 ` [PATCH v2] " yaroshchuk2000
@ 2021-01-19 18:01   ` Roman Bolshakov
  2021-01-19 18:14     ` Paolo Bonzini
  2021-01-22 14:29     ` Vladislav Yaroshchuk
  2021-01-19 22:37   ` dirty--- via
  2021-01-22 15:05   ` [PATCH v3] " yaroshchuk2000
  2 siblings, 2 replies; 11+ messages in thread
From: Roman Bolshakov @ 2021-01-19 18:01 UTC (permalink / raw)
  To: yaroshchuk2000
  Cc: Paolo Bonzini, Richard Henderson, qemu-devel, Cameron Esfahani,
	Eduardo Habkost

On Thu, Jan 14, 2021 at 10:47:03PM +0300, yaroshchuk2000@gmail.com wrote:
> From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> 
> For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
> add paravirtualization cpuid leaf 0x40000010
> https://lkml.org/lkml/2008/10/1/246
> 
> Leaf 0x40000010, Timing Information:
> EAX: (Virtual) TSC frequency in kHz.
> EBX: (Virtual) Bus (local apic timer) frequency in kHz.
> ECX, EDX: RESERVED (Per above, reserved fields are set to zero).
> 
> On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
> names `machdep.tsc.frequency` and `hw.busfrequency`
> 
> This options is required for Darwin-XNU guest to be synchronized with
> host
> 
> Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> ---
>  target/i386/hvf/hvf.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 89 insertions(+), 1 deletion(-)
> 
> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> index ed9356565c..a5daafe202 100644
> --- a/target/i386/hvf/hvf.c
> +++ b/target/i386/hvf/hvf.c
> @@ -65,6 +65,7 @@
>  
>  #include <Hypervisor/hv.h>
>  #include <Hypervisor/hv_vmx.h>
> +#include <sys/sysctl.h>
>  
>  #include "exec/address-spaces.h"
>  #include "hw/i386/apic_internal.h"
> @@ -456,6 +457,48 @@ static void dummy_signal(int sig)
>  {
>  }
>  
> +static void init_tsc_freq(CPUX86State *env)
> +{
> +    size_t length;
> +    uint64_t tsc_freq;
> +
> +    if (env->tsc_khz != 0) {
> +        return;
> +    }
> +
> +    length = sizeof(uint64_t);
> +    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL, 0)) {
> +        return;
> +    }
> +    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
> +}
> +
> +static void init_apic_bus_freq(CPUX86State *env)
> +{
> +    size_t length;
> +    uint64_t bus_freq;
> +
> +    if (env->apic_bus_freq != 0) {
> +        return;
> +    }
> +
> +    length = sizeof(uint64_t);
> +    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
> +        return;
> +    }
> +    env->apic_bus_freq = bus_freq;
> +}
> +
> +static inline bool tsc_is_known(CPUX86State *env)
> +{
> +    return env->tsc_khz != 0;
> +}
> +
> +static inline bool apic_bus_freq_is_known(CPUX86State *env)
> +{
> +    return env->apic_bus_freq != 0;
> +}
> +
>  int hvf_init_vcpu(CPUState *cpu)
>  {
>  
> @@ -480,6 +523,15 @@ int hvf_init_vcpu(CPUState *cpu)
>      hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
>      env->hvf_mmio_buf = g_new(char, 4096);
>  
> +    if (x86cpu->vmware_cpuid_freq) {
> +        init_tsc_freq(env);
> +        init_apic_bus_freq(env);
> +
> +        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> +            error_report("vmware-cpuid-freq: feature couldn't be enabled");
> +        }
> +    }
> +
>      r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
>      cpu->vcpu_dirty = 1;
>      assert_hvf_ok(r);
> @@ -597,6 +649,42 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
>      }
>  }
>  
> +static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> +                              uint32_t *eax, uint32_t *ebx,
> +                              uint32_t *ecx, uint32_t *edx)
> +{
> +    /*
> +     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010 leafs
> +     * Provides vmware-cpuid-freq support to hvf
> +     */
> +
> +    uint32_t signature[3];
> +
> +    if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> +        return;
> +    }
> +
> +    switch (index) {
> +    case 0x40000000:
> +        memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */

Hi Vladislav,

TCG belongs to TCG accel identification, for HVF it should be
HVFHVFHVFHVF.

> +        *eax = 0x40000010;                     /* Max available cpuid leaf */
> +        *ebx = signature[0];
> +        *ecx = signature[1];
> +        *edx = signature[2];

TCG and KVM don't report their identity unless kvm or tcg-cpuid
properties are set. I wonder if we need to guard it likewise?

But as of now QEMU is not consistent in that regard. Two parameters are
needed for KVM - kvm=on,vmware-cpuid-freq=on. vmware-cpuid-freq is
sufficient for WHPX but WHPX doesn't expose itself (ebx=ecx=edx=0). TCG
doesn't seem to support vmware-cpuid-freq but reports it's name only if
tcg-cpuid property is set.

> +        break;

CPUID for not implemented hypervisor-specific leafs from 0x40000001 up
to 0x4000000f should be all zeroes but cpu_x86_cpuid() only returns zero
values for 0x40000001. Likely, you need to reset return values for the
leafs here or in cpu_x86_cpuid(). In the latter case you'll also fix a
similar bug in WHPX accel.

Otherwise, looks good.

Thanks,
Roman

> +    case 0x40000010:
> +        *eax = env->tsc_khz;
> +        *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
> +        *ecx = 0;
> +        *edx = 0;
> +        break;
> +    default:
> +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> +        break;
> +    }
> +}
> +
>  int hvf_vcpu_exec(CPUState *cpu)
>  {
>      X86CPU *x86_cpu = X86_CPU(cpu);
> @@ -734,7 +822,7 @@ int hvf_vcpu_exec(CPUState *cpu)
>              uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
>              uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
>  
> -            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> +            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
>  
>              wreg(cpu->hvf_fd, HV_X86_RAX, rax);
>              wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
> -- 
> 2.28.0
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-19 18:01   ` Roman Bolshakov
@ 2021-01-19 18:14     ` Paolo Bonzini
  2021-01-22 14:29     ` Vladislav Yaroshchuk
  1 sibling, 0 replies; 11+ messages in thread
From: Paolo Bonzini @ 2021-01-19 18:14 UTC (permalink / raw)
  To: Roman Bolshakov, yaroshchuk2000
  Cc: Richard Henderson, qemu-devel, Cameron Esfahani, Eduardo Habkost

On 19/01/21 19:01, Roman Bolshakov wrote:
>> +    switch (index) {
>> +    case 0x40000000:
>> +        memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */
> Hi Vladislav,
> 
> TCG belongs to TCG accel identification, for HVF it should be
> HVFHVFHVFHVF.

You can use the KVM identification just fine, as long as you comply with 
the rest of the KVM CPUID specification.

Paolo



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-14 19:47 ` [PATCH v2] " yaroshchuk2000
  2021-01-19 18:01   ` Roman Bolshakov
@ 2021-01-19 22:37   ` dirty--- via
  2021-01-22 14:51     ` Vladislav Yaroshchuk
  2021-01-22 15:05   ` [PATCH v3] " yaroshchuk2000
  2 siblings, 1 reply; 11+ messages in thread
From: dirty--- via @ 2021-01-19 22:37 UTC (permalink / raw)
  To: yaroshchuk2000; +Cc: qemu-trivial, r.bolshakov, qemu-devel



> On Jan 14, 2021, at 11:47 AM, yaroshchuk2000@gmail.com wrote:
> 
> From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> 
> For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
> add paravirtualization cpuid leaf 0x40000010
> https://lkml.org/lkml/2008/10/1/246
> 
> Leaf 0x40000010, Timing Information:
> EAX: (Virtual) TSC frequency in kHz.
> EBX: (Virtual) Bus (local apic timer) frequency in kHz.
> ECX, EDX: RESERVED (Per above, reserved fields are set to zero).
> 
> On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
> names `machdep.tsc.frequency` and `hw.busfrequency`
> 
> This options is required for Darwin-XNU guest to be synchronized with
> host
> 
> Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> ---
> target/i386/hvf/hvf.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 89 insertions(+), 1 deletion(-)
> 
> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> index ed9356565c..a5daafe202 100644
> --- a/target/i386/hvf/hvf.c
> +++ b/target/i386/hvf/hvf.c
> @@ -65,6 +65,7 @@
> 
> #include <Hypervisor/hv.h>
> #include <Hypervisor/hv_vmx.h>
> +#include <sys/sysctl.h>
> 
> #include "exec/address-spaces.h"
> #include "hw/i386/apic_internal.h"
> @@ -456,6 +457,48 @@ static void dummy_signal(int sig)
> {
> }
> 
> +static void init_tsc_freq(CPUX86State *env)
> +{
> +    size_t length;
> +    uint64_t tsc_freq;
> +
> +    if (env->tsc_khz != 0) {
> +        return;
> +    }
> +
> +    length = sizeof(uint64_t);
> +    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL, 0)) {
> +        return;
> +    }
> +    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
> +}
> +
> +static void init_apic_bus_freq(CPUX86State *env)
> +{
> +    size_t length;
> +    uint64_t bus_freq;
> +
> +    if (env->apic_bus_freq != 0) {
> +        return;
> +    }
> +
> +    length = sizeof(uint64_t);
> +    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
> +        return;
> +    }
> +    env->apic_bus_freq = bus_freq;
> +}
> +
> +static inline bool tsc_is_known(CPUX86State *env)
> +{
> +    return env->tsc_khz != 0;
> +}
> +
> +static inline bool apic_bus_freq_is_known(CPUX86State *env)
> +{
> +    return env->apic_bus_freq != 0;
> +}
> +
> int hvf_init_vcpu(CPUState *cpu)
> {
> 
> @@ -480,6 +523,15 @@ int hvf_init_vcpu(CPUState *cpu)
>     hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
>     env->hvf_mmio_buf = g_new(char, 4096);
> 
> +    if (x86cpu->vmware_cpuid_freq) {
> +        init_tsc_freq(env);
> +        init_apic_bus_freq(env);
> +
> +        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> +            error_report("vmware-cpuid-freq: feature couldn't be enabled");
> +        }
> +    }
> +
>     r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
>     cpu->vcpu_dirty = 1;
>     assert_hvf_ok(r);
> @@ -597,6 +649,42 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
>     }
> }
> 

We already have hvf/x86_cpuid.c.  Can we put hvf_cpu_x86_cpuid() in there?

> +static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> +                              uint32_t *eax, uint32_t *ebx,
> +                              uint32_t *ecx, uint32_t *edx)
> +{
> +    /*
> +     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010 leafs
> +     * Provides vmware-cpuid-freq support to hvf
> +     */
> +
> +    uint32_t signature[3];
> +
> +    if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> +        return;
> +    }
> +
> +    switch (index) {
> +    case 0x40000000:
> +        memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */

I agree with Roman, using "HVFHVFHVFHVF" is better.

> +        *eax = 0x40000010;                     /* Max available cpuid leaf */
> +        *ebx = signature[0];
> +        *ecx = signature[1];
> +        *edx = signature[2];
> +        break;
> +    case 0x40000010:
> +        *eax = env->tsc_khz;
> +        *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
> +        *ecx = 0;
> +        *edx = 0;
> +        break;
> +    default:
> +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> +        break;
> +    }
> +}
> +
> int hvf_vcpu_exec(CPUState *cpu)
> {
>     X86CPU *x86_cpu = X86_CPU(cpu);
> @@ -734,7 +822,7 @@ int hvf_vcpu_exec(CPUState *cpu)
>             uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
>             uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
> 
> -            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> +            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> 
>             wreg(cpu->hvf_fd, HV_X86_RAX, rax);
>             wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
> -- 
> 2.28.0
> 
> 

Looks good.

Cameron Esfahani
dirty@apple.com



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-19 18:01   ` Roman Bolshakov
  2021-01-19 18:14     ` Paolo Bonzini
@ 2021-01-22 14:29     ` Vladislav Yaroshchuk
  1 sibling, 0 replies; 11+ messages in thread
From: Vladislav Yaroshchuk @ 2021-01-22 14:29 UTC (permalink / raw)
  To: Roman Bolshakov; +Cc: qemu-trivial, pbonzini, qemu-devel, dirty

[-- Attachment #1: Type: text/plain, Size: 6760 bytes --]

Hi Roman,

вт, 19 янв. 2021 г. в 21:01, Roman Bolshakov <r.bolshakov@yadro.com>:

> On Thu, Jan 14, 2021 at 10:47:03PM +0300, yaroshchuk2000@gmail.com wrote:
> > From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> >
> > For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
> > add paravirtualization cpuid leaf 0x40000010
> > https://lkml.org/lkml/2008/10/1/246
> >
> > Leaf 0x40000010, Timing Information:
> > EAX: (Virtual) TSC frequency in kHz.
> > EBX: (Virtual) Bus (local apic timer) frequency in kHz.
> > ECX, EDX: RESERVED (Per above, reserved fields are set to zero).
> >
> > On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
> > names `machdep.tsc.frequency` and `hw.busfrequency`
> >
> > This options is required for Darwin-XNU guest to be synchronized with
> > host
> >
> > Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> > ---
> >  target/i386/hvf/hvf.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 89 insertions(+), 1 deletion(-)
> >
> > diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> > index ed9356565c..a5daafe202 100644
> > --- a/target/i386/hvf/hvf.c
> > +++ b/target/i386/hvf/hvf.c
> > @@ -65,6 +65,7 @@
> >
> >  #include <Hypervisor/hv.h>
> >  #include <Hypervisor/hv_vmx.h>
> > +#include <sys/sysctl.h>
> >
> >  #include "exec/address-spaces.h"
> >  #include "hw/i386/apic_internal.h"
> > @@ -456,6 +457,48 @@ static void dummy_signal(int sig)
> >  {
> >  }
> >
> > +static void init_tsc_freq(CPUX86State *env)
> > +{
> > +    size_t length;
> > +    uint64_t tsc_freq;
> > +
> > +    if (env->tsc_khz != 0) {
> > +        return;
> > +    }
> > +
> > +    length = sizeof(uint64_t);
> > +    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL,
> 0)) {
> > +        return;
> > +    }
> > +    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
> > +}
> > +
> > +static void init_apic_bus_freq(CPUX86State *env)
> > +{
> > +    size_t length;
> > +    uint64_t bus_freq;
> > +
> > +    if (env->apic_bus_freq != 0) {
> > +        return;
> > +    }
> > +
> > +    length = sizeof(uint64_t);
> > +    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
> > +        return;
> > +    }
> > +    env->apic_bus_freq = bus_freq;
> > +}
> > +
> > +static inline bool tsc_is_known(CPUX86State *env)
> > +{
> > +    return env->tsc_khz != 0;
> > +}
> > +
> > +static inline bool apic_bus_freq_is_known(CPUX86State *env)
> > +{
> > +    return env->apic_bus_freq != 0;
> > +}
> > +
> >  int hvf_init_vcpu(CPUState *cpu)
> >  {
> >
> > @@ -480,6 +523,15 @@ int hvf_init_vcpu(CPUState *cpu)
> >      hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
> >      env->hvf_mmio_buf = g_new(char, 4096);
> >
> > +    if (x86cpu->vmware_cpuid_freq) {
> > +        init_tsc_freq(env);
> > +        init_apic_bus_freq(env);
> > +
> > +        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> > +            error_report("vmware-cpuid-freq: feature couldn't be
> enabled");
> > +        }
> > +    }
> > +
> >      r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
> >      cpu->vcpu_dirty = 1;
> >      assert_hvf_ok(r);
> > @@ -597,6 +649,42 @@ static void hvf_store_events(CPUState *cpu,
> uint32_t ins_len, uint64_t idtvec_in
> >      }
> >  }
> >
> > +static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index,
> uint32_t count,
> > +                              uint32_t *eax, uint32_t *ebx,
> > +                              uint32_t *ecx, uint32_t *edx)
> > +{
> > +    /*
> > +     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010
> leafs
> > +     * Provides vmware-cpuid-freq support to hvf
> > +     */
> > +
> > +    uint32_t signature[3];
> > +
> > +    if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> > +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> > +        return;
> > +    }
> > +
> > +    switch (index) {
> > +    case 0x40000000:
> > +        memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */
>
> Hi Vladislav,
>
>

> TCG belongs to TCG accel identification, for HVF it should be
> HVFHVFHVFHVF.
>
> > +        *eax = 0x40000010;                     /* Max available cpuid
> leaf */
> > +        *ebx = signature[0];
> > +        *ecx = signature[1];
> > +        *edx = signature[2];
>
> TCG and KVM don't report their identity unless kvm or tcg-cpuid
> properties are set. I wonder if we need to guard it likewise?
>
> But as of now QEMU is not consistent in that regard. Two parameters are
> needed for KVM - kvm=on,vmware-cpuid-freq=on. vmware-cpuid-freq is
> sufficient for WHPX but WHPX doesn't expose itself (ebx=ecx=edx=0). TCG
> doesn't seem to support vmware-cpuid-freq but reports it's name only if
> tcg-cpuid property is set.
>
>
Ok, I understood the mistake. HVFHVFHVFHVF sounds more suitable, but
hypervisor signature is not a necessary thing for vmware-cpuid-freq
(especially unknown to anyone `HVFHVFHVFHVF`). Seems it can be dropped
by filling ebx=ecx=edx=0, as WHPX does. No reason to expose the HVF in
this case. If needed, it can be added as another feature.

> +        break;
>
> CPUID for not implemented hypervisor-specific leafs from 0x40000001 up
> to 0x4000000f should be all zeroes but cpu_x86_cpuid() only returns zero
> values for 0x40000001. Likely, you need to reset return values for the
> leafs here or in cpu_x86_cpuid(). In the latter case you'll also fix a
> similar bug in WHPX accel.
>
>
I'll fix it in-place, resetting values in hvf_cpu_x86_cpuid()

Thank you for the review!

Sincerely,

Vladislav Yaroshchuk


> Otherwise, looks good.
>
> Thanks,
> Roman
>
> > +    case 0x40000010:
> > +        *eax = env->tsc_khz;
> > +        *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
> > +        *ecx = 0;
> > +        *edx = 0;
> > +        break;
> > +    default:
> > +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> > +        break;
> > +    }
> > +}
> > +
> >  int hvf_vcpu_exec(CPUState *cpu)
> >  {
> >      X86CPU *x86_cpu = X86_CPU(cpu);
> > @@ -734,7 +822,7 @@ int hvf_vcpu_exec(CPUState *cpu)
> >              uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
> >              uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
> >
> > -            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> > +            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> >
> >              wreg(cpu->hvf_fd, HV_X86_RAX, rax);
> >              wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
> > --
> > 2.28.0
> >
>

[-- Attachment #2: Type: text/html, Size: 9266 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-19 22:37   ` dirty--- via
@ 2021-01-22 14:51     ` Vladislav Yaroshchuk
  0 siblings, 0 replies; 11+ messages in thread
From: Vladislav Yaroshchuk @ 2021-01-22 14:51 UTC (permalink / raw)
  To: Cameron Esfahani; +Cc: qemu-trivial, pbonzini, Roman Bolshakov, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 5792 bytes --]

Hi Cameron,

ср, 20 янв. 2021 г. в 01:37, Cameron Esfahani <dirty@apple.com>:

>
>
> > On Jan 14, 2021, at 11:47 AM, yaroshchuk2000@gmail.com wrote:
> >
> > From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> >
> > For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
> > add paravirtualization cpuid leaf 0x40000010
> > https://lkml.org/lkml/2008/10/1/246
> >
> > Leaf 0x40000010, Timing Information:
> > EAX: (Virtual) TSC frequency in kHz.
> > EBX: (Virtual) Bus (local apic timer) frequency in kHz.
> > ECX, EDX: RESERVED (Per above, reserved fields are set to zero).
> >
> > On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
> > names `machdep.tsc.frequency` and `hw.busfrequency`
> >
> > This options is required for Darwin-XNU guest to be synchronized with
> > host
> >
> > Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> > ---
> > target/i386/hvf/hvf.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 89 insertions(+), 1 deletion(-)
> >
> > diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> > index ed9356565c..a5daafe202 100644
> > --- a/target/i386/hvf/hvf.c
> > +++ b/target/i386/hvf/hvf.c
> > @@ -65,6 +65,7 @@
> >
> > #include <Hypervisor/hv.h>
> > #include <Hypervisor/hv_vmx.h>
> > +#include <sys/sysctl.h>
> >
> > #include "exec/address-spaces.h"
> > #include "hw/i386/apic_internal.h"
> > @@ -456,6 +457,48 @@ static void dummy_signal(int sig)
> > {
> > }
> >
> > +static void init_tsc_freq(CPUX86State *env)
> > +{
> > +    size_t length;
> > +    uint64_t tsc_freq;
> > +
> > +    if (env->tsc_khz != 0) {
> > +        return;
> > +    }
> > +
> > +    length = sizeof(uint64_t);
> > +    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL,
> 0)) {
> > +        return;
> > +    }
> > +    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
> > +}
> > +
> > +static void init_apic_bus_freq(CPUX86State *env)
> > +{
> > +    size_t length;
> > +    uint64_t bus_freq;
> > +
> > +    if (env->apic_bus_freq != 0) {
> > +        return;
> > +    }
> > +
> > +    length = sizeof(uint64_t);
> > +    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
> > +        return;
> > +    }
> > +    env->apic_bus_freq = bus_freq;
> > +}
> > +
> > +static inline bool tsc_is_known(CPUX86State *env)
> > +{
> > +    return env->tsc_khz != 0;
> > +}
> > +
> > +static inline bool apic_bus_freq_is_known(CPUX86State *env)
> > +{
> > +    return env->apic_bus_freq != 0;
> > +}
> > +
> > int hvf_init_vcpu(CPUState *cpu)
> > {
> >
> > @@ -480,6 +523,15 @@ int hvf_init_vcpu(CPUState *cpu)
> >     hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
> >     env->hvf_mmio_buf = g_new(char, 4096);
> >
> > +    if (x86cpu->vmware_cpuid_freq) {
> > +        init_tsc_freq(env);
> > +        init_apic_bus_freq(env);
> > +
> > +        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> > +            error_report("vmware-cpuid-freq: feature couldn't be
> enabled");
> > +        }
> > +    }
> > +
> >     r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
> >     cpu->vcpu_dirty = 1;
> >     assert_hvf_ok(r);
> > @@ -597,6 +649,42 @@ static void hvf_store_events(CPUState *cpu,
> uint32_t ins_len, uint64_t idtvec_in
> >     }
> > }
> >
>
> Seems that

> We already have hvf/x86_cpuid.c.  Can we put hvf_cpu_x86_cpuid() in there?
>
> hvf/x86_cpuid.c is about host features, hvf_cpu_x86_cpuid() does not fit
it, as for me.
Also, KVM extends cpuid in target/i386/kvm/kvm.c. Same to WHPX:
target/i386/whpx/whpx-all.c.
I wanted to meet this rule: target/i386/hvf/hvf.c

Thank you!

Vladislav Yaroshchuk

> +static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t
> count,
> > +                              uint32_t *eax, uint32_t *ebx,
> > +                              uint32_t *ecx, uint32_t *edx)
> > +{
> > +    /*
> > +     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010
> leafs
> > +     * Provides vmware-cpuid-freq support to hvf
> > +     */
> > +
> > +    uint32_t signature[3];
> > +
> > +    if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
> > +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> > +        return;
> > +    }
> > +
> > +    switch (index) {
> > +    case 0x40000000:
> > +        memcpy(signature, "TCGTCGTCGTCG", 12); /* QEMU Signature */
>
> I agree with Roman, using "HVFHVFHVFHVF" is better.
>
> > +        *eax = 0x40000010;                     /* Max available cpuid
> leaf */
> > +        *ebx = signature[0];
> > +        *ecx = signature[1];
> > +        *edx = signature[2];
> > +        break;
> > +    case 0x40000010:
> > +        *eax = env->tsc_khz;
> > +        *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
> > +        *ecx = 0;
> > +        *edx = 0;
> > +        break;
> > +    default:
> > +        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
> > +        break;
> > +    }
> > +}
> > +
> > int hvf_vcpu_exec(CPUState *cpu)
> > {
> >     X86CPU *x86_cpu = X86_CPU(cpu);
> > @@ -734,7 +822,7 @@ int hvf_vcpu_exec(CPUState *cpu)
> >             uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
> >             uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
> >
> > -            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> > +            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
> >
> >             wreg(cpu->hvf_fd, HV_X86_RAX, rax);
> >             wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
> > --
> > 2.28.0
> >
> >
>
> Looks good.
>
> Cameron Esfahani
> dirty@apple.com
>
>

[-- Attachment #2: Type: text/html, Size: 8070 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v3] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-14 19:47 ` [PATCH v2] " yaroshchuk2000
  2021-01-19 18:01   ` Roman Bolshakov
  2021-01-19 22:37   ` dirty--- via
@ 2021-01-22 15:05   ` yaroshchuk2000
  2021-02-04  9:51     ` Roman Bolshakov
  2021-02-09 10:32     ` Roman Bolshakov
  2 siblings, 2 replies; 11+ messages in thread
From: yaroshchuk2000 @ 2021-01-22 15:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-trivial, pbonzini, r.bolshakov, Vladislav Yaroshchuk, dirty

From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>

For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
add paravirtualization cpuid leaf 0x40000010
https://lkml.org/lkml/2008/10/1/246

Leaf 0x40000010, Timing Information:
EAX: (Virtual) TSC frequency in kHz.
EBX: (Virtual) Bus (local apic timer) frequency in kHz.
ECX, EDX: RESERVED (Per above, reserved fields are set to zero).

On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
names `machdep.tsc.frequency` and `hw.busfrequency`

This options is required for Darwin-XNU guest to be synchronized with
host

Leaf 0x40000000 not exposes HVF leaving hypervisor signature empty

Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
---
 target/i386/hvf/hvf.c | 96 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 95 insertions(+), 1 deletion(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ed9356565c..5a8914564b 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -65,6 +65,7 @@
 
 #include <Hypervisor/hv.h>
 #include <Hypervisor/hv_vmx.h>
+#include <sys/sysctl.h>
 
 #include "exec/address-spaces.h"
 #include "hw/i386/apic_internal.h"
@@ -456,6 +457,48 @@ static void dummy_signal(int sig)
 {
 }
 
+static void init_tsc_freq(CPUX86State *env)
+{
+    size_t length;
+    uint64_t tsc_freq;
+
+    if (env->tsc_khz != 0) {
+        return;
+    }
+
+    length = sizeof(uint64_t);
+    if (sysctlbyname("machdep.tsc.frequency", &tsc_freq, &length, NULL, 0)) {
+        return;
+    }
+    env->tsc_khz = tsc_freq / 1000;  /* Hz to KHz */
+}
+
+static void init_apic_bus_freq(CPUX86State *env)
+{
+    size_t length;
+    uint64_t bus_freq;
+
+    if (env->apic_bus_freq != 0) {
+        return;
+    }
+
+    length = sizeof(uint64_t);
+    if (sysctlbyname("hw.busfrequency", &bus_freq, &length, NULL, 0)) {
+        return;
+    }
+    env->apic_bus_freq = bus_freq;
+}
+
+static inline bool tsc_is_known(CPUX86State *env)
+{
+    return env->tsc_khz != 0;
+}
+
+static inline bool apic_bus_freq_is_known(CPUX86State *env)
+{
+    return env->apic_bus_freq != 0;
+}
+
 int hvf_init_vcpu(CPUState *cpu)
 {
 
@@ -480,6 +523,15 @@ int hvf_init_vcpu(CPUState *cpu)
     hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1);
     env->hvf_mmio_buf = g_new(char, 4096);
 
+    if (x86cpu->vmware_cpuid_freq) {
+        init_tsc_freq(env);
+        init_apic_bus_freq(env);
+
+        if (!tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
+            error_report("vmware-cpuid-freq: feature couldn't be enabled");
+        }
+    }
+
     r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT);
     cpu->vcpu_dirty = 1;
     assert_hvf_ok(r);
@@ -597,6 +649,48 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in
     }
 }
 
+static void hvf_cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+                              uint32_t *eax, uint32_t *ebx,
+                              uint32_t *ecx, uint32_t *edx)
+{
+    /*
+     * A wrapper extends cpu_x86_cpuid with 0x40000000 and 0x40000010 leafs,
+     * leafs 0x40000001-0x4000000F are filled with zeros
+     * Provides vmware-cpuid-freq support to hvf
+     *
+     * Note: leaf 0x40000000 not exposes HVF,
+     * leaving hypervisor signature empty
+     */
+
+    if (index < 0x40000000 || index > 0x40000010 ||
+        !tsc_is_known(env) || !apic_bus_freq_is_known(env)) {
+
+        cpu_x86_cpuid(env, index, count, eax, ebx, ecx, edx);
+        return;
+    }
+
+    switch (index) {
+    case 0x40000000:
+        *eax = 0x40000010;    /* Max available cpuid leaf */
+        *ebx = 0;             /* Leave signature empty */
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0x40000010:
+        *eax = env->tsc_khz;
+        *ebx = env->apic_bus_freq / 1000; /* Hz to KHz */
+        *ecx = 0;
+        *edx = 0;
+        break;
+    default:
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    }
+}
+
 int hvf_vcpu_exec(CPUState *cpu)
 {
     X86CPU *x86_cpu = X86_CPU(cpu);
@@ -734,7 +828,7 @@ int hvf_vcpu_exec(CPUState *cpu)
             uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX);
             uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX);
 
-            cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
+            hvf_cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx);
 
             wreg(cpu->hvf_fd, HV_X86_RAX, rax);
             wreg(cpu->hvf_fd, HV_X86_RBX, rbx);
-- 
2.23.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v3] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-22 15:05   ` [PATCH v3] " yaroshchuk2000
@ 2021-02-04  9:51     ` Roman Bolshakov
  2021-02-09 10:32     ` Roman Bolshakov
  1 sibling, 0 replies; 11+ messages in thread
From: Roman Bolshakov @ 2021-02-04  9:51 UTC (permalink / raw)
  To: yaroshchuk2000; +Cc: qemu-trivial, pbonzini, qemu-devel, dirty

On Fri, Jan 22, 2021 at 06:05:18PM +0300, yaroshchuk2000@gmail.com wrote:
> From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> 
> For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
> add paravirtualization cpuid leaf 0x40000010
> https://lkml.org/lkml/2008/10/1/246
> 
> Leaf 0x40000010, Timing Information:
> EAX: (Virtual) TSC frequency in kHz.
> EBX: (Virtual) Bus (local apic timer) frequency in kHz.
> ECX, EDX: RESERVED (Per above, reserved fields are set to zero).
> 
> On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
> names `machdep.tsc.frequency` and `hw.busfrequency`
> 
> This options is required for Darwin-XNU guest to be synchronized with
> host
> 
> Leaf 0x40000000 not exposes HVF leaving hypervisor signature empty
> 
> Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> ---
>  target/i386/hvf/hvf.c | 96 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 95 insertions(+), 1 deletion(-)
> 

I'd prefer to have generic expose-accel option for CPU and
vmware-cpuid-freq=on would depend on expose-accel=on.

Regardless of that,

Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
Tested-by: Roman Bolshakov <r.bolshakov@yadro.com>

Thanks,
Roman


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v3] target/i386/hvf: add vmware-cpuid-freq cpu feature
  2021-01-22 15:05   ` [PATCH v3] " yaroshchuk2000
  2021-02-04  9:51     ` Roman Bolshakov
@ 2021-02-09 10:32     ` Roman Bolshakov
  1 sibling, 0 replies; 11+ messages in thread
From: Roman Bolshakov @ 2021-02-09 10:32 UTC (permalink / raw)
  To: yaroshchuk2000; +Cc: qemu-trivial, pbonzini, qemu-devel, dirty

On Fri, Jan 22, 2021 at 06:05:18PM +0300, yaroshchuk2000@gmail.com wrote:
> From: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> 
> For `-accel hvf` cpu_x86_cpuid() is wrapped with hvf_cpu_x86_cpuid() to
> add paravirtualization cpuid leaf 0x40000010
> https://lkml.org/lkml/2008/10/1/246
> 
> Leaf 0x40000010, Timing Information:
> EAX: (Virtual) TSC frequency in kHz.
> EBX: (Virtual) Bus (local apic timer) frequency in kHz.
> ECX, EDX: RESERVED (Per above, reserved fields are set to zero).
> 
> On macOS TSC and APIC Bus frequencies can be readed by sysctl call with
> names `machdep.tsc.frequency` and `hw.busfrequency`
> 
> This options is required for Darwin-XNU guest to be synchronized with
> host
> 
> Leaf 0x40000000 not exposes HVF leaving hypervisor signature empty
> 
> Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
> ---
>  target/i386/hvf/hvf.c | 96 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 95 insertions(+), 1 deletion(-)
> 

Queued, thanks!

-Roman


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-02-09 10:33 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-13 20:52 [PATCH] target/i386/hvf: add vmware-cpuid-freq cpu feature yaroshchuk2000
2021-01-13 21:25 ` no-reply
2021-01-14 19:47 ` [PATCH v2] " yaroshchuk2000
2021-01-19 18:01   ` Roman Bolshakov
2021-01-19 18:14     ` Paolo Bonzini
2021-01-22 14:29     ` Vladislav Yaroshchuk
2021-01-19 22:37   ` dirty--- via
2021-01-22 14:51     ` Vladislav Yaroshchuk
2021-01-22 15:05   ` [PATCH v3] " yaroshchuk2000
2021-02-04  9:51     ` Roman Bolshakov
2021-02-09 10:32     ` Roman Bolshakov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.