|
@@ -97,6 +97,14 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;
|
|
*/
|
|
*/
|
|
static int have_vcpu_info_placement = 1;
|
|
static int have_vcpu_info_placement = 1;
|
|
|
|
|
|
|
|
+static void clamp_max_cpus(void)
|
|
|
|
+{
|
|
|
|
+#ifdef CONFIG_SMP
|
|
|
|
+ if (setup_max_cpus > MAX_VIRT_CPUS)
|
|
|
|
+ setup_max_cpus = MAX_VIRT_CPUS;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
static void xen_vcpu_setup(int cpu)
|
|
static void xen_vcpu_setup(int cpu)
|
|
{
|
|
{
|
|
struct vcpu_register_vcpu_info info;
|
|
struct vcpu_register_vcpu_info info;
|
|
@@ -104,13 +112,17 @@ static void xen_vcpu_setup(int cpu)
|
|
struct vcpu_info *vcpup;
|
|
struct vcpu_info *vcpup;
|
|
|
|
|
|
BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
|
|
BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
|
|
- per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
|
|
|
|
|
|
|
|
- if (!have_vcpu_info_placement)
|
|
|
|
- return; /* already tested, not available */
|
|
|
|
|
|
+ if (cpu < MAX_VIRT_CPUS)
|
|
|
|
+ per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
|
|
|
|
|
|
- vcpup = &per_cpu(xen_vcpu_info, cpu);
|
|
|
|
|
|
+ if (!have_vcpu_info_placement) {
|
|
|
|
+ if (cpu >= MAX_VIRT_CPUS)
|
|
|
|
+ clamp_max_cpus();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ vcpup = &per_cpu(xen_vcpu_info, cpu);
|
|
info.mfn = arbitrary_virt_to_mfn(vcpup);
|
|
info.mfn = arbitrary_virt_to_mfn(vcpup);
|
|
info.offset = offset_in_page(vcpup);
|
|
info.offset = offset_in_page(vcpup);
|
|
|
|
|
|
@@ -125,6 +137,7 @@ static void xen_vcpu_setup(int cpu)
|
|
if (err) {
|
|
if (err) {
|
|
printk(KERN_DEBUG "register_vcpu_info failed: err=%d\n", err);
|
|
printk(KERN_DEBUG "register_vcpu_info failed: err=%d\n", err);
|
|
have_vcpu_info_placement = 0;
|
|
have_vcpu_info_placement = 0;
|
|
|
|
+ clamp_max_cpus();
|
|
} else {
|
|
} else {
|
|
/* This cpu is using the registered vcpu info, even if
|
|
/* This cpu is using the registered vcpu info, even if
|
|
later ones fail to. */
|
|
later ones fail to. */
|
|
@@ -731,7 +744,6 @@ static void set_xen_basic_apic_ops(void)
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-
|
|
|
|
static void xen_clts(void)
|
|
static void xen_clts(void)
|
|
{
|
|
{
|
|
struct multicall_space mcs;
|
|
struct multicall_space mcs;
|
|
@@ -927,7 +939,7 @@ static const struct pv_init_ops xen_init_ops __initdata = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct pv_time_ops xen_time_ops __initdata = {
|
|
static const struct pv_time_ops xen_time_ops __initdata = {
|
|
- .sched_clock = xen_sched_clock,
|
|
|
|
|
|
+ .sched_clock = xen_clocksource_read,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct pv_cpu_ops xen_cpu_ops __initdata = {
|
|
static const struct pv_cpu_ops xen_cpu_ops __initdata = {
|
|
@@ -1028,6 +1040,23 @@ static void xen_crash_shutdown(struct pt_regs *regs)
|
|
xen_reboot(SHUTDOWN_crash);
|
|
xen_reboot(SHUTDOWN_crash);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int
|
|
|
|
+xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
|
|
|
|
+{
|
|
|
|
+ xen_reboot(SHUTDOWN_crash);
|
|
|
|
+ return NOTIFY_DONE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct notifier_block xen_panic_block = {
|
|
|
|
+ .notifier_call= xen_panic_event,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int xen_panic_handler_init(void)
|
|
|
|
+{
|
|
|
|
+ atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct machine_ops __initdata xen_machine_ops = {
|
|
static const struct machine_ops __initdata xen_machine_ops = {
|
|
.restart = xen_restart,
|
|
.restart = xen_restart,
|
|
.halt = xen_machine_halt,
|
|
.halt = xen_machine_halt,
|