[PATCH 1/1] powerpc: Fix to handle slb resize across migration
Benjamin Herrenschmidt
benh at kernel.crashing.org
Mon Aug 31 16:22:55 EST 2009
On Fri, 2009-08-28 at 17:06 -0500, Brian King wrote:
> 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.
>
> Signed-off-by: Brian King <brking at linux.vnet.ibm.com>
> ---
Thanks. I'll apply to -next hopefully tomorrow, and then we can send it
to the various -stable.
Cheers,
Ben.
> arch/powerpc/include/asm/mmu-hash64.h | 2 ++
> arch/powerpc/kernel/lparcfg.c | 3 +++
> arch/powerpc/kernel/rtas.c | 7 ++++++-
> arch/powerpc/mm/slb.c | 16 ++++++++++++----
> arch/powerpc/platforms/pseries/reconfig.c | 9 ++++++++-
> 5 files changed, 31 insertions(+), 6 deletions(-)
>
> diff -puN arch/powerpc/kernel/rtas.c~powerpc_slb_resize arch/powerpc/kernel/rtas.c
> --- linux-2.6/arch/powerpc/kernel/rtas.c~powerpc_slb_resize 2009-08-21 16:14:41.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/kernel/rtas.c 2009-08-21 16:14:41.000000000 -0500
> @@ -39,6 +39,7 @@
> #include <asm/smp.h>
> #include <asm/atomic.h>
> #include <asm/time.h>
> +#include <asm/mmu-hash64.h>
>
> struct rtas_t rtas = {
> .lock = __RAW_SPIN_LOCK_UNLOCKED
> @@ -713,6 +714,7 @@ static void rtas_percpu_suspend_me(void
> {
> long rc = H_SUCCESS;
> unsigned long msr_save;
> + u16 slb_size = mmu_slb_size;
> int cpu;
> struct rtas_suspend_me_data *data =
> (struct rtas_suspend_me_data *)info;
> @@ -735,13 +737,16 @@ static void rtas_percpu_suspend_me(void
> /* All other cpus are in H_JOIN, this cpu does
> * the suspend.
> */
> + slb_set_size(SLB_MIN_SIZE);
> printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n",
> smp_processor_id());
> data->error = rtas_call(data->token, 0, 1, NULL);
>
> - if (data->error)
> + if (data->error) {
> printk(KERN_DEBUG "ibm,suspend-me returned %d\n",
> data->error);
> + slb_set_size(slb_size);
> + }
> } else {
> printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
> smp_processor_id(), rc);
> diff -puN arch/powerpc/include/asm/mmu-hash64.h~powerpc_slb_resize arch/powerpc/include/asm/mmu-hash64.h
> --- linux-2.6/arch/powerpc/include/asm/mmu-hash64.h~powerpc_slb_resize 2009-08-21 16:14:41.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/include/asm/mmu-hash64.h 2009-08-21 16:14:41.000000000 -0500
> @@ -41,6 +41,7 @@ extern char initial_stab[];
>
> #define SLB_NUM_BOLTED 3
> #define SLB_CACHE_ENTRIES 8
> +#define SLB_MIN_SIZE 32
>
> /* Bits in the SLB ESID word */
> #define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
> @@ -296,6 +297,7 @@ extern void slb_flush_and_rebolt(void);
> extern void stab_initialize(unsigned long stab);
>
> extern void slb_vmalloc_update(void);
> +extern void slb_set_size(u16 size);
> #endif /* __ASSEMBLY__ */
>
> /*
> diff -puN arch/powerpc/mm/slb.c~powerpc_slb_resize arch/powerpc/mm/slb.c
> --- linux-2.6/arch/powerpc/mm/slb.c~powerpc_slb_resize 2009-08-21 16:14:41.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/mm/slb.c 2009-08-21 16:14:41.000000000 -0500
> @@ -240,14 +240,22 @@ void switch_slb(struct task_struct *tsk,
> static inline void patch_slb_encoding(unsigned int *insn_addr,
> unsigned int immed)
> {
> - /* Assume the instruction had a "0" immediate value, just
> - * "or" in the new value
> - */
> - *insn_addr |= immed;
> + *insn_addr = (*insn_addr & 0xffff0000) | immed;
> flush_icache_range((unsigned long)insn_addr, 4+
> (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)
> {
> unsigned long linear_llp, vmalloc_llp, io_llp;
> diff -puN arch/powerpc/platforms/pseries/reconfig.c~powerpc_slb_resize arch/powerpc/platforms/pseries/reconfig.c
> --- linux-2.6/arch/powerpc/platforms/pseries/reconfig.c~powerpc_slb_resize 2009-08-21 16:14:41.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/reconfig.c 2009-08-28 13:36:55.000000000 -0500
> @@ -20,6 +20,7 @@
> #include <asm/machdep.h>
> #include <asm/uaccess.h>
> #include <asm/pSeries_reconfig.h>
> +#include <asm/mmu-hash64.h>
>
>
>
> @@ -439,9 +440,15 @@ static int do_update_property(char *buf,
> if (!newprop)
> return -ENOMEM;
>
> + if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
> + slb_set_size(*(int *)value);
> +
> oldprop = of_find_property(np, name,NULL);
> - if (!oldprop)
> + if (!oldprop) {
> + if (strlen(name))
> + return prom_add_property(np, newprop);
> return -ENODEV;
> + }
>
> rc = prom_update_property(np, newprop, oldprop);
> if (rc)
> diff -puN arch/powerpc/kernel/lparcfg.c~powerpc_slb_resize arch/powerpc/kernel/lparcfg.c
> --- linux-2.6/arch/powerpc/kernel/lparcfg.c~powerpc_slb_resize 2009-08-21 16:14:41.000000000 -0500
> +++ linux-2.6-bjking1/arch/powerpc/kernel/lparcfg.c 2009-08-21 16:14:41.000000000 -0500
> @@ -35,6 +35,7 @@
> #include <asm/prom.h>
> #include <asm/vdso_datapage.h>
> #include <asm/vio.h>
> +#include <asm/mmu-hash64.h>
>
> #define MODULE_VERS "1.8"
> #define MODULE_NAME "lparcfg"
> @@ -537,6 +538,8 @@ static int pseries_lparcfg_data(struct s
>
> seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
>
> + seq_printf(m, "slb_size=%d\n", mmu_slb_size);
> +
> return 0;
> }
>
> _
More information about the Linuxppc-dev
mailing list