diff options
-rw-r--r-- | include/exec/memory.h | 18 | ||||
-rw-r--r-- | softmmu/physmem.c | 54 |
2 files changed, 64 insertions, 8 deletions
diff --git a/include/exec/memory.h b/include/exec/memory.h index 27a8833173..c3d417d317 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2894,6 +2894,12 @@ static inline MemOp devend_memop(enum device_endian end) int ram_block_discard_disable(bool state); /* + * See ram_block_discard_disable(): only disable uncoordinated discards, + * keeping coordinated discards (via the RamDiscardManager) enabled. + */ +int ram_block_uncoordinated_discard_disable(bool state); + +/* * Inhibit technologies that disable discarding of pages in RAM blocks. * * Returns 0 if successful. Returns -EBUSY if discards are already set to @@ -2902,12 +2908,20 @@ int ram_block_discard_disable(bool state); int ram_block_discard_require(bool state); /* - * Test if discarding of memory in ram blocks is disabled. + * See ram_block_discard_require(): only inhibit technologies that disable + * uncoordinated discarding of pages in RAM blocks, allowing co-existance with + * technologies that only inhibit uncoordinated discards (via the + * RamDiscardManager). + */ +int ram_block_coordinated_discard_require(bool state); + +/* + * Test if any discarding of memory in ram blocks is disabled. */ bool ram_block_discard_is_disabled(void); /* - * Test if discarding of memory in ram blocks is required to work reliably. + * Test if any discarding of memory in ram blocks is required to work reliably. */ bool ram_block_discard_is_required(void); diff --git a/softmmu/physmem.c b/softmmu/physmem.c index f1275b61f8..3c1912a1a0 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -3684,8 +3684,14 @@ void mtree_print_dispatch(AddressSpaceDispatch *d, MemoryRegion *root) } } +/* Require any discards to work. */ static unsigned int ram_block_discard_required_cnt; +/* Require only coordinated discards to work. */ +static unsigned int ram_block_coordinated_discard_required_cnt; +/* Disable any discards. */ static unsigned int ram_block_discard_disabled_cnt; +/* Disable only uncoordinated discards. */ +static unsigned int ram_block_uncoordinated_discard_disabled_cnt; static QemuMutex ram_block_discard_disable_mutex; static void ram_block_discard_disable_mutex_lock(void) @@ -3711,10 +3717,27 @@ int ram_block_discard_disable(bool state) ram_block_discard_disable_mutex_lock(); if (!state) { ram_block_discard_disabled_cnt--; - } else if (!ram_block_discard_required_cnt) { - ram_block_discard_disabled_cnt++; + } else if (ram_block_discard_required_cnt || + ram_block_coordinated_discard_required_cnt) { + ret = -EBUSY; } else { + ram_block_discard_disabled_cnt++; + } + ram_block_discard_disable_mutex_unlock(); + return ret; +} + +int ram_block_uncoordinated_discard_disable(bool state) +{ + int ret = 0; + + ram_block_discard_disable_mutex_lock(); + if (!state) { + ram_block_uncoordinated_discard_disabled_cnt--; + } else if (ram_block_discard_required_cnt) { ret = -EBUSY; + } else { + ram_block_uncoordinated_discard_disabled_cnt++; } ram_block_discard_disable_mutex_unlock(); return ret; @@ -3727,10 +3750,27 @@ int ram_block_discard_require(bool state) ram_block_discard_disable_mutex_lock(); if (!state) { ram_block_discard_required_cnt--; - } else if (!ram_block_discard_disabled_cnt) { - ram_block_discard_required_cnt++; + } else if (ram_block_discard_disabled_cnt || + ram_block_uncoordinated_discard_disabled_cnt) { + ret = -EBUSY; } else { + ram_block_discard_required_cnt++; + } + ram_block_discard_disable_mutex_unlock(); + return ret; +} + +int ram_block_coordinated_discard_require(bool state) +{ + int ret = 0; + + ram_block_discard_disable_mutex_lock(); + if (!state) { + ram_block_coordinated_discard_required_cnt--; + } else if (ram_block_discard_disabled_cnt) { ret = -EBUSY; + } else { + ram_block_coordinated_discard_required_cnt++; } ram_block_discard_disable_mutex_unlock(); return ret; @@ -3738,10 +3778,12 @@ int ram_block_discard_require(bool state) bool ram_block_discard_is_disabled(void) { - return qatomic_read(&ram_block_discard_disabled_cnt); + return qatomic_read(&ram_block_discard_disabled_cnt) || + qatomic_read(&ram_block_uncoordinated_discard_disabled_cnt); } bool ram_block_discard_is_required(void) { - return qatomic_read(&ram_block_discard_required_cnt); + return qatomic_read(&ram_block_discard_required_cnt) || + qatomic_read(&ram_block_coordinated_discard_required_cnt); } |