On 09.02.2024 12:40, Roger Pau Monne wrote:
> @@ -1378,6 +1379,10 @@ static int construct_vmcs(struct vcpu *v)
>          rc = vmx_add_msr(v, MSR_PRED_CMD, PRED_CMD_IBPB,
>                           VMX_MSR_HOST);
>  
> +    /* Set any bits we don't allow toggling in the mask field. */
> +    if ( cpu_has_vmx_virt_spec_ctrl && v->arch.msrs->spec_ctrl.raw )
> +        __vmwrite(SPEC_CTRL_MASK, v->arch.msrs->spec_ctrl.raw);

The right side of the conditional isn't strictly necessary here, is it?
Might it be better to omit it, for clarity?

> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -823,18 +823,29 @@ static void cf_check vmx_cpuid_policy_changed(struct 
> vcpu *v)
>      {
>          vmx_clear_msr_intercept(v, MSR_SPEC_CTRL, VMX_MSR_RW);
>  
> -        rc = vmx_add_guest_msr(v, MSR_SPEC_CTRL, 0);
> -        if ( rc )
> -            goto out;
> +        if ( !cpu_has_vmx_virt_spec_ctrl )
> +        {
> +            rc = vmx_add_guest_msr(v, MSR_SPEC_CTRL, 0);
> +            if ( rc )
> +                goto out;
> +        }
>      }
>      else
>      {
>          vmx_set_msr_intercept(v, MSR_SPEC_CTRL, VMX_MSR_RW);
>  
> -        rc = vmx_del_msr(v, MSR_SPEC_CTRL, VMX_MSR_GUEST);
> -        if ( rc && rc != -ESRCH )
> -            goto out;
> -        rc = 0; /* Tolerate -ESRCH */
> +        /*
> +         * NB: there's no need to clear the virtualize SPEC_CTRL control, as
> +         * the MSR intercept takes precedence.  The SPEC_CTRL shadow VMCS 
> field
> +         * is also not loaded on guest entry/exit if the intercept is set.
> +         */

It wasn't so much the shadow field than the mask one that I was concerned
might be used in some way. The shadow one clearly is used only during
guest RDMSR/WRMSR processing. To not focus on "shadow", maybe simple say
"The SPEC_CTRL shadow VMCS fields are also not ..."?

> +        if ( !cpu_has_vmx_virt_spec_ctrl )
> +        {
> +            rc = vmx_del_msr(v, MSR_SPEC_CTRL, VMX_MSR_GUEST);
> +            if ( rc && rc != -ESRCH )
> +                goto out;
> +            rc = 0; /* Tolerate -ESRCH */
> +        }
>      }
>  
>      /* MSR_PRED_CMD is safe to pass through if the guest knows about it. */
> @@ -2629,6 +2640,9 @@ static uint64_t cf_check vmx_get_reg(struct vcpu *v, 
> unsigned int reg)
>      switch ( reg )
>      {
>      case MSR_SPEC_CTRL:
> +        if ( cpu_has_vmx_virt_spec_ctrl )
> +            /* Requires remote VMCS loaded - fetched below. */

I could see what "fetch" refers to here, but ...

> +            break;
>          rc = vmx_read_guest_msr(v, reg, &val);
>          if ( rc )
>          {
> @@ -2652,6 +2666,11 @@ static uint64_t cf_check vmx_get_reg(struct vcpu *v, 
> unsigned int reg)
>      vmx_vmcs_enter(v);
>      switch ( reg )
>      {
> +    case MSR_SPEC_CTRL:
> +        ASSERT(cpu_has_vmx_virt_spec_ctrl);
> +        __vmread(SPEC_CTRL_SHADOW, &val);
> +        break;
> +
>      case MSR_IA32_BNDCFGS:
>          __vmread(GUEST_BNDCFGS, &val);
>          break;
> @@ -2678,6 +2697,9 @@ static void cf_check vmx_set_reg(struct vcpu *v, 
> unsigned int reg, uint64_t val)
>      switch ( reg )
>      {
>      case MSR_SPEC_CTRL:
> +        if ( cpu_has_vmx_virt_spec_ctrl )
> +            /* Requires remote VMCS loaded - fetched below. */

... since you also use the word here, I'm not sure it's really
the VMREAD up there.

Jan

Reply via email to