Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 36201
b: refs/heads/master
c: 9a4b9ef
h: refs/heads/master
i:
  36199: 107ee6e
v: v3
  • Loading branch information
Shaohua Li authored and Linus Torvalds committed Sep 27, 2006
1 parent 5e33602 commit 5457f8e
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a30a6a2cb0fdc2c9701d6ddfb21affeb8146c038
refs/heads/master: 9a4b9efa1d39d7d31bed08fbe5a9b2a03b2759d4
1 change: 1 addition & 0 deletions trunk/arch/i386/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ config X86_REBOOTFIXUPS

config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
select FW_LOADER
---help---
If you say Y here and also to "/dev file system support" in the
'File systems' section, you will be able to update the microcode on
Expand Down
154 changes: 151 additions & 3 deletions trunk/arch/i386/kernel/microcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ static int microcode_sanity_check(void *mc)
/* check extended table checksum */
if (ext_table_size) {
int ext_table_sum = 0;
int * ext_tablep = (int *)ext_header;
int *ext_tablep = (int *)ext_header;

i = ext_table_size / DWSIZE;
while (i--)
Expand Down Expand Up @@ -386,7 +386,7 @@ static int do_microcode_update (void)
{
long cursor = 0;
int error = 0;
void * new_mc;
void *new_mc;
int cpu;
cpumask_t old;

Expand Down Expand Up @@ -531,7 +531,7 @@ static int cpu_request_microcode(int cpu)
char name[30];
struct cpuinfo_x86 *c = cpu_data + cpu;
const struct firmware *firmware;
void * buf;
void *buf;
unsigned long size;
long offset = 0;
int error;
Expand Down Expand Up @@ -602,6 +602,136 @@ static void microcode_fini_cpu(int cpu)
mutex_unlock(&microcode_mutex);
}

static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
char *end;
unsigned long val = simple_strtoul(buf, &end, 0);
int err = 0;
int cpu = dev->id;

if (end == buf)
return -EINVAL;
if (val == 1) {
cpumask_t old;

old = current->cpus_allowed;

lock_cpu_hotplug();
set_cpus_allowed(current, cpumask_of_cpu(cpu));

mutex_lock(&microcode_mutex);
if (uci->valid)
err = cpu_request_microcode(cpu);
mutex_unlock(&microcode_mutex);
unlock_cpu_hotplug();
set_cpus_allowed(current, old);
}
if (err)
return err;
return sz;
}

static ssize_t version_show(struct sys_device *dev, char *buf)
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;

return sprintf(buf, "0x%x\n", uci->rev);
}

static ssize_t pf_show(struct sys_device *dev, char *buf)
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;

return sprintf(buf, "0x%x\n", uci->pf);
}

static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
static SYSDEV_ATTR(version, 0400, version_show, NULL);
static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);

static struct attribute *mc_default_attrs[] = {
&attr_reload.attr,
&attr_version.attr,
&attr_processor_flags.attr,
NULL
};

static struct attribute_group mc_attr_group = {
.attrs = mc_default_attrs,
.name = "microcode",
};

static int mc_sysdev_add(struct sys_device *sys_dev)
{
int cpu = sys_dev->id;
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;

if (!cpu_online(cpu))
return 0;
pr_debug("Microcode:CPU %d added\n", cpu);
memset(uci, 0, sizeof(*uci));
sysfs_create_group(&sys_dev->kobj, &mc_attr_group);

microcode_init_cpu(cpu);
return 0;
}

static int mc_sysdev_remove(struct sys_device *sys_dev)
{
int cpu = sys_dev->id;

if (!cpu_online(cpu))
return 0;
pr_debug("Microcode:CPU %d removed\n", cpu);
microcode_fini_cpu(cpu);
sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
return 0;
}

static int mc_sysdev_resume(struct sys_device *dev)
{
int cpu = dev->id;

if (!cpu_online(cpu))
return 0;
pr_debug("Microcode:CPU %d resumed\n", cpu);
/* only CPU 0 will apply ucode here */
apply_microcode(0);
return 0;
}

static struct sysdev_driver mc_sysdev_driver = {
.add = mc_sysdev_add,
.remove = mc_sysdev_remove,
.resume = mc_sysdev_resume,
};

#ifdef CONFIG_HOTPLUG_CPU
static __cpuinit int
mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev;

sys_dev = get_cpu_sysdev(cpu);
switch (action) {
case CPU_ONLINE:
case CPU_DOWN_FAILED:
mc_sysdev_add(sys_dev);
break;
case CPU_DOWN_PREPARE:
mc_sysdev_remove(sys_dev);
break;
}
return NOTIFY_OK;
}

static struct notifier_block mc_cpu_notifier = {
.notifier_call = mc_cpu_callback,
};
#endif

static int __init microcode_init (void)
{
int error;
Expand All @@ -616,6 +746,17 @@ static int __init microcode_init (void)
return PTR_ERR(microcode_pdev);
}

lock_cpu_hotplug();
error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
unlock_cpu_hotplug();
if (error) {
microcode_dev_exit();
platform_device_unregister(microcode_pdev);
return error;
}

register_hotcpu_notifier(&mc_cpu_notifier);

printk(KERN_INFO
"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
return 0;
Expand All @@ -624,6 +765,13 @@ static int __init microcode_init (void)
static void __exit microcode_exit (void)
{
microcode_dev_exit();

unregister_hotcpu_notifier(&mc_cpu_notifier);

lock_cpu_hotplug();
sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
unlock_cpu_hotplug();

platform_device_unregister(microcode_pdev);
}

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86_64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ config X86_GOOD_APIC

config MICROCODE
tristate "/dev/cpu/microcode - Intel CPU microcode support"
select FW_LOADER
---help---
If you say Y here the 'File systems' section, you will be
able to update the microcode on Intel processors. You will
Expand Down

0 comments on commit 5457f8e

Please sign in to comment.