diff mbox series

[RFC,v4,13/36] i386/tdx: Validate TD attributes

Message ID 20220512031803.3315890-14-xiaoyao.li@intel.com (mailing list archive)
State New, archived
Headers show
Series TDX QEMU support | expand

Commit Message

Xiaoyao Li May 12, 2022, 3:17 a.m. UTC
Validate TD attributes with tdx_caps that fixed-0 bits must be zero and
fixed-1 bits must be set.

Besides, sanity check the attribute bits that have not been supported by
QEMU yet. e.g., debug bit, it will be allowed in the future when debug
TD support lands in QEMU.

Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
---
 target/i386/kvm/tdx.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

Comments

Gerd Hoffmann May 23, 2022, 9:39 a.m. UTC | #1
> Validate TD attributes with tdx_caps that fixed-0 bits must be zero and
> fixed-1 bits must be set.

> -static void setup_td_guest_attributes(X86CPU *x86cpu)
> +static int tdx_validate_attributes(TdxGuest *tdx)
> +{
> +    if (((tdx->attributes & tdx_caps->attrs_fixed0) | tdx_caps->attrs_fixed1) !=
> +        tdx->attributes) {
> +            error_report("Invalid attributes 0x%lx for TDX VM (fixed0 0x%llx, fixed1 0x%llx)",
> +                          tdx->attributes, tdx_caps->attrs_fixed0, tdx_caps->attrs_fixed1);
> +            return -EINVAL;
> +    }

So, how is this supposed to work?  Patch #2 introduces attributes as
user-settable property.  So do users have to manually figure and pass
the correct value, so the check passes?  Specifically the fixed1 check?

I think 'attributes' should not be user-settable in the first place.
Each feature-bit which is actually user-settable (and not already
covered by another option like pmu) should be a separate attribute for
tdx-object.  Then the tdx code can create attributes from hardware
capabilities and user settings.

When user-settable options might not be available depending on hardware
capabilities best practice is to create them as OnOffAuto properties.

  Auto == qemu can pick the value, typical behavior is to enable the
          feature if the hardware supports it.
  On == must enable, if it isn't possible throw an error and exit.
  Off == must disable, if it isn't possible throw an error and exit. 

take care,
  Gerd
Xiaoyao Li May 24, 2022, 4:19 a.m. UTC | #2
On 5/23/2022 5:39 PM, Gerd Hoffmann wrote:
>> Validate TD attributes with tdx_caps that fixed-0 bits must be zero and
>> fixed-1 bits must be set.
> 
>> -static void setup_td_guest_attributes(X86CPU *x86cpu)
>> +static int tdx_validate_attributes(TdxGuest *tdx)
>> +{
>> +    if (((tdx->attributes & tdx_caps->attrs_fixed0) | tdx_caps->attrs_fixed1) !=
>> +        tdx->attributes) {
>> +            error_report("Invalid attributes 0x%lx for TDX VM (fixed0 0x%llx, fixed1 0x%llx)",
>> +                          tdx->attributes, tdx_caps->attrs_fixed0, tdx_caps->attrs_fixed1);
>> +            return -EINVAL;
>> +    }
> 
> So, how is this supposed to work?  Patch #2 introduces attributes as
> user-settable property.  So do users have to manually figure and pass
> the correct value, so the check passes?  Specifically the fixed1 check?
> 
> I think 'attributes' should not be user-settable in the first place.
> Each feature-bit which is actually user-settable (and not already
> covered by another option like pmu) should be a separate attribute for
> tdx-object.  Then the tdx code can create attributes from hardware
> capabilities and user settings.

In patch #2, tdx-guest.attributes is defined as a field to hold a 64 
bits value of attributes but it doesn't provide any getter/setter for 
it. So it's *not* user-settable.

Did I miss something? (I'm not good at QEMU object)

> When user-settable options might not be available depending on hardware
> capabilities best practice is to create them as OnOffAuto properties.
> 
>    Auto == qemu can pick the value, typical behavior is to enable the
>            feature if the hardware supports it.
>    On == must enable, if it isn't possible throw an error and exit.
>    Off == must disable, if it isn't possible throw an error and exit.
> 
> take care,
>    Gerd
>
Gerd Hoffmann May 24, 2022, 6:59 a.m. UTC | #3
On Tue, May 24, 2022 at 12:19:51PM +0800, Xiaoyao Li wrote:
> On 5/23/2022 5:39 PM, Gerd Hoffmann wrote:
> > So, how is this supposed to work?  Patch #2 introduces attributes as
> > user-settable property.  So do users have to manually figure and pass
> > the correct value, so the check passes?  Specifically the fixed1 check?
> > 
> > I think 'attributes' should not be user-settable in the first place.
> > Each feature-bit which is actually user-settable (and not already
> > covered by another option like pmu) should be a separate attribute for
> > tdx-object.  Then the tdx code can create attributes from hardware
> > capabilities and user settings.
> 
> In patch #2, tdx-guest.attributes is defined as a field to hold a 64 bits
> value of attributes but it doesn't provide any getter/setter for it. So it's
> *not* user-settable.

Ok.  Why it is declared as object property in the first place then?

take care,
  Gerd
Xiaoyao Li May 24, 2022, 8:11 a.m. UTC | #4
On 5/24/2022 2:59 PM, Gerd Hoffmann wrote:
> On Tue, May 24, 2022 at 12:19:51PM +0800, Xiaoyao Li wrote:
>> On 5/23/2022 5:39 PM, Gerd Hoffmann wrote:
>>> So, how is this supposed to work?  Patch #2 introduces attributes as
>>> user-settable property.  So do users have to manually figure and pass
>>> the correct value, so the check passes?  Specifically the fixed1 check?
>>>
>>> I think 'attributes' should not be user-settable in the first place.
>>> Each feature-bit which is actually user-settable (and not already
>>> covered by another option like pmu) should be a separate attribute for
>>> tdx-object.  Then the tdx code can create attributes from hardware
>>> capabilities and user settings.
>>
>> In patch #2, tdx-guest.attributes is defined as a field to hold a 64 bits
>> value of attributes but it doesn't provide any getter/setter for it. So it's
>> *not* user-settable.
> 
> Ok.  Why it is declared as object property in the first place then?

Is there another way to define a member/field of object besides property?

> take care,
>    Gerd
>
Gerd Hoffmann May 24, 2022, 8:29 a.m. UTC | #5
On Tue, May 24, 2022 at 04:11:56PM +0800, Xiaoyao Li wrote:
> On 5/24/2022 2:59 PM, Gerd Hoffmann wrote:
> > On Tue, May 24, 2022 at 12:19:51PM +0800, Xiaoyao Li wrote:
> > > On 5/23/2022 5:39 PM, Gerd Hoffmann wrote:
> > > > So, how is this supposed to work?  Patch #2 introduces attributes as
> > > > user-settable property.  So do users have to manually figure and pass
> > > > the correct value, so the check passes?  Specifically the fixed1 check?
> > > > 
> > > > I think 'attributes' should not be user-settable in the first place.
> > > > Each feature-bit which is actually user-settable (and not already
> > > > covered by another option like pmu) should be a separate attribute for
> > > > tdx-object.  Then the tdx code can create attributes from hardware
> > > > capabilities and user settings.
> > > 
> > > In patch #2, tdx-guest.attributes is defined as a field to hold a 64 bits
> > > value of attributes but it doesn't provide any getter/setter for it. So it's
> > > *not* user-settable.
> > 
> > Ok.  Why it is declared as object property in the first place then?
> 
> Is there another way to define a member/field of object besides property?

Well, the C object struct is completely independent from the qapi
struct.  Typically qapi-generated structs are added as struct fields.
Look at ui/input-linux.c for example.

struct InputLinux holds all the object state.  It has a GrabToggleKeys
field, that is a qapi-generated enum (see qapi/common.json) and is
user-configurable (there are getter and setter for it).

So, you can have a private 'attributes' struct field in your tdx class,
but the field doesn't have to be in the qapi struct for that.

HTH,
  Gerd
Xiaoyao Li May 26, 2022, 3:44 a.m. UTC | #6
On 5/24/2022 4:29 PM, Gerd Hoffmann wrote:
> On Tue, May 24, 2022 at 04:11:56PM +0800, Xiaoyao Li wrote:
>> On 5/24/2022 2:59 PM, Gerd Hoffmann wrote:
>>> On Tue, May 24, 2022 at 12:19:51PM +0800, Xiaoyao Li wrote:
>>>> On 5/23/2022 5:39 PM, Gerd Hoffmann wrote:
>>>>> So, how is this supposed to work?  Patch #2 introduces attributes as
>>>>> user-settable property.  So do users have to manually figure and pass
>>>>> the correct value, so the check passes?  Specifically the fixed1 check?
>>>>>
>>>>> I think 'attributes' should not be user-settable in the first place.
>>>>> Each feature-bit which is actually user-settable (and not already
>>>>> covered by another option like pmu) should be a separate attribute for
>>>>> tdx-object.  Then the tdx code can create attributes from hardware
>>>>> capabilities and user settings.
>>>>
>>>> In patch #2, tdx-guest.attributes is defined as a field to hold a 64 bits
>>>> value of attributes but it doesn't provide any getter/setter for it. So it's
>>>> *not* user-settable.
>>>
>>> Ok.  Why it is declared as object property in the first place then?
>>
>> Is there another way to define a member/field of object besides property?
> 
> Well, the C object struct is completely independent from the qapi
> struct.  Typically qapi-generated structs are added as struct fields.
> Look at ui/input-linux.c for example.
> 
> struct InputLinux holds all the object state.  It has a GrabToggleKeys
> field, that is a qapi-generated enum (see qapi/common.json) and is
> user-configurable (there are getter and setter for it).
> 
> So, you can have a private 'attributes' struct field in your tdx class,
> but the field doesn't have to be in the qapi struct for that.

I see. Thanks for the explanation!

I will remove the qom property definition in patch 2.

> HTH,
>    Gerd
>
diff mbox series

Patch

diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
index e9c6e6fb396c..9f2cdf640b5c 100644
--- a/target/i386/kvm/tdx.c
+++ b/target/i386/kvm/tdx.c
@@ -31,6 +31,7 @@ 
                                      (1ULL << KVM_FEATURE_PV_SCHED_YIELD) | \
                                      (1ULL << KVM_FEATURE_MSI_EXT_DEST_ID))
 
+#define TDX_TD_ATTRIBUTES_DEBUG             BIT_ULL(0)
 #define TDX_TD_ATTRIBUTES_PKS               BIT_ULL(30)
 #define TDX_TD_ATTRIBUTES_PERFMON           BIT_ULL(63)
 
@@ -169,13 +170,32 @@  void tdx_get_supported_cpuid(uint32_t function, uint32_t index, int reg,
     }
 }
 
-static void setup_td_guest_attributes(X86CPU *x86cpu)
+static int tdx_validate_attributes(TdxGuest *tdx)
+{
+    if (((tdx->attributes & tdx_caps->attrs_fixed0) | tdx_caps->attrs_fixed1) !=
+        tdx->attributes) {
+            error_report("Invalid attributes 0x%lx for TDX VM (fixed0 0x%llx, fixed1 0x%llx)",
+                          tdx->attributes, tdx_caps->attrs_fixed0, tdx_caps->attrs_fixed1);
+            return -EINVAL;
+    }
+
+    if (tdx->attributes & TDX_TD_ATTRIBUTES_DEBUG) {
+        error_report("Current QEMU doesn't support attributes.debug[bit 0] for TDX VM");
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static int setup_td_guest_attributes(X86CPU *x86cpu)
 {
     CPUX86State *env = &x86cpu->env;
 
     tdx_guest->attributes |= (env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKS) ?
                              TDX_TD_ATTRIBUTES_PKS : 0;
     tdx_guest->attributes |= x86cpu->enable_pmu ? TDX_TD_ATTRIBUTES_PERFMON : 0;
+
+    return tdx_validate_attributes(tdx_guest);
 }
 
 int tdx_pre_create_vcpu(CPUState *cpu)
@@ -191,7 +211,10 @@  int tdx_pre_create_vcpu(CPUState *cpu)
         goto out;
     }
 
-    setup_td_guest_attributes(x86cpu);
+    r = setup_td_guest_attributes(x86cpu);
+    if (r) {
+        goto out;
+    }
 
     memset(&init_vm, 0, sizeof(init_vm));
     init_vm.cpuid.nent = kvm_x86_arch_cpuid(env, init_vm.entries, 0);