[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Merge



# HG changeset patch
# User Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
# Date 1322760408 0
# Node ID 3b409f65abae294b8ba9b6b34c5324854d780514
# Parent  b6962c4b0dfd29b3fd1d02e6e0074ae871d99ec5
# Parent  f30a33c5b5bd1e2b0bdffa3a649490157e451a4e
Merge
---


diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/Makefile     Thu Dec 01 17:26:48 2011 +0000
@@ -30,9 +30,10 @@
 obj-y += msi.o
 obj-y += ioport_emulate.o
 obj-y += irq.o
-obj-y += microcode.o
 obj-y += microcode_amd.o
 obj-y += microcode_intel.o
+# This must come after the vendor specific files.
+obj-y += microcode.o
 obj-y += mm.o
 obj-y += mpparse.o
 obj-y += nmi.o
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/efi/boot.c
--- a/xen/arch/x86/efi/boot.c   Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/efi/boot.c   Thu Dec 01 17:26:48 2011 +0000
@@ -49,6 +49,7 @@
 static struct file __initdata cfg;
 static struct file __initdata kernel;
 static struct file __initdata ramdisk;
+static struct file __initdata ucode;
 static struct file __initdata xsm;
 
 static multiboot_info_t __initdata mbi = {
@@ -174,6 +175,8 @@
         efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
     if ( ramdisk.addr )
         efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
+    if ( ucode.addr )
+        efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
     if ( xsm.addr )
         efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
 
@@ -806,6 +809,17 @@
         efi_bs->FreePool(name.w);
     }
 
+    name.s = get_value(&cfg, section.s, "ucode");
+    if ( !name.s )
+        name.s = get_value(&cfg, "global", "ucode");
+    if ( name.s )
+    {
+        microcode_set_module(mbi.mods_count);
+        split_value(name.s);
+        read_file(dir_handle, s2w(&name), &ucode);
+        efi_bs->FreePool(name.w);
+    }
+
     name.s = get_value(&cfg, section.s, "xsm");
     if ( name.s )
     {
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Thu Dec 01 17:26:48 2011 +0000
@@ -1823,12 +1823,16 @@
     return 0;
 }
 
-/* We leave this function holding a lock on the p2m entry */
+/* On non-NULL return, we leave this function holding an additional 
+ * ref on the underlying mfn, if any */
 static void *__hvm_map_guest_frame(unsigned long gfn, bool_t writable)
 {
+    void *map;
     unsigned long mfn;
     p2m_type_t p2mt;
+    struct page_info *pg;
     struct domain *d = current->domain;
+    int rc;
 
     mfn = mfn_x(writable
                 ? get_gfn_unshare(d, gfn, &p2mt)
@@ -1850,7 +1854,21 @@
     if ( writable )
         paging_mark_dirty(d, mfn);
 
-    return map_domain_page(mfn);
+    /* Get a ref on the page, considering that it could be shared */
+    pg = mfn_to_page(mfn);
+    rc = get_page(pg, d);
+    if ( !rc && !writable )
+        /* Page could be shared */
+        rc = get_page(pg, dom_cow);
+    if ( !rc )
+    {
+        put_gfn(d, gfn);
+        return NULL;
+    }
+
+    map = map_domain_page(mfn);
+    put_gfn(d, gfn);
+    return map;
 }
 
 void *hvm_map_guest_frame_rw(unsigned long gfn)
@@ -1866,11 +1884,16 @@
 void hvm_unmap_guest_frame(void *p)
 {
     if ( p )
+    {
+        unsigned long mfn = domain_page_map_to_mfn(p);
         unmap_domain_page(p);
+        put_page(mfn_to_page(mfn));
+    }
 }
 
-static void *hvm_map_entry(unsigned long va, unsigned long *gfn)
+static void *hvm_map_entry(unsigned long va)
 {
+    unsigned long gfn;
     uint32_t pfec;
     char *v;
 
@@ -1887,11 +1910,11 @@
      * treat it as a kernel-mode read (i.e. no access checks).
      */
     pfec = PFEC_page_present;
-    *gfn = paging_gva_to_gfn(current, va, &pfec);
+    gfn = paging_gva_to_gfn(current, va, &pfec);
     if ( (pfec == PFEC_page_paged) || (pfec == PFEC_page_shared) )
         goto fail;
 
-    v = hvm_map_guest_frame_rw(*gfn);
+    v = hvm_map_guest_frame_rw(gfn);
     if ( v == NULL )
         goto fail;
 
@@ -1902,11 +1925,9 @@
     return NULL;
 }
 
-static void hvm_unmap_entry(void *p, unsigned long gfn)
+static void hvm_unmap_entry(void *p)
 {
     hvm_unmap_guest_frame(p);
-    if ( p && (gfn != INVALID_GFN) )
-        put_gfn(current->domain, gfn);
 }
 
 static int hvm_load_segment_selector(
@@ -1918,7 +1939,6 @@
     int fault_type = TRAP_invalid_tss;
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     struct vcpu *v = current;
-    unsigned long pdesc_gfn = INVALID_GFN;
 
     if ( regs->eflags & X86_EFLAGS_VM )
     {
@@ -1952,7 +1972,7 @@
     if ( ((sel & 0xfff8) + 7) > desctab.limit )
         goto fail;
 
-    pdesc = hvm_map_entry(desctab.base + (sel & 0xfff8), &pdesc_gfn);
+    pdesc = hvm_map_entry(desctab.base + (sel & 0xfff8));
     if ( pdesc == NULL )
         goto hvm_map_fail;
 
@@ -2012,7 +2032,7 @@
     desc.b |= 0x100;
 
  skip_accessed_flag:
-    hvm_unmap_entry(pdesc, pdesc_gfn);
+    hvm_unmap_entry(pdesc);
 
     segr.base = (((desc.b <<  0) & 0xff000000u) |
                  ((desc.b << 16) & 0x00ff0000u) |
@@ -2028,7 +2048,7 @@
     return 0;
 
  unmap_and_fail:
-    hvm_unmap_entry(pdesc, pdesc_gfn);
+    hvm_unmap_entry(pdesc);
  fail:
     hvm_inject_exception(fault_type, sel & 0xfffc, 0);
  hvm_map_fail:
@@ -2043,7 +2063,7 @@
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     struct segment_register gdt, tr, prev_tr, segr;
     struct desc_struct *optss_desc = NULL, *nptss_desc = NULL, tss_desc;
-    unsigned long eflags, optss_gfn = INVALID_GFN, nptss_gfn = INVALID_GFN;
+    unsigned long eflags;
     int exn_raised, rc;
     struct {
         u16 back_link,__blh;
@@ -2069,11 +2089,11 @@
         goto out;
     }
 
-    optss_desc = hvm_map_entry(gdt.base + (prev_tr.sel & 0xfff8), &optss_gfn);
+    optss_desc = hvm_map_entry(gdt.base + (prev_tr.sel & 0xfff8)); 
     if ( optss_desc == NULL )
         goto out;
 
-    nptss_desc = hvm_map_entry(gdt.base + (tss_sel & 0xfff8), &nptss_gfn);
+    nptss_desc = hvm_map_entry(gdt.base + (tss_sel & 0xfff8)); 
     if ( nptss_desc == NULL )
         goto out;
 
@@ -2238,8 +2258,8 @@
     }
 
  out:
-    hvm_unmap_entry(optss_desc, optss_gfn);
-    hvm_unmap_entry(nptss_desc, nptss_gfn);
+    hvm_unmap_entry(optss_desc);
+    hvm_unmap_entry(nptss_desc);
 }
 
 #define HVMCOPY_from_guest (0u<<0)
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/hvm/svm/nestedsvm.c
--- a/xen/arch/x86/hvm/svm/nestedsvm.c  Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c  Thu Dec 01 17:26:48 2011 +0000
@@ -81,10 +81,6 @@
         if (nv->nv_vvmcx == NULL)
             return 0;
         nv->nv_vvmcxaddr = vmcbaddr;
-        /* put_gfn here even though the map survives beyond this caller.
-         * The map can likely survive beyond a hypervisor exit, thus we
-         * need to put the gfn */
-        put_gfn(current->domain, vmcbaddr >> PAGE_SHIFT);
     }
 
     return 1;
@@ -358,7 +354,6 @@
     ioport_80 = test_bit(0x80, ns_viomap);
     ioport_ed = test_bit(0xed, ns_viomap);
     hvm_unmap_guest_frame(ns_viomap);
-    put_gfn(current->domain, svm->ns_iomap_pa >> PAGE_SHIFT);
 
     svm->ns_iomap = nestedhvm_vcpu_iomap_get(ioport_80, ioport_ed);
 
@@ -889,7 +884,6 @@
 
     enabled = test_bit(port, io_bitmap);
     hvm_unmap_guest_frame(io_bitmap);
-    put_gfn(current->domain, gfn);
 
     if (!enabled)
         return NESTEDHVM_VMEXIT_HOST;
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/hvm/vmx/vvmx.c
--- a/xen/arch/x86/hvm/vmx/vvmx.c       Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/hvm/vmx/vvmx.c       Thu Dec 01 17:26:48 2011 +0000
@@ -560,10 +560,7 @@
     if (nvmx->iobitmap[index])
         hvm_unmap_guest_frame (nvmx->iobitmap[index]); 
     gpa = __get_vvmcs(vcpu_nestedhvm(v).nv_vvmcx, vmcs_reg);
-    nvmx->iobitmap[index] = hvm_map_guest_frame_ro (gpa >> PAGE_SHIFT);
-    /* See comment in nestedsvm_vmcb_map re putting this gfn and 
-     * liveness of the map it backs */
-    put_gfn(current->domain, gpa >> PAGE_SHIFT);
+    nvmx->iobitmap[index] = hvm_map_guest_frame_ro(gpa >> PAGE_SHIFT);
 }
 
 static inline void map_io_bitmap_all(struct vcpu *v)
@@ -1138,12 +1135,9 @@
 
     if ( nvcpu->nv_vvmcxaddr == VMCX_EADDR )
     {
-        nvcpu->nv_vvmcx = hvm_map_guest_frame_rw (gpa >> PAGE_SHIFT);
+        nvcpu->nv_vvmcx = hvm_map_guest_frame_rw(gpa >> PAGE_SHIFT);
         nvcpu->nv_vvmcxaddr = gpa;
         map_io_bitmap_all (v);
-        /* See comment in nestedsvm_vmcb_map regarding putting this 
-         * gfn and liveness of the map that uses it */
-        put_gfn(current->domain, gpa >> PAGE_SHIFT);
     }
 
     vmreturn(regs, VMSUCCEED);
@@ -1205,7 +1199,6 @@
         if ( vvmcs ) 
             __set_vvmcs(vvmcs, NVMX_LAUNCH_STATE, 0);
         hvm_unmap_guest_frame(vvmcs);
-        put_gfn(current->domain, gpa >> PAGE_SHIFT);
     }
 
     vmreturn(regs, VMSUCCEED);
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/microcode.c
--- a/xen/arch/x86/microcode.c  Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/microcode.c  Thu Dec 01 17:26:48 2011 +0000
@@ -22,20 +22,56 @@
  */
 
 #include <xen/config.h>
+#include <xen/cpu.h>
 #include <xen/lib.h>
 #include <xen/kernel.h>
 #include <xen/init.h>
+#include <xen/notifier.h>
 #include <xen/sched.h>
 #include <xen/smp.h>
+#include <xen/softirq.h>
 #include <xen/spinlock.h>
+#include <xen/tasklet.h>
 #include <xen/guest_access.h>
 
-#include <asm/current.h>
 #include <asm/msr.h>
-#include <asm/uaccess.h>
 #include <asm/processor.h>
+#include <asm/setup.h>
 #include <asm/microcode.h>
 
+static module_t __initdata ucode_mod;
+static void *(*__initdata ucode_mod_map)(const module_t *);
+static unsigned int __initdata ucode_mod_idx;
+static bool_t __initdata ucode_mod_forced;
+static cpumask_t __initdata init_mask;
+
+void __init microcode_set_module(unsigned int idx)
+{
+    ucode_mod_idx = idx;
+    ucode_mod_forced = 1;
+}
+
+static void __init parse_ucode(char *s)
+{
+    if ( !ucode_mod_forced )
+        ucode_mod_idx = simple_strtoul(s, NULL, 0);
+}
+custom_param("ucode", parse_ucode);
+
+void __init microcode_grab_module(
+    unsigned long *module_map,
+    const multiboot_info_t *mbi,
+    void *(*map)(const module_t *))
+{
+    module_t *mod = (module_t *)__va(mbi->mods_addr);
+
+    if ( !ucode_mod_idx || ucode_mod_idx >= mbi->mods_count ||
+         !__test_and_clear_bit(ucode_mod_idx, module_map) )
+        return;
+    ucode_mod = mod[ucode_mod_idx];
+    ucode_mod_map = map;
+}
+
 const struct microcode_ops *microcode_ops;
 
 static DEFINE_SPINLOCK(microcode_mutex);
@@ -69,30 +105,50 @@
     int err;
     struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
     struct cpu_signature nsig;
+    unsigned int cpu2;
 
-    if ( !uci->mc.mc_valid )
-        return -EIO;
+    spin_lock(&microcode_mutex);
 
-    /*
-     * Let's verify that the 'cached' ucode does belong
-     * to this cpu (a bit of paranoia):
-     */
-    err = microcode_ops->collect_cpu_info(cpu, &nsig);
+    err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
     if ( err )
     {
-        microcode_fini_cpu(cpu);
+        __microcode_fini_cpu(cpu);
+        spin_unlock(&microcode_mutex);
         return err;
     }
 
-    if ( microcode_ops->microcode_resume_match(cpu, &nsig) )
+    if ( uci->mc.mc_valid )
     {
-        return microcode_ops->apply_microcode(cpu);
+        err = microcode_ops->microcode_resume_match(cpu, uci->mc.mc_valid);
+        if ( err >= 0 )
+        {
+            if ( err )
+                err = microcode_ops->apply_microcode(cpu);
+            spin_unlock(&microcode_mutex);
+            return err;
+        }
     }
-    else
+
+    nsig = uci->cpu_sig;
+    __microcode_fini_cpu(cpu);
+    uci->cpu_sig = nsig;
+
+    err = -EIO;
+    for_each_online_cpu ( cpu2 )
     {
-        microcode_fini_cpu(cpu);
-        return -EIO;
+        uci = &per_cpu(ucode_cpu_info, cpu2);
+        if ( uci->mc.mc_valid &&
+             microcode_ops->microcode_resume_match(cpu, uci->mc.mc_valid) > 0 )
+        {
+            err = microcode_ops->apply_microcode(cpu);
+            break;
+        }
     }
+
+    __microcode_fini_cpu(cpu);
+    spin_unlock(&microcode_mutex);
+
+    return err;
 }
 
 static int microcode_update_cpu(const void *buf, size_t size)
@@ -162,3 +218,78 @@
 
     return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info);
 }
+
+static void __init _do_microcode_update(unsigned long data)
+{
+    microcode_update_cpu((void *)data, ucode_mod.mod_end);
+    cpumask_set_cpu(smp_processor_id(), &init_mask);
+}
+
+static int __init microcode_init(void)
+{
+    void *data;
+    static struct tasklet __initdata tasklet;
+    unsigned int cpu;
+
+    if ( !microcode_ops || !ucode_mod.mod_end )
+        return 0;
+
+    data = ucode_mod_map(&ucode_mod);
+    if ( !data )
+        return -ENOMEM;
+
+    softirq_tasklet_init(&tasklet, _do_microcode_update, (unsigned long)data);
+
+    for_each_online_cpu ( cpu )
+    {
+        tasklet_schedule_on_cpu(&tasklet, cpu);
+        do {
+            process_pending_softirqs();
+        } while ( !cpumask_test_cpu(cpu, &init_mask) );
+    }
+
+    ucode_mod_map(NULL);
+
+    return 0;
+}
+__initcall(microcode_init);
+
+static int microcode_percpu_callback(
+    struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+    unsigned int cpu = (unsigned long)hcpu;
+
+    switch ( action )
+    {
+    case CPU_DEAD:
+        microcode_fini_cpu(cpu);
+        break;
+    }
+
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block microcode_percpu_nfb = {
+    .notifier_call = microcode_percpu_callback,
+};
+
+static int __init microcode_presmp_init(void)
+{
+    if ( microcode_ops )
+    {
+        if ( ucode_mod.mod_end )
+        {
+            void *data = ucode_mod_map(&ucode_mod);
+
+            if ( data )
+                microcode_update_cpu(data, ucode_mod.mod_end);
+
+            ucode_mod_map(NULL);
+        }
+
+        register_cpu_notifier(&microcode_percpu_nfb);
+    }
+
+    return 0;
+}
+presmp_initcall(microcode_presmp_init);
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/microcode_amd.c
--- a/xen/arch/x86/microcode_amd.c      Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/microcode_amd.c      Thu Dec 01 17:26:48 2011 +0000
@@ -23,27 +23,53 @@
 #include <xen/spinlock.h>
 
 #include <asm/msr.h>
-#include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/microcode.h>
 
 #define pr_debug(x...) ((void)0)
 
+struct equiv_cpu_entry {
+    uint32_t installed_cpu;
+    uint32_t fixed_errata_mask;
+    uint32_t fixed_errata_compare;
+    uint16_t equiv_cpu;
+    uint16_t reserved;
+} __attribute__((packed));
+
+struct microcode_header_amd {
+    uint32_t data_code;
+    uint32_t patch_id;
+    uint8_t  mc_patch_data_id[2];
+    uint8_t  mc_patch_data_len;
+    uint8_t  init_flag;
+    uint32_t mc_patch_data_checksum;
+    uint32_t nb_dev_id;
+    uint32_t sb_dev_id;
+    uint16_t processor_rev_id;
+    uint8_t  nb_rev_id;
+    uint8_t  sb_rev_id;
+    uint8_t  bios_api_rev;
+    uint8_t  reserved1[3];
+    uint32_t match_reg[8];
+} __attribute__((packed));
+
 #define UCODE_MAGIC                0x00414d44
 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
 #define UCODE_UCODE_TYPE           0x00000001
 
 #define UCODE_MAX_SIZE          (2048)
-#define DEFAULT_UCODE_DATASIZE  (896)
 #define MC_HEADER_SIZE          (sizeof(struct microcode_header_amd))
-#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
-#define DWSIZE                  (sizeof(uint32_t))
+
+struct microcode_amd {
+    struct microcode_header_amd hdr;
+    unsigned int mpb[(UCODE_MAX_SIZE - MC_HEADER_SIZE) / 4];
+    unsigned int equiv_cpu_table_size;
+    struct equiv_cpu_entry equiv_cpu_table[];
+};
 
 /* serialize access to the physical write */
 static DEFINE_SPINLOCK(microcode_update_lock);
 
-struct equiv_cpu_entry *equiv_cpu_table;
-
 static int collect_cpu_info(int cpu, struct cpu_signature *csig)
 {
     struct cpuinfo_x86 *c = &cpu_data[cpu];
@@ -65,10 +91,11 @@
     return 0;
 }
 
-static int microcode_fits(void *mc, int cpu)
+static int microcode_fits(const struct microcode_amd *mc_amd, int cpu)
 {
     struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
-    struct microcode_header_amd *mc_header = mc;
+    const struct microcode_header_amd *mc_header = &mc_amd->hdr;
+    const struct equiv_cpu_entry *equiv_cpu_table = mc_amd->equiv_cpu_table;
     unsigned int current_cpu_id;
     unsigned int equiv_cpu_id = 0x0;
     unsigned int i;
@@ -99,7 +126,7 @@
     }
 
     if ( mc_header->patch_id <= uci->cpu_sig.rev )
-        return -EINVAL;
+        return 0;
 
     printk(KERN_DEBUG "microcode: CPU%d found a matching microcode "
            "update with version 0x%x (current=0x%x)\n",
@@ -186,17 +213,15 @@
     return 0;
 }
 
-static int install_equiv_cpu_table(const void *buf, uint32_t size,
-                                   unsigned long *offset)
+static int install_equiv_cpu_table(
+    struct microcode_amd *mc_amd,
+    const uint32_t *buf_pos,
+    unsigned long *offset)
 {
-    const uint32_t *buf_pos = buf;
-    unsigned long off;
-
-    off = *offset;
-    *offset = 0;
+    uint32_t size = buf_pos[2];
 
     /* No more data */
-    if ( off >= size )
+    if ( size + 12 >= *offset )
         return -EINVAL;
 
     if ( buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE )
@@ -213,15 +238,8 @@
         return -EINVAL;
     }
 
-    equiv_cpu_table = xmalloc_bytes(size);
-    if ( equiv_cpu_table == NULL )
-    {
-        printk(KERN_ERR "microcode: error, can't allocate "
-               "memory for equiv CPU table\n");
-        return -ENOMEM;
-    }
-
-    memcpy(equiv_cpu_table, (const void *)&buf_pos[3], size);
+    memcpy(mc_amd->equiv_cpu_table, &buf_pos[3], size);
+    mc_amd->equiv_cpu_table_size = size;
 
     *offset = size + 12;       /* add header length */
 
@@ -231,11 +249,11 @@
 static int cpu_request_microcode(int cpu, const void *buf, size_t size)
 {
     const uint32_t *buf_pos;
-    unsigned long offset = 0;
+    struct microcode_amd *mc_amd, *mc_old;
+    unsigned long offset = size;
     int error = 0;
     int ret;
     struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
-    void *mc;
 
     /* We should bind the task to the CPU */
     BUG_ON(cpu != raw_smp_processor_id());
@@ -249,59 +267,85 @@
         return -EINVAL;
     }
 
-    error = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), &offset);
+    mc_amd = xmalloc_bytes(sizeof(*mc_amd) + buf_pos[2]);
+    if ( !mc_amd )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Can not allocate memory for microcode patch\n");
+        return -ENOMEM;
+    }
+
+    error = install_equiv_cpu_table(mc_amd, buf, &offset);
     if ( error )
     {
+        xfree(mc_amd);
         printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
         return -EINVAL;
     }
 
-    mc = xmalloc_bytes(UCODE_MAX_SIZE);
-    if ( mc == NULL )
-    {
-        printk(KERN_ERR "microcode: error! "
-               "Can not allocate memory for microcode patch\n");
-        error = -ENOMEM;
-        goto out;
-    }
-
+    mc_old = uci->mc.mc_amd;
     /* implicitely validates uci->mc.mc_valid */
-    uci->mc.mc_amd = mc;
+    uci->mc.mc_amd = mc_amd;
 
     /*
      * It's possible the data file has multiple matching ucode,
      * lets keep searching till the latest version
      */
-    while ( (ret = get_next_ucode_from_buffer_amd(mc, buf, size, &offset)) == 
0)
+    while ( (ret = get_next_ucode_from_buffer_amd(&mc_amd->hdr, buf, size,
+                                                  &offset)) == 0 )
     {
-        error = microcode_fits(mc, cpu);
+        error = microcode_fits(mc_amd, cpu);
         if (error <= 0)
             continue;
 
         error = apply_microcode(cpu);
         if (error == 0)
+        {
+            error = 1;
             break;
+        }
     }
 
+    if ( ret < 0 )
+        error = ret;
+
     /* On success keep the microcode patch for
      * re-apply on resume.
      */
-    if (error) {
-        xfree(mc);
-        mc = NULL;
+    if (error == 1)
+    {
+        xfree(mc_old);
+        return 0;
     }
-    uci->mc.mc_amd = mc;
-
-out:
-    xfree(equiv_cpu_table);
-    equiv_cpu_table = NULL;
+    xfree(mc_amd);
+    uci->mc.mc_amd = mc_old;
 
     return error;
 }
 
-static int microcode_resume_match(int cpu, struct cpu_signature *nsig)
+static int microcode_resume_match(int cpu, const void *mc)
 {
-    return 0;
+    struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
+    struct microcode_amd *mc_amd = uci->mc.mc_amd;
+    const struct microcode_amd *src = mc;
+    int res = microcode_fits(src, cpu);
+
+    if ( res <= 0 )
+        return res;
+
+    if ( src != mc_amd )
+    {
+        xfree(mc_amd);
+        mc_amd = xmalloc_bytes(sizeof(*src) + src->equiv_cpu_table_size);
+        uci->mc.mc_amd = mc_amd;
+        if ( !mc_amd )
+            return -ENOMEM;
+        memcpy(mc_amd, src, UCODE_MAX_SIZE);
+        memcpy(mc_amd->equiv_cpu_table, src->equiv_cpu_table,
+               src->equiv_cpu_table_size);
+    }
+
+    return 1;
 }
 
 static const struct microcode_ops microcode_amd_ops = {
@@ -317,4 +361,4 @@
         microcode_ops = &microcode_amd_ops;
     return 0;
 }
-__initcall(microcode_init_amd);
+presmp_initcall(microcode_init_amd);
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/microcode_intel.c
--- a/xen/arch/x86/microcode_intel.c    Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/microcode_intel.c    Thu Dec 01 17:26:48 2011 +0000
@@ -30,12 +30,43 @@
 #include <xen/spinlock.h>
 
 #include <asm/msr.h>
-#include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/microcode.h>
 
 #define pr_debug(x...) ((void)0)
 
+struct microcode_header_intel {
+    unsigned int hdrver;
+    unsigned int rev;
+    unsigned int date;
+    unsigned int sig;
+    unsigned int cksum;
+    unsigned int ldrver;
+    unsigned int pf;
+    unsigned int datasize;
+    unsigned int totalsize;
+    unsigned int reserved[3];
+};
+
+struct microcode_intel {
+    struct microcode_header_intel hdr;
+    unsigned int bits[0];
+};
+
+/* microcode format is extended from prescott processors */
+struct extended_signature {
+    unsigned int sig;
+    unsigned int pf;
+    unsigned int cksum;
+};
+
+struct extended_sigtable {
+    unsigned int count;
+    unsigned int cksum;
+    unsigned int reserved[3];
+    struct extended_signature sigs[0];
+};
+
 #define DEFAULT_UCODE_DATASIZE  (2000)
 #define MC_HEADER_SIZE          (sizeof(struct microcode_header_intel))
 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
@@ -98,7 +129,8 @@
 }
 
 static inline int microcode_update_match(
-    int cpu_num, struct microcode_header_intel *mc_header, int sig, int pf)
+    int cpu_num, const struct microcode_header_intel *mc_header,
+    int sig, int pf)
 {
     struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu_num);
 
@@ -200,11 +232,11 @@
  * return 1 - found update
  * return < 0 - error
  */
-static int get_matching_microcode(void *mc, int cpu)
+static int get_matching_microcode(const void *mc, int cpu)
 {
     struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
-    struct microcode_header_intel *mc_header = mc;
-    struct extended_sigtable *ext_header;
+    const struct microcode_header_intel *mc_header = mc;
+    const struct extended_sigtable *ext_header;
     unsigned long total_size = get_totalsize(mc_header);
     int ext_sigcount, i;
     struct extended_signature *ext_sig;
@@ -229,6 +261,8 @@
     }
     return 0;
  find:
+    if ( uci->mc.mc_intel && uci->mc.mc_intel->hdr.rev >= mc_header->rev )
+        return 0;
     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);
@@ -239,10 +273,8 @@
         return -ENOMEM;
     }
 
-    /* free previous update file */
+    memcpy(new_mc, mc, total_size);
     xfree(uci->mc.mc_intel);
-
-    memcpy(new_mc, mc, total_size);
     uci->mc.mc_intel = new_mc;
     return 1;
 }
@@ -361,12 +393,9 @@
     return error;
 }
 
-static int microcode_resume_match(int cpu, struct cpu_signature *nsig)
+static int microcode_resume_match(int cpu, const void *mc)
 {
-    struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
-
-    return (sigmatch(nsig->sig, uci->cpu_sig.sig, nsig->pf, uci->cpu_sig.pf) &&
-            (uci->cpu_sig.rev > nsig->rev));
+    return get_matching_microcode(mc, cpu);
 }
 
 static const struct microcode_ops microcode_intel_ops = {
@@ -382,4 +411,4 @@
         microcode_ops = &microcode_intel_ops;
     return 0;
 }
-__initcall(microcode_init_intel);
+presmp_initcall(microcode_init_intel);
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/mm.c Thu Dec 01 17:26:48 2011 +0000
@@ -3572,7 +3572,8 @@
                         rc = -ENOENT;
                         break;
                     }
-                    else if ( p2m_ram_paging_in_start == l1e_p2mt && 
!mfn_valid(mfn) )
+                    else if ( p2m_ram_paging_in_start == l1e_p2mt && 
+                                !mfn_valid(l1emfn) )
                     {
                         put_gfn(pg_owner, l1egfn);
                         rc = -ENOENT;
@@ -3620,7 +3621,8 @@
                         rc = -ENOENT;
                         break;
                     }
-                    else if ( p2m_ram_paging_in_start == l2e_p2mt && 
!mfn_valid(mfn) )
+                    else if ( p2m_ram_paging_in_start == l2e_p2mt && 
+                                !mfn_valid(l2emfn) )
                     {
                         put_gfn(pg_owner, l2egfn);
                         rc = -ENOENT;
@@ -3654,7 +3656,8 @@
                         rc = -ENOENT;
                         break;
                     }
-                    else if ( p2m_ram_paging_in_start == l3e_p2mt && 
!mfn_valid(mfn) )
+                    else if ( p2m_ram_paging_in_start == l3e_p2mt && 
+                                !mfn_valid(l3emfn) )
                     {
                         put_gfn(pg_owner, l3egfn);
                         rc = -ENOENT;
@@ -3688,7 +3691,8 @@
                         rc = -ENOENT;
                         break;
                     }
-                    else if ( p2m_ram_paging_in_start == l4e_p2mt && 
!mfn_valid(mfn) )
+                    else if ( p2m_ram_paging_in_start == l4e_p2mt && 
+                                !mfn_valid(l4emfn) )
                     {
                         put_gfn(pg_owner, l4egfn);
                         rc = -ENOENT;
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/setup.c      Thu Dec 01 17:26:48 2011 +0000
@@ -550,10 +550,10 @@
 {
     char *memmap_type = NULL;
     char *cmdline, *kextra, *loader;
-    unsigned int initrdidx = 1;
+    unsigned int initrdidx;
     multiboot_info_t *mbi = __va(mbi_p);
     module_t *mod = (module_t *)__va(mbi->mods_addr);
-    unsigned long nr_pages, modules_headroom;
+    unsigned long nr_pages, modules_headroom, *module_map;
     int i, j, e820_warn = 0, bytes = 0;
     bool_t acpi_boot_table_init_done = 0;
     struct ns16550_defaults ns16550 = {
@@ -1229,7 +1229,13 @@
 
     init_IRQ();
 
-    xsm_init(&initrdidx, mbi, bootstrap_map);
+    module_map = xmalloc_array(unsigned long, BITS_TO_LONGS(mbi->mods_count));
+    bitmap_fill(module_map, mbi->mods_count);
+    __clear_bit(0, module_map); /* Dom0 kernel is always first */
+
+    xsm_init(module_map, mbi, bootstrap_map);
+
+    microcode_grab_module(module_map, mbi, bootstrap_map);
 
     timer_init();
 
@@ -1356,6 +1362,12 @@
     if ( xen_cpuidle )
         xen_processor_pmbits |= XEN_PROCESSOR_PM_CX;
 
+    initrdidx = find_first_bit(module_map, mbi->mods_count);
+    if ( bitmap_weight(module_map, mbi->mods_count) > 1 )
+        printk(XENLOG_WARNING
+               "Multiple initrd candidates, picking module #%u\n",
+               initrdidx);
+
     /*
      * We're going to setup domain0 using the module(s) that we stashed safely
      * above our heap. The second module, if present, is an initrd ramdisk.
diff -r b6962c4b0dfd -r 3b409f65abae xen/arch/x86/x86_32/domain_page.c
--- a/xen/arch/x86/x86_32/domain_page.c Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/arch/x86/x86_32/domain_page.c Thu Dec 01 17:26:48 2011 +0000
@@ -265,3 +265,15 @@
     idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT;
     set_bit(idx, garbage);
 }
+
+/* Translate a map-domain-page'd address to the underlying MFN */
+unsigned long domain_page_map_to_mfn(void *va)
+{
+    l1_pgentry_t *l1e;
+
+    ASSERT( (((unsigned long) va) >= MAPCACHE_VIRT_START) &&
+            (((unsigned long) va) <= MAPCACHE_VIRT_END) );
+    l1e = &__linear_l1_table[
+            l1_linear_offset((unsigned long) va)];
+    return l1e_get_pfn(*l1e);
+}
diff -r b6962c4b0dfd -r 3b409f65abae xen/include/asm-x86/microcode.h
--- a/xen/include/asm-x86/microcode.h   Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/include/asm-x86/microcode.h   Thu Dec 01 17:26:48 2011 +0000
@@ -7,74 +7,12 @@
 struct ucode_cpu_info;
 
 struct microcode_ops {
-    int (*microcode_resume_match)(int cpu, struct cpu_signature *nsig);
+    int (*microcode_resume_match)(int cpu, const void *mc);
     int (*cpu_request_microcode)(int cpu, const void *buf, size_t size);
     int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
     int (*apply_microcode)(int cpu);
 };
 
-struct microcode_header_intel {
-    unsigned int hdrver;
-    unsigned int rev;
-    unsigned int date;
-    unsigned int sig;
-    unsigned int cksum;
-    unsigned int ldrver;
-    unsigned int pf;
-    unsigned int datasize;
-    unsigned int totalsize;
-    unsigned int reserved[3];
-};
-
-struct microcode_intel {
-    struct microcode_header_intel hdr;
-    unsigned int bits[0];
-};
-
-/* microcode format is extended from prescott processors */
-struct extended_signature {
-    unsigned int sig;
-    unsigned int pf;
-    unsigned int cksum;
-};
-
-struct extended_sigtable {
-    unsigned int count;
-    unsigned int cksum;
-    unsigned int reserved[3];
-    struct extended_signature sigs[0];
-};
-
-struct equiv_cpu_entry {
-    uint32_t installed_cpu;
-    uint32_t fixed_errata_mask;
-    uint32_t fixed_errata_compare;
-    uint16_t equiv_cpu;
-    uint16_t reserved;
-} __attribute__((packed));
-
-struct microcode_header_amd {
-    uint32_t data_code;
-    uint32_t patch_id;
-    uint8_t  mc_patch_data_id[2];
-    uint8_t  mc_patch_data_len;
-    uint8_t  init_flag;
-    uint32_t mc_patch_data_checksum;
-    uint32_t nb_dev_id;
-    uint32_t sb_dev_id;
-    uint16_t processor_rev_id;
-    uint8_t  nb_rev_id;
-    uint8_t  sb_rev_id;
-    uint8_t  bios_api_rev;
-    uint8_t  reserved1[3];
-    uint32_t match_reg[8];
-} __attribute__((packed));
-
-struct microcode_amd {
-    struct microcode_header_amd hdr;
-    unsigned int mpb[0];
-};
-
 struct cpu_signature {
     unsigned int sig;
     unsigned int pf;
diff -r b6962c4b0dfd -r 3b409f65abae xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h   Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/include/asm-x86/processor.h   Thu Dec 01 17:26:48 2011 +0000
@@ -599,6 +599,7 @@
 int rdmsr_hypervisor_regs(uint32_t idx, uint64_t *val);
 int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val);
 
+void microcode_set_module(unsigned int);
 int microcode_update(XEN_GUEST_HANDLE(const_void), unsigned long len);
 int microcode_resume_cpu(int cpu);
 
diff -r b6962c4b0dfd -r 3b409f65abae xen/include/asm-x86/setup.h
--- a/xen/include/asm-x86/setup.h       Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/include/asm-x86/setup.h       Thu Dec 01 17:26:48 2011 +0000
@@ -44,4 +44,7 @@
 int xen_in_range(unsigned long mfn);
 void arch_get_xen_caps(xen_capabilities_info_t *info);
 
+void microcode_grab_module(
+    unsigned long *, const multiboot_info_t *, void *(*)(const module_t *));
+
 #endif
diff -r b6962c4b0dfd -r 3b409f65abae xen/include/xen/domain_page.h
--- a/xen/include/xen/domain_page.h     Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/include/xen/domain_page.h     Thu Dec 01 17:26:48 2011 +0000
@@ -26,6 +26,12 @@
  */
 void unmap_domain_page(const void *va);
 
+
+/* 
+ * Given a VA from map_domain_page(), return its underlying MFN.
+ */
+unsigned long domain_page_map_to_mfn(void *va);
+
 /*
  * Similar to the above calls, except the mapping is accessible in all
  * address spaces (not just within the VCPU that created the mapping). Global
@@ -102,6 +108,7 @@
 #define map_domain_page(mfn)                mfn_to_virt(mfn)
 #define __map_domain_page(pg)               page_to_virt(pg)
 #define unmap_domain_page(va)               ((void)(va))
+#define domain_page_map_to_mfn(va)          virt_to_mfn((unsigned long)(va))
 
 #define map_domain_page_global(mfn)         mfn_to_virt(mfn)
 #define __map_domain_page_global(pg)        page_to_virt(pg)
diff -r b6962c4b0dfd -r 3b409f65abae xen/include/xsm/xsm.h
--- a/xen/include/xsm/xsm.h     Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/include/xsm/xsm.h     Thu Dec 01 17:26:48 2011 +0000
@@ -454,14 +454,15 @@
 }
 
 #ifdef XSM_ENABLE
-extern int xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+extern int xsm_init(unsigned long *module_map, const multiboot_info_t *mbi,
                     void *(*bootstrap_map)(const module_t *));
-extern int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t 
*mbi,
+extern int xsm_policy_init(unsigned long *module_map,
+                           const multiboot_info_t *mbi,
                            void *(*bootstrap_map)(const module_t *));
 extern int register_xsm(struct xsm_operations *ops);
 extern int unregister_xsm(struct xsm_operations *ops);
 #else
-static inline int xsm_init (unsigned int *initrdidx,
+static inline int xsm_init (unsigned long *module_map,
                             const multiboot_info_t *mbi,
                             void *(*bootstrap_map)(const module_t *))
 {
diff -r b6962c4b0dfd -r 3b409f65abae xen/xsm/xsm_core.c
--- a/xen/xsm/xsm_core.c        Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/xsm/xsm_core.c        Thu Dec 01 17:26:48 2011 +0000
@@ -43,7 +43,7 @@
     }
 }
 
-int __init xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+int __init xsm_init(unsigned long *module_map, const multiboot_info_t *mbi,
                     void *(*bootstrap_map)(const module_t *))
 {
     int ret = 0;
@@ -52,7 +52,7 @@
 
     if ( XSM_MAGIC )
     {
-        ret = xsm_policy_init(initrdidx, mbi, bootstrap_map);
+        ret = xsm_policy_init(module_map, mbi, bootstrap_map);
         if ( ret )
         {
             bootstrap_map(NULL);
diff -r b6962c4b0dfd -r 3b409f65abae xen/xsm/xsm_policy.c
--- a/xen/xsm/xsm_policy.c      Thu Dec 01 17:25:39 2011 +0000
+++ b/xen/xsm/xsm_policy.c      Thu Dec 01 17:26:48 2011 +0000
@@ -20,11 +20,12 @@
 
 #include <xsm/xsm.h>
 #include <xen/multiboot.h>
+#include <asm/bitops.h>
 
 char *__initdata policy_buffer = NULL;
 u32 __initdata policy_size = 0;
 
-int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+int xsm_policy_init(unsigned long *module_map, const multiboot_info_t *mbi,
                     void *(*bootstrap_map)(const module_t *))
 {
     int i;
@@ -35,10 +36,13 @@
 
     /*
      * Try all modules and see whichever could be the binary policy.
-     * Adjust the initrdidx if module[1] is the binary policy.
+     * Adjust module_map for the module that is the binary policy.
      */
     for ( i = mbi->mods_count-1; i >= 1; i-- )
     {
+        if ( !test_bit(i, module_map) )
+            continue;
+
         _policy_start = bootstrap_map(mod + i);
         _policy_len   = mod[i].mod_end;
 
@@ -50,8 +54,7 @@
             printk("Policy len  0x%lx, start at %p.\n",
                    _policy_len,_policy_start);
 
-            if ( i == 1 )
-                *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
+            __clear_bit(i, module_map);
             break;
 
         }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.