powerpc/kernel: Enables memory hot-remove after reboot on pseries guests
authorLeonardo Bras <leonardo@linux.ibm.com>
Thu, 2 Apr 2020 19:51:57 +0000 (16:51 -0300)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 2 Jun 2020 10:59:07 +0000 (20:59 +1000)
While providing guests, it's desirable to resize it's memory on demand.

By now, it's possible to do so by creating a guest with a small base
memory, hot-plugging all the rest, and using 'movable_node' kernel
command-line parameter, which puts all hot-plugged memory in
ZONE_MOVABLE, allowing it to be removed whenever needed.

But there is an issue regarding guest reboot:
If memory is hot-plugged, and then the guest is rebooted, all hot-plugged
memory goes to ZONE_NORMAL, which offers no guaranteed hot-removal.
It usually prevents this memory to be hot-removed from the guest.

It's possible to use device-tree information to fix that behavior, as
it stores flags for LMB ranges on ibm,dynamic-memory-vN.
It involves marking each memblock with the correct flags as hotpluggable
memory, which mm/memblock.c puts in ZONE_MOVABLE during boot if
'movable_node' is passed.

For carrying such information, the new flag DRCONF_MEM_HOTREMOVABLE was
proposed and accepted into Power Architecture documentation.
This flag should be:
- true (b=1) if the hypervisor may want to hot-remove it later, and
- false (b=0) if it does not care.

During boot, guest kernel reads the device-tree, early_init_drmem_lmb()
is called for every added LMBs. Here, checking for this new flag and
marking memblocks as hotplugable memory is enough to get the desirable
behavior.

This should cause no change if 'movable_node' parameter is not passed
in kernel command-line.

Signed-off-by: Leonardo Bras <leonardo@linux.ibm.com>
Reviewed-by: Bharata B Rao <bharata@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200402195156.626430-1-leonardo@linux.ibm.com
arch/powerpc/include/asm/drmem.h
arch/powerpc/kernel/prom.c

index 28c3d936fdf32a29193281d1f6e97296bc8b536f..414d209f45bbe9b07dff10db5855f2f5d53c5026 100644 (file)
@@ -65,6 +65,7 @@ struct of_drconf_cell_v2 {
 #define DRCONF_MEM_ASSIGNED    0x00000008
 #define DRCONF_MEM_AI_INVALID  0x00000040
 #define DRCONF_MEM_RESERVED    0x00000080
+#define DRCONF_MEM_HOTREMOVABLE        0x00000100
 
 static inline u32 drmem_lmb_size(void)
 {
index 1dcf0e214a223b2ac4919cc25fe47108c0cfdfa9..9a651366d3851089759b9b4684b99bc7e57e5cda 100644 (file)
@@ -515,9 +515,14 @@ static void __init early_init_drmem_lmb(struct drmem_lmb *lmb,
                                size = 0x80000000ul - base;
                }
 
+               if (!validate_mem_limit(base, &size))
+                       continue;
+
                DBG("Adding: %llx -> %llx\n", base, size);
-               if (validate_mem_limit(base, &size))
-                       memblock_add(base, size);
+               memblock_add(base, size);
+
+               if (lmb->flags & DRCONF_MEM_HOTREMOVABLE)
+                       memblock_mark_hotplug(base, size);
        } while (--rngs);
 }
 #endif /* CONFIG_PPC_PSERIES */