commitfa41ba0d08
("s390/mm: avoid empty zero pages for KVM guests to avoid postcopy hangs") introduced an undesired side effect when combined with memory ballooning and VM migration: memory part of the inflated memory balloon will consume memory. Assuming we have a 100GiB VM and inflated the balloon to 40GiB. Our VM will consume ~60GiB of memory. If we now trigger a VM migration, hypervisors like QEMU will read all VM memory. As s390x does not support the shared zeropage, we'll end up allocating for all previously-inflated memory part of the memory balloon: 50 GiB. So we might easily (unexpectedly) crash the VM on the migration source. Even worse, hypervisors like QEMU optimize for zeropage migration to not consume memory on the migration destination: when migrating a "page full of zeroes", on the migration destination they check whether the target memory is already zero (by reading the destination memory) and avoid writing to the memory to not allocate memory: however, s390x will also allocate memory here, implying that also on the migration destination, we will end up allocating all previously-inflated memory part of the memory balloon. This is especially bad if actual memory overcommit was not desired, when memory ballooning is used for dynamic VM memory resizing, setting aside some memory during boot that can be added later on demand. Alternatives like virtio-mem that would avoid this issue are not yet available on s390x. There could be ways to optimize some cases in user space: before reading memory in an anonymous private mapping on the migration source, check via /proc/self/pagemap if anything is already populated. Similarly check on the migration destination before reading. While that would avoid populating tables full of shared zeropages on all architectures, it's harder to get right and performant, and requires user space changes. Further, with posctopy live migration we must place a page, so there, "avoid touching memory to avoid allocating memory" is not really possible. (Note that a previously we would have falsely inserted shared zeropages into processes using UFFDIO_ZEROPAGE where mm_forbids_zeropage() would have actually forbidden it) PV is currently incompatible with memory ballooning, and in the common case, KVM guests don't make use of storage keys. Instead of zapping zeropages when enabling storage keys / PV, that turned out to be problematic in the past, let's do exactly the same we do with KSM pages: trigger unsharing faults to replace the shared zeropages by proper anonymous folios. What about added latency when enabling storage kes? Having a lot of zeropages in applicable environments (PV, legacy guests, unittests) is unexpected. Further, KSM could today already unshare the zeropages and unmerging KSM pages when enabling storage kets would unshare the KSM-placed zeropages in the same way, resulting in the same latency. [ agordeev: Fixed sparse and checkpatch complaints and error handling ] Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com> Tested-by: Christian Borntraeger <borntraeger@linux.ibm.com> Fixes:fa41ba0d08
("s390/mm: avoid empty zero pages for KVM guests to avoid postcopy hangs") Signed-off-by: David Hildenbrand <david@redhat.com> Link: https://lore.kernel.org/r/20240411161441.910170-3-david@redhat.com Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
48 lines
1.4 KiB
C
48 lines
1.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __MMU_H
|
|
#define __MMU_H
|
|
|
|
#include <linux/cpumask.h>
|
|
#include <linux/errno.h>
|
|
#include <asm/asm-extable.h>
|
|
|
|
typedef struct {
|
|
spinlock_t lock;
|
|
cpumask_t cpu_attach_mask;
|
|
atomic_t flush_count;
|
|
unsigned int flush_mm;
|
|
struct list_head gmap_list;
|
|
unsigned long gmap_asce;
|
|
unsigned long asce;
|
|
unsigned long asce_limit;
|
|
unsigned long vdso_base;
|
|
/* The mmu context belongs to a secure guest. */
|
|
atomic_t protected_count;
|
|
/*
|
|
* The following bitfields need a down_write on the mm
|
|
* semaphore when they are written to. As they are only
|
|
* written once, they can be read without a lock.
|
|
*
|
|
* The mmu context allocates 4K page tables.
|
|
*/
|
|
unsigned int alloc_pgste:1;
|
|
/* The mmu context uses extended page tables. */
|
|
unsigned int has_pgste:1;
|
|
/* The mmu context uses storage keys. */
|
|
unsigned int uses_skeys:1;
|
|
/* The mmu context uses CMM. */
|
|
unsigned int uses_cmm:1;
|
|
/*
|
|
* The mmu context allows COW-sharing of memory pages (KSM, zeropage).
|
|
* Note that COW-sharing during fork() is currently always allowed.
|
|
*/
|
|
unsigned int allow_cow_sharing:1;
|
|
/* The gmaps associated with this context are allowed to use huge pages. */
|
|
unsigned int allow_gmap_hpage_1m:1;
|
|
} mm_context_t;
|
|
|
|
#define INIT_MM_CONTEXT(name) \
|
|
.context.lock = __SPIN_LOCK_UNLOCKED(name.context.lock), \
|
|
.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
|
|
|
|
#endif
|