Re: [PATCH v19 027/130] KVM: TDX: Define TDX architectural definitions

From: Sean Christopherson
Date: Wed Apr 03 2024 - 11:04:31 EST


On Mon, Feb 26, 2024, isaku.yamahata@xxxxxxxxx wrote:
> +union tdx_vcpu_state_details {
> + struct {
> + u64 vmxip : 1;
> + u64 reserved : 63;
> + };
> + u64 full;
> +};

No unions please. KVM uses unions in a few places where they are the lesser of
all evils, but in general, unions are frowned upon. Bitfields in particular are
strongly discourage, as they are a nightmare to read/review and tend to generate
bad code.

E.g. for this one, something like (names aren't great)

static inline bool tdx_has_pending_virtual_interrupt(struct kvm_vcpu *vcpu)
{
return <get "non arch field"> & TDX_VCPU_STATE_VMXIP;
}

> +union tdx_sept_entry {
> + struct {
> + u64 r : 1;
> + u64 w : 1;
> + u64 x : 1;
> + u64 mt : 3;
> + u64 ipat : 1;
> + u64 leaf : 1;
> + u64 a : 1;
> + u64 d : 1;
> + u64 xu : 1;
> + u64 ignored0 : 1;
> + u64 pfn : 40;
> + u64 reserved : 5;
> + u64 vgp : 1;
> + u64 pwa : 1;
> + u64 ignored1 : 1;
> + u64 sss : 1;
> + u64 spp : 1;
> + u64 ignored2 : 1;
> + u64 sve : 1;

Yeah, NAK to these unions. They are crappy duplicates of existing definitions,
e.g. it took me a few seconds to realize SVE is SUPPRESS_VE, which is far too
long.

> + };
> + u64 raw;
> +};
> +enum tdx_sept_entry_state {
> + TDX_SEPT_FREE = 0,
> + TDX_SEPT_BLOCKED = 1,
> + TDX_SEPT_PENDING = 2,
> + TDX_SEPT_PENDING_BLOCKED = 3,
> + TDX_SEPT_PRESENT = 4,
> +};
> +
> +union tdx_sept_level_state {
> + struct {
> + u64 level : 3;
> + u64 reserved0 : 5;
> + u64 state : 8;
> + u64 reserved1 : 48;
> + };
> + u64 raw;
> +};

Similar thing here. Depending on what happens with the SEAMCALL argument mess,
the code can look somethign like:

static u8 tdx_get_sept_level(struct tdx_module_args *out)
{
return out->rdx & TDX_SEPT_LEVEL_MASK;
}

static u8 tdx_get_sept_state(struct tdx_module_args *out)
{
return (out->rdx & TDX_SEPT_STATE_MASK) >> TDX_SEPT_STATE_SHIFT;
}

> +union tdx_md_field_id {
> + struct {
> + u64 field : 24;
> + u64 reserved0 : 8;
> + u64 element_size_code : 2;
> + u64 last_element_in_field : 4;
> + u64 reserved1 : 3;
> + u64 inc_size : 1;
> + u64 write_mask_valid : 1;
> + u64 context : 3;
> + u64 reserved2 : 1;
> + u64 class : 6;
> + u64 reserved3 : 1;
> + u64 non_arch : 1;
> + };
> + u64 raw;
> +};
> +
> +#define TDX_MD_ELEMENT_SIZE_CODE(_field_id) \
> + ({ union tdx_md_field_id _fid = { .raw = (_field_id)}; \
> + _fid.element_size_code; })

Yeah, no thanks. MASK + SHIFT will do just fine.