|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |