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 = {
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));
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 )
{
#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/msr.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);
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)
{
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);
{
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 = {
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();
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.
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);
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
}
#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 *))
{
}
}
-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;
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);
#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;
/*
* 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;
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;
}