[Devel] [PATCH vz8 v2 2/2] x86: don't enable cpuid faults if /proc/vz/cpuid_override unused
We don't need to enable cpuid faults if /proc/vz/cpuid_override was never used. If task was attached to ve before a write to 'cpuid_override' it will not get cpuid faults now. It shouldn't be a problem since the proper use of 'cpuid_override' requires stopping all containers. https://jira.sw.ru/browse/PSBM-121823 Signed-off-by: Andrey Ryabinin --- Changes since v1: - git add include/linux/cpuid_override.h arch/x86/kernel/cpuid_fault.c | 21 ++--- include/linux/cpuid_override.h | 30 ++ kernel/ve/ve.c | 5 - 3 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 include/linux/cpuid_override.h diff --git a/arch/x86/kernel/cpuid_fault.c b/arch/x86/kernel/cpuid_fault.c index 1e8ffacc4412..cb6c2216fa8a 100644 --- a/arch/x86/kernel/cpuid_fault.c +++ b/arch/x86/kernel/cpuid_fault.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,25 +10,7 @@ #include #include -struct cpuid_override_entry { - unsigned int op; - unsigned int count; - bool has_count; - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; -}; - -#define MAX_CPUID_OVERRIDE_ENTRIES 16 - -struct cpuid_override_table { - struct rcu_head rcu_head; - int size; - struct cpuid_override_entry entries[MAX_CPUID_OVERRIDE_ENTRIES]; -}; - -static struct cpuid_override_table __rcu *cpuid_override __read_mostly; +struct cpuid_override_table __rcu *cpuid_override __read_mostly; static DEFINE_SPINLOCK(cpuid_override_lock); static void cpuid_override_update(struct cpuid_override_table *new_table) diff --git a/include/linux/cpuid_override.h b/include/linux/cpuid_override.h new file mode 100644 index ..ea0fa7af3d3c --- /dev/null +++ b/include/linux/cpuid_override.h @@ -0,0 +1,30 @@ +#ifndef __CPUID_OVERRIDE_H +#define __CPUID_OVERRIDE_H + +#include + +struct cpuid_override_entry { + unsigned int op; + unsigned int count; + bool has_count; + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; +}; + +#define MAX_CPUID_OVERRIDE_ENTRIES 16 + +struct cpuid_override_table { + struct rcu_head rcu_head; + int size; + struct cpuid_override_entry entries[MAX_CPUID_OVERRIDE_ENTRIES]; +}; + +extern struct cpuid_override_table __rcu *cpuid_override; + +static inline bool cpuid_override_on(void) +{ + return rcu_access_pointer(cpuid_override); +} +#endif diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c index aad8ce69ca1f..0d4d0ab70369 100644 --- a/kernel/ve/ve.c +++ b/kernel/ve/ve.c @@ -9,6 +9,7 @@ * 've.c' helper file performing VE sub-system initialization */ +#include #include #include #include @@ -801,6 +802,7 @@ static void ve_attach(struct cgroup_taskset *tset) { struct cgroup_subsys_state *css; struct task_struct *task; + extern struct cpuid_override_table __rcu *cpuid_override; cgroup_taskset_for_each(task, css, tset) { struct ve_struct *ve = css_to_ve(css); @@ -816,7 +818,8 @@ static void ve_attach(struct cgroup_taskset *tset) /* Leave parent exec domain */ task->parent_exec_id--; - set_tsk_thread_flag(task, TIF_CPUID_OVERRIDE); + if (cpuid_override_on()) + set_tsk_thread_flag(task, TIF_CPUID_OVERRIDE); task->task_ve = ve; } } -- 2.26.2 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
[Devel] [PATCH vz8 v2 1/2] x86, cpuinfo: Fix race on parallel /proc/cpuinfo read
If several threads read /proc/cpuinfo some can see in 'flags' values from c->x86_capability, before __do_cpuid_fault() called and masks applied. Fix this by forming 'flags' on stack first and copy them in per_cpu(cpu_flags, cpu) as a last step. https://jira.sw.ru/browse/PSBM-121823 Signed-off-by: Andrey Ryabinin --- Changes since v1: - none arch/x86/kernel/cpu/proc.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 4fe1577d5e6f..4cc2951e34fb 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -69,11 +69,11 @@ 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 = _cpu(cpu_flags, cpu); + struct cpu_flags flags; struct cpuinfo_x86 *c = _data(cpu); unsigned int eax, ebx, ecx, edx; - memcpy(flags->val, c->x86_capability, NCAPINTS * sizeof(u32)); + memcpy(, c->x86_capability, sizeof(flags)); /* * Clear feature bits masked using cpuid masking/faulting. @@ -81,26 +81,27 @@ static void init_cpu_flags(void *dummy) if (c->cpuid_level >= 0x0001) { __do_cpuid_fault(0x0001, 0, , , , ); - flags->val[4] &= ecx; - flags->val[0] &= edx; + flags.val[4] &= ecx; + flags.val[0] &= edx; } if (c->cpuid_level >= 0x0007) { __do_cpuid_fault(0x0007, 0, , , , ); - flags->val[9] &= ebx; + flags.val[9] &= ebx; } if ((c->extended_cpuid_level & 0x) == 0x8000 && c->extended_cpuid_level >= 0x8001) { __do_cpuid_fault(0x8001, 0, , , , ); - flags->val[6] &= ecx; - flags->val[1] &= edx; + flags.val[6] &= ecx; + flags.val[1] &= edx; } if (c->cpuid_level >= 0x000d) { __do_cpuid_fault(0x000d, 1, , , , ); - flags->val[10] &= eax; + flags.val[10] &= eax; } + memcpy(_cpu(cpu_flags, cpu), , sizeof(flags)); } static int show_cpuinfo(struct seq_file *m, void *v) -- 2.26.2 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
[Devel] [PATCH vz8 2/2] x86: don't enable cpuid faults if /proc/vz/cpuid_override unused
We don't need to enable cpuid faults if /proc/vz/cpuid_override was never used. If task was attached to ve before a write to 'cpuid_override' it will not get cpuid faults now. It shouldn't be a problem since the proper use of 'cpuid_override' requires stopping all containers. https://jira.sw.ru/browse/PSBM-121823 Signed-off-by: Andrey Ryabinin --- arch/x86/kernel/cpuid_fault.c | 21 ++--- kernel/ve/ve.c| 5 - 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/cpuid_fault.c b/arch/x86/kernel/cpuid_fault.c index 1e8ffacc4412..cb6c2216fa8a 100644 --- a/arch/x86/kernel/cpuid_fault.c +++ b/arch/x86/kernel/cpuid_fault.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,25 +10,7 @@ #include #include -struct cpuid_override_entry { - unsigned int op; - unsigned int count; - bool has_count; - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; -}; - -#define MAX_CPUID_OVERRIDE_ENTRIES 16 - -struct cpuid_override_table { - struct rcu_head rcu_head; - int size; - struct cpuid_override_entry entries[MAX_CPUID_OVERRIDE_ENTRIES]; -}; - -static struct cpuid_override_table __rcu *cpuid_override __read_mostly; +struct cpuid_override_table __rcu *cpuid_override __read_mostly; static DEFINE_SPINLOCK(cpuid_override_lock); static void cpuid_override_update(struct cpuid_override_table *new_table) diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c index aad8ce69ca1f..0d4d0ab70369 100644 --- a/kernel/ve/ve.c +++ b/kernel/ve/ve.c @@ -9,6 +9,7 @@ * 've.c' helper file performing VE sub-system initialization */ +#include #include #include #include @@ -801,6 +802,7 @@ static void ve_attach(struct cgroup_taskset *tset) { struct cgroup_subsys_state *css; struct task_struct *task; + extern struct cpuid_override_table __rcu *cpuid_override; cgroup_taskset_for_each(task, css, tset) { struct ve_struct *ve = css_to_ve(css); @@ -816,7 +818,8 @@ static void ve_attach(struct cgroup_taskset *tset) /* Leave parent exec domain */ task->parent_exec_id--; - set_tsk_thread_flag(task, TIF_CPUID_OVERRIDE); + if (cpuid_override_on()) + set_tsk_thread_flag(task, TIF_CPUID_OVERRIDE); task->task_ve = ve; } } -- 2.26.2 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel
[Devel] [PATCH vz8 1/2] x86, cpuinfo: Fix race on parallel /proc/cpuinfo read
If several threads read /proc/cpuinfo some can see in 'flags' values from c->x86_capability, before __do_cpuid_fault() called and masks applied. Fix this by forming 'flags' on stack first and copy them in per_cpu(cpu_flags, cpu) as a last step. https://jira.sw.ru/browse/PSBM-121823 Signed-off-by: Andrey Ryabinin --- arch/x86/kernel/cpu/proc.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 4fe1577d5e6f..4cc2951e34fb 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -69,11 +69,11 @@ 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 = _cpu(cpu_flags, cpu); + struct cpu_flags flags; struct cpuinfo_x86 *c = _data(cpu); unsigned int eax, ebx, ecx, edx; - memcpy(flags->val, c->x86_capability, NCAPINTS * sizeof(u32)); + memcpy(, c->x86_capability, sizeof(flags)); /* * Clear feature bits masked using cpuid masking/faulting. @@ -81,26 +81,27 @@ static void init_cpu_flags(void *dummy) if (c->cpuid_level >= 0x0001) { __do_cpuid_fault(0x0001, 0, , , , ); - flags->val[4] &= ecx; - flags->val[0] &= edx; + flags.val[4] &= ecx; + flags.val[0] &= edx; } if (c->cpuid_level >= 0x0007) { __do_cpuid_fault(0x0007, 0, , , , ); - flags->val[9] &= ebx; + flags.val[9] &= ebx; } if ((c->extended_cpuid_level & 0x) == 0x8000 && c->extended_cpuid_level >= 0x8001) { __do_cpuid_fault(0x8001, 0, , , , ); - flags->val[6] &= ecx; - flags->val[1] &= edx; + flags.val[6] &= ecx; + flags.val[1] &= edx; } if (c->cpuid_level >= 0x000d) { __do_cpuid_fault(0x000d, 1, , , , ); - flags->val[10] &= eax; + flags.val[10] &= eax; } + memcpy(_cpu(cpu_flags, cpu), , sizeof(flags)); } static int show_cpuinfo(struct seq_file *m, void *v) -- 2.26.2 ___ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel