|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v4 5/8] plat: Add global struct to keep x86 CPU information
Hi,
looks good to me.
Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
BR, Yuri.
Florian Schmidt <florian.schmidt@xxxxxxxxx> writes:
> Currently, all information relates to the additional registers that can
> be available on x86 CPUs, and how to save and restore them.
>
> For Arm, there is only a dummy function so far that can be filled later
> when we support extended registers on Arm.
>
> Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx>
> ---
> plat/common/include/arm/arm64/cpu.h | 4 +++
> plat/common/include/x86/cpu.h | 56 ++++++++++++++++++++++++++---
> plat/common/x86/cpu_features.c | 37 +++++++++++++++++++
> plat/kvm/Makefile.uk | 1 +
> plat/kvm/x86/setup.c | 2 ++
> plat/linuxu/Makefile.uk | 1 +
> plat/linuxu/setup.c | 5 +++
> plat/xen/Makefile.uk | 1 +
> plat/xen/x86/setup.c | 2 ++
> 9 files changed, 104 insertions(+), 5 deletions(-)
> create mode 100644 plat/common/x86/cpu_features.c
>
> diff --git a/plat/common/include/arm/arm64/cpu.h
> b/plat/common/include/arm/arm64/cpu.h
> index bfea4617..503bc68b 100644
> --- a/plat/common/include/arm/arm64/cpu.h
> +++ b/plat/common/include/arm/arm64/cpu.h
> @@ -74,6 +74,10 @@ static inline void ioreg_write64(volatile uint64_t *addr,
> uint64_t value)
> *addr = value;
> }
>
> +static inline void _init_cpufeatures(void)
> +{
> +}
> +
> /* Define compatibility IO macros */
> #define outb(addr, v) UK_BUG()
> #define outw(addr, v) UK_BUG()
> diff --git a/plat/common/include/x86/cpu.h b/plat/common/include/x86/cpu.h
> index 001e9cac..6de62dc0 100644
> --- a/plat/common/include/x86/cpu.h
> +++ b/plat/common/include/x86/cpu.h
> @@ -31,16 +31,62 @@
> #define __PLAT_COMMON_X86_CPU_H__
>
> #include <uk/arch/types.h>
> +#include <x86/cpu_defs.h>
> +#include <stdint.h>
>
> void halt(void);
> void system_off(void);
>
> -static inline void cpuid(__u32 leaf, __u32 *eax, __u32 *ebx,
> - __u32 *ecx, __u32 *edx)
> +enum save_cmd {
> + X86_SAVE_NONE,
> + X86_SAVE_FSAVE,
> + X86_SAVE_FXSAVE,
> + X86_SAVE_XSAVE,
> + X86_SAVE_XSAVEOPT
> +};
> +
> +struct _x86_features {
> + unsigned long extregs_size; /* Size of the extregs area */
> + unsigned long extregs_align; /* Alignment of the extregs area */
> + enum save_cmd save; /* which CPU instruction to use for
> + * saving/restoring extregs.
> + */
> +};
> +
> +extern struct _x86_features x86_cpu_features;
> +
> +static inline void _init_cpufeatures(void)
> {
> - asm volatile("cpuid"
> - : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
> - : "0"(leaf));
> + __u32 eax, ebx, ecx, edx;
> +
> + /* Why are we saving the eax register content to the eax variable with
> + * "=a(eax)", but then never use it?
> + * Because gcc otherwise will assume that the eax register still
> + * contains "1" after this asm expression. See the "Warning" note at
> + * https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands
> + */
> + asm volatile("cpuid" : "=a"(eax), "=c"(ecx), "=d"(edx) : "a"(1)
> + : "ebx");
> + if (ecx & X86_CPUID1_ECX_OSXSAVE) {
> + asm volatile("cpuid" : "=a"(eax), "=c"(ecx) : "a"(0xd), "c"(1)
> + : "ebx", "edx");
> + if (eax & X86_CPUIDD1_EAX_XSAVEOPT)
> + x86_cpu_features.save = X86_SAVE_XSAVEOPT;
> + else
> + x86_cpu_features.save = X86_SAVE_XSAVE;
> + asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx)
> + : "a"(0xd), "c"(0) : "edx");
> + x86_cpu_features.extregs_size = ebx;
> + x86_cpu_features.extregs_align = 64;
> + } else if (edx & X86_CPUID1_EDX_FXSR) {
> + x86_cpu_features.save = X86_SAVE_FXSAVE;
> + x86_cpu_features.extregs_size = 512;
> + x86_cpu_features.extregs_align = 16;
> + } else {
> + x86_cpu_features.save = X86_SAVE_FSAVE;
> + x86_cpu_features.extregs_size = 108;
> + x86_cpu_features.extregs_align = 1;
> + }
> }
>
> unsigned long read_cr2(void);
> diff --git a/plat/common/x86/cpu_features.c b/plat/common/x86/cpu_features.c
> new file mode 100644
> index 00000000..07097397
> --- /dev/null
> +++ b/plat/common/x86/cpu_features.c
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: BSD-3-Clause */
> +/*
> + * Authors: Florian Schmidt <florian.schmidt@xxxxxxxxx>
> + *
> + * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the copyright holder nor the names of its
> + * contributors may be used to endorse or promote products derived from
> + * this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + *
> + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
> + */
> +
> +#include <x86/cpu.h>
> +
> +struct _x86_features x86_cpu_features;
> diff --git a/plat/kvm/Makefile.uk b/plat/kvm/Makefile.uk
> index 72dd8a30..5fb56ee9 100644
> --- a/plat/kvm/Makefile.uk
> +++ b/plat/kvm/Makefile.uk
> @@ -27,6 +27,7 @@ LIBKVMPLAT_CXXFLAGS += -DKVMPLAT
> ##
> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/trace.c|common
> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/traps.c|common
> +LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/cpu_features.c|common
> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/cpu_native.c|common
> ifeq ($(CONFIG_HAVE_SCHED),y)
> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/thread_start.S|common
> diff --git a/plat/kvm/x86/setup.c b/plat/kvm/x86/setup.c
> index 47a78dcf..c17a7dd5 100644
> --- a/plat/kvm/x86/setup.c
> +++ b/plat/kvm/x86/setup.c
> @@ -27,6 +27,7 @@
> */
>
> #include <string.h>
> +#include <x86/cpu.h>
> #include <x86/traps.h>
> #include <kvm/console.h>
> #include <kvm/intctrl.h>
> @@ -118,6 +119,7 @@ void _libkvmplat_entry(void *arg)
> {
> struct multiboot_info *mi = (struct multiboot_info *)arg;
>
> + _init_cpufeatures();
> _libkvmplat_init_console();
> traps_init();
> intctrl_init();
> diff --git a/plat/linuxu/Makefile.uk b/plat/linuxu/Makefile.uk
> index e70b4b7a..2c0de76c 100644
> --- a/plat/linuxu/Makefile.uk
> +++ b/plat/linuxu/Makefile.uk
> @@ -20,6 +20,7 @@ LIBLINUXUPLAT_ASFLAGS += -DLINUXUPLAT
> LIBLINUXUPLAT_CFLAGS += -DLINUXUPLAT
> LIBLINUXUPLAT_CXXFLAGS += -DLINUXUPLAT
>
> +LIBLINUXUPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/cpu_features.c|common
> LIBLINUXUPLAT_SRCS-$(CONFIG_ARCH_X86_32) +=
> $(LIBLINUXUPLAT_BASE)/x86/entry32.S
> LIBLINUXUPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(LIBLINUXUPLAT_BASE)/x86/entry64.S
> LIBLINUXUPLAT_SRCS-$(CONFIG_ARCH_ARM_32) +=
> $(LIBLINUXUPLAT_BASE)/arm/entry32.S
> diff --git a/plat/linuxu/setup.c b/plat/linuxu/setup.c
> index 5fbf54b1..7849f682 100644
> --- a/plat/linuxu/setup.c
> +++ b/plat/linuxu/setup.c
> @@ -45,6 +45,9 @@
> #include <uk/plat/bootstrap.h>
> #include <uk/assert.h>
> #include <uk/errptr.h>
> +#if defined __X86_64__
> +#include <x86/cpu.h>
> +#endif
>
> struct liblinuxuplat_opts _liblinuxuplat_opts = { 0 };
>
> @@ -150,6 +153,8 @@ void _liblinuxuplat_entry(int argc, char *argv[])
> int ret;
> void *pret;
>
> + _init_cpufeatures();
> +
> /*
> * Initialize platform console
> */
> diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk
> index 20d1e5af..38b510ad 100644
> --- a/plat/xen/Makefile.uk
> +++ b/plat/xen/Makefile.uk
> @@ -33,6 +33,7 @@ LIBXENPLAT_SRCS-y +=
> $(UK_PLAT_COMMON_BASE)/memory.c|common
>
> LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/trace.c|common
> LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/traps.c|common
> +LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/cpu_features.c|common
> ifeq ($(CONFIG_HAVE_SCHED),y)
> LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/x86/thread_start.S|common
> LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
> $(UK_PLAT_COMMON_BASE)/thread.c|common
> diff --git a/plat/xen/x86/setup.c b/plat/xen/x86/setup.c
> index a41d5cb3..60a9f9e6 100644
> --- a/plat/xen/x86/setup.c
> +++ b/plat/xen/x86/setup.c
> @@ -74,6 +74,7 @@
> #include <uk/plat/config.h>
> #include <uk/plat/console.h>
> #include <uk/plat/bootstrap.h>
> +#include <x86/cpu.h>
>
> #include <xen/xen.h>
> #include <common/console.h>
> @@ -170,6 +171,7 @@ void _libxenplat_x86entry(void *start_info) __noreturn;
> void _libxenplat_x86entry(void *start_info)
> {
> _init_traps();
> + _init_cpufeatures();
> HYPERVISOR_start_info = (start_info_t *)start_info;
> _libxenplat_prepare_console(); /* enables buffering for console */
>
> --
> 2.20.1
>
--
Yuri Volchkov
Software Specialist
NEC Europe Ltd
Kurfürsten-Anlage 36
D-69115 Heidelberg
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |