[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(µcode_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(µcode_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(µcode_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(µcode_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(µcode_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 = µcode_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 = µcode_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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |