[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 1/8] x86/domctl: introduce a pair of hypercall to set and get cpu topology
On Mon, Jan 08, 2018 at 01:14:44PM -0500, Daniel De Graaf wrote: >On 01/07/2018 11:01 PM, Chao Gao wrote: >> Define interface, structures and hypercalls for toolstack to build >> cpu topology and for guest that will retrieve it [1]. >> Two subop hypercalls introduced by this patch: >> XEN_DOMCTL_set_cpu_topology to define cpu topology information per domain >> and XENMEM_get_cpu_topology to retrieve cpu topology information. >> >> [1]: during guest creation, those information helps hvmloader to build ACPI. >> >> Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx> > >When adding new XSM controls for use by device models, you also >need to add the permissions to the device_model macro defined in >tools/flask/policy/modules/xen.if. If domains need to call this >function on themselves (is this only true for get?), you will also >need to add it to declare_domain_common. > Hi, Daniel. Yes. XENMEM_get_cpu_topology will be called by the domain itself. And Both get and set will be called by dom0 when creating one domain. So I need: 1. add *set* and *get* to create_domain_common. 2. add *set* to declare_domain_common. Is it right? Thanks Chao >> --- >> xen/arch/x86/domctl.c | 27 ++++++++++++++++++++++ >> xen/arch/x86/hvm/hvm.c | 7 ++++++ >> xen/arch/x86/mm.c | 45 >> +++++++++++++++++++++++++++++++++++++ >> xen/include/asm-x86/hvm/domain.h | 15 +++++++++++++ >> xen/include/public/domctl.h | 22 ++++++++++++++++++ >> xen/include/public/memory.h | 27 +++++++++++++++++++++- >> xen/include/xsm/dummy.h | 6 +++++ >> xen/xsm/dummy.c | 1 + >> xen/xsm/flask/hooks.c | 10 +++++++++ >> xen/xsm/flask/policy/access_vectors | 4 ++++ >> 10 files changed, 163 insertions(+), 1 deletion(-) >> >> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c >> index 36ab235..4e1bbd5 100644 >> --- a/xen/arch/x86/domctl.c >> +++ b/xen/arch/x86/domctl.c >> @@ -347,6 +347,29 @@ void arch_get_domain_info(const struct domain *d, >> info->flags |= XEN_DOMINF_hap; >> } >> +static int arch_set_cpu_topology(struct domain *d, >> + struct xen_domctl_cpu_topology *topology) >> +{ >> + if ( !is_hvm_domain(d) || >> + !topology->size || topology->size > HVM_MAX_VCPUS ) >> + return -EINVAL; >> + >> + if ( !d->arch.hvm_domain.apic_id ) >> + d->arch.hvm_domain.apic_id = xmalloc_array(uint32_t, >> topology->size); >> + >> + if ( !d->arch.hvm_domain.apic_id ) >> + return -ENOMEM; >> + >> + if ( copy_from_guest(d->arch.hvm_domain.apic_id, topology->tid, >> + topology->size) ) >> + return -EFAULT; >> + >> + d->arch.hvm_domain.apic_id_size = topology->size; >> + d->arch.hvm_domain.core_per_socket = topology->core_per_socket; >> + d->arch.hvm_domain.thread_per_core = topology->thread_per_core; >> + return 0; >> +} >> + >> #define MAX_IOPORTS 0x10000 >> long arch_do_domctl( >> @@ -1555,6 +1578,10 @@ long arch_do_domctl( >> recalculate_cpuid_policy(d); >> break; >> + case XEN_DOMCTL_set_cpu_topology: >> + ret = arch_set_cpu_topology(d, &domctl->u.cpu_topology); >> + break; >> + >> default: >> ret = iommu_do_domctl(domctl, d, u_domctl); >> break; >> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c >> index 71fddfd..b3b3224 100644 >> --- a/xen/arch/x86/hvm/hvm.c >> +++ b/xen/arch/x86/hvm/hvm.c >> @@ -1509,6 +1509,13 @@ int hvm_vcpu_initialise(struct vcpu *v) >> int rc; >> struct domain *d = v->domain; >> + if ( v->vcpu_id > d->arch.hvm_domain.apic_id_size ) >> + { >> + printk(XENLOG_ERR "d%dv%d's apic id isn't set.\n", >> + d->domain_id, v->vcpu_id); >> + return -ENOENT; >> + } >> + >> hvm_asid_flush_vcpu(v); >> spin_lock_init(&v->arch.hvm_vcpu.tm_lock); >> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c >> index a56f875..b90e663 100644 >> --- a/xen/arch/x86/mm.c >> +++ b/xen/arch/x86/mm.c >> @@ -4413,6 +4413,51 @@ long arch_memory_op(unsigned long cmd, >> XEN_GUEST_HANDLE_PARAM(void) arg) >> return rc; >> } >> + case XENMEM_get_cpu_topology: >> + { >> + struct domain *d; >> + struct xen_cpu_topology_info topology; >> + >> + if ( copy_from_guest(&topology, arg, 1) ) >> + return -EFAULT; >> + >> + if ( topology.pad || topology.pad2 ) >> + return -EINVAL; >> + >> + if ( (d = rcu_lock_domain_by_any_id(topology.domid)) == NULL ) >> + return -ESRCH; >> + >> + rc = xsm_get_cpu_topology(XSM_TARGET, d); >> + if ( rc ) >> + goto get_cpu_topology_failed; >> + >> + rc = -EOPNOTSUPP; >> + if ( !is_hvm_domain(d) || !d->arch.hvm_domain.apic_id ) >> + goto get_cpu_topology_failed; >> + >> + /* allow the size to be zero for users who don't care apic_id */ >> + if ( topology.size ) >> + { >> + rc = -E2BIG; >> + if ( topology.size != d->arch.hvm_domain.apic_id_size ) >> + goto get_cpu_topology_failed; >> + >> + rc = -EFAULT; >> + if ( copy_to_guest(topology.tid.h, d->arch.hvm_domain.apic_id, >> + topology.size) ) >> + goto get_cpu_topology_failed; >> + } >> + >> + topology.core_per_socket = d->arch.hvm_domain.core_per_socket; >> + topology.thread_per_core = d->arch.hvm_domain.thread_per_core; >> + >> + rc = __copy_to_guest(arg, &topology, 1) ? -EFAULT : 0; >> + >> + get_cpu_topology_failed: >> + rcu_unlock_domain(d); >> + return rc; >> + } >> + >> default: >> return subarch_memory_op(cmd, arg); >> } >> diff --git a/xen/include/asm-x86/hvm/domain.h >> b/xen/include/asm-x86/hvm/domain.h >> index 7f128c0..501ed99 100644 >> --- a/xen/include/asm-x86/hvm/domain.h >> +++ b/xen/include/asm-x86/hvm/domain.h >> @@ -196,6 +196,21 @@ struct hvm_domain { >> struct vmx_domain vmx; >> struct svm_domain svm; >> }; >> + >> + /* >> + * an array of apic_id, which is unique and can be used to extract >> + * socket ID, core ID and thread ID >> + */ >> + uint32_t *apic_id; >> + uint32_t apic_id_size; >> + >> + /* >> + * reports the number of core/thread in a socket/core, determining the >> + * right-shift value to extract {core/thread} ID from apic_id (defined >> + * above). >> + */ >> + uint8_t core_per_socket; >> + uint8_t thread_per_core; >> }; >> #define hap_enabled(d) ((d)->arch.hvm_domain.hap_enabled) >> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h >> index 9ae72959..99392b7 100644 >> --- a/xen/include/public/domctl.h >> +++ b/xen/include/public/domctl.h >> @@ -1109,6 +1109,26 @@ struct xen_domctl_vuart_op { >> */ >> }; >> +/* XEN_DOMCTL_set_cpu_topology */ >> +struct xen_domctl_cpu_topology { >> + /* IN - size of 'topology' array */ >> + uint32_t size; >> + /* IN - the number of core in the same socket */ >> + uint8_t core_per_socket; >> + /* IN - the number of thread in the same core */ >> + uint8_t thread_per_core; >> + /* IN - should be 0 */ >> + uint8_t pad[2]; >> + /* >> + * IN - an array of topology ID (tid), which is used to compute a given >> + * vcpu's core id and thread id. For x86, topology ID is the APIC ID, >> + * which is system-level unique. >> + */ >> + XEN_GUEST_HANDLE_64(uint32) tid; >> +}; >> +typedef struct xen_domctl_cpu_topology xen_domctl_cpu_topology; >> +DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpu_topology); >> + >> struct xen_domctl { >> uint32_t cmd; >> #define XEN_DOMCTL_createdomain 1 >> @@ -1188,6 +1208,7 @@ struct xen_domctl { >> #define XEN_DOMCTL_soft_reset 79 >> #define XEN_DOMCTL_set_gnttab_limits 80 >> #define XEN_DOMCTL_vuart_op 81 >> +#define XEN_DOMCTL_set_cpu_topology 82 >> #define XEN_DOMCTL_gdbsx_guestmemio 1000 >> #define XEN_DOMCTL_gdbsx_pausevcpu 1001 >> #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 >> @@ -1252,6 +1273,7 @@ struct xen_domctl { >> struct xen_domctl_psr_alloc psr_alloc; >> struct xen_domctl_set_gnttab_limits set_gnttab_limits; >> struct xen_domctl_vuart_op vuart_op; >> + struct xen_domctl_cpu_topology cpu_topology; >> uint8_t pad[128]; >> } u; >> }; >> diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h >> index 29386df..a6bcc64 100644 >> --- a/xen/include/public/memory.h >> +++ b/xen/include/public/memory.h >> @@ -650,7 +650,32 @@ struct xen_vnuma_topology_info { >> typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t; >> DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t); >> -/* Next available subop number is 28 */ >> +/* >> + * XENMEM_get_cpu_topology is used by guest to acquire vcpu topology from >> + * hypervisor. >> + */ >> +#define XENMEM_get_cpu_topology 28 >> + >> +struct xen_cpu_topology_info { >> + /* IN */ >> + domid_t domid; >> + uint16_t pad; >> + >> + /* IN/OUT */ >> + uint32_t size; >> + >> + /* OUT */ >> + uint8_t core_per_socket; >> + uint8_t thread_per_core; >> + uint16_t pad2; >> + >> + union { >> + XEN_GUEST_HANDLE(uint32) h; >> + uint64_t pad; >> + } tid; >> +}; >> +typedef struct xen_cpu_topology_info xen_cpu_topology_info_t; >> +DEFINE_XEN_GUEST_HANDLE(xen_cpu_topology_info_t); >> #endif /* __XEN_PUBLIC_MEMORY_H__ */ >> diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h >> index d6ddadc..3ac59c7 100644 >> --- a/xen/include/xsm/dummy.h >> +++ b/xen/include/xsm/dummy.h >> @@ -330,6 +330,12 @@ static XSM_INLINE int xsm_get_vnumainfo(XSM_DEFAULT_ARG >> struct domain *d) >> return xsm_default_action(action, current->domain, d); >> } >> +static XSM_INLINE int xsm_get_cpu_topology(XSM_DEFAULT_ARG struct domain *d) >> +{ >> + XSM_ASSERT_ACTION(XSM_TARGET); >> + return xsm_default_action(action, current->domain, d); >> +} >> + >> #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI) >> static XSM_INLINE int xsm_get_device_group(XSM_DEFAULT_ARG uint32_t >> machine_bdf) >> { >> diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c >> index 479b103..98eb86f 100644 >> --- a/xen/xsm/dummy.c >> +++ b/xen/xsm/dummy.c >> @@ -88,6 +88,7 @@ void __init xsm_fixup_ops (struct xsm_operations *ops) >> set_to_dummy_if_null(ops, iomem_mapping); >> set_to_dummy_if_null(ops, pci_config_permission); >> set_to_dummy_if_null(ops, get_vnumainfo); >> + set_to_dummy_if_null(ops, get_cpu_topology); >> #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI) >> set_to_dummy_if_null(ops, get_device_group); >> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c >> index 19ceacf..29ee1e1 100644 >> --- a/xen/xsm/flask/hooks.c >> +++ b/xen/xsm/flask/hooks.c >> @@ -427,6 +427,11 @@ static int flask_get_vnumainfo(struct domain *d) >> return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GET_VNUMAINFO); >> } >> +static int flask_get_cpu_topology(struct domain *d) >> +{ >> + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GET_CPU_TOPOLOGY); >> +} >> + >> static int flask_console_io(struct domain *d, int cmd) >> { >> u32 perm; >> @@ -752,6 +757,9 @@ static int flask_domctl(struct domain *d, int cmd) >> case XEN_DOMCTL_set_gnttab_limits: >> return current_has_perm(d, SECCLASS_DOMAIN2, >> DOMAIN2__SET_GNTTAB_LIMITS); >> + case XEN_DOMCTL_set_cpu_topology: >> + return current_has_perm(d, SECCLASS_DOMAIN2, >> DOMAIN2__SET_CPU_TOPOLOGY); >> + >> default: >> return avc_unknown_permission("domctl", cmd); >> } >> @@ -1800,6 +1808,8 @@ static struct xsm_operations flask_ops = { >> .do_xsm_op = do_flask_op, >> .get_vnumainfo = flask_get_vnumainfo, >> + .get_cpu_topology = flask_get_cpu_topology, >> + >> .vm_event_control = flask_vm_event_control, >> #ifdef CONFIG_HAS_MEM_ACCESS >> diff --git a/xen/xsm/flask/policy/access_vectors >> b/xen/xsm/flask/policy/access_vectors >> index d0a1ec5..e531ec0 100644 >> --- a/xen/xsm/flask/policy/access_vectors >> +++ b/xen/xsm/flask/policy/access_vectors >> @@ -250,6 +250,10 @@ class domain2 >> psr_alloc >> # XEN_DOMCTL_set_gnttab_limits >> set_gnttab_limits >> +# XEN_DOMCTL_set_cpu_topology >> + set_cpu_topology >> +# XENMEM_get_cpu_topology >> + get_cpu_topology >> } >> # Similar to class domain, but primarily contains domctls related to HVM >> domains >> > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |