* [PATCH] x86, microcode rework, v2, renaming
2008-09-16 21:43 ` Dmitry Adamushko
@ 2001-09-16 22:00 ` Peter Oruba
2008-09-17 13:39 ` [PATCH] x86, microcode rework, v2, renaming cont Peter Oruba
1 sibling, 0 replies; 6+ messages in thread
From: Peter Oruba @ 2001-09-16 22:00 UTC (permalink / raw)
To: Dmitry Adamushko, Ingo Molnar; +Cc: Tigran Aivazian, LKML
Renaming based on patch from Dmitry Adamushko.
Made code more readable by renaming define and variables related
to microcode _container_file_ header to make it distinguishable from
microcode _patch_ header.
Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
arch/x86/kernel/microcode_amd.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 48aec9f..8d97840 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -274,12 +274,12 @@ static void * get_next_ucode(u8 *buf, unsigned int size,
static int install_equiv_cpu_table(u8 *buf,
int (*get_ucode_data)(void *, const void *, size_t))
{
-#define UCODE_HEADER_SIZE 12
- u8 *hdr[UCODE_HEADER_SIZE];
- unsigned int *buf_pos = (unsigned int *)hdr;
+#define UCODE_CONTAINER_HEADER_SIZE 12
+ u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE];
+ unsigned int *buf_pos = (unsigned int *)container_hdr;
unsigned long size;
- if (get_ucode_data(&hdr, buf, UCODE_HEADER_SIZE))
+ if (get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE))
return 0;
size = buf_pos[2];
@@ -296,14 +296,14 @@ static int install_equiv_cpu_table(u8 *buf,
return 0;
}
- buf += UCODE_HEADER_SIZE;
+ buf += UCODE_CONTAINER_HEADER_SIZE;
if (get_ucode_data(equiv_cpu_table, buf, size)) {
vfree(equiv_cpu_table);
return 0;
}
- return size + UCODE_HEADER_SIZE; /* add header length */
-#undef UCODE_HEADER_SIZE
+ return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */
+#undef UCODE_CONTAINER_HEADER_SIZE
}
static void free_equiv_cpu_table(void)
--
1.5.4.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [x86-tip, patch] rework of the microcode splitup
@ 2008-09-14 9:14 Dmitry Adamushko
2008-09-14 9:18 ` Dmitry Adamushko
2008-09-14 12:55 ` Ingo Molnar
0 siblings, 2 replies; 6+ messages in thread
From: Dmitry Adamushko @ 2008-09-14 9:14 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Peter Oruba, Tigran Aivazian, LKML
Ingo, Peter,
this version is slightly different from the current one in -tip (added missing vfree()).
I have tested it only with "microcode_ctl" (update via /dev/cpu/microcode).
Since my CPUs already have the revision equal to the recent microcode revision
from Intel, I temporarily altered the logic of checks in order to verify that
the correct microcode file is found and applied. That proved to work well.
Peter: please take a look at the "microcode_amd" part, esp. 2 "FIXME" notes.
todo (not dependent on this patch):
- perhaps, move arch-specific structures from microcode.h to arch-specific *.c files;
- remove union in struct ucode_cpu_info;
- see how we could apply microcode as early as possible;
- don't use set_cpus_allowed()
anyway, I think this new interface is cleaner and better maintainability-wise.
4 files changed, 304 insertions(+), 362 deletions(-)
---
From: Dmitry Adamushko <dmitry.adamushko@gmail.com>
Subject: x86-microcode, rework of the microcode splitup
x86, microcode rework, v2
this is a rework of the microcode splitup in tip/x86/microcode
This new interface is supposed to be cleaner and better maintainability-wise;
4 files changed, 304 insertions(+), 362 deletions(-)
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -70,8 +70,9 @@
* Fix sigmatch() macro to handle old CPUs with pf == 0.
* Thanks to Stuart Swales for pointing out this bug.
*/
-
-/* #define DEBUG pr_debug */
+#if 0
+#define DEBUG /* pr_debug */
+#endif
#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -110,50 +111,28 @@ struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
EXPORT_SYMBOL_GPL(ucode_cpu_info);
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
-void __user *user_buffer; /* user area microcode data buffer */
-EXPORT_SYMBOL_GPL(user_buffer);
-unsigned int user_buffer_size; /* it's size */
-EXPORT_SYMBOL_GPL(user_buffer_size);
-
-static int do_microcode_update(void)
+static int do_microcode_update(const void __user *buf, size_t size)
{
- long cursor = 0;
+ cpumask_t old;
int error = 0;
- void *new_mc = NULL;
int cpu;
- cpumask_t old;
old = current->cpus_allowed;
- while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) {
- if (microcode_ops->microcode_sanity_check != NULL)
- error = microcode_ops->microcode_sanity_check(new_mc);
- if (error)
+ for_each_online_cpu(cpu) {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+ if (!uci->valid)
+ continue;
+
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ error = microcode_ops->request_microcode_user(cpu, buf, size);
+ if (error < 0)
goto out;
- /*
- * It's possible the data file has multiple matching ucode,
- * lets keep searching till the latest version
- */
- for_each_online_cpu(cpu) {
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
- if (!uci->valid)
- continue;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- error = microcode_ops->get_matching_microcode(new_mc,
- cpu);
- if (error < 0)
- goto out;
- if (error == 1)
- microcode_ops->apply_microcode(cpu);
- }
- vfree(new_mc);
+ if (!error)
+ microcode_ops->apply_microcode(cpu);
}
out:
- if (cursor > 0)
- vfree(new_mc);
- if (cursor < 0)
- error = cursor;
set_cpus_allowed_ptr(current, &old);
return error;
}
@@ -178,10 +157,7 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
get_online_cpus();
mutex_lock(µcode_mutex);
- user_buffer = (void __user *) buf;
- user_buffer_size = (int) len;
-
- ret = do_microcode_update();
+ ret = do_microcode_update(buf, len);
if (!ret)
ret = (ssize_t)len;
@@ -231,7 +207,6 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
/* fake device for request_firmware */
struct platform_device *microcode_pdev;
-EXPORT_SYMBOL_GPL(microcode_pdev);
static ssize_t reload_store(struct sys_device *dev,
struct sysdev_attribute *attr,
@@ -252,8 +227,12 @@ static ssize_t reload_store(struct sys_device *dev,
if (cpu_online(cpu)) {
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
mutex_lock(µcode_mutex);
- if (uci->valid)
- err = microcode_ops->cpu_request_microcode(cpu);
+ if (uci->valid) {
+ err = microcode_ops->request_microcode_fw(cpu,
+ µcode_pdev->dev);
+ if (!err)
+ microcode_ops->apply_microcode(cpu);
+ }
mutex_unlock(µcode_mutex);
set_cpus_allowed_ptr(current, &old);
}
@@ -315,7 +294,7 @@ static void collect_cpu_info(int cpu)
uci->valid = 1;
}
-static void microcode_resume_cpu(int cpu)
+static int microcode_resume_cpu(int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
struct cpu_signature nsig;
@@ -323,7 +302,7 @@ static void microcode_resume_cpu(int cpu)
pr_debug("microcode: CPU%d resumed\n", cpu);
if (!uci->mc.valid_mc)
- return;
+ return 1;
/*
* Let's verify that the 'cached' ucode does belong
@@ -331,21 +310,22 @@ static void microcode_resume_cpu(int cpu)
*/
if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
microcode_fini_cpu(cpu);
- return;
+ return -1;
}
if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
microcode_fini_cpu(cpu);
/* Should we look for a new ucode here? */
- return;
+ return 1;
}
- microcode_ops->apply_microcode(cpu);
+ return 0;
}
void microcode_update_cpu(int cpu)
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ int err = 0;
/* We should bind the task to the CPU */
BUG_ON(raw_smp_processor_id() != cpu);
@@ -356,12 +336,17 @@ void microcode_update_cpu(int cpu)
* otherwise just request a firmware:
*/
if (uci->valid) {
- microcode_resume_cpu(cpu);
+ err = microcode_resume_cpu(cpu);
} else {
collect_cpu_info(cpu);
if (uci->valid && system_state == SYSTEM_RUNNING)
- microcode_ops->cpu_request_microcode(cpu);
+ err = microcode_ops->request_microcode_fw(cpu,
+ µcode_pdev->dev);
}
+
+ if (!err)
+ microcode_ops->apply_microcode(cpu);
+
mutex_unlock(µcode_mutex);
}
@@ -412,9 +397,9 @@ static int mc_sysdev_resume(struct sys_device *dev)
if (!cpu_online(cpu))
return 0;
- pr_debug("microcode: CPU%d resumed\n", cpu);
+
/* only CPU 0 will apply ucode here */
- microcode_ops->apply_microcode(0);
+ microcode_update_cpu(0);
return 0;
}
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index d606a05..48aec9f 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -59,7 +59,7 @@ MODULE_LICENSE("GPL v2");
/* serialize access to the physical write */
static DEFINE_SPINLOCK(microcode_update_lock);
-struct equiv_cpu_entry *equiv_cpu_table;
+static struct equiv_cpu_entry *equiv_cpu_table;
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
{
@@ -83,36 +83,37 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
return 0;
}
-static int get_matching_microcode_amd(void *mc, int cpu)
+static int get_matching_microcode(int cpu, void *mc, int rev)
{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
struct microcode_header_amd *mc_header = mc;
- unsigned long total_size = get_totalsize(mc_header);
- void *new_mc;
struct pci_dev *nb_pci_dev, *sb_pci_dev;
unsigned int current_cpu_id;
unsigned int equiv_cpu_id = 0x00;
unsigned int i = 0;
- /* We should bind the task to the CPU */
- BUG_ON(cpu != raw_smp_processor_id());
-
- /* This is a tricky part. We might be called from a write operation */
- /* to the device file instead of the usual process of firmware */
- /* loading. This routine needs to be able to distinguish both */
-/* cases. This is done by checking if there alread is a equivalent */
- /* CPU table installed. If not, we're written through */
- /* /dev/cpu/microcode. */
-/* Since we ignore all checks. The error case in which going through */
-/* firmware loading and that table is not loaded has already been */
- /* checked earlier. */
+ /*
+ * FIXME! dimm: do we need this? Why an update via /dev/... is different
+ * from the one via firmware?
+ *
+ * This is a tricky part. We might be called from a write operation
+ * to the device file instead of the usual process of firmware
+ * loading. This routine needs to be able to distinguish both
+ * cases. This is done by checking if there alread is a equivalent
+ * CPU table installed. If not, we're written through
+ * /dev/cpu/microcode.
+ * Since we ignore all checks. The error case in which going through
+ * firmware loading and that table is not loaded has already been
+ * checked earlier.
+ */
+ BUG_ON(equiv_cpu_table == NULL);
+#if 0
if (equiv_cpu_table == NULL) {
printk(KERN_INFO "microcode: CPU%d microcode update with "
"version 0x%x (current=0x%x)\n",
cpu, mc_header->patch_id, uci->cpu_sig.rev);
goto out;
}
-
+#endif
current_cpu_id = cpuid_eax(0x00000001);
while (equiv_cpu_table[i].installed_cpu != 0) {
@@ -175,27 +176,9 @@ static int get_matching_microcode_amd(void *mc, int cpu)
pci_dev_put(sb_pci_dev);
}
- if (mc_header->patch_id <= uci->cpu_sig.rev)
+ if (mc_header->patch_id <= rev)
return 0;
- printk(KERN_INFO "microcode: CPU%d found a matching microcode "
- "update with version 0x%x (current=0x%x)\n",
- cpu, mc_header->patch_id, uci->cpu_sig.rev);
-
-out:
- new_mc = vmalloc(UCODE_MAX_SIZE);
- if (!new_mc) {
- printk(KERN_ERR "microcode: error, can't allocate memory\n");
- return -ENOMEM;
- }
- memset(new_mc, 0, UCODE_MAX_SIZE);
-
- /* free previous update file */
- vfree(uci->mc.mc_amd);
-
- memcpy(new_mc, mc, total_size);
-
- uci->mc.mc_amd = new_mc;
return 1;
}
@@ -245,104 +228,65 @@ static void apply_microcode_amd(int cpu)
uci->cpu_sig.rev = rev;
}
-#ifdef CONFIG_MICROCODE_OLD_INTERFACE
-extern void __user *user_buffer; /* user area microcode data buffer */
-extern unsigned int user_buffer_size; /* it's size */
-
-static long get_next_ucode_amd(void **mc, long offset)
-{
- struct microcode_header_amd mc_header;
- unsigned long total_size;
-
- /* No more data */
- if (offset >= user_buffer_size)
- return 0;
- if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- return -EFAULT;
- }
- total_size = get_totalsize(&mc_header);
- if (offset + total_size > user_buffer_size) {
- printk(KERN_ERR "microcode: error! Bad total size in microcode "
- "data file\n");
- return -EINVAL;
- }
- *mc = vmalloc(UCODE_MAX_SIZE);
- if (!*mc)
- return -ENOMEM;
- memset(*mc, 0, UCODE_MAX_SIZE);
-
- if (copy_from_user(*mc, user_buffer + offset, total_size)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- vfree(*mc);
- return -EFAULT;
- }
- return offset + total_size;
-}
-#else
-#define get_next_ucode_amd() NULL
-#endif
-
-static long get_next_ucode_from_buffer_amd(void **mc, void *buf,
- unsigned long size, long offset)
+static void * get_next_ucode(u8 *buf, unsigned int size,
+ int (*get_ucode_data)(void *, const void *, size_t),
+ unsigned int *mc_size)
{
- struct microcode_header_amd *mc_header;
- unsigned long total_size;
- unsigned char *buf_pos = buf;
+ unsigned int total_size;
+#define UCODE_UNKNOWN_HDR 8
+ u8 hdr[UCODE_UNKNOWN_HDR];
+ void *mc;
- /* No more data */
- if (offset >= size)
- return 0;
+ if (get_ucode_data(hdr, buf, UCODE_UNKNOWN_HDR))
+ return NULL;
- if (buf_pos[offset] != UCODE_UCODE_TYPE) {
+ if (hdr[0] != UCODE_UCODE_TYPE) {
printk(KERN_ERR "microcode: error! "
"Wrong microcode payload type field\n");
- return -EINVAL;
+ return NULL;
}
- mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
+ /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */
+ total_size = (unsigned long) (hdr[4] + (hdr[5] << 8));
- total_size = (unsigned long) (buf_pos[offset+4] +
- (buf_pos[offset+5] << 8));
+ printk(KERN_INFO "microcode: size %u, total_size %u\n",
+ size, total_size);
- printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
- size, total_size, offset);
-
- if (offset + total_size > size) {
+ if (total_size > size || total_size > UCODE_MAX_SIZE) {
printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
- return -EINVAL;
+ return NULL;
}
- *mc = vmalloc(UCODE_MAX_SIZE);
- if (!*mc) {
- printk(KERN_ERR "microcode: error! "
- "Can not allocate memory for microcode patch\n");
- return -ENOMEM;
+ mc = vmalloc(UCODE_MAX_SIZE);
+ if (mc) {
+ memset(mc, 0, UCODE_MAX_SIZE);
+ if (get_ucode_data(mc, buf + UCODE_UNKNOWN_HDR, total_size)) {
+ vfree(mc);
+ mc = NULL;
+ } else
+ *mc_size = total_size + UCODE_UNKNOWN_HDR;
}
-
- memset(*mc, 0, UCODE_MAX_SIZE);
- memcpy(*mc, buf + offset + 8, total_size);
-
- return offset + total_size + 8;
+#undef UCODE_UNKNOWN_HDR
+ return mc;
}
-static long install_equiv_cpu_table(void *buf, unsigned long size, long offset)
+
+static int install_equiv_cpu_table(u8 *buf,
+ int (*get_ucode_data)(void *, const void *, size_t))
{
- unsigned int *buf_pos = buf;
+#define UCODE_HEADER_SIZE 12
+ u8 *hdr[UCODE_HEADER_SIZE];
+ unsigned int *buf_pos = (unsigned int *)hdr;
+ unsigned long size;
- /* No more data */
- if (offset >= size)
+ if (get_ucode_data(&hdr, buf, UCODE_HEADER_SIZE))
return 0;
- if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) {
- printk(KERN_ERR "microcode: error! "
- "Wrong microcode equivalnet cpu table type field\n");
- return 0;
- }
+ size = buf_pos[2];
- if (size == 0) {
+ if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
printk(KERN_ERR "microcode: error! "
- "Wrong microcode equivalnet cpu table length\n");
+ "Wrong microcode equivalnet cpu table\n");
return 0;
}
@@ -352,79 +296,120 @@ static long install_equiv_cpu_table(void *buf, unsigned long size, long offset)
return 0;
}
- memset(equiv_cpu_table, 0, size);
- memcpy(equiv_cpu_table, &buf_pos[3], size);
+ buf += UCODE_HEADER_SIZE;
+ if (get_ucode_data(equiv_cpu_table, buf, size)) {
+ vfree(equiv_cpu_table);
+ return 0;
+ }
- return size + 12; /* add header length */
+ return size + UCODE_HEADER_SIZE; /* add header length */
+#undef UCODE_HEADER_SIZE
}
-/* fake device for request_firmware */
-extern struct platform_device *microcode_pdev;
-
-static int cpu_request_microcode_amd(int cpu)
+static void free_equiv_cpu_table(void)
{
- char name[30];
- const struct firmware *firmware;
- void *buf;
- unsigned int *buf_pos;
- unsigned long size;
- long offset = 0;
- int error;
- void *mc;
-
- /* We should bind the task to the CPU */
- BUG_ON(cpu != raw_smp_processor_id());
-
- sprintf(name, "amd-ucode/microcode_amd.bin");
- error = request_firmware(&firmware, "amd-ucode/microcode_amd.bin",
- µcode_pdev->dev);
- if (error) {
- printk(KERN_ERR "microcode: ucode data file %s load failed\n",
- name);
- return error;
- }
-
- buf_pos = (unsigned int *)firmware->data;
- buf = (void *)firmware->data;
- size = firmware->size;
-
- if (buf_pos[0] != UCODE_MAGIC) {
- printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n");
- return -EINVAL;
+ if (equiv_cpu_table) {
+ vfree(equiv_cpu_table);
+ equiv_cpu_table = NULL;
}
+}
- offset = install_equiv_cpu_table(buf, buf_pos[2], offset);
+static int generic_load_microcode(int cpu, void *data, size_t size,
+ int (*get_ucode_data)(void *, const void *, size_t))
+{
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ u8 *ucode_ptr = data, *new_mc = NULL, *mc;
+ int new_rev = uci->cpu_sig.rev;
+ unsigned int leftover;
+ unsigned long offset;
+ offset = install_equiv_cpu_table(ucode_ptr, get_ucode_data);
if (!offset) {
printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
return -EINVAL;
}
- while ((offset =
- get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) {
- error = get_matching_microcode_amd(mc, cpu);
- if (error < 0)
+ ucode_ptr += offset;
+ leftover = size - offset;
+
+ while (leftover) {
+ unsigned int mc_size;
+ struct microcode_header_amd *mc_header;
+
+ mc = get_next_ucode(ucode_ptr, leftover, get_ucode_data, &mc_size);
+ if (!mc)
break;
- /*
- * It's possible the data file has multiple matching ucode,
- * lets keep searching till the latest version
- */
- if (error == 1) {
- apply_microcode_amd(cpu);
- error = 0;
- }
- vfree(mc);
+
+ mc_header = (struct microcode_header_amd *)mc;
+ if (get_matching_microcode(cpu, mc, new_rev)) {
+ if (new_mc)
+ vfree(new_mc);
+ new_rev = mc_header->patch_id;
+ new_mc = mc;
+ } else
+ vfree(mc);
+
+ ucode_ptr += mc_size;
+ leftover -= mc_size;
}
- if (offset > 0) {
- vfree(mc);
- vfree(equiv_cpu_table);
- equiv_cpu_table = NULL;
+
+ if (new_mc) {
+ if (!leftover) {
+ if (uci->mc.mc_amd)
+ vfree(uci->mc.mc_amd);
+ uci->mc.mc_amd = (struct microcode_amd *)new_mc;
+ pr_debug("microcode: CPU%d found a matching microcode update with"
+ " version 0x%x (current=0x%x)\n",
+ cpu, uci->mc.mc_amd->hdr.patch_id, uci->cpu_sig.rev);
+ } else
+ vfree(new_mc);
+ }
+
+ free_equiv_cpu_table();
+
+ return (int)leftover;
+}
+
+static int get_ucode_fw(void *to, const void *from, size_t n)
+{
+ memcpy(to, from, n);
+ return 0;
+}
+
+static int request_microcode_fw(int cpu, struct device *device)
+{
+ const char *fw_name = "amd-ucode/microcode_amd.bin";
+ const struct firmware *firmware;
+ int ret;
+
+ /* We should bind the task to the CPU */
+ BUG_ON(cpu != raw_smp_processor_id());
+
+ ret = request_firmware(&firmware, fw_name, device);
+ if (ret) {
+ printk(KERN_ERR "microcode: ucode data file %s load failed\n", fw_name);
+ return ret;
}
- if (offset < 0)
- error = offset;
+
+ ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size,
+ &get_ucode_fw);
+
release_firmware(firmware);
- return error;
+ return ret;
+}
+
+static int get_ucode_user(void *to, const void *from, size_t n)
+{
+ return copy_from_user(to, from, n);
+}
+
+static int request_microcode_user(int cpu, const void __user *buf, size_t size)
+{
+ /* We should bind the task to the CPU */
+ BUG_ON(cpu != raw_smp_processor_id());
+
+ return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user);
}
static void microcode_fini_cpu_amd(int cpu)
@@ -436,10 +421,8 @@ static void microcode_fini_cpu_amd(int cpu)
}
static struct microcode_ops microcode_amd_ops = {
- .get_next_ucode = get_next_ucode_amd,
- .get_matching_microcode = get_matching_microcode_amd,
- .microcode_sanity_check = NULL,
- .cpu_request_microcode = cpu_request_microcode_amd,
+ .request_microcode_user = request_microcode_user,
+ .request_microcode_fw = request_microcode_fw,
.collect_cpu_info = collect_cpu_info_amd,
.apply_microcode = apply_microcode_amd,
.microcode_fini_cpu = microcode_fini_cpu_amd,
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index c9b5320..f05a37e 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -70,8 +70,9 @@
* Fix sigmatch() macro to handle old CPUs with pf == 0.
* Thanks to Stuart Swales for pointing out this bug.
*/
-
-/* #define DEBUG */ /* pr_debug */
+#if 0
+#define DEBUG /* pr_debug */
+#endif
#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -155,15 +156,15 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
return 0;
}
-static inline int microcode_update_match(int cpu_num,
- struct microcode_header_intel *mc_header, int sig, int pf)
+static inline int update_match_cpu(struct cpu_signature *csig, int sig, int pf)
{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+ return (!sigmatch(sig, csig->sig, pf, csig->pf)) ? 0 : 1;
+}
- if (!sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf)
- || mc_header->rev <= uci->cpu_sig.rev)
- return 0;
- return 1;
+static inline int
+update_match_revision(struct microcode_header_intel *mc_header, int rev)
+{
+ return (mc_header->rev <= rev) ? 0 : 1;
}
static int microcode_sanity_check(void *mc)
@@ -248,51 +249,36 @@ static int microcode_sanity_check(void *mc)
/*
* return 0 - no update found
* return 1 - found update
- * return < 0 - error
*/
-static int get_matching_microcode(void *mc, int cpu)
+static int
+get_matching_microcode(struct cpu_signature *cpu_sig, void *mc, int rev)
{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
struct microcode_header_intel *mc_header = mc;
struct extended_sigtable *ext_header;
unsigned long total_size = get_totalsize(mc_header);
int ext_sigcount, i;
struct extended_signature *ext_sig;
- void *new_mc;
- if (microcode_update_match(cpu, mc_header,
- mc_header->sig, mc_header->pf))
- goto find;
+ if (!update_match_revision(mc_header, rev))
+ return 0;
+
+ if (update_match_cpu(cpu_sig, mc_header->sig, mc_header->pf))
+ return 1;
+ /* Look for ext. headers: */
if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
return 0;
ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
ext_sigcount = ext_header->count;
ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
+
for (i = 0; i < ext_sigcount; i++) {
- if (microcode_update_match(cpu, mc_header,
- ext_sig->sig, ext_sig->pf))
- goto find;
+ if (update_match_cpu(cpu_sig, ext_sig->sig, ext_sig->pf))
+ return 1;
ext_sig++;
}
return 0;
-find:
- pr_debug("microcode: CPU%d found a matching microcode update with"
- " version 0x%x (current=0x%x)\n",
- cpu, mc_header->rev, uci->cpu_sig.rev);
- new_mc = vmalloc(total_size);
- if (!new_mc) {
- printk(KERN_ERR "microcode: error! Can not allocate memory\n");
- return -ENOMEM;
- }
-
- /* free previous update file */
- vfree(uci->mc.mc_intel);
-
- memcpy(new_mc, mc, total_size);
- uci->mc.mc_intel = new_mc;
- return 1;
}
static void apply_microcode(int cpu)
@@ -300,7 +286,7 @@ static void apply_microcode(int cpu)
unsigned long flags;
unsigned int val[2];
int cpu_num = raw_smp_processor_id();
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
/* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu);
@@ -338,116 +324,107 @@ static void apply_microcode(int cpu)
uci->cpu_sig.rev = val[1];
}
-#ifdef CONFIG_MICROCODE_OLD_INTERFACE
-extern void __user *user_buffer; /* user area microcode data buffer */
-extern unsigned int user_buffer_size; /* it's size */
-
-static long get_next_ucode(void **mc, long offset)
+static int generic_load_microcode(int cpu, void *data, size_t size,
+ int (*get_ucode_data)(void *, const void *, size_t))
{
- struct microcode_header_intel mc_header;
- unsigned long total_size;
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ u8 *ucode_ptr = data, *new_mc = NULL, *mc;
+ int new_rev = uci->cpu_sig.rev;
+ unsigned int leftover = size;
- /* No more data */
- if (offset >= user_buffer_size)
- return 0;
- if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- return -EFAULT;
- }
- total_size = get_totalsize(&mc_header);
- if (offset + total_size > user_buffer_size) {
- printk(KERN_ERR "microcode: error! Bad total size in microcode "
- "data file\n");
- return -EINVAL;
- }
- *mc = vmalloc(total_size);
- if (!*mc)
- return -ENOMEM;
- if (copy_from_user(*mc, user_buffer + offset, total_size)) {
- printk(KERN_ERR "microcode: error! Can not read user data\n");
- vfree(*mc);
- return -EFAULT;
- }
- return offset + total_size;
-}
-#endif
+ while (leftover) {
+ struct microcode_header_intel mc_header;
+ unsigned int mc_size;
-static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
- unsigned long size, long offset)
-{
- struct microcode_header_intel *mc_header;
- unsigned long total_size;
+ if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
+ break;
- /* No more data */
- if (offset >= size)
- return 0;
- mc_header = (struct microcode_header_intel *)(buf + offset);
- total_size = get_totalsize(mc_header);
+ mc_size = get_totalsize(&mc_header);
+ if (!mc_size || mc_size > leftover) {
+ printk(KERN_ERR "microcode: error!"
+ "Bad data in microcode data file\n");
+ break;
+ }
- if (offset + total_size > size) {
- printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
- return -EINVAL;
+ mc = vmalloc(mc_size);
+ if (!mc)
+ break;
+
+ if (get_ucode_data(mc, ucode_ptr, mc_size) ||
+ microcode_sanity_check(mc) < 0) {
+ vfree(mc);
+ break;
+ }
+
+ if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) {
+ if (new_mc)
+ vfree(new_mc);
+ new_rev = mc_header.rev;
+ new_mc = mc;
+ } else
+ vfree(mc);
+
+ ucode_ptr += mc_size;
+ leftover -= mc_size;
}
- *mc = vmalloc(total_size);
- if (!*mc) {
- printk(KERN_ERR "microcode: error! Can not allocate memory\n");
- return -ENOMEM;
+ if (new_mc) {
+ if (!leftover) {
+ if (uci->mc.mc_intel)
+ vfree(uci->mc.mc_intel);
+ uci->mc.mc_intel = (struct microcode_intel *)new_mc;
+ pr_debug("microcode: CPU%d found a matching microcode update with"
+ " version 0x%x (current=0x%x)\n",
+ cpu, uci->mc.mc_intel->hdr.rev, uci->cpu_sig.rev);
+ } else
+ vfree(new_mc);
}
- memcpy(*mc, buf + offset, total_size);
- return offset + total_size;
+
+ return (int)leftover;
}
-/* fake device for request_firmware */
-extern struct platform_device *microcode_pdev;
+static int get_ucode_fw(void *to, const void *from, size_t n)
+{
+ memcpy(to, from, n);
+ return 0;
+}
-static int cpu_request_microcode(int cpu)
+static int request_microcode_fw(int cpu, struct device *device)
{
char name[30];
struct cpuinfo_x86 *c = &cpu_data(cpu);
const struct firmware *firmware;
- const u8 *buf;
- unsigned long size;
- long offset = 0;
- int error;
- void *mc;
+ int ret;
/* We should bind the task to the CPU */
BUG_ON(cpu != raw_smp_processor_id());
sprintf(name, "intel-ucode/%02x-%02x-%02x",
c->x86, c->x86_model, c->x86_mask);
- error = request_firmware(&firmware, name, µcode_pdev->dev);
- if (error) {
+ ret = request_firmware(&firmware, name, device);
+ if (ret) {
pr_debug("microcode: data file %s load failed\n", name);
- return error;
+ return ret;
}
- buf = firmware->data;
- size = firmware->size;
- while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
- > 0) {
- error = microcode_sanity_check(mc);
- if (error)
- break;
- error = get_matching_microcode(mc, cpu);
- if (error < 0)
- break;
- /*
- * It's possible the data file has multiple matching ucode,
- * lets keep searching till the latest version
- */
- if (error == 1) {
- apply_microcode(cpu);
- error = 0;
- }
- vfree(mc);
- }
- if (offset > 0)
- vfree(mc);
- if (offset < 0)
- error = offset;
+
+ ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size,
+ &get_ucode_fw);
+
release_firmware(firmware);
- return error;
+ return ret;
+}
+
+static int get_ucode_user(void *to, const void *from, size_t n)
+{
+ return copy_from_user(to, from, n);
+}
+
+static int request_microcode_user(int cpu, const void __user *buf, size_t size)
+{
+ /* We should bind the task to the CPU */
+ BUG_ON(cpu != raw_smp_processor_id());
+
+ return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user);
}
static void microcode_fini_cpu(int cpu)
@@ -459,10 +436,8 @@ static void microcode_fini_cpu(int cpu)
}
static struct microcode_ops microcode_intel_ops = {
- .get_next_ucode = get_next_ucode,
- .get_matching_microcode = get_matching_microcode,
- .microcode_sanity_check = microcode_sanity_check,
- .cpu_request_microcode = cpu_request_microcode,
+ .request_microcode_user = request_microcode_user,
+ .request_microcode_fw = request_microcode_fw,
.collect_cpu_info = collect_cpu_info,
.apply_microcode = apply_microcode,
.microcode_fini_cpu = microcode_fini_cpu,
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index 7ceff48..e2887fa 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -5,17 +5,16 @@ extern int microcode_init(void *opaque, struct module *module);
extern void microcode_exit(void);
struct cpu_signature;
+struct device;
struct microcode_ops {
- long (*get_next_ucode)(void **mc, long offset);
- long (*microcode_get_next_ucode)(void **mc, long offset);
- int (*get_matching_microcode)(void *mc, int cpu);
- int (*microcode_sanity_check)(void *mc);
- int (*cpu_request_microcode)(int cpu);
- int (*collect_cpu_info)(int cpu_num, struct cpu_signature *csig);
- void (*apply_microcode)(int cpu);
- void (*microcode_fini_cpu)(int cpu);
- void (*clear_patch)(void *data);
+ int (*request_microcode_user) (int cpu, const void __user *buf, size_t size);
+ int (*request_microcode_fw) (int cpu, struct device *device);
+
+ void (*apply_microcode) (int cpu);
+
+ int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
+ void (*microcode_fini_cpu) (int cpu);
};
struct microcode_header_intel {
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [x86-tip, patch] rework of the microcode splitup
2008-09-14 9:14 [x86-tip, patch] rework of the microcode splitup Dmitry Adamushko
@ 2008-09-14 9:18 ` Dmitry Adamushko
2008-09-14 12:55 ` Ingo Molnar
1 sibling, 0 replies; 6+ messages in thread
From: Dmitry Adamushko @ 2008-09-14 9:18 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Peter Oruba, Tigran Aivazian, LKML
[ forgot to add my SOB line ]
>
> From: Dmitry Adamushko <dmitry.adamushko@gmail.com>
> Subject: x86-microcode, rework of the microcode splitup
>
> x86, microcode rework, v2
>
> this is a rework of the microcode splitup in tip/x86/microcode
>
> This new interface is supposed to be cleaner and better maintainability-wise;
>
> 4 files changed, 304 insertions(+), 362 deletions(-)
Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com>
>
>
> --- a/arch/x86/kernel/microcode.c
> +++ b/arch/x86/kernel/microcode.c
> @@ -70,8 +70,9 @@
> * Fix sigmatch() macro to handle old CPUs with pf == 0.
> * Thanks to Stuart Swales for pointing out this bug.
> */
> -
[ ... ]
--
Best regards,
Dmitry Adamushko
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [x86-tip, patch] rework of the microcode splitup
2008-09-14 9:14 [x86-tip, patch] rework of the microcode splitup Dmitry Adamushko
2008-09-14 9:18 ` Dmitry Adamushko
@ 2008-09-14 12:55 ` Ingo Molnar
2008-09-16 21:43 ` Dmitry Adamushko
1 sibling, 1 reply; 6+ messages in thread
From: Ingo Molnar @ 2008-09-14 12:55 UTC (permalink / raw)
To: Dmitry Adamushko; +Cc: Peter Oruba, Tigran Aivazian, LKML
* Dmitry Adamushko <dmitry.adamushko@gmail.com> wrote:
> Ingo, Peter,
>
>
> this version is slightly different from the current one in -tip (added
> missing vfree()).
i've added the delta patch below. I removed the #if 0's as they are
ugly. (and editing the file to enable debug printouts is easy anyway)
regarding this FIXME:
+ /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */
total_size = (unsigned long) (hdr[4] + (hdr[5] << 8));
please just use get_totalsize(hdr) and get rid of the fixme that way :)
Ingo
------------------>
>From a1c75cc5018f17ff6d80ce45a13435b1536f76db Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Sun, 14 Sep 2008 14:50:26 +0200
Subject: [PATCH] x86, microcode rework, v2, fix
based on patch from Dmitry Adamushko.
- add missing vfree()
- update debug printks
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/kernel/microcode.c | 4 +---
arch/x86/kernel/microcode_amd.c | 6 ++++--
arch/x86/kernel/microcode_intel.c | 4 ++--
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 902dada..0c2634f 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -70,8 +70,6 @@
* Fix sigmatch() macro to handle old CPUs with pf == 0.
* Thanks to Stuart Swales for pointing out this bug.
*/
-
-/* #define DEBUG pr_debug */
#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -396,7 +394,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
if (!cpu_online(cpu))
return 0;
- pr_debug("microcode: CPU%d resumed\n", cpu);
+
/* only CPU 0 will apply ucode here */
microcode_update_cpu(0);
return 0;
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 6815837..48aec9f 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -92,7 +92,7 @@ static int get_matching_microcode(int cpu, void *mc, int rev)
unsigned int i = 0;
/*
- * dimm: do we need this? Why an update via /dev/... is different
+ * FIXME! dimm: do we need this? Why an update via /dev/... is different
* from the one via firmware?
*
* This is a tricky part. We might be called from a write operation
@@ -246,7 +246,7 @@ static void * get_next_ucode(u8 *buf, unsigned int size,
return NULL;
}
- /* Why not by means of get_totalsize(hdr)? */
+ /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */
total_size = (unsigned long) (hdr[4] + (hdr[5] << 8));
printk(KERN_INFO "microcode: size %u, total_size %u\n",
@@ -342,6 +342,8 @@ static int generic_load_microcode(int cpu, void *data, size_t size,
mc_header = (struct microcode_header_amd *)mc;
if (get_matching_microcode(cpu, mc, new_rev)) {
+ if (new_mc)
+ vfree(new_mc);
new_rev = mc_header->patch_id;
new_mc = mc;
} else
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index f4930b5..48ed3ce 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -70,8 +70,6 @@
* Fix sigmatch() macro to handle old CPUs with pf == 0.
* Thanks to Stuart Swales for pointing out this bug.
*/
-
-/* #define DEBUG */ /* pr_debug */
#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -356,6 +354,8 @@ static int generic_load_microcode(int cpu, void *data, size_t size,
}
if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) {
+ if (new_mc)
+ vfree(new_mc);
new_rev = mc_header.rev;
new_mc = mc;
} else
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [x86-tip, patch] rework of the microcode splitup
2008-09-14 12:55 ` Ingo Molnar
@ 2008-09-16 21:43 ` Dmitry Adamushko
2001-09-16 22:00 ` [PATCH] x86, microcode rework, v2, renaming Peter Oruba
2008-09-17 13:39 ` [PATCH] x86, microcode rework, v2, renaming cont Peter Oruba
0 siblings, 2 replies; 6+ messages in thread
From: Dmitry Adamushko @ 2008-09-16 21:43 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Peter Oruba, Tigran Aivazian, LKML
2008/9/14 Ingo Molnar <mingo@elte.hu>:
>
> * Dmitry Adamushko <dmitry.adamushko@gmail.com> wrote:
>
>> Ingo, Peter,
>>
>>
>> this version is slightly different from the current one in -tip (added
>> missing vfree()).
>
> i've added the delta patch below. I removed the #if 0's as they are
> ugly. (and editing the file to enable debug printouts is easy anyway)
ok, thanks.
>
> regarding this FIXME:
>
> + /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */
> total_size = (unsigned long) (hdr[4] + (hdr[5] << 8));
>
> please just use get_totalsize(hdr) and get rid of the fixme that way :)
The thing is that it looks like there are 2 headers that contain the size.
'hdr' taken by get_totalsize() is not the same as 'hdr' from which
total_size is calculated here. :^)
A quick search didn't reveal any docs describing the AMD microcode
file format, so I'd rather leave it up to Peter.
>
> Ingo
>
--
Best regards,
Dmitry Adamushko
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] x86, microcode rework, v2, renaming cont.
2008-09-16 21:43 ` Dmitry Adamushko
2001-09-16 22:00 ` [PATCH] x86, microcode rework, v2, renaming Peter Oruba
@ 2008-09-17 13:39 ` Peter Oruba
1 sibling, 0 replies; 6+ messages in thread
From: Peter Oruba @ 2008-09-17 13:39 UTC (permalink / raw)
To: Dmitry Adamushko, Ingo Molnar; +Cc: Tigran Aivazian, LKML
Renaming based on patch from Dmitry Adamushko.
Further clarification by renaming define and variable related to
microcode container file.
Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
arch/x86/kernel/microcode_amd.c | 17 ++++++++---------
1 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 8d97840..113be63 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -233,21 +233,20 @@ static void * get_next_ucode(u8 *buf, unsigned int size,
unsigned int *mc_size)
{
unsigned int total_size;
-#define UCODE_UNKNOWN_HDR 8
- u8 hdr[UCODE_UNKNOWN_HDR];
+#define UCODE_CONTAINER_SECTION_HDR 8
+ u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
void *mc;
- if (get_ucode_data(hdr, buf, UCODE_UNKNOWN_HDR))
+ if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR))
return NULL;
- if (hdr[0] != UCODE_UCODE_TYPE) {
+ if (section_hdr[0] != UCODE_UCODE_TYPE) {
printk(KERN_ERR "microcode: error! "
"Wrong microcode payload type field\n");
return NULL;
}
- /* FIXME! dimm: Why not by means of get_totalsize(hdr)? */
- total_size = (unsigned long) (hdr[4] + (hdr[5] << 8));
+ total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8));
printk(KERN_INFO "microcode: size %u, total_size %u\n",
size, total_size);
@@ -260,13 +259,13 @@ static void * get_next_ucode(u8 *buf, unsigned int size,
mc = vmalloc(UCODE_MAX_SIZE);
if (mc) {
memset(mc, 0, UCODE_MAX_SIZE);
- if (get_ucode_data(mc, buf + UCODE_UNKNOWN_HDR, total_size)) {
+ if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size)) {
vfree(mc);
mc = NULL;
} else
- *mc_size = total_size + UCODE_UNKNOWN_HDR;
+ *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
}
-#undef UCODE_UNKNOWN_HDR
+#undef UCODE_CONTAINER_SECTION_HDR
return mc;
}
--
1.5.4.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-09-17 14:12 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-14 9:14 [x86-tip, patch] rework of the microcode splitup Dmitry Adamushko
2008-09-14 9:18 ` Dmitry Adamushko
2008-09-14 12:55 ` Ingo Molnar
2008-09-16 21:43 ` Dmitry Adamushko
2001-09-16 22:00 ` [PATCH] x86, microcode rework, v2, renaming Peter Oruba
2008-09-17 13:39 ` [PATCH] x86, microcode rework, v2, renaming cont Peter Oruba
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.