|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 1/4] xen/libxc: Allow changes to hypervisor CPUID leaf from config file
On 11/03/14 03:54, Boris Ostrovsky wrote:
> Currently only "real" cpuid leaves can be overwritten by users via
> 'cpuid' option in the configuration file. This patch provides ability to
> do the same for hypervisor leaves (those in the 0x40000000 range).
>
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
How? There is nothing stopping leaves in 0x40000000 being set in the
policy with XEN_DOMCTL_set_cpuid, but I dont see anything which plumbs
this together at the Xen level.
> ---
> tools/libxc/xc_cpuid_x86.c | 23 ++++++++++++++++++++++-
> tools/libxc/xc_misc.c | 18 ++++++++++++++++++
> tools/libxc/xenctrl.h | 2 ++
> xen/arch/x86/domain.c | 19 ++++++++++++++++---
> xen/arch/x86/sysctl.c | 17 +++++++++++++++++
> xen/arch/x86/traps.c | 3 +++
> xen/include/asm-x86/domain.h | 7 +++++++
> xen/include/public/sysctl.h | 18 ++++++++++++++++++
> 8 files changed, 103 insertions(+), 4 deletions(-)
>
> diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
> index bbbf9b8..544a0fd 100644
> --- a/tools/libxc/xc_cpuid_x86.c
> +++ b/tools/libxc/xc_cpuid_x86.c
> @@ -33,6 +33,8 @@
> #define DEF_MAX_INTELEXT 0x80000008u
> #define DEF_MAX_AMDEXT 0x8000001cu
>
> +#define HYPERVISOR_LEAF(idx) (((idx) & 0x40000000) == 0x40000000)
> +
This check is wrong.
> static int hypervisor_is_64bit(xc_interface *xch)
> {
> xen_capabilities_info_t xen_caps = "";
> @@ -555,6 +557,9 @@ static int xc_cpuid_policy(
> {
> xc_dominfo_t info;
>
> + if ( HYPERVISOR_LEAF(input[0]) )
> + return 0;
> +
> if ( xc_domain_getinfo(xch, domid, 1, &info) == 0 )
> return -EINVAL;
>
> @@ -754,7 +759,23 @@ int xc_cpuid_set(
>
> memset(config_transformed, 0, 4 * sizeof(*config_transformed));
>
> - cpuid(input, regs);
> + if ( HYPERVISOR_LEAF(input[0]) )
> + {
> + xc_cpuid_t cpuid;
> +
> + cpuid.input[0] = input[0];
> + cpuid.input[1] = input[1];
> +
> + if (xc_cpuid(xch, &cpuid))
> + regs[0] = regs[1] = regs[2] = regs[3] = 0;
> + else {
> + regs[0] = cpuid.eax;
> + regs[1] = cpuid.ebx;
> + regs[2] = cpuid.ecx;
> + regs[3] = cpuid.edx;
> + }
> + } else
> + cpuid(input, regs);
>
> memcpy(polregs, regs, sizeof(regs));
> xc_cpuid_policy(xch, domid, input, polregs);
> diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
> index 3303454..4e8669b 100644
> --- a/tools/libxc/xc_misc.c
> +++ b/tools/libxc/xc_misc.c
> @@ -159,6 +159,24 @@ int xc_send_debug_keys(xc_interface *xch, char *keys)
> return ret;
> }
>
> +int xc_cpuid(xc_interface *xch,
> + xc_cpuid_t *cpuid)
> +{
> + int ret;
> + DECLARE_SYSCTL;
> +
> + sysctl.cmd = XEN_SYSCTL_cpuid_op;
> +
> + memcpy(&sysctl.u.cpuid, cpuid, sizeof(*cpuid));
> +
> + if ( (ret = do_sysctl(xch, &sysctl)) != 0 )
> + return ret;
> +
> + memcpy(cpuid, &sysctl.u.cpuid, sizeof(*cpuid));
> +
> + return 0;
> +}
> +
> int xc_physinfo(xc_interface *xch,
> xc_physinfo_t *put_info)
> {
> diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
> index 13f816b..6c709f5 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -1135,6 +1135,7 @@ int xc_send_debug_keys(xc_interface *xch, char *keys);
> typedef xen_sysctl_physinfo_t xc_physinfo_t;
> typedef xen_sysctl_topologyinfo_t xc_topologyinfo_t;
> typedef xen_sysctl_numainfo_t xc_numainfo_t;
> +typedef xen_sysctl_cpuid_t xc_cpuid_t;
>
> typedef uint32_t xc_cpu_to_node_t;
> typedef uint32_t xc_cpu_to_socket_t;
> @@ -1146,6 +1147,7 @@ typedef uint32_t xc_node_to_node_dist_t;
> int xc_physinfo(xc_interface *xch, xc_physinfo_t *info);
> int xc_topologyinfo(xc_interface *xch, xc_topologyinfo_t *info);
> int xc_numainfo(xc_interface *xch, xc_numainfo_t *info);
> +int xc_cpuid(xc_interface *xch, xc_cpuid_t *cpuid);
>
> int xc_sched_id(xc_interface *xch,
> int *sched_id);
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index c42a079..98e2b5f 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -1997,7 +1997,7 @@ void arch_dump_vcpu_info(struct vcpu *v)
> vpmu_dump(v);
> }
>
> -void domain_cpuid(
> +bool_t domain_cpuid_exists(
> struct domain *d,
> unsigned int input,
> unsigned int sub_input,
> @@ -2030,11 +2030,24 @@ void domain_cpuid(
> !d->disable_migrate && !d->arch.vtsc )
> *edx &= ~(1u<<8); /* TSC Invariant */
>
> - return;
> + return 1;
> }
> }
>
> - *eax = *ebx = *ecx = *edx = 0;
> + return 0;
> +}
> +
> +void domain_cpuid(
> + struct domain *d,
> + unsigned int input,
> + unsigned int sub_input,
> + unsigned int *eax,
> + unsigned int *ebx,
> + unsigned int *ecx,
> + unsigned int *edx)
> +{
> + if ( !domain_cpuid_exists(d, input, sub_input, eax, ebx, ecx, edx) )
> + *eax = *ebx = *ecx = *edx = 0;
> }
>
> void vcpu_kick(struct vcpu *v)
> diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
> index 15d4b91..08f8038 100644
> --- a/xen/arch/x86/sysctl.c
> +++ b/xen/arch/x86/sysctl.c
> @@ -101,6 +101,23 @@ long arch_do_sysctl(
> }
> break;
>
> + case XEN_SYSCTL_cpuid_op:
This would appear to be a cpuid instruction in the context of a domain,
which should be a domctl, not a sysctl. I have a different
implementation of sysctl cpuid posted, which takes a pcpu parameter.
> + {
> + struct xen_sysctl_cpuid *cpuid = &sysctl->u.cpuid;
> +
> + if ( !cpuid_hypervisor_leaves(cpuid->input[0], cpuid->input[1],
> + &cpuid->eax,&cpuid->ebx,
> + &cpuid->ecx, &cpuid->edx) )
> + asm ( "cpuid"
> + :"=a" (cpuid->eax), "=b" (cpuid->ebx),
> + "=c" (cpuid->ecx), "=d" (cpuid->edx)
> + : "0" (cpuid->input[0]), "1" (cpuid->input[1]) );
This will likely bypass masking/levelling for a domain. As suggested,
the hypervisor leaves should be plumbed properly through to be usable
from domain_cpuid().
~Andrew
> +
> + if ( __copy_to_guest(u_sysctl, sysctl, 1) )
> + ret = -EFAULT;
> + }
> + break;
> +
> default:
> ret = -ENOSYS;
> break;
> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
> index c462317..e1f39d9 100644
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -690,6 +690,9 @@ int cpuid_hypervisor_leaves( uint32_t idx, uint32_t
> sub_idx,
> if ( idx > limit )
> return 0;
>
> + if ( domain_cpuid_exists(d, base + idx, sub_idx, eax, ebx, ecx, edx) )
> + return 1;
> +
> switch ( idx )
> {
> case 0:
> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
> index 49f7c0c..5fd47de 100644
> --- a/xen/include/asm-x86/domain.h
> +++ b/xen/include/asm-x86/domain.h
> @@ -471,6 +471,13 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *,
> unsigned long guest_cr4);
> ((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD | \
> X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE))
>
> +bool_t domain_cpuid_exists(struct domain *d,
> + unsigned int input,
> + unsigned int sub_input,
> + unsigned int *eax,
> + unsigned int *ebx,
> + unsigned int *ecx,
> + unsigned int *edx);
> void domain_cpuid(struct domain *d,
> unsigned int input,
> unsigned int sub_input,
> diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
> index 8437d31..7c1c662 100644
> --- a/xen/include/public/sysctl.h
> +++ b/xen/include/public/sysctl.h
> @@ -632,6 +632,20 @@ struct xen_sysctl_coverage_op {
> typedef struct xen_sysctl_coverage_op xen_sysctl_coverage_op_t;
> DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t);
>
> +#if defined(__i386__) || defined(__x86_64__)
> +/* XEN_SYSCTL_cpuid_op */
> +/* Get CPUID of a particular leaf */
> +
> +struct xen_sysctl_cpuid {
> + uint32_t input[2];
> + uint32_t eax;
> + uint32_t ebx;
> + uint32_t ecx;
> + uint32_t edx;
> +};
> +typedef struct xen_sysctl_cpuid xen_sysctl_cpuid_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuid_t);
> +#endif
>
> struct xen_sysctl {
> uint32_t cmd;
> @@ -654,6 +668,7 @@ struct xen_sysctl {
> #define XEN_SYSCTL_cpupool_op 18
> #define XEN_SYSCTL_scheduler_op 19
> #define XEN_SYSCTL_coverage_op 20
> +#define XEN_SYSCTL_cpuid_op 21
> uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
> union {
> struct xen_sysctl_readconsole readconsole;
> @@ -675,6 +690,9 @@ struct xen_sysctl {
> struct xen_sysctl_cpupool_op cpupool_op;
> struct xen_sysctl_scheduler_op scheduler_op;
> struct xen_sysctl_coverage_op coverage_op;
> +#if defined(__i386__) || defined(__x86_64__)
> + struct xen_sysctl_cpuid cpuid;
> +#endif
> uint8_t pad[128];
> } u;
> };
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |