[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] x86/domctl: Move all CPUID update logic into update_domain_cpuid_info()



commit 07097cc0c6bdb08873ae627ca0f36e593be1d7c0
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Wed Jan 4 12:43:57 2017 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Fri Jan 13 13:16:57 2017 +0000

    x86/domctl: Move all CPUID update logic into update_domain_cpuid_info()
    
    This simplifies the XEN_DOMCTL_set_cpuid handling, splitting the safety 
logic
    away from the internals of how an update is completed.
    
    The legacy cpuids[] logic is left in alone in a fuction, as it wont survive
    very long.  update_domain_cpuid_info() gains a small performance 
optimisation
    to skip all update activites for leaves which won't have any impact on the
    guest.  This is temporary until the new hypercall API is completed.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/domctl.c | 140 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 86 insertions(+), 54 deletions(-)

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index b01a1f9..a5a56ee 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -48,30 +48,98 @@ static int gdbsx_guest_mem_io(domid_t domid, struct 
xen_domctl_gdbsx_memio *iop)
     return iop->remain ? -EFAULT : 0;
 }
 
-static void update_domain_cpuid_info(struct domain *d,
+static int update_legacy_cpuid_array(struct domain *d,
                                      const xen_domctl_cpuid_t *ctl)
 {
+    cpuid_input_t *cpuid, *unused = NULL;
+    unsigned int i;
+
+    /* Try to insert ctl into d->arch.cpuids[] */
+    for ( i = 0; i < MAX_CPUID_INPUT; i++ )
+    {
+        cpuid = &d->arch.cpuids[i];
+
+        if ( cpuid->input[0] == XEN_CPUID_INPUT_UNUSED )
+        {
+            if ( !unused )
+                unused = cpuid;
+            continue;
+        }
+
+        if ( (cpuid->input[0] == ctl->input[0]) &&
+             ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) ||
+              (cpuid->input[1] == ctl->input[1])) )
+            break;
+    }
+
+    if ( !(ctl->eax | ctl->ebx | ctl->ecx | ctl->edx) )
+    {
+        if ( i < MAX_CPUID_INPUT )
+            cpuid->input[0] = XEN_CPUID_INPUT_UNUSED;
+    }
+    else if ( i < MAX_CPUID_INPUT )
+        *cpuid = *ctl;
+    else if ( unused )
+        *unused = *ctl;
+    else
+        return -ENOENT;
+
+    return 0;
+}
+
+static int update_domain_cpuid_info(struct domain *d,
+                                    const xen_domctl_cpuid_t *ctl)
+{
     struct cpuid_policy *p = d->arch.cpuid;
     const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
+    int rc;
+
+    /*
+     * Skip update for leaves we don't care about.  This avoids the overhead
+     * of recalculate_cpuid_policy() and making d->arch.cpuids[] needlessly
+     * longer to search.
+     */
+    switch ( ctl->input[0] )
+    {
+    case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1:
+        if ( ctl->input[0] == 7 &&
+             ctl->input[1] >= ARRAY_SIZE(p->feat.raw) )
+            return 0;
+        if ( ctl->input[0] == XSTATE_CPUID &&
+             ctl->input[1] >= ARRAY_SIZE(p->xstate.raw) )
+            return 0;
+        break;
+
+    case 0x40000000: case 0x40000100:
+        /* Only care about the max_leaf limit. */
+
+    case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
+        break;
+
+    default:
+        return 0;
+    }
+
+    rc = update_legacy_cpuid_array(d, ctl);
+    if ( rc )
+        return rc;
 
     /* Insert ctl data into cpuid_policy. */
-    if ( ctl->input[0] < ARRAY_SIZE(p->basic.raw) )
+    switch ( ctl->input[0] )
     {
+    case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1:
         if ( ctl->input[0] == 7 )
-        {
-            if ( ctl->input[1] < ARRAY_SIZE(p->feat.raw) )
-                p->feat.raw[ctl->input[1]] = leaf;
-        }
+            p->feat.raw[ctl->input[1]] = leaf;
         else if ( ctl->input[0] == XSTATE_CPUID )
-        {
-            if ( ctl->input[1] < ARRAY_SIZE(p->xstate.raw) )
-                p->xstate.raw[ctl->input[1]] = leaf;
-        }
+            p->xstate.raw[ctl->input[1]] = leaf;
         else
             p->basic.raw[ctl->input[0]] = leaf;
-    }
-    else if ( (ctl->input[0] - 0x80000000) < ARRAY_SIZE(p->extd.raw) )
+        break;
+
+    case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
         p->extd.raw[ctl->input[0] - 0x80000000] = leaf;
+        break;
+    }
 
     recalculate_cpuid_policy(d);
 
@@ -243,6 +311,8 @@ static void update_domain_cpuid_info(struct domain *d,
         }
         break;
     }
+
+    return 0;
 }
 
 void arch_get_domain_info(const struct domain *d,
@@ -869,53 +939,15 @@ long arch_do_domctl(
     }
 
     case XEN_DOMCTL_set_cpuid:
-    {
-        const xen_domctl_cpuid_t *ctl = &domctl->u.cpuid;
-        cpuid_input_t *cpuid, *unused = NULL;
-
         if ( d == currd ) /* no domain_pause() */
-        {
             ret = -EINVAL;
-            break;
-        }
-
-        for ( i = 0; i < MAX_CPUID_INPUT; i++ )
-        {
-            cpuid = &d->arch.cpuids[i];
-
-            if ( cpuid->input[0] == XEN_CPUID_INPUT_UNUSED )
-            {
-                if ( !unused )
-                    unused = cpuid;
-                continue;
-            }
-
-            if ( (cpuid->input[0] == ctl->input[0]) &&
-                 ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) ||
-                  (cpuid->input[1] == ctl->input[1])) )
-                break;
-        }
-
-        domain_pause(d);
-
-        if ( !(ctl->eax | ctl->ebx | ctl->ecx | ctl->edx) )
+        else
         {
-            if ( i < MAX_CPUID_INPUT )
-                cpuid->input[0] = XEN_CPUID_INPUT_UNUSED;
+            domain_pause(d);
+            ret = update_domain_cpuid_info(d, &domctl->u.cpuid);
+            domain_unpause(d);
         }
-        else if ( i < MAX_CPUID_INPUT )
-            *cpuid = *ctl;
-        else if ( unused )
-            *unused = *ctl;
-        else
-            ret = -ENOENT;
-
-        if ( !ret )
-            update_domain_cpuid_info(d, ctl);
-
-        domain_unpause(d);
         break;
-    }
 
     case XEN_DOMCTL_gettscinfo:
         if ( d == currd ) /* no domain_pause() */
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.