0001
0002
0003 #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
0004 #include <linux/memblock.h>
0005 #endif
0006 #include <linux/console.h>
0007 #include <linux/cpu.h>
0008 #include <linux/kexec.h>
0009 #include <linux/slab.h>
0010 #include <linux/panic_notifier.h>
0011
0012 #include <xen/xen.h>
0013 #include <xen/features.h>
0014 #include <xen/interface/sched.h>
0015 #include <xen/interface/version.h>
0016 #include <xen/page.h>
0017
0018 #include <asm/xen/hypercall.h>
0019 #include <asm/xen/hypervisor.h>
0020 #include <asm/cpu.h>
0021 #include <asm/e820/api.h>
0022 #include <asm/setup.h>
0023
0024 #include "xen-ops.h"
0025 #include "smp.h"
0026 #include "pmu.h"
0027
0028 EXPORT_SYMBOL_GPL(hypercall_page);
0029
0030
0031
0032
0033
0034
0035
0036
0037 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
0038 DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
0039
0040
0041 DEFINE_PER_CPU(uint32_t, xen_vcpu_id);
0042 EXPORT_PER_CPU_SYMBOL(xen_vcpu_id);
0043
0044 unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
0045 EXPORT_SYMBOL(machine_to_phys_mapping);
0046 unsigned long machine_to_phys_nr;
0047 EXPORT_SYMBOL(machine_to_phys_nr);
0048
0049 struct start_info *xen_start_info;
0050 EXPORT_SYMBOL_GPL(xen_start_info);
0051
0052 struct shared_info xen_dummy_shared_info;
0053
0054 __read_mostly bool xen_have_vector_callback = true;
0055 EXPORT_SYMBOL_GPL(xen_have_vector_callback);
0056
0057
0058
0059
0060
0061 enum xen_domain_type __ro_after_init xen_domain_type = XEN_NATIVE;
0062 EXPORT_SYMBOL_GPL(xen_domain_type);
0063 uint32_t __ro_after_init xen_start_flags;
0064 EXPORT_SYMBOL(xen_start_flags);
0065
0066
0067
0068
0069
0070 struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info;
0071
0072 static int xen_cpu_up_online(unsigned int cpu)
0073 {
0074 xen_init_lock_cpu(cpu);
0075 return 0;
0076 }
0077
0078 int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
0079 int (*cpu_dead_cb)(unsigned int))
0080 {
0081 int rc;
0082
0083 rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE,
0084 "x86/xen/guest:prepare",
0085 cpu_up_prepare_cb, cpu_dead_cb);
0086 if (rc >= 0) {
0087 rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
0088 "x86/xen/guest:online",
0089 xen_cpu_up_online, NULL);
0090 if (rc < 0)
0091 cpuhp_remove_state_nocalls(CPUHP_XEN_PREPARE);
0092 }
0093
0094 return rc >= 0 ? 0 : rc;
0095 }
0096
0097 static void xen_vcpu_setup_restore(int cpu)
0098 {
0099
0100 xen_vcpu_info_reset(cpu);
0101
0102
0103
0104
0105
0106 if (xen_pv_domain() ||
0107 (xen_hvm_domain() && cpu_online(cpu)))
0108 xen_vcpu_setup(cpu);
0109 }
0110
0111
0112
0113
0114
0115
0116 void xen_vcpu_restore(void)
0117 {
0118 int cpu;
0119
0120 for_each_possible_cpu(cpu) {
0121 bool other_cpu = (cpu != smp_processor_id());
0122 bool is_up;
0123
0124 if (xen_vcpu_nr(cpu) == XEN_VCPU_ID_INVALID)
0125 continue;
0126
0127
0128 is_up = HYPERVISOR_vcpu_op(VCPUOP_is_up,
0129 xen_vcpu_nr(cpu), NULL) > 0;
0130
0131 if (other_cpu && is_up &&
0132 HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL))
0133 BUG();
0134
0135 if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
0136 xen_setup_runstate_info(cpu);
0137
0138 xen_vcpu_setup_restore(cpu);
0139
0140 if (other_cpu && is_up &&
0141 HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL))
0142 BUG();
0143 }
0144 }
0145
0146 void xen_vcpu_info_reset(int cpu)
0147 {
0148 if (xen_vcpu_nr(cpu) < MAX_VIRT_CPUS) {
0149 per_cpu(xen_vcpu, cpu) =
0150 &HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)];
0151 } else {
0152
0153 per_cpu(xen_vcpu, cpu) = NULL;
0154 }
0155 }
0156
0157 void xen_vcpu_setup(int cpu)
0158 {
0159 struct vcpu_register_vcpu_info info;
0160 int err;
0161 struct vcpu_info *vcpup;
0162
0163 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 if (xen_hvm_domain()) {
0177 if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu))
0178 return;
0179 }
0180
0181 vcpup = &per_cpu(xen_vcpu_info, cpu);
0182 info.mfn = arbitrary_virt_to_mfn(vcpup);
0183 info.offset = offset_in_page(vcpup);
0184
0185
0186
0187
0188
0189
0190
0191
0192 err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, xen_vcpu_nr(cpu),
0193 &info);
0194 if (err)
0195 panic("register_vcpu_info failed: cpu=%d err=%d\n", cpu, err);
0196
0197 per_cpu(xen_vcpu, cpu) = vcpup;
0198 }
0199
0200 void __init xen_banner(void)
0201 {
0202 unsigned version = HYPERVISOR_xen_version(XENVER_version, NULL);
0203 struct xen_extraversion extra;
0204
0205 HYPERVISOR_xen_version(XENVER_extraversion, &extra);
0206
0207 pr_info("Booting kernel on %s\n", pv_info.name);
0208 pr_info("Xen version: %u.%u%s%s\n",
0209 version >> 16, version & 0xffff, extra.extraversion,
0210 xen_feature(XENFEAT_mmu_pt_update_preserve_ad)
0211 ? " (preserve-AD)" : "");
0212 }
0213
0214
0215 bool xen_running_on_version_or_later(unsigned int major, unsigned int minor)
0216 {
0217 unsigned int version;
0218
0219 if (!xen_domain())
0220 return false;
0221
0222 version = HYPERVISOR_xen_version(XENVER_version, NULL);
0223 if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) ||
0224 ((version >> 16) > major))
0225 return true;
0226 return false;
0227 }
0228
0229 void __init xen_add_preferred_consoles(void)
0230 {
0231 add_preferred_console("xenboot", 0, NULL);
0232 if (!boot_params.screen_info.orig_video_isVGA)
0233 add_preferred_console("tty", 0, NULL);
0234 add_preferred_console("hvc", 0, NULL);
0235 if (boot_params.screen_info.orig_video_isVGA)
0236 add_preferred_console("tty", 0, NULL);
0237 }
0238
0239 void xen_reboot(int reason)
0240 {
0241 struct sched_shutdown r = { .reason = reason };
0242 int cpu;
0243
0244 for_each_online_cpu(cpu)
0245 xen_pmu_finish(cpu);
0246
0247 if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r))
0248 BUG();
0249 }
0250
0251 static int reboot_reason = SHUTDOWN_reboot;
0252 static bool xen_legacy_crash;
0253 void xen_emergency_restart(void)
0254 {
0255 xen_reboot(reboot_reason);
0256 }
0257
0258 static int
0259 xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
0260 {
0261 if (!kexec_crash_loaded()) {
0262 if (xen_legacy_crash)
0263 xen_reboot(SHUTDOWN_crash);
0264
0265 reboot_reason = SHUTDOWN_crash;
0266
0267
0268
0269
0270
0271
0272
0273 if (panic_timeout == 0)
0274 panic_timeout = -1;
0275 }
0276 return NOTIFY_DONE;
0277 }
0278
0279 static int __init parse_xen_legacy_crash(char *arg)
0280 {
0281 xen_legacy_crash = true;
0282 return 0;
0283 }
0284 early_param("xen_legacy_crash", parse_xen_legacy_crash);
0285
0286 static struct notifier_block xen_panic_block = {
0287 .notifier_call = xen_panic_event,
0288 .priority = INT_MIN
0289 };
0290
0291 int xen_panic_handler_init(void)
0292 {
0293 atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
0294 return 0;
0295 }
0296
0297 void xen_pin_vcpu(int cpu)
0298 {
0299 static bool disable_pinning;
0300 struct sched_pin_override pin_override;
0301 int ret;
0302
0303 if (disable_pinning)
0304 return;
0305
0306 pin_override.pcpu = cpu;
0307 ret = HYPERVISOR_sched_op(SCHEDOP_pin_override, &pin_override);
0308
0309
0310 if (cpu < 0)
0311 return;
0312
0313 switch (ret) {
0314 case -ENOSYS:
0315 pr_warn("Unable to pin on physical cpu %d. In case of problems consider vcpu pinning.\n",
0316 cpu);
0317 disable_pinning = true;
0318 break;
0319 case -EPERM:
0320 WARN(1, "Trying to pin vcpu without having privilege to do so\n");
0321 disable_pinning = true;
0322 break;
0323 case -EINVAL:
0324 case -EBUSY:
0325 pr_warn("Physical cpu %d not available for pinning. Check Xen cpu configuration.\n",
0326 cpu);
0327 break;
0328 case 0:
0329 break;
0330 default:
0331 WARN(1, "rc %d while trying to pin vcpu\n", ret);
0332 disable_pinning = true;
0333 }
0334 }
0335
0336 #ifdef CONFIG_HOTPLUG_CPU
0337 void xen_arch_register_cpu(int num)
0338 {
0339 arch_register_cpu(num);
0340 }
0341 EXPORT_SYMBOL(xen_arch_register_cpu);
0342
0343 void xen_arch_unregister_cpu(int num)
0344 {
0345 arch_unregister_cpu(num);
0346 }
0347 EXPORT_SYMBOL(xen_arch_unregister_cpu);
0348 #endif