diff mbox series

[v2,2/2,RfC] expose host-phys-bits to guest

Message ID 20220908113109.470792-3-kraxel@redhat.com (mailing list archive)
State New, archived
Headers show
Series expose host-phys-bits to guest | expand

Commit Message

Gerd Hoffmann Sept. 8, 2022, 11:31 a.m. UTC
Move "host-phys-bits" property from cpu->host_phys_bits to
cpu->env.features[FEAT_KVM_HINTS] (KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID bit).

This has the effect that the guest can see whenever host-phys-bits
is turned on or not and act accordingly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 target/i386/cpu.h      | 3 ---
 hw/i386/microvm.c      | 7 ++++++-
 target/i386/cpu.c      | 3 +--
 target/i386/host-cpu.c | 5 ++++-
 target/i386/kvm/kvm.c  | 1 +
 5 files changed, 12 insertions(+), 7 deletions(-)

Comments

Michael S. Tsirkin Sept. 8, 2022, 2:19 p.m. UTC | #1
On Thu, Sep 08, 2022 at 01:31:09PM +0200, Gerd Hoffmann wrote:
> Move "host-phys-bits" property from cpu->host_phys_bits to
> cpu->env.features[FEAT_KVM_HINTS] (KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID bit).
> 
> This has the effect that the guest can see whenever host-phys-bits
> is turned on or not and act accordingly.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  target/i386/cpu.h      | 3 ---
>  hw/i386/microvm.c      | 7 ++++++-
>  target/i386/cpu.c      | 3 +--
>  target/i386/host-cpu.c | 5 ++++-
>  target/i386/kvm/kvm.c  | 1 +
>  5 files changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 82004b65b944..b9c6d3d9cac6 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1898,9 +1898,6 @@ struct ArchCPU {
>      /* if true fill the top bits of the MTRR_PHYSMASKn variable range */
>      bool fill_mtrr_mask;
>  
> -    /* if true override the phys_bits value with a value read from the host */
> -    bool host_phys_bits;
> -
>      /* if set, limit maximum value for phys_bits when host_phys_bits is true */
>      uint8_t host_phys_bits_limit;
>  
> diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
> index 52cafa003d8a..316bbc8ef946 100644
> --- a/hw/i386/microvm.c
> +++ b/hw/i386/microvm.c
> @@ -54,6 +54,8 @@
>  #include "kvm/kvm_i386.h"
>  #include "hw/xen/start_info.h"
>  
> +#include "standard-headers/asm-x86/kvm_para.h"
> +
>  #define MICROVM_QBOOT_FILENAME "qboot.rom"
>  #define MICROVM_BIOS_FILENAME  "bios-microvm.bin"
>  
> @@ -424,7 +426,10 @@ static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev,
>  {
>      X86CPU *cpu = X86_CPU(dev);
>  
> -    cpu->host_phys_bits = true; /* need reliable phys-bits */
> +    /* need reliable phys-bits */
> +    cpu->env.features[FEAT_KVM_HINTS] |=
> +        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID);
> +

Do we need compat machinery for this?

>      x86_cpu_pre_plug(hotplug_dev, dev, errp);
>  }
>  
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 1db1278a599b..d60f4498a3c3 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -778,7 +778,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>      [FEAT_KVM_HINTS] = {
>          .type = CPUID_FEATURE_WORD,
>          .feat_names = {
> -            "kvm-hint-dedicated", NULL, NULL, NULL,
> +            "kvm-hint-dedicated", "host-phys-bits", NULL, NULL,
>              NULL, NULL, NULL, NULL,
>              NULL, NULL, NULL, NULL,
>              NULL, NULL, NULL, NULL,
> @@ -7016,7 +7016,6 @@ static Property x86_cpu_properties[] = {
>      DEFINE_PROP_BOOL("x-force-features", X86CPU, force_features, false),
>      DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
>      DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0),
> -    DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false),
>      DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0),
>      DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true),
>      DEFINE_PROP_UINT32("level-func7", X86CPU, env.cpuid_level_func7,
> diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c
> index 10f8aba86e53..a1d6b3ac962e 100644
> --- a/target/i386/host-cpu.c
> +++ b/target/i386/host-cpu.c
> @@ -13,6 +13,8 @@
>  #include "qapi/error.h"
>  #include "sysemu/sysemu.h"
>  
> +#include "standard-headers/asm-x86/kvm_para.h"
> +
>  /* Note: Only safe for use on x86(-64) hosts */
>  static uint32_t host_cpu_phys_bits(void)
>  {
> @@ -68,7 +70,8 @@ static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu)
>          warned = true;
>      }
>  
> -    if (cpu->host_phys_bits) {
> +    if (cpu->env.features[FEAT_KVM_HINTS] &
> +        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID)) {
>          /* The user asked for us to use the host physical bits */
>          phys_bits = host_phys_bits;
>          if (cpu->host_phys_bits_limit &&

I think we still want to key this one off host_phys_bits
so it works for e.g. hyperv emulation too.

> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index a1fd1f53791d..3335c57b21b2 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -459,6 +459,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
>          }
>      } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) {
>          ret |= 1U << KVM_HINTS_REALTIME;
> +        ret |= 1U << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID;
>      }
>  
>      return ret;
> -- 
> 2.37.3
Gerd Hoffmann Sept. 9, 2022, 5:18 a.m. UTC | #2
Hi,

> > @@ -424,7 +426,10 @@ static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> >  {
> >      X86CPU *cpu = X86_CPU(dev);
> >  
> > -    cpu->host_phys_bits = true; /* need reliable phys-bits */
> > +    /* need reliable phys-bits */
> > +    cpu->env.features[FEAT_KVM_HINTS] |=
> > +        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID);
> > +
> 
> Do we need compat machinery for this?

Don't think so, microvm has no versioned machine types anyway.

> > --- a/target/i386/cpu.c
> > +++ b/target/i386/cpu.c

> >      [FEAT_KVM_HINTS] = {
> >          .type = CPUID_FEATURE_WORD,
> >          .feat_names = {
> > -            "kvm-hint-dedicated", NULL, NULL, NULL,
> > +            "kvm-hint-dedicated", "host-phys-bits", NULL, NULL,

> > -    DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false),

> > -    if (cpu->host_phys_bits) {
> > +    if (cpu->env.features[FEAT_KVM_HINTS] &
> > +        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID)) {
> >          /* The user asked for us to use the host physical bits */
> >          phys_bits = host_phys_bits;
> >          if (cpu->host_phys_bits_limit &&
> 
> I think we still want to key this one off host_phys_bits
> so it works for e.g. hyperv emulation too.

I think that should be the case.  The chunks above change the
host-phys-bits option from setting cpu->host_phys_bits to setting
the FEAT_KVM_HINTS bit.  That should also happen with hyperv emulation
enabled, and the bit should also be visible to the guest then, just at
another location (base 0x40000100 instead of 0x40000000).

take care,
  Gerd
Michael S. Tsirkin Sept. 9, 2022, 5:51 a.m. UTC | #3
On Fri, Sep 09, 2022 at 07:18:17AM +0200, Gerd Hoffmann wrote:
>   Hi,
> 
> > > @@ -424,7 +426,10 @@ static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev,
> > >  {
> > >      X86CPU *cpu = X86_CPU(dev);
> > >  
> > > -    cpu->host_phys_bits = true; /* need reliable phys-bits */
> > > +    /* need reliable phys-bits */
> > > +    cpu->env.features[FEAT_KVM_HINTS] |=
> > > +        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID);
> > > +
> > 
> > Do we need compat machinery for this?
> 
> Don't think so, microvm has no versioned machine types anyway.
> 
> > > --- a/target/i386/cpu.c
> > > +++ b/target/i386/cpu.c
> 
> > >      [FEAT_KVM_HINTS] = {
> > >          .type = CPUID_FEATURE_WORD,
> > >          .feat_names = {
> > > -            "kvm-hint-dedicated", NULL, NULL, NULL,
> > > +            "kvm-hint-dedicated", "host-phys-bits", NULL, NULL,
> 
> > > -    DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false),
> 
> > > -    if (cpu->host_phys_bits) {
> > > +    if (cpu->env.features[FEAT_KVM_HINTS] &
> > > +        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID)) {
> > >          /* The user asked for us to use the host physical bits */
> > >          phys_bits = host_phys_bits;
> > >          if (cpu->host_phys_bits_limit &&
> > 
> > I think we still want to key this one off host_phys_bits
> > so it works for e.g. hyperv emulation too.
> 
> I think that should be the case.  The chunks above change the
> host-phys-bits option from setting cpu->host_phys_bits to setting
> the FEAT_KVM_HINTS bit.  That should also happen with hyperv emulation
> enabled, and the bit should also be visible to the guest then, just at
> another location (base 0x40000100 instead of 0x40000000).
> 
> take care,
>   Gerd


You are right, I forgot. Hmm, ok. What about !cpu->expose_kvm ?

We have

    if (!kvm_enabled() || !cpu->expose_kvm) {
        env->features[FEAT_KVM] = 0;
    }   
        
This is quick grep, I didn't check whether this is called
after the point where you currently use it, but
it frankly seems fragile to pass a generic user specified flag
inside a cpuid where everyone pokes at it.
Gerd Hoffmann Sept. 9, 2022, 6:06 a.m. UTC | #4
Hi,

> > > I think we still want to key this one off host_phys_bits
> > > so it works for e.g. hyperv emulation too.
> > 
> > I think that should be the case.  The chunks above change the
> > host-phys-bits option from setting cpu->host_phys_bits to setting
> > the FEAT_KVM_HINTS bit.  That should also happen with hyperv emulation
> > enabled, and the bit should also be visible to the guest then, just at
> > another location (base 0x40000100 instead of 0x40000000).
> > 
> > take care,
> >   Gerd
> 
> 
> You are right, I forgot. Hmm, ok. What about !cpu->expose_kvm ?
> 
> We have
> 
>     if (!kvm_enabled() || !cpu->expose_kvm) {
>         env->features[FEAT_KVM] = 0;
>     }   
>         
> This is quick grep, I didn't check whether this is called
> after the point where you currently use it, but
> it frankly seems fragile to pass a generic user specified flag
> inside a cpuid where everyone pokes at it.

I tried to avoid keeping the state of the host_phys_bits option at
multiple places.  Maybe that wasn't a good idea after all.  How about
doing this instead:

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1db1278a599b..279fde095d7c 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6219,6 +6219,11 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
         env->features[FEAT_KVM] = 0;
     }
 
+    if (kvm_enabled() && cpu->host_phys_bits) {
+        env->features[FEAT_KVM_HINTS] |=
+            (1U << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID);
+    }
+
     x86_cpu_enable_xsave_components(cpu);
 
     /* CPUID[EAX=7,ECX=0].EBX always increased level automatically: */
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index a1fd1f53791d..3335c57b21b2 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -459,6 +459,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
         }
     } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) {
         ret |= 1U << KVM_HINTS_REALTIME;
+        ret |= 1U << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID;
     }
 
     return ret;
Michael S. Tsirkin Sept. 9, 2022, 6:13 a.m. UTC | #5
On Fri, Sep 09, 2022 at 08:06:53AM +0200, Gerd Hoffmann wrote:
>   Hi,
> 
> > > > I think we still want to key this one off host_phys_bits
> > > > so it works for e.g. hyperv emulation too.
> > > 
> > > I think that should be the case.  The chunks above change the
> > > host-phys-bits option from setting cpu->host_phys_bits to setting
> > > the FEAT_KVM_HINTS bit.  That should also happen with hyperv emulation
> > > enabled, and the bit should also be visible to the guest then, just at
> > > another location (base 0x40000100 instead of 0x40000000).
> > > 
> > > take care,
> > >   Gerd
> > 
> > 
> > You are right, I forgot. Hmm, ok. What about !cpu->expose_kvm ?
> > 
> > We have
> > 
> >     if (!kvm_enabled() || !cpu->expose_kvm) {
> >         env->features[FEAT_KVM] = 0;
> >     }   
> >         
> > This is quick grep, I didn't check whether this is called
> > after the point where you currently use it, but
> > it frankly seems fragile to pass a generic user specified flag
> > inside a cpuid where everyone pokes at it.
> 
> I tried to avoid keeping the state of the host_phys_bits option at
> multiple places.  Maybe that wasn't a good idea after all.  How about
> doing this instead:
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 1db1278a599b..279fde095d7c 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -6219,6 +6219,11 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
>          env->features[FEAT_KVM] = 0;
>      }
>  
> +    if (kvm_enabled() && cpu->host_phys_bits) {
> +        env->features[FEAT_KVM_HINTS] |=
> +            (1U << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID);
> +    }
> +
>      x86_cpu_enable_xsave_components(cpu);
>  
>      /* CPUID[EAX=7,ECX=0].EBX always increased level automatically: */
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index a1fd1f53791d..3335c57b21b2 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -459,6 +459,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
>          }
>      } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) {
>          ret |= 1U << KVM_HINTS_REALTIME;
> +        ret |= 1U << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID;
>      }
>  
>      return ret;


/me nods.
That seems much more straight-forward.
diff mbox series

Patch

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 82004b65b944..b9c6d3d9cac6 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1898,9 +1898,6 @@  struct ArchCPU {
     /* if true fill the top bits of the MTRR_PHYSMASKn variable range */
     bool fill_mtrr_mask;
 
-    /* if true override the phys_bits value with a value read from the host */
-    bool host_phys_bits;
-
     /* if set, limit maximum value for phys_bits when host_phys_bits is true */
     uint8_t host_phys_bits_limit;
 
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 52cafa003d8a..316bbc8ef946 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -54,6 +54,8 @@ 
 #include "kvm/kvm_i386.h"
 #include "hw/xen/start_info.h"
 
+#include "standard-headers/asm-x86/kvm_para.h"
+
 #define MICROVM_QBOOT_FILENAME "qboot.rom"
 #define MICROVM_BIOS_FILENAME  "bios-microvm.bin"
 
@@ -424,7 +426,10 @@  static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev,
 {
     X86CPU *cpu = X86_CPU(dev);
 
-    cpu->host_phys_bits = true; /* need reliable phys-bits */
+    /* need reliable phys-bits */
+    cpu->env.features[FEAT_KVM_HINTS] |=
+        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID);
+
     x86_cpu_pre_plug(hotplug_dev, dev, errp);
 }
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1db1278a599b..d60f4498a3c3 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -778,7 +778,7 @@  FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
     [FEAT_KVM_HINTS] = {
         .type = CPUID_FEATURE_WORD,
         .feat_names = {
-            "kvm-hint-dedicated", NULL, NULL, NULL,
+            "kvm-hint-dedicated", "host-phys-bits", NULL, NULL,
             NULL, NULL, NULL, NULL,
             NULL, NULL, NULL, NULL,
             NULL, NULL, NULL, NULL,
@@ -7016,7 +7016,6 @@  static Property x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("x-force-features", X86CPU, force_features, false),
     DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
     DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0),
-    DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false),
     DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0),
     DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true),
     DEFINE_PROP_UINT32("level-func7", X86CPU, env.cpuid_level_func7,
diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c
index 10f8aba86e53..a1d6b3ac962e 100644
--- a/target/i386/host-cpu.c
+++ b/target/i386/host-cpu.c
@@ -13,6 +13,8 @@ 
 #include "qapi/error.h"
 #include "sysemu/sysemu.h"
 
+#include "standard-headers/asm-x86/kvm_para.h"
+
 /* Note: Only safe for use on x86(-64) hosts */
 static uint32_t host_cpu_phys_bits(void)
 {
@@ -68,7 +70,8 @@  static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu)
         warned = true;
     }
 
-    if (cpu->host_phys_bits) {
+    if (cpu->env.features[FEAT_KVM_HINTS] &
+        (1 << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID)) {
         /* The user asked for us to use the host physical bits */
         phys_bits = host_phys_bits;
         if (cpu->host_phys_bits_limit &&
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index a1fd1f53791d..3335c57b21b2 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -459,6 +459,7 @@  uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
         }
     } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) {
         ret |= 1U << KVM_HINTS_REALTIME;
+        ret |= 1U << KVM_HINTS_PHYS_ADDRESS_SIZE_DATA_VALID;
     }
 
     return ret;