[Devel] [PATCH rh7 09/11] Port diff-arch-x86-assure-cpuinfo-inside-ct-is-subset-of-hosts-one

Vladimir Davydov vdavydov at virtuozzo.com
Fri Oct 16 09:22:53 PDT 2015


Author: Vladimir Davydov
Email: vdavydov at parallels.com
Subject: arch: x86: assure cpuinfo inside ct is subset of host's one
Date: Fri, 12 Dec 2014 12:58:47 +0300

In order to reflect cpuid masking setup, /proc/cpuinfo output inside a
container is reported basing on an immediate output of the cpuid
instruction, while host's /proc/cpuinfo still uses cached in-kernel
value. The cached value is usually equal to the output of cpuid at boot
time, but it isn't always true. The kernel can clear some capability
bits due to a hardware bug or because it was explicitly disabled by
passing the appropriate boot parameter. As a result the output of
/proc/cpuinfo inside a container can be wider than that on host, which
looks ridiculous. Let's fix this by using logical AND to combine the
kernel cached value and the raw output of cpuid while reporting cpu
features in /proc/cpuinfo inside a container.

https://jira.sw.ru/browse/PSBM-30688

Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
=============================================================================

Changes in port:
 - cleanup flags->val initialization: use memcpy instead of looping over
   individual feature bits

https://jira.sw.ru/browse/PSBM-33638

Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
 arch/x86/kernel/cpu/proc.c | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 1a95a06b8f9a..ee32933617be 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -67,26 +67,31 @@ 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 tmp1, tmp2, tmp3;
-	int i;
+	unsigned int eax, ebx, ecx, edx;
 
-	bitmap_zero((unsigned long *)flags, 32*NCAPINTS);
-	for (i = 0; i < 32*NCAPINTS; i++)
-		if (cpu_has(c, i))
-			set_bit(i, (unsigned long *)flags);
+	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, &tmp1, &tmp2,
-				 &flags->val[4], &flags->val[0]);
+	if (c->cpuid_level >= 0x00000001) {
+		__do_cpuid_fault(0x00000001, 0, &eax, &ebx, &ecx, &edx);
+		flags->val[4] &= ecx;
+		flags->val[0] &= edx;
+	}
 
 	if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000 &&
-	    c->extended_cpuid_level >= 0x80000001)
-		__do_cpuid_fault(0x80000001, 0, &tmp1, &tmp2,
-				 &flags->val[6], &flags->val[1]);
+	    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, &flags->val[10],
-				 &tmp1, &tmp2, &tmp3);
+	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)
-- 
2.1.4




More information about the Devel mailing list