From: Kirill Tkhai <ktk...@virtuozzo.com> Show cpu_i flags as flags of vcpu_i.
Extracted from "Initial patch". Merged several reworks. TODO: Maybe replace/rework on_each_cpu() with smp_call_function_single(). Then we won't need split c_start() in previous patch (as the call function will be called right before specific cpu is being prepared to show). This should be rather easy. [aryabinin: Don't see what it buys us, so I didn't try to implement it] Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com> https://jira.sw.ru/browse/PSBM-121823 [aryabinin:vz8 rebase] Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com> Reviewed-by: Kirill Tkhai <ktk...@virtuozzo.com> (cherry-picked from vz8 commit e6af3b34391e ("x86: Show vcpu cpuflags in cpuinfo")) Signed-off-by: Nikita Yushchenko <nikita.yushche...@virtuozzo.com> --- arch/x86/kernel/cpu/proc.c | 63 +++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 165056e939ef..a88574652276 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -4,6 +4,8 @@ #include <linux/string.h> #include <linux/seq_file.h> #include <linux/cpufreq.h> +#include <linux/sched.h> +#include <linux/ve_proto.h> #include "cpu.h" @@ -62,10 +64,54 @@ extern void __do_cpuid_fault(unsigned int op, unsigned int count, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx); +struct cpu_flags { + u32 val[NCAPINTS]; +}; + +static DEFINE_PER_CPU(struct cpu_flags, cpu_flags); + +static void init_cpu_flags(void *dummy) +{ + int cpu = smp_processor_id(); + struct cpu_flags *flags = &per_cpu(cpu_flags, cpu); + struct cpuinfo_x86 *c = &cpu_data(cpu); + unsigned int eax, ebx, ecx, edx; + + memcpy(flags->val, c->x86_capability, NCAPINTS * sizeof(u32)); + + /* + * Clear feature bits masked using cpuid masking/faulting. + */ + + if (c->cpuid_level >= 0x00000001) { + __do_cpuid_fault(0x00000001, 0, &eax, &ebx, &ecx, &edx); + flags->val[4] &= ecx; + flags->val[0] &= edx; + } + + if (c->cpuid_level >= 0x00000007) { + __do_cpuid_fault(0x00000007, 0, &eax, &ebx, &ecx, &edx); + flags->val[9] &= ebx; + } + + if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000 && + c->extended_cpuid_level >= 0x80000001) { + __do_cpuid_fault(0x80000001, 0, &eax, &ebx, &ecx, &edx); + flags->val[6] &= ecx; + flags->val[1] &= edx; + } + + if (c->cpuid_level >= 0x0000000d) { + __do_cpuid_fault(0x0000000d, 1, &eax, &ebx, &ecx, &edx); + flags->val[10] &= eax; + } +} + static int show_cpuinfo(struct seq_file *m, void *v) { struct cpuinfo_x86 *c = v; unsigned int cpu; + int is_super = ve_is_super(get_exec_env()); int i; cpu = c->cpu_index; @@ -107,7 +153,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_puts(m, "flags\t\t:"); for (i = 0; i < 32*NCAPINTS; i++) - if (cpu_has(c, i) && x86_cap_flags[i] != NULL) + if (x86_cap_flags[i] != NULL && + ((is_super && cpu_has(c, i)) || + (!is_super && test_bit(i, (unsigned long *) + &per_cpu(cpu_flags, cpu))))) seq_printf(m, " %s", x86_cap_flags[i]); #ifdef CONFIG_X86_VMX_FEATURE_NAMES @@ -160,18 +209,24 @@ static int show_cpuinfo(struct seq_file *m, void *v) return 0; } -static void *c_start(struct seq_file *m, loff_t *pos) +static void *__c_start(struct seq_file *m, loff_t *pos) { *pos = cpumask_next(*pos - 1, cpu_online_mask); - if ((*pos) < nr_cpu_ids) + if (bitmap_weight(cpumask_bits(cpu_online_mask), *pos) < num_online_vcpus()) return &cpu_data(*pos); return NULL; } +static void *c_start(struct seq_file *m, loff_t *pos) +{ + on_each_cpu(init_cpu_flags, NULL, 1); + return __c_start(m, pos); +} + static void *c_next(struct seq_file *m, void *v, loff_t *pos) { (*pos)++; - return c_start(m, pos); + return __c_start(m, pos); } static void c_stop(struct seq_file *m, void *v) -- 2.30.2 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel