diff options
-rw-r--r-- | arch/powerpc/include/asm/hvcall.h | 9 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 18 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 8 |
3 files changed, 32 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 0975e5c0bb19..4bc2c3dad6ad 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
@@ -395,6 +395,15 @@ static inline unsigned long cmo_get_page_size(void) | |||
395 | { | 395 | { |
396 | return CMO_PageSize; | 396 | return CMO_PageSize; |
397 | } | 397 | } |
398 | |||
399 | extern long pSeries_enable_reloc_on_exc(void); | ||
400 | extern long pSeries_disable_reloc_on_exc(void); | ||
401 | |||
402 | #else | ||
403 | |||
404 | #define pSeries_enable_reloc_on_exc() do {} while (0) | ||
405 | #define pSeries_disable_reloc_on_exc() do {} while (0) | ||
406 | |||
398 | #endif /* CONFIG_PPC_PSERIES */ | 407 | #endif /* CONFIG_PPC_PSERIES */ |
399 | 408 | ||
400 | #endif /* __ASSEMBLY__ */ | 409 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 28d38adeca73..67e4708388a0 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/kvm_book3s.h> | 34 | #include <asm/kvm_book3s.h> |
35 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
36 | #include <asm/switch_to.h> | 36 | #include <asm/switch_to.h> |
37 | #include <asm/firmware.h> | ||
37 | #include <linux/gfp.h> | 38 | #include <linux/gfp.h> |
38 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
39 | #include <linux/vmalloc.h> | 40 | #include <linux/vmalloc.h> |
@@ -1284,12 +1285,21 @@ void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | |||
1284 | { | 1285 | { |
1285 | } | 1286 | } |
1286 | 1287 | ||
1288 | static unsigned int kvm_global_user_count = 0; | ||
1289 | static DEFINE_SPINLOCK(kvm_global_user_count_lock); | ||
1290 | |||
1287 | int kvmppc_core_init_vm(struct kvm *kvm) | 1291 | int kvmppc_core_init_vm(struct kvm *kvm) |
1288 | { | 1292 | { |
1289 | #ifdef CONFIG_PPC64 | 1293 | #ifdef CONFIG_PPC64 |
1290 | INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); | 1294 | INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); |
1291 | #endif | 1295 | #endif |
1292 | 1296 | ||
1297 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { | ||
1298 | spin_lock(&kvm_global_user_count_lock); | ||
1299 | if (++kvm_global_user_count == 1) | ||
1300 | pSeries_disable_reloc_on_exc(); | ||
1301 | spin_unlock(&kvm_global_user_count_lock); | ||
1302 | } | ||
1293 | return 0; | 1303 | return 0; |
1294 | } | 1304 | } |
1295 | 1305 | ||
@@ -1298,6 +1308,14 @@ void kvmppc_core_destroy_vm(struct kvm *kvm) | |||
1298 | #ifdef CONFIG_PPC64 | 1308 | #ifdef CONFIG_PPC64 |
1299 | WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables)); | 1309 | WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables)); |
1300 | #endif | 1310 | #endif |
1311 | |||
1312 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { | ||
1313 | spin_lock(&kvm_global_user_count_lock); | ||
1314 | BUG_ON(kvm_global_user_count == 0); | ||
1315 | if (--kvm_global_user_count == 0) | ||
1316 | pSeries_enable_reloc_on_exc(); | ||
1317 | spin_unlock(&kvm_global_user_count_lock); | ||
1318 | } | ||
1301 | } | 1319 | } |
1302 | 1320 | ||
1303 | static int kvmppc_book3s_init(void) | 1321 | static int kvmppc_book3s_init(void) |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ca55882465d6..1890730354bb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -375,7 +375,7 @@ static void pSeries_idle(void) | |||
375 | * to ever be a problem in practice we can move this into a kernel thread to | 375 | * to ever be a problem in practice we can move this into a kernel thread to |
376 | * finish off the process later in boot. | 376 | * finish off the process later in boot. |
377 | */ | 377 | */ |
378 | static int __init pSeries_enable_reloc_on_exc(void) | 378 | long pSeries_enable_reloc_on_exc(void) |
379 | { | 379 | { |
380 | long rc; | 380 | long rc; |
381 | unsigned int delay, total_delay = 0; | 381 | unsigned int delay, total_delay = 0; |
@@ -397,9 +397,9 @@ static int __init pSeries_enable_reloc_on_exc(void) | |||
397 | mdelay(delay); | 397 | mdelay(delay); |
398 | } | 398 | } |
399 | } | 399 | } |
400 | EXPORT_SYMBOL(pSeries_enable_reloc_on_exc); | ||
400 | 401 | ||
401 | #ifdef CONFIG_KEXEC | 402 | long pSeries_disable_reloc_on_exc(void) |
402 | static long pSeries_disable_reloc_on_exc(void) | ||
403 | { | 403 | { |
404 | long rc; | 404 | long rc; |
405 | 405 | ||
@@ -410,7 +410,9 @@ static long pSeries_disable_reloc_on_exc(void) | |||
410 | mdelay(get_longbusy_msecs(rc)); | 410 | mdelay(get_longbusy_msecs(rc)); |
411 | } | 411 | } |
412 | } | 412 | } |
413 | EXPORT_SYMBOL(pSeries_disable_reloc_on_exc); | ||
413 | 414 | ||
415 | #ifdef CONFIG_KEXEC | ||
414 | static void pSeries_machine_kexec(struct kimage *image) | 416 | static void pSeries_machine_kexec(struct kimage *image) |
415 | { | 417 | { |
416 | long rc; | 418 | long rc; |