aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2009-08-28 08:06:29 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-09-02 02:19:01 -0400
commit46db2f86a3b2a94e0b33e0b4548fb7b7b6bdff66 (patch)
tree6aef8ab146a54d04dd207b0f85f362a4aee3ef5d /arch/powerpc
parentb8e4a7dae53760b9791aca96e74366078692d90f (diff)
powerpc/pseries: Fix to handle slb resize across migration
The SLB can change sizes across a live migration, which was not being handled, resulting in possible machine crashes during migration if migrating to a machine which has a smaller max SLB size than the source machine. Fix this by first reducing the SLB size to the minimum possible value, which is 32, prior to migration. Then during the device tree update which occurs after migration, we make the call to ensure the SLB gets updated. Also add the slb_size to the lparcfg output so that the migration tools can check to make sure the kernel has this capability before allowing migration in scenarios where the SLB size will change. BenH: Fixed #include <asm/mmu-hash64.h> -> <asm/mmu.h> to avoid breaking ppc32 build Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h2
-rw-r--r--arch/powerpc/kernel/lparcfg.c3
-rw-r--r--arch/powerpc/kernel/rtas.c7
-rw-r--r--arch/powerpc/mm/slb.c16
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c9
5 files changed, 31 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index b537903b9fca..bebe31c2e907 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -41,6 +41,7 @@ extern char initial_stab[];
41 41
42#define SLB_NUM_BOLTED 3 42#define SLB_NUM_BOLTED 3
43#define SLB_CACHE_ENTRIES 8 43#define SLB_CACHE_ENTRIES 8
44#define SLB_MIN_SIZE 32
44 45
45/* Bits in the SLB ESID word */ 46/* Bits in the SLB ESID word */
46#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ 47#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
@@ -276,6 +277,7 @@ extern void slb_flush_and_rebolt(void);
276extern void stab_initialize(unsigned long stab); 277extern void stab_initialize(unsigned long stab);
277 278
278extern void slb_vmalloc_update(void); 279extern void slb_vmalloc_update(void);
280extern void slb_set_size(u16 size);
279#endif /* __ASSEMBLY__ */ 281#endif /* __ASSEMBLY__ */
280 282
281/* 283/*
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 2419cc706ff1..ed0ac4e4b8d8 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -35,6 +35,7 @@
35#include <asm/prom.h> 35#include <asm/prom.h>
36#include <asm/vdso_datapage.h> 36#include <asm/vdso_datapage.h>
37#include <asm/vio.h> 37#include <asm/vio.h>
38#include <asm/mmu.h>
38 39
39#define MODULE_VERS "1.8" 40#define MODULE_VERS "1.8"
40#define MODULE_NAME "lparcfg" 41#define MODULE_NAME "lparcfg"
@@ -537,6 +538,8 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
537 538
538 seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); 539 seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
539 540
541 seq_printf(m, "slb_size=%d\n", mmu_slb_size);
542
540 return 0; 543 return 0;
541} 544}
542 545
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index c434823b8c83..bf90361bb70f 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -39,6 +39,7 @@
39#include <asm/smp.h> 39#include <asm/smp.h>
40#include <asm/atomic.h> 40#include <asm/atomic.h>
41#include <asm/time.h> 41#include <asm/time.h>
42#include <asm/mmu.h>
42 43
43struct rtas_t rtas = { 44struct rtas_t rtas = {
44 .lock = __RAW_SPIN_LOCK_UNLOCKED 45 .lock = __RAW_SPIN_LOCK_UNLOCKED
@@ -713,6 +714,7 @@ static void rtas_percpu_suspend_me(void *info)
713{ 714{
714 long rc = H_SUCCESS; 715 long rc = H_SUCCESS;
715 unsigned long msr_save; 716 unsigned long msr_save;
717 u16 slb_size = mmu_slb_size;
716 int cpu; 718 int cpu;
717 struct rtas_suspend_me_data *data = 719 struct rtas_suspend_me_data *data =
718 (struct rtas_suspend_me_data *)info; 720 (struct rtas_suspend_me_data *)info;
@@ -735,13 +737,16 @@ static void rtas_percpu_suspend_me(void *info)
735 /* All other cpus are in H_JOIN, this cpu does 737 /* All other cpus are in H_JOIN, this cpu does
736 * the suspend. 738 * the suspend.
737 */ 739 */
740 slb_set_size(SLB_MIN_SIZE);
738 printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", 741 printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n",
739 smp_processor_id()); 742 smp_processor_id());
740 data->error = rtas_call(data->token, 0, 1, NULL); 743 data->error = rtas_call(data->token, 0, 1, NULL);
741 744
742 if (data->error) 745 if (data->error) {
743 printk(KERN_DEBUG "ibm,suspend-me returned %d\n", 746 printk(KERN_DEBUG "ibm,suspend-me returned %d\n",
744 data->error); 747 data->error);
748 slb_set_size(slb_size);
749 }
745 } else { 750 } else {
746 printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", 751 printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
747 smp_processor_id(), rc); 752 smp_processor_id(), rc);
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index 07961c5c169e..1d98ecc8eecd 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -249,14 +249,22 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
249static inline void patch_slb_encoding(unsigned int *insn_addr, 249static inline void patch_slb_encoding(unsigned int *insn_addr,
250 unsigned int immed) 250 unsigned int immed)
251{ 251{
252 /* Assume the instruction had a "0" immediate value, just 252 *insn_addr = (*insn_addr & 0xffff0000) | immed;
253 * "or" in the new value
254 */
255 *insn_addr |= immed;
256 flush_icache_range((unsigned long)insn_addr, 4+ 253 flush_icache_range((unsigned long)insn_addr, 4+
257 (unsigned long)insn_addr); 254 (unsigned long)insn_addr);
258} 255}
259 256
257void slb_set_size(u16 size)
258{
259 extern unsigned int *slb_compare_rr_to_size;
260
261 if (mmu_slb_size == size)
262 return;
263
264 mmu_slb_size = size;
265 patch_slb_encoding(slb_compare_rr_to_size, mmu_slb_size);
266}
267
260void slb_initialize(void) 268void slb_initialize(void)
261{ 269{
262 unsigned long linear_llp, vmalloc_llp, io_llp; 270 unsigned long linear_llp, vmalloc_llp, io_llp;
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index b6f1b137d427..2e2bbe120b90 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -20,6 +20,7 @@
20#include <asm/machdep.h> 20#include <asm/machdep.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22#include <asm/pSeries_reconfig.h> 22#include <asm/pSeries_reconfig.h>
23#include <asm/mmu.h>
23 24
24 25
25 26
@@ -439,9 +440,15 @@ static int do_update_property(char *buf, size_t bufsize)
439 if (!newprop) 440 if (!newprop)
440 return -ENOMEM; 441 return -ENOMEM;
441 442
443 if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
444 slb_set_size(*(int *)value);
445
442 oldprop = of_find_property(np, name,NULL); 446 oldprop = of_find_property(np, name,NULL);
443 if (!oldprop) 447 if (!oldprop) {
448 if (strlen(name))
449 return prom_add_property(np, newprop);
444 return -ENODEV; 450 return -ENODEV;
451 }
445 452
446 rc = prom_update_property(np, newprop, oldprop); 453 rc = prom_update_property(np, newprop, oldprop);
447 if (rc) 454 if (rc)