Re: [PATCH 9/8] CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts

From: Kay Sievers
Date: Wed Dec 21 2011 - 10:32:50 EST


2011/12/21 Thomas Renninger <trenn@xxxxxxx>:

Cool. That sounds good. Nice work. Thanks.

Adding Greg, so he's in the loop.

Greg, Andi's upcoming CPU modaliases are temporarily hooked into the
'cpuid' class devices to make them work with userspace, which isn't
possible with the weird sysdev stuff.

We don't want to depend on the 'cpuid' class, but hook into the real
'cpu' subsystem. This switches them over after we have the
sysdev-cpu-conversion stuff merged.

Thanks,
Kay

> CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts
>
> This patch is based on Andi Kleen's work:
> Implement autoprobing/loading of modules serving CPU
> specific features (x86cpu autoloading).
>
> And Kay Siever's work to get rid of sysdev cpu structures
> and making use of struct device instead.
>
> Signed-off-by: Thomas Renninger <trenn@xxxxxxx>
> CC: ak@xxxxxxxxxxxxxxx
> CC: kay.sievers@xxxxxxxx
> CC: hpa@xxxxxxxxx
> CC: davej@xxxxxxxxxx
> CC: kay.sievers@xxxxxxxx
> CC: axboe@xxxxxxxxx
> CC: hpa@xxxxxxxxx
> CC: herbert@xxxxxxxxxxxxxxxxxxx
> CC: ying.huang@xxxxxxxxx
> CC: lenb@xxxxxxxxxx
>
> ---
> Âarch/x86/Kconfig      Â|  Â3 ++
> Âarch/x86/kernel/cpu/match.c | Â 43 ++++++++++++++++++++++++++++++++
> Âarch/x86/kernel/cpuid.c   |  58 --------------------------------------------
> Âdrivers/base/cpu.c     Â|  11 ++++++++
> Âinclude/linux/cpu.h     |  Â7 +++++
> Â5 files changed, 65 insertions(+), 57 deletions(-)
>
> Index: linux-3.2-rc6-master/arch/x86/kernel/cpuid.c
> ===================================================================
> --- linux-3.2-rc6-master.orig/arch/x86/kernel/cpuid.c
> +++ linux-3.2-rc6-master/arch/x86/kernel/cpuid.c
> @@ -40,7 +40,6 @@
> Â#include <linux/notifier.h>
> Â#include <linux/uaccess.h>
> Â#include <linux/gfp.h>
> -#include <linux/slab.h>
>
> Â#include <asm/processor.h>
> Â#include <asm/msr.h>
> @@ -139,56 +138,13 @@ static const struct file_operations cpui
> Â Â Â Â.open = cpuid_open,
> Â};
>
> -static ssize_t print_cpu_modalias(struct device *dev,
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct device_attribute *attr,
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â char *bufptr)
> -{
> - Â Â Â int size = PAGE_SIZE;
> - Â Â Â int i, n;
> - Â Â Â char *buf = bufptr;
> -
> - Â Â Â n = snprintf(buf, size, "x86cpu:vendor:%04x:family:%04x:model:%04x:feature:",
> - Â Â Â Â Â Â Â boot_cpu_data.x86_vendor,
> - Â Â Â Â Â Â Â boot_cpu_data.x86,
> - Â Â Â Â Â Â Â boot_cpu_data.x86_model);
> - Â Â Â size -= n;
> - Â Â Â buf += n;
> - Â Â Â size -= 2;
> - Â Â Â for (i = 0; i < NCAPINTS*32; i++) {
> - Â Â Â Â Â Â Â if (boot_cpu_has(i)) {
> - Â Â Â Â Â Â Â Â Â Â Â n = snprintf(buf, size, ",%04x", i);
> - Â Â Â Â Â Â Â Â Â Â Â if (n < 0) {
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â WARN(1, "x86 features overflow page\n");
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
> - Â Â Â Â Â Â Â Â Â Â Â }
> - Â Â Â Â Â Â Â Â Â Â Â size -= n;
> - Â Â Â Â Â Â Â Â Â Â Â buf += n;
> - Â Â Â Â Â Â Â }
> - Â Â Â }
> - Â Â Â *buf++ = ',';
> - Â Â Â *buf++ = '\n';
> - Â Â Â return buf - bufptr;
> -}
> -
> -static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
> -
> Âstatic __cpuinit int cpuid_device_create(int cpu)
> Â{
> Â Â Â Âstruct device *dev;
> - Â Â Â int err;
>
> Â Â Â Âdev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â"cpu%d", cpu);
> - Â Â Â if (IS_ERR(dev))
> - Â Â Â Â Â Â Â return PTR_ERR(dev);
> -
> - Â Â Â err = device_create_file(dev, &dev_attr_modalias);
> - Â Â Â if (err) {
> - Â Â Â Â Â Â Â /* keep device around on error. attribute is optional. */
> - Â Â Â Â Â Â Â err = 0;
> - Â Â Â }
> -
> - Â Â Â return 0;
> + Â Â Â return IS_ERR(dev) ? PTR_ERR(dev) : 0;
> Â}
>
> Âstatic void cpuid_device_destroy(int cpu)
> @@ -226,17 +182,6 @@ static char *cpuid_devnode(struct device
> Â Â Â Âreturn kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
> Â}
>
> -static int cpuid_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
> -{
> - Â Â Â char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> - Â Â Â if (buf) {
> - Â Â Â Â Â Â Â print_cpu_modalias(NULL, NULL, buf);
> - Â Â Â Â Â Â Â add_uevent_var(env, "MODALIAS=%s", buf);
> - Â Â Â Â Â Â Â kfree(buf);
> - Â Â Â }
> - Â Â Â return 0;
> -}
> -
> Âstatic int __init cpuid_init(void)
> Â{
> Â Â Â Âint i, err = 0;
> @@ -255,7 +200,6 @@ static int __init cpuid_init(void)
> Â Â Â Â Â Â Â Âgoto out_chrdev;
> Â Â Â Â}
> Â Â Â Âcpuid_class->devnode = cpuid_devnode;
> - Â Â Â cpuid_class->dev_uevent = cpuid_dev_uevent;
> Â Â Â Âfor_each_online_cpu(i) {
> Â Â Â Â Â Â Â Âerr = cpuid_device_create(i);CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts
> Â Â Â Â Â Â Â Âif (err != 0)
> Index: linux-3.2-rc6-master/arch/x86/Kconfig
> ===================================================================
> --- linux-3.2-rc6-master.orig/arch/x86/Kconfig
> +++ linux-3.2-rc6-master/arch/x86/Kconfig
> @@ -185,6 +185,9 @@ config ARCH_HAS_DEFAULT_IDLE
> Âconfig ARCH_HAS_CACHE_LINE_SIZE
> Â Â Â Âdef_bool y
>
> +config ARCH_HAS_CPU_AUTOPROBE
> + Â Â Â def_bool y
> +
> Âconfig HAVE_SETUP_PER_CPU_AREA
> Â Â Â Âdef_bool y
>
> Index: linux-3.2-rc6-master/drivers/base/cpu.c
> ===================================================================
> --- linux-3.2-rc6-master.orig/drivers/base/cpu.c
> +++ linux-3.2-rc6-master/drivers/base/cpu.c
> @@ -10,6 +10,7 @@
> Â#include <linux/device.h>
> Â#include <linux/node.h>
> Â#include <linux/gfp.h>
> +#include <linux/slab.h>
>
> Â#include "base.h"
>
> @@ -221,6 +222,9 @@ int __cpuinit register_cpu(struct cpu *c
> Â Â Â Âcpu->node_id = cpu_to_node(num);
> Â Â Â Âcpu->dev.id = num;
> Â Â Â Âcpu->dev.bus = &cpu_subsys;
> +#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> + Â Â Â cpu->dev.bus->uevent = arch_cpu_uevent;
> +#endif
> Â Â Â Âerror = device_register(&cpu->dev);
> Â Â Â Âif (!error && cpu->hotpluggable)
> Â Â Â Â Â Â Â Âregister_cpu_control(cpu);
> @@ -245,6 +249,10 @@ struct device *get_cpu_device(unsigned c
> Â}
> ÂEXPORT_SYMBOL_GPL(get_cpu_device);
>
> +#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
> +#endif
> +
> Âstatic struct attribute *cpu_root_attrs[] = {
> Â#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
> Â Â Â Â&dev_attr_probe.attr,
> @@ -255,6 +263,9 @@ static struct attribute *cpu_root_attrs[
> Â Â Â Â&cpu_attrs[2].attr.attr,
> Â Â Â Â&dev_attr_kernel_max.attr,
> Â Â Â Â&dev_attr_offline.attr,
> +#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> + Â Â Â &dev_attr_modalias.attr,
> +#endif
> Â Â Â ÂNULL
> Â};
>
> Index: linux-3.2-rc6-master/arch/x86/kernel/cpu/match.c
> ===================================================================
> --- linux-3.2-rc6-master.orig/arch/x86/kernel/cpu/match.c
> +++ linux-3.2-rc6-master/arch/x86/kernel/cpu/match.c
> @@ -2,6 +2,7 @@
> Â#include <asm/processor.h>
> Â#include <linux/cpu.h>
> Â#include <linux/module.h>
> +#include <linux/slab.h>
>
> Â/**
> Â* x86_match_cpu - match current CPU again an array of x86_cpu_ids
> @@ -46,3 +47,45 @@ const struct x86_cpu_id *x86_match_cpu(c
> Â Â Â Âreturn NULL;
> Â}
> ÂEXPORT_SYMBOL(x86_match_cpu);
> +
> +ssize_t arch_print_cpu_modalias(struct device *dev,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct device_attribute *attr,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â char *bufptr)
> +{
> + Â Â Â int size = PAGE_SIZE;
> + Â Â Â int i, n;
> + Â Â Â char *buf = bufptr;
> +
> + Â Â Â n = snprintf(buf, size, "x86cpu:vendor:%04x:family:%04x:model:%04x:feature:",
> + Â Â Â Â Â Â Â boot_cpu_data.x86_vendor,
> + Â Â Â Â Â Â Â boot_cpu_data.x86,
> + Â Â Â Â Â Â Â boot_cpu_data.x86_model);
> + Â Â Â size -= n;
> + Â Â Â buf += n;
> + Â Â Â size -= 2;
> + Â Â Â for (i = 0; i < NCAPINTS*32; i++) {
> + Â Â Â Â Â Â Â if (boot_cpu_has(i)) {
> + Â Â Â Â Â Â Â Â Â Â Â n = snprintf(buf, size, ",%04x", i);
> + Â Â Â Â Â Â Â Â Â Â Â if (n < 0) {
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â WARN(1, "x86 features overflow page\n");
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
> + Â Â Â Â Â Â Â Â Â Â Â }
> + Â Â Â Â Â Â Â Â Â Â Â size -= n;
> + Â Â Â Â Â Â Â Â Â Â Â buf += n;
> + Â Â Â Â Â Â Â }
> + Â Â Â }
> + Â Â Â *buf++ = ',';
> + Â Â Â *buf++ = '\n';
> + Â Â Â return buf - bufptr;
> +}
> +
> +int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
> +{
> + Â Â Â char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> + Â Â Â if (buf) {
> + Â Â Â Â Â Â Â arch_print_cpu_modalias(NULL, NULL, buf);
> + Â Â Â Â Â Â Â add_uevent_var(env, "MODALIAS=%s", buf);
> + Â Â Â Â Â Â Â kfree(buf);
> + Â Â Â }
> + Â Â Â return 0;
> +}
> Index: linux-3.2-rc6-master/include/linux/cpu.h
> ===================================================================
> --- linux-3.2-rc6-master.orig/include/linux/cpu.h
> +++ linux-3.2-rc6-master/include/linux/cpu.h
> @@ -43,6 +43,13 @@ extern ssize_t arch_cpu_release(const ch
> Â#endif
> Âstruct notifier_block;
>
> +#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
> +extern ssize_t arch_print_cpu_modalias(struct device *dev,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âstruct device_attribute *attr,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âchar *bufptr);
> +#endif
> +
> Â/*
> Â* CPU notifier priorities.
> Â*/
èº{.nÇ+‰·Ÿ®‰­†+%ŠËlzwm…ébëæìr¸›zX§»®w¥Š{ayºÊÚë,j­¢f£¢·hš‹àz¹®w¥¢¸ ¢·¦j:+v‰¨ŠwèjØm¶Ÿÿ¾«‘êçzZ+ƒùšŽŠÝj"ú!¶iO•æ¬z·švØ^¶m§ÿðà nÆàþY&—