diff mbox series

[RFC,5/6] capabilities: add dom0 cpu faulting disable

Message ID 20230801202006.20322-6-dpsmith@apertussolutions.com (mailing list archive)
State New, archived
Headers show
Series Hyperlaunch domain roles and capabilities | expand

Commit Message

Daniel P. Smith Aug. 1, 2023, 8:20 p.m. UTC
This encapsulates disableing cpu faulting for PV dom0 as a capability.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/arch/x86/cpu-policy.c |  2 +-
 xen/arch/x86/cpu/common.c | 82 +++++++++++++++++++--------------------
 xen/arch/x86/setup.c      |  4 ++
 xen/include/xen/sched.h   |  8 +++-
 4 files changed, 52 insertions(+), 44 deletions(-)

Comments

Jan Beulich Aug. 8, 2023, 3:30 p.m. UTC | #1
On 01.08.2023 22:20, Daniel P. Smith wrote:
> --- a/xen/arch/x86/cpu/common.c
> +++ b/xen/arch/x86/cpu/common.c
> @@ -164,48 +164,46 @@ static void set_cpuid_faulting(bool enable)
>  
>  void ctxt_switch_levelling(const struct vcpu *next)
>  {
> -	const struct domain *nextd = next ? next->domain : NULL;
> -	bool enable_cpuid_faulting;
> -
> -	if (cpu_has_cpuid_faulting ||
> -	    boot_cpu_has(X86_FEATURE_CPUID_USER_DIS)) {
> -		/*
> -		 * No need to alter the faulting setting if we are switching
> -		 * to idle; it won't affect any code running in idle context.
> -		 */
> -		if (nextd && is_idle_domain(nextd))
> -			return;
> -		/*
> -		 * We *should* be enabling faulting for PV control domains.
> -		 *
> -		 * The domain builder has now been updated to not depend on
> -		 * seeing host CPUID values.  This makes it compatible with
> -		 * PVH toolstack domains, and lets us enable faulting by
> -		 * default for all PV domains.
> -		 *
> -		 * However, as PV control domains have never had faulting
> -		 * enforced on them before, there might plausibly be other
> -		 * dependenices on host CPUID data.  Therefore, we have left
> -		 * an interim escape hatch in the form of
> -		 * `dom0=no-cpuid-faulting` to restore the older behaviour.
> -		 */
> -		enable_cpuid_faulting = nextd && (opt_dom0_cpuid_faulting ||
> -		                                  !is_control_domain(nextd) ||
> -		                                  !is_pv_domain(nextd)) &&
> -		                        (is_pv_domain(nextd) ||
> -		                         next->arch.msrs->
> -		                         misc_features_enables.cpuid_faulting);
> -
> -		if (cpu_has_cpuid_faulting)
> -			set_cpuid_faulting(enable_cpuid_faulting);
> -		else
> -			amd_set_cpuid_user_dis(enable_cpuid_faulting);
> -
> -		return;
> -	}
> -
> -	if (ctxt_switch_masking)
> -		alternative_vcall(ctxt_switch_masking, next);
> +    const struct domain *nextd = next ? next->domain : NULL;
> +    bool enable_cpuid_faulting;
> +
> +    if ( cpu_has_cpuid_faulting ||
> +         boot_cpu_has(X86_FEATURE_CPUID_USER_DIS) ) {
> +        /*
> +        * No need to alter the faulting setting if we are switching
> +        * to idle; it won't affect any code running in idle context.
> +        */
> +        if (nextd && is_idle_domain(nextd))
> +            return;
> +        /*
> +        * We *should* be enabling faulting for PV control domains.
> +        *
> +        * The domain builder has now been updated to not depend on
> +        * seeing host CPUID values.  This makes it compatible with
> +        * PVH toolstack domains, and lets us enable faulting by
> +        * default for all PV domains.
> +        *
> +        * However, as PV control domains have never had faulting
> +        * enforced on them before, there might plausibly be other
> +        * dependenices on host CPUID data.  Therefore, we have left
> +        * an interim escape hatch in the form of
> +        * `dom0=no-cpuid-faulting` to restore the older behaviour.
> +        */
> +        enable_cpuid_faulting = nextd &&
> +            domain_has_cap(nextd, CAP_DISABLE_CPU_FAULT) &&
> +            (is_pv_domain(nextd) ||
> +            next->arch.msrs->misc_features_enables.cpuid_faulting);
> +
> +        if (cpu_has_cpuid_faulting)
> +            set_cpuid_faulting(enable_cpuid_faulting);
> +        else
> +            amd_set_cpuid_user_dis(enable_cpuid_faulting);
> +
> +        return;
> +    }
> +
> +    if (ctxt_switch_masking)
> +        alternative_vcall(ctxt_switch_masking, next);
>  }

I don't think I can spot what exactly changes here. Please avoid re-
indenting the entire function.

> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -907,6 +907,10 @@ static struct domain *__init create_dom0(const module_t *image,
>  
>      d->role |= ROLE_UNBOUNDED_DOMAIN;
>  
> +    if ( !opt_dom0_cpuid_faulting &&
> +         !domain_set_cap(d, CAP_DISABLE_CPU_FAULT) )
> +        printk(XENLOG_WARNING "failed to set CPU faulting on Dom %pd\n", d);

No "Dom" please when you use %pd. Also I don't think you mean "set". Plus
we commonly use "%pd: xyz failed\n".

> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -472,7 +472,8 @@ struct domain
>  #define ROLE_HARDWARE_DOMAIN   (1U<<2)
>  #define ROLE_XENSTORE_DOMAIN   (1U<<3)
>      uint8_t          role;
> -#define CAP_CONSOLE_IO  (1U<<0)
> +#define CAP_CONSOLE_IO         (1U<<0)
> +#define CAP_DISABLE_CPU_FAULT  (1U<<1)
>      uint8_t          capabilities;
>      /* Is this guest being debugged by dom0? */
>      bool             debugger_attached;
> @@ -1160,6 +1161,11 @@ static always_inline bool domain_set_cap(
>      case CAP_CONSOLE_IO:
>          d->capabilities |= cap;
>          break;
> +    case CAP_DISABLE_CPU_FAULT:
> +        /* Disabling cpu faulting is only allowed for a PV control domain. */
> +        if ( is_pv_domain(d) && is_control_domain(d) )
> +            d->capabilities |= cap;
> +        break;

How do you express the x86-ness of this? Plus shouldn't this fail when
either of the two conditions isn't met?

Jan
Daniel P. Smith Aug. 8, 2023, 11:59 p.m. UTC | #2
On 8/8/23 11:30, Jan Beulich wrote:
> On 01.08.2023 22:20, Daniel P. Smith wrote:
>> --- a/xen/arch/x86/cpu/common.c
>> +++ b/xen/arch/x86/cpu/common.c
>> @@ -164,48 +164,46 @@ static void set_cpuid_faulting(bool enable)
>>   
>>   void ctxt_switch_levelling(const struct vcpu *next)
>>   {
>> -	const struct domain *nextd = next ? next->domain : NULL;
>> -	bool enable_cpuid_faulting;
>> -
>> -	if (cpu_has_cpuid_faulting ||
>> -	    boot_cpu_has(X86_FEATURE_CPUID_USER_DIS)) {
>> -		/*
>> -		 * No need to alter the faulting setting if we are switching
>> -		 * to idle; it won't affect any code running in idle context.
>> -		 */
>> -		if (nextd && is_idle_domain(nextd))
>> -			return;
>> -		/*
>> -		 * We *should* be enabling faulting for PV control domains.
>> -		 *
>> -		 * The domain builder has now been updated to not depend on
>> -		 * seeing host CPUID values.  This makes it compatible with
>> -		 * PVH toolstack domains, and lets us enable faulting by
>> -		 * default for all PV domains.
>> -		 *
>> -		 * However, as PV control domains have never had faulting
>> -		 * enforced on them before, there might plausibly be other
>> -		 * dependenices on host CPUID data.  Therefore, we have left
>> -		 * an interim escape hatch in the form of
>> -		 * `dom0=no-cpuid-faulting` to restore the older behaviour.
>> -		 */
>> -		enable_cpuid_faulting = nextd && (opt_dom0_cpuid_faulting ||
>> -		                                  !is_control_domain(nextd) ||
>> -		                                  !is_pv_domain(nextd)) &&
>> -		                        (is_pv_domain(nextd) ||
>> -		                         next->arch.msrs->
>> -		                         misc_features_enables.cpuid_faulting);
>> -
>> -		if (cpu_has_cpuid_faulting)
>> -			set_cpuid_faulting(enable_cpuid_faulting);
>> -		else
>> -			amd_set_cpuid_user_dis(enable_cpuid_faulting);
>> -
>> -		return;
>> -	}
>> -
>> -	if (ctxt_switch_masking)
>> -		alternative_vcall(ctxt_switch_masking, next);
>> +    const struct domain *nextd = next ? next->domain : NULL;
>> +    bool enable_cpuid_faulting;
>> +
>> +    if ( cpu_has_cpuid_faulting ||
>> +         boot_cpu_has(X86_FEATURE_CPUID_USER_DIS) ) {
>> +        /*
>> +        * No need to alter the faulting setting if we are switching
>> +        * to idle; it won't affect any code running in idle context.
>> +        */
>> +        if (nextd && is_idle_domain(nextd))
>> +            return;
>> +        /*
>> +        * We *should* be enabling faulting for PV control domains.
>> +        *
>> +        * The domain builder has now been updated to not depend on
>> +        * seeing host CPUID values.  This makes it compatible with
>> +        * PVH toolstack domains, and lets us enable faulting by
>> +        * default for all PV domains.
>> +        *
>> +        * However, as PV control domains have never had faulting
>> +        * enforced on them before, there might plausibly be other
>> +        * dependenices on host CPUID data.  Therefore, we have left
>> +        * an interim escape hatch in the form of
>> +        * `dom0=no-cpuid-faulting` to restore the older behaviour.
>> +        */
>> +        enable_cpuid_faulting = nextd &&
>> +            domain_has_cap(nextd, CAP_DISABLE_CPU_FAULT) &&
>> +            (is_pv_domain(nextd) ||
>> +            next->arch.msrs->misc_features_enables.cpuid_faulting);
>> +
>> +        if (cpu_has_cpuid_faulting)
>> +            set_cpuid_faulting(enable_cpuid_faulting);
>> +        else
>> +            amd_set_cpuid_user_dis(enable_cpuid_faulting);
>> +
>> +        return;
>> +    }
>> +
>> +    if (ctxt_switch_masking)
>> +        alternative_vcall(ctxt_switch_masking, next);
>>   }
> 
> I don't think I can spot what exactly changes here. Please avoid re-
> indenting the entire function.

Oh, that was not intentional. I must have done a retab as that entire 
function is indented using hardtabs.

>> --- a/xen/arch/x86/setup.c
>> +++ b/xen/arch/x86/setup.c
>> @@ -907,6 +907,10 @@ static struct domain *__init create_dom0(const module_t *image,
>>   
>>       d->role |= ROLE_UNBOUNDED_DOMAIN;
>>   
>> +    if ( !opt_dom0_cpuid_faulting &&
>> +         !domain_set_cap(d, CAP_DISABLE_CPU_FAULT) )
>> +        printk(XENLOG_WARNING "failed to set CPU faulting on Dom %pd\n", d);
> 
> No "Dom" please when you use %pd. Also I don't think you mean "set". Plus
> we commonly use "%pd: xyz failed\n".

Ack on the "Dom" removal and "%pd:".

As for set, it failed to set the capability on the domain. You could say 
enable but that is nothing more than synonyms, not changing the meaning 
of the statement.

>> --- a/xen/include/xen/sched.h
>> +++ b/xen/include/xen/sched.h
>> @@ -472,7 +472,8 @@ struct domain
>>   #define ROLE_HARDWARE_DOMAIN   (1U<<2)
>>   #define ROLE_XENSTORE_DOMAIN   (1U<<3)
>>       uint8_t          role;
>> -#define CAP_CONSOLE_IO  (1U<<0)
>> +#define CAP_CONSOLE_IO         (1U<<0)
>> +#define CAP_DISABLE_CPU_FAULT  (1U<<1)
>>       uint8_t          capabilities;
>>       /* Is this guest being debugged by dom0? */
>>       bool             debugger_attached;
>> @@ -1160,6 +1161,11 @@ static always_inline bool domain_set_cap(
>>       case CAP_CONSOLE_IO:
>>           d->capabilities |= cap;
>>           break;
>> +    case CAP_DISABLE_CPU_FAULT:
>> +        /* Disabling cpu faulting is only allowed for a PV control domain. */
>> +        if ( is_pv_domain(d) && is_control_domain(d) )
>> +            d->capabilities |= cap;
>> +        break;
> 
> How do you express the x86-ness of this? Plus shouldn't this fail when
> either of the two conditions isn't met?

You are correct, since this moves an x86 capability out into common, it 
should be ifdef'ed for x86.

Correct me if I am wrong here, but in the original check it would 
evaluate that all three conditions to be true. All this change did is 
effectively move the last two conditions into domain_set_cap(). Thus 
storing the evaluation of the first two conditions during dom0 
capability setup for the result to later be evaluated during dom0 cpuid 
policy setup as it was done before.

v/r,
dps
Jan Beulich Aug. 9, 2023, 6:53 a.m. UTC | #3
On 09.08.2023 01:59, Daniel P. Smith wrote:
> On 8/8/23 11:30, Jan Beulich wrote:
>> On 01.08.2023 22:20, Daniel P. Smith wrote:
>>> --- a/xen/arch/x86/setup.c
>>> +++ b/xen/arch/x86/setup.c
>>> @@ -907,6 +907,10 @@ static struct domain *__init create_dom0(const module_t *image,
>>>   
>>>       d->role |= ROLE_UNBOUNDED_DOMAIN;
>>>   
>>> +    if ( !opt_dom0_cpuid_faulting &&
>>> +         !domain_set_cap(d, CAP_DISABLE_CPU_FAULT) )
>>> +        printk(XENLOG_WARNING "failed to set CPU faulting on Dom %pd\n", d);
>>
>> No "Dom" please when you use %pd. Also I don't think you mean "set". Plus
>> we commonly use "%pd: xyz failed\n".
> 
> Ack on the "Dom" removal and "%pd:".
> 
> As for set, it failed to set the capability on the domain. You could say 
> enable but that is nothing more than synonyms, not changing the meaning 
> of the statement.

But you don't say "capability" in the message. That's what is being set.
But what you do instead is disable CPUID faulting. In fact I wonder
whether expressing that as a capability actually makes sense. To me a
capability is something a domain may make use of, but doesn't have to.
That's not the case here: CPUID faulting is either active for a domain,
or it is not.

Jan
diff mbox series

Patch

diff --git a/xen/arch/x86/cpu-policy.c b/xen/arch/x86/cpu-policy.c
index 1f954d4e59..42c3193938 100644
--- a/xen/arch/x86/cpu-policy.c
+++ b/xen/arch/x86/cpu-policy.c
@@ -912,7 +912,7 @@  void __init init_dom0_cpuid_policy(struct domain *d)
      * If the domain is getting unfiltered CPUID, don't let the guest kernel
      * play with CPUID faulting either, as Xen's CPUID path won't cope.
      */
-    if ( !opt_dom0_cpuid_faulting && is_control_domain(d) && is_pv_domain(d) )
+    if ( domain_has_cap(d, CAP_DISABLE_CPU_FAULT) )
         p->platform_info.cpuid_faulting = false;
 
     recalculate_cpuid_policy(d);
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index cfcdaace12..937581e353 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -164,48 +164,46 @@  static void set_cpuid_faulting(bool enable)
 
 void ctxt_switch_levelling(const struct vcpu *next)
 {
-	const struct domain *nextd = next ? next->domain : NULL;
-	bool enable_cpuid_faulting;
-
-	if (cpu_has_cpuid_faulting ||
-	    boot_cpu_has(X86_FEATURE_CPUID_USER_DIS)) {
-		/*
-		 * No need to alter the faulting setting if we are switching
-		 * to idle; it won't affect any code running in idle context.
-		 */
-		if (nextd && is_idle_domain(nextd))
-			return;
-		/*
-		 * We *should* be enabling faulting for PV control domains.
-		 *
-		 * The domain builder has now been updated to not depend on
-		 * seeing host CPUID values.  This makes it compatible with
-		 * PVH toolstack domains, and lets us enable faulting by
-		 * default for all PV domains.
-		 *
-		 * However, as PV control domains have never had faulting
-		 * enforced on them before, there might plausibly be other
-		 * dependenices on host CPUID data.  Therefore, we have left
-		 * an interim escape hatch in the form of
-		 * `dom0=no-cpuid-faulting` to restore the older behaviour.
-		 */
-		enable_cpuid_faulting = nextd && (opt_dom0_cpuid_faulting ||
-		                                  !is_control_domain(nextd) ||
-		                                  !is_pv_domain(nextd)) &&
-		                        (is_pv_domain(nextd) ||
-		                         next->arch.msrs->
-		                         misc_features_enables.cpuid_faulting);
-
-		if (cpu_has_cpuid_faulting)
-			set_cpuid_faulting(enable_cpuid_faulting);
-		else
-			amd_set_cpuid_user_dis(enable_cpuid_faulting);
-
-		return;
-	}
-
-	if (ctxt_switch_masking)
-		alternative_vcall(ctxt_switch_masking, next);
+    const struct domain *nextd = next ? next->domain : NULL;
+    bool enable_cpuid_faulting;
+
+    if ( cpu_has_cpuid_faulting ||
+         boot_cpu_has(X86_FEATURE_CPUID_USER_DIS) ) {
+        /*
+        * No need to alter the faulting setting if we are switching
+        * to idle; it won't affect any code running in idle context.
+        */
+        if (nextd && is_idle_domain(nextd))
+            return;
+        /*
+        * We *should* be enabling faulting for PV control domains.
+        *
+        * The domain builder has now been updated to not depend on
+        * seeing host CPUID values.  This makes it compatible with
+        * PVH toolstack domains, and lets us enable faulting by
+        * default for all PV domains.
+        *
+        * However, as PV control domains have never had faulting
+        * enforced on them before, there might plausibly be other
+        * dependenices on host CPUID data.  Therefore, we have left
+        * an interim escape hatch in the form of
+        * `dom0=no-cpuid-faulting` to restore the older behaviour.
+        */
+        enable_cpuid_faulting = nextd &&
+            domain_has_cap(nextd, CAP_DISABLE_CPU_FAULT) &&
+            (is_pv_domain(nextd) ||
+            next->arch.msrs->misc_features_enables.cpuid_faulting);
+
+        if (cpu_has_cpuid_faulting)
+            set_cpuid_faulting(enable_cpuid_faulting);
+        else
+            amd_set_cpuid_user_dis(enable_cpuid_faulting);
+
+        return;
+    }
+
+    if (ctxt_switch_masking)
+        alternative_vcall(ctxt_switch_masking, next);
 }
 
 bool_t opt_cpu_info;
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 4e20edc3bf..d65144da01 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -907,6 +907,10 @@  static struct domain *__init create_dom0(const module_t *image,
 
     d->role |= ROLE_UNBOUNDED_DOMAIN;
 
+    if ( !opt_dom0_cpuid_faulting &&
+         !domain_set_cap(d, CAP_DISABLE_CPU_FAULT) )
+        printk(XENLOG_WARNING "failed to set CPU faulting on Dom %pd\n", d);
+
     init_dom0_cpuid_policy(d);
 
     if ( alloc_dom0_vcpu0(d) == NULL )
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index b04fbe0565..ebfe65cd73 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -472,7 +472,8 @@  struct domain
 #define ROLE_HARDWARE_DOMAIN   (1U<<2)
 #define ROLE_XENSTORE_DOMAIN   (1U<<3)
     uint8_t          role;
-#define CAP_CONSOLE_IO  (1U<<0)
+#define CAP_CONSOLE_IO         (1U<<0)
+#define CAP_DISABLE_CPU_FAULT  (1U<<1)
     uint8_t          capabilities;
     /* Is this guest being debugged by dom0? */
     bool             debugger_attached;
@@ -1160,6 +1161,11 @@  static always_inline bool domain_set_cap(
     case CAP_CONSOLE_IO:
         d->capabilities |= cap;
         break;
+    case CAP_DISABLE_CPU_FAULT:
+        /* Disabling cpu faulting is only allowed for a PV control domain. */
+        if ( is_pv_domain(d) && is_control_domain(d) )
+            d->capabilities |= cap;
+        break;
     default:
         return false;
     }