Commit 79619412 authored by Brian King's avatar Brian King Committed by Greg Kroah-Hartman

powerpc/pseries: Fix to handle slb resize across migration

commit 46db2f86 upstream.

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: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6cc51b05
...@@ -41,6 +41,7 @@ extern char initial_stab[]; ...@@ -41,6 +41,7 @@ extern char initial_stab[];
#define SLB_NUM_BOLTED 3 #define SLB_NUM_BOLTED 3
#define SLB_CACHE_ENTRIES 8 #define SLB_CACHE_ENTRIES 8
#define SLB_MIN_SIZE 32
/* Bits in the SLB ESID word */ /* Bits in the SLB ESID word */
#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ #define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
...@@ -296,6 +297,7 @@ extern void slb_flush_and_rebolt(void); ...@@ -296,6 +297,7 @@ extern void slb_flush_and_rebolt(void);
extern void stab_initialize(unsigned long stab); extern void stab_initialize(unsigned long stab);
extern void slb_vmalloc_update(void); extern void slb_vmalloc_update(void);
extern void slb_set_size(u16 size);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* /*
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/mmu.h>
#define MODULE_VERS "1.8" #define MODULE_VERS "1.8"
#define MODULE_NAME "lparcfg" #define MODULE_NAME "lparcfg"
...@@ -537,6 +538,8 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) ...@@ -537,6 +538,8 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
seq_printf(m, "slb_size=%d\n", mmu_slb_size);
return 0; return 0;
} }
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/mmu.h>
struct rtas_t rtas = { struct rtas_t rtas = {
.lock = __RAW_SPIN_LOCK_UNLOCKED .lock = __RAW_SPIN_LOCK_UNLOCKED
...@@ -713,6 +714,7 @@ static void rtas_percpu_suspend_me(void *info) ...@@ -713,6 +714,7 @@ static void rtas_percpu_suspend_me(void *info)
{ {
long rc = H_SUCCESS; long rc = H_SUCCESS;
unsigned long msr_save; unsigned long msr_save;
u16 slb_size = mmu_slb_size;
int cpu; int cpu;
struct rtas_suspend_me_data *data = struct rtas_suspend_me_data *data =
(struct rtas_suspend_me_data *)info; (struct rtas_suspend_me_data *)info;
...@@ -735,13 +737,16 @@ static void rtas_percpu_suspend_me(void *info) ...@@ -735,13 +737,16 @@ static void rtas_percpu_suspend_me(void *info)
/* All other cpus are in H_JOIN, this cpu does /* All other cpus are in H_JOIN, this cpu does
* the suspend. * the suspend.
*/ */
slb_set_size(SLB_MIN_SIZE);
printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n",
smp_processor_id()); smp_processor_id());
data->error = rtas_call(data->token, 0, 1, NULL); data->error = rtas_call(data->token, 0, 1, NULL);
if (data->error) if (data->error) {
printk(KERN_DEBUG "ibm,suspend-me returned %d\n", printk(KERN_DEBUG "ibm,suspend-me returned %d\n",
data->error); data->error);
slb_set_size(slb_size);
}
} else { } else {
printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
smp_processor_id(), rc); smp_processor_id(), rc);
......
...@@ -240,14 +240,22 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) ...@@ -240,14 +240,22 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
static inline void patch_slb_encoding(unsigned int *insn_addr, static inline void patch_slb_encoding(unsigned int *insn_addr,
unsigned int immed) unsigned int immed)
{ {
/* Assume the instruction had a "0" immediate value, just *insn_addr = (*insn_addr & 0xffff0000) | immed;
* "or" in the new value
*/
*insn_addr |= immed;
flush_icache_range((unsigned long)insn_addr, 4+ flush_icache_range((unsigned long)insn_addr, 4+
(unsigned long)insn_addr); (unsigned long)insn_addr);
} }
void slb_set_size(u16 size)
{
extern unsigned int *slb_compare_rr_to_size;
if (mmu_slb_size == size)
return;
mmu_slb_size = size;
patch_slb_encoding(slb_compare_rr_to_size, mmu_slb_size);
}
void slb_initialize(void) void slb_initialize(void)
{ {
unsigned long linear_llp, vmalloc_llp, io_llp; unsigned long linear_llp, vmalloc_llp, io_llp;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pSeries_reconfig.h> #include <asm/pSeries_reconfig.h>
#include <asm/mmu.h>
...@@ -439,9 +440,15 @@ static int do_update_property(char *buf, size_t bufsize) ...@@ -439,9 +440,15 @@ static int do_update_property(char *buf, size_t bufsize)
if (!newprop) if (!newprop)
return -ENOMEM; return -ENOMEM;
if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
slb_set_size(*(int *)value);
oldprop = of_find_property(np, name,NULL); oldprop = of_find_property(np, name,NULL);
if (!oldprop) if (!oldprop) {
if (strlen(name))
return prom_add_property(np, newprop);
return -ENODEV; return -ENODEV;
}
rc = prom_update_property(np, newprop, oldprop); rc = prom_update_property(np, newprop, oldprop);
if (rc) if (rc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment