diff options
| -rw-r--r-- | arch/arm/xen/enlighten.c | 14 | ||||
| -rw-r--r-- | arch/x86/xen/enlighten.c | 1 | ||||
| -rw-r--r-- | arch/x86/xen/p2m.c | 10 | ||||
| -rw-r--r-- | arch/x86/xen/smp.c | 28 | ||||
| -rw-r--r-- | arch/x86/xen/spinlock.c | 45 |
5 files changed, 50 insertions, 48 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 8a6295c86209..83e4f959ee47 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
| 22 | #include <linux/of_irq.h> | 22 | #include <linux/of_irq.h> |
| 23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
| 24 | #include <linux/cpuidle.h> | ||
| 25 | #include <linux/cpufreq.h> | ||
| 24 | 26 | ||
| 25 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
| 26 | 28 | ||
| @@ -267,18 +269,28 @@ static int __init xen_guest_init(void) | |||
| 267 | if (!xen_initial_domain()) | 269 | if (!xen_initial_domain()) |
| 268 | xenbus_probe(NULL); | 270 | xenbus_probe(NULL); |
| 269 | 271 | ||
| 272 | /* | ||
| 273 | * Making sure board specific code will not set up ops for | ||
| 274 | * cpu idle and cpu freq. | ||
| 275 | */ | ||
| 276 | disable_cpuidle(); | ||
| 277 | disable_cpufreq(); | ||
| 278 | |||
| 270 | return 0; | 279 | return 0; |
| 271 | } | 280 | } |
| 272 | core_initcall(xen_guest_init); | 281 | core_initcall(xen_guest_init); |
| 273 | 282 | ||
| 274 | static int __init xen_pm_init(void) | 283 | static int __init xen_pm_init(void) |
| 275 | { | 284 | { |
| 285 | if (!xen_domain()) | ||
| 286 | return -ENODEV; | ||
| 287 | |||
| 276 | pm_power_off = xen_power_off; | 288 | pm_power_off = xen_power_off; |
| 277 | arm_pm_restart = xen_restart; | 289 | arm_pm_restart = xen_restart; |
| 278 | 290 | ||
| 279 | return 0; | 291 | return 0; |
| 280 | } | 292 | } |
| 281 | subsys_initcall(xen_pm_init); | 293 | late_initcall(xen_pm_init); |
| 282 | 294 | ||
| 283 | static irqreturn_t xen_arm_callback(int irq, void *arg) | 295 | static irqreturn_t xen_arm_callback(int irq, void *arg) |
| 284 | { | 296 | { |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 2fc216dfbd9c..fa6ade76ef3f 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -1692,7 +1692,6 @@ static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action, | |||
| 1692 | case CPU_UP_PREPARE: | 1692 | case CPU_UP_PREPARE: |
| 1693 | xen_vcpu_setup(cpu); | 1693 | xen_vcpu_setup(cpu); |
| 1694 | if (xen_have_vector_callback) { | 1694 | if (xen_have_vector_callback) { |
| 1695 | xen_init_lock_cpu(cpu); | ||
| 1696 | if (xen_feature(XENFEAT_hvm_safe_pvclock)) | 1695 | if (xen_feature(XENFEAT_hvm_safe_pvclock)) |
| 1697 | xen_setup_timer(cpu); | 1696 | xen_setup_timer(cpu); |
| 1698 | } | 1697 | } |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 0d4ec35895d4..8b901e8d782d 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
| @@ -990,10 +990,13 @@ int m2p_remove_override(struct page *page, | |||
| 990 | printk(KERN_WARNING "m2p_remove_override: " | 990 | printk(KERN_WARNING "m2p_remove_override: " |
| 991 | "pfn %lx mfn %lx, failed to modify kernel mappings", | 991 | "pfn %lx mfn %lx, failed to modify kernel mappings", |
| 992 | pfn, mfn); | 992 | pfn, mfn); |
| 993 | put_balloon_scratch_page(); | ||
| 993 | return -1; | 994 | return -1; |
| 994 | } | 995 | } |
| 995 | 996 | ||
| 996 | mcs = xen_mc_entry( | 997 | xen_mc_batch(); |
| 998 | |||
| 999 | mcs = __xen_mc_entry( | ||
| 997 | sizeof(struct gnttab_unmap_and_replace)); | 1000 | sizeof(struct gnttab_unmap_and_replace)); |
| 998 | unmap_op = mcs.args; | 1001 | unmap_op = mcs.args; |
| 999 | unmap_op->host_addr = kmap_op->host_addr; | 1002 | unmap_op->host_addr = kmap_op->host_addr; |
| @@ -1003,12 +1006,11 @@ int m2p_remove_override(struct page *page, | |||
| 1003 | MULTI_grant_table_op(mcs.mc, | 1006 | MULTI_grant_table_op(mcs.mc, |
| 1004 | GNTTABOP_unmap_and_replace, unmap_op, 1); | 1007 | GNTTABOP_unmap_and_replace, unmap_op, 1); |
| 1005 | 1008 | ||
| 1006 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
| 1007 | |||
| 1008 | mcs = __xen_mc_entry(0); | 1009 | mcs = __xen_mc_entry(0); |
| 1009 | MULTI_update_va_mapping(mcs.mc, scratch_page_address, | 1010 | MULTI_update_va_mapping(mcs.mc, scratch_page_address, |
| 1010 | pfn_pte(page_to_pfn(get_balloon_scratch_page()), | 1011 | pfn_pte(page_to_pfn(scratch_page), |
| 1011 | PAGE_KERNEL_RO), 0); | 1012 | PAGE_KERNEL_RO), 0); |
| 1013 | |||
| 1012 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 1014 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
| 1013 | 1015 | ||
| 1014 | kmap_op->host_addr = 0; | 1016 | kmap_op->host_addr = 0; |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 9235842cd76a..d1e4777b4e75 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
| @@ -273,12 +273,20 @@ static void __init xen_smp_prepare_boot_cpu(void) | |||
| 273 | BUG_ON(smp_processor_id() != 0); | 273 | BUG_ON(smp_processor_id() != 0); |
| 274 | native_smp_prepare_boot_cpu(); | 274 | native_smp_prepare_boot_cpu(); |
| 275 | 275 | ||
| 276 | /* We've switched to the "real" per-cpu gdt, so make sure the | 276 | if (xen_pv_domain()) { |
| 277 | old memory can be recycled */ | 277 | /* We've switched to the "real" per-cpu gdt, so make sure the |
| 278 | make_lowmem_page_readwrite(xen_initial_gdt); | 278 | old memory can be recycled */ |
| 279 | make_lowmem_page_readwrite(xen_initial_gdt); | ||
| 279 | 280 | ||
| 280 | xen_filter_cpu_maps(); | 281 | xen_filter_cpu_maps(); |
| 281 | xen_setup_vcpu_info_placement(); | 282 | xen_setup_vcpu_info_placement(); |
| 283 | } | ||
| 284 | /* | ||
| 285 | * The alternative logic (which patches the unlock/lock) runs before | ||
| 286 | * the smp bootup up code is activated. Hence we need to set this up | ||
| 287 | * the core kernel is being patched. Otherwise we will have only | ||
| 288 | * modules patched but not core code. | ||
| 289 | */ | ||
| 282 | xen_init_spinlocks(); | 290 | xen_init_spinlocks(); |
| 283 | } | 291 | } |
| 284 | 292 | ||
| @@ -709,6 +717,15 @@ static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle) | |||
| 709 | WARN_ON(rc); | 717 | WARN_ON(rc); |
| 710 | if (!rc) | 718 | if (!rc) |
| 711 | rc = native_cpu_up(cpu, tidle); | 719 | rc = native_cpu_up(cpu, tidle); |
| 720 | |||
| 721 | /* | ||
| 722 | * We must initialize the slowpath CPU kicker _after_ the native | ||
| 723 | * path has executed. If we initialized it before none of the | ||
| 724 | * unlocker IPI kicks would reach the booting CPU as the booting | ||
| 725 | * CPU had not set itself 'online' in cpu_online_mask. That mask | ||
| 726 | * is checked when IPIs are sent (on HVM at least). | ||
| 727 | */ | ||
| 728 | xen_init_lock_cpu(cpu); | ||
| 712 | return rc; | 729 | return rc; |
| 713 | } | 730 | } |
| 714 | 731 | ||
| @@ -728,4 +745,5 @@ void __init xen_hvm_smp_init(void) | |||
| 728 | smp_ops.cpu_die = xen_hvm_cpu_die; | 745 | smp_ops.cpu_die = xen_hvm_cpu_die; |
| 729 | smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi; | 746 | smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi; |
| 730 | smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi; | 747 | smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi; |
| 748 | smp_ops.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu; | ||
| 731 | } | 749 | } |
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 0438b9324a72..253f63fceea1 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c | |||
| @@ -81,7 +81,6 @@ static inline void spin_time_accum_blocked(u64 start) | |||
| 81 | spinlock_stats.time_blocked += delta; | 81 | spinlock_stats.time_blocked += delta; |
| 82 | } | 82 | } |
| 83 | #else /* !CONFIG_XEN_DEBUG_FS */ | 83 | #else /* !CONFIG_XEN_DEBUG_FS */ |
| 84 | #define TIMEOUT (1 << 10) | ||
| 85 | static inline void add_stats(enum xen_contention_stat var, u32 val) | 84 | static inline void add_stats(enum xen_contention_stat var, u32 val) |
| 86 | { | 85 | { |
| 87 | } | 86 | } |
| @@ -96,23 +95,6 @@ static inline void spin_time_accum_blocked(u64 start) | |||
| 96 | } | 95 | } |
| 97 | #endif /* CONFIG_XEN_DEBUG_FS */ | 96 | #endif /* CONFIG_XEN_DEBUG_FS */ |
| 98 | 97 | ||
| 99 | /* | ||
| 100 | * Size struct xen_spinlock so it's the same as arch_spinlock_t. | ||
| 101 | */ | ||
| 102 | #if NR_CPUS < 256 | ||
| 103 | typedef u8 xen_spinners_t; | ||
| 104 | # define inc_spinners(xl) \ | ||
| 105 | asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory"); | ||
| 106 | # define dec_spinners(xl) \ | ||
| 107 | asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory"); | ||
| 108 | #else | ||
| 109 | typedef u16 xen_spinners_t; | ||
| 110 | # define inc_spinners(xl) \ | ||
| 111 | asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory"); | ||
| 112 | # define dec_spinners(xl) \ | ||
| 113 | asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory"); | ||
| 114 | #endif | ||
| 115 | |||
| 116 | struct xen_lock_waiting { | 98 | struct xen_lock_waiting { |
| 117 | struct arch_spinlock *lock; | 99 | struct arch_spinlock *lock; |
| 118 | __ticket_t want; | 100 | __ticket_t want; |
| @@ -123,6 +105,7 @@ static DEFINE_PER_CPU(char *, irq_name); | |||
| 123 | static DEFINE_PER_CPU(struct xen_lock_waiting, lock_waiting); | 105 | static DEFINE_PER_CPU(struct xen_lock_waiting, lock_waiting); |
| 124 | static cpumask_t waiting_cpus; | 106 | static cpumask_t waiting_cpus; |
| 125 | 107 | ||
| 108 | static bool xen_pvspin = true; | ||
| 126 | static void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) | 109 | static void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) |
| 127 | { | 110 | { |
| 128 | int irq = __this_cpu_read(lock_kicker_irq); | 111 | int irq = __this_cpu_read(lock_kicker_irq); |
| @@ -241,16 +224,12 @@ void xen_init_lock_cpu(int cpu) | |||
| 241 | int irq; | 224 | int irq; |
| 242 | char *name; | 225 | char *name; |
| 243 | 226 | ||
| 227 | if (!xen_pvspin) | ||
| 228 | return; | ||
| 229 | |||
| 244 | WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n", | 230 | WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n", |
| 245 | cpu, per_cpu(lock_kicker_irq, cpu)); | 231 | cpu, per_cpu(lock_kicker_irq, cpu)); |
| 246 | 232 | ||
| 247 | /* | ||
| 248 | * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23 | ||
| 249 | * (xen: disable PV spinlocks on HVM) | ||
| 250 | */ | ||
| 251 | if (xen_hvm_domain()) | ||
| 252 | return; | ||
| 253 | |||
| 254 | name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); | 233 | name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); |
| 255 | irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, | 234 | irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, |
| 256 | cpu, | 235 | cpu, |
| @@ -270,11 +249,7 @@ void xen_init_lock_cpu(int cpu) | |||
| 270 | 249 | ||
| 271 | void xen_uninit_lock_cpu(int cpu) | 250 | void xen_uninit_lock_cpu(int cpu) |
| 272 | { | 251 | { |
| 273 | /* | 252 | if (!xen_pvspin) |
| 274 | * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23 | ||
| 275 | * (xen: disable PV spinlocks on HVM) | ||
| 276 | */ | ||
| 277 | if (xen_hvm_domain()) | ||
| 278 | return; | 253 | return; |
| 279 | 254 | ||
| 280 | unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); | 255 | unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); |
| @@ -283,16 +258,9 @@ void xen_uninit_lock_cpu(int cpu) | |||
| 283 | per_cpu(irq_name, cpu) = NULL; | 258 | per_cpu(irq_name, cpu) = NULL; |
| 284 | } | 259 | } |
| 285 | 260 | ||
| 286 | static bool xen_pvspin __initdata = true; | ||
| 287 | 261 | ||
| 288 | void __init xen_init_spinlocks(void) | 262 | void __init xen_init_spinlocks(void) |
| 289 | { | 263 | { |
| 290 | /* | ||
| 291 | * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23 | ||
| 292 | * (xen: disable PV spinlocks on HVM) | ||
| 293 | */ | ||
| 294 | if (xen_hvm_domain()) | ||
| 295 | return; | ||
| 296 | 264 | ||
| 297 | if (!xen_pvspin) { | 265 | if (!xen_pvspin) { |
| 298 | printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); | 266 | printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); |
| @@ -323,6 +291,9 @@ static int __init xen_spinlock_debugfs(void) | |||
| 323 | if (d_xen == NULL) | 291 | if (d_xen == NULL) |
| 324 | return -ENOMEM; | 292 | return -ENOMEM; |
| 325 | 293 | ||
| 294 | if (!xen_pvspin) | ||
| 295 | return 0; | ||
| 296 | |||
| 326 | d_spin_debug = debugfs_create_dir("spinlocks", d_xen); | 297 | d_spin_debug = debugfs_create_dir("spinlocks", d_xen); |
| 327 | 298 | ||
| 328 | debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats); | 299 | debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats); |
