/* * Machine specific setup for generic */ #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) #else #define DEFAULT_SEND_IPI (0) #endif int no_broadcast=DEFAULT_SEND_IPI; static __init int no_ipi_broadcast(char *str) { get_option(&str, &no_broadcast); printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" : "IPI Broadcast"); return 1; } __setup("no_ipi_broadcast", no_ipi_broadcast); static int __init print_ipi_mode(void) { printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" : "Shortcut"); return 0; } late_initcall(print_ipi_mode); /** * machine_specific_memory_setup - Hook for machine specific memory setup. * * Description: * This is included late in kernel/setup.c so that it can make * use of all of the static functions. **/ char * __init machine_specific_memory_setup(void) { int rc; struct xen_memory_map memmap; /* * This is rather large for a stack variable but this early in * the boot process we know we have plenty slack space. */ struct e820entry map[E820MAX]; memmap.nr_entries = E820MAX; set_xen_guest_handle(memmap.buffer, map); rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); if ( rc == -ENOSYS ) { memmap.nr_entries = 1; map[0].addr = 0ULL; map[0].size = PFN_PHYS(xen_start_info->nr_pages); /* 8MB slack (to balance backend allocations). */ map[0].size += 8ULL << 20; map[0].type = E820_RAM; rc = 0; } BUG_ON(rc); sanitize_e820_map(map, (char *)&memmap.nr_entries); BUG_ON(copy_e820_map(map, (char)memmap.nr_entries) < 0); return "Xen"; } extern void hypervisor_callback(void); extern void failsafe_callback(void); extern void nmi(void); unsigned long *machine_to_phys_mapping; EXPORT_SYMBOL(machine_to_phys_mapping); unsigned int machine_to_phys_order; EXPORT_SYMBOL(machine_to_phys_order); void __init machine_specific_arch_setup(void) { int ret; struct xen_machphys_mapping mapping; unsigned long machine_to_phys_nr_ents; struct xen_platform_parameters pp; struct callback_register event = { .type = CALLBACKTYPE_event, .address = { __KERNEL_CS, (unsigned long)hypervisor_callback }, }; struct callback_register failsafe = { .type = CALLBACKTYPE_failsafe, .address = { __KERNEL_CS, (unsigned long)failsafe_callback }, }; struct callback_register nmi_cb = { .type = CALLBACKTYPE_nmi, .address = { __KERNEL_CS, (unsigned long)nmi }, }; ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event); if (ret == 0) ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); if (ret == -ENOSYS) ret = HYPERVISOR_set_callbacks( event.address.cs, event.address.eip, failsafe.address.cs, failsafe.address.eip); BUG_ON(ret); ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb); if (ret == -ENOSYS) { struct xennmi_callback cb; cb.handler_address = nmi_cb.address.eip; HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); } if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) set_fixaddr_top(pp.virt_start - PAGE_SIZE); machine_to_phys_mapping = (unsigned long *)MACH2PHYS_VIRT_START; machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES; if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) { machine_to_phys_mapping = (unsigned long *)mapping.v_start; machine_to_phys_nr_ents = mapping.max_mfn + 1; } while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents ) machine_to_phys_order++; } /** * pre_setup_arch_hook - hook called prior to any setup_arch() execution * * Description: * generally used to activate any machine specific identification * routines that may be needed before setup_arch() runs. On VISWS * this is used to get the board revision and type. **/ void __init pre_setup_arch_hook(void) { int max_cmdline; if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE) max_cmdline = COMMAND_LINE_SIZE; memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline); /* Save unparsed command line copy for /proc/cmdline */ saved_command_line[max_cmdline-1] = '\0'; }