aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-09-24 18:48:45 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-09-24 18:48:45 +0100
commit8c1c07929feae876202ba26f07a540c5115c18cd (patch)
tree20f6c8e2ac556bfb3c88a98c0d0cb2689de0263e /docs
parent1bd5556f6686365e76f7ff67fe67260c449e8345 (diff)
parentd73415a315471ac0b127ed3fad45c8ec5d711de1 (diff)
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Pull request This includes the atomic_ -> qatomic_ rename that touches many files and is prone to conflicts. # gpg: Signature made Wed 23 Sep 2020 17:08:43 BST # gpg: using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [full] # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" [full] # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/block-pull-request: qemu/atomic.h: rename atomic_ to qatomic_ tests: add test-fdmon-epoll fdmon-poll: reset npfd when upgrading to fdmon-epoll gitmodules: add qemu.org vbootrom submodule gitmodules: switch to qemu.org meson mirror gitmodules: switch to qemu.org qboot mirror docs/system: clarify deprecation schedule virtio-crypto: don't modify elem->in/out_sg virtio-blk: undo destructive iov_discard_*() operations util/iov: add iov_discard_undo() virtio: add vhost-user-fs-ccw device libvhost-user: handle endianness as mandated by the spec MAINTAINERS: add Stefan Hajnoczi as block/nvme.c maintainer Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'docs')
-rw-r--r--docs/devel/atomics.rst136
-rw-r--r--docs/devel/lockcnt.txt8
-rw-r--r--docs/devel/rcu.txt34
-rw-r--r--docs/system/deprecated.rst9
4 files changed, 94 insertions, 93 deletions
diff --git a/docs/devel/atomics.rst b/docs/devel/atomics.rst
index 445c3b3503..52baa0736d 100644
--- a/docs/devel/atomics.rst
+++ b/docs/devel/atomics.rst
@@ -23,9 +23,9 @@ provides macros that fall in three camps:
- compiler barriers: ``barrier()``;
-- weak atomic access and manual memory barriers: ``atomic_read()``,
- ``atomic_set()``, ``smp_rmb()``, ``smp_wmb()``, ``smp_mb()``, ``smp_mb_acquire()``,
- ``smp_mb_release()``, ``smp_read_barrier_depends()``;
+- weak atomic access and manual memory barriers: ``qatomic_read()``,
+ ``qatomic_set()``, ``smp_rmb()``, ``smp_wmb()``, ``smp_mb()``,
+ ``smp_mb_acquire()``, ``smp_mb_release()``, ``smp_read_barrier_depends()``;
- sequentially consistent atomic access: everything else.
@@ -67,23 +67,23 @@ in the order specified by its program".
``qemu/atomic.h`` provides the following set of atomic read-modify-write
operations::
- void atomic_inc(ptr)
- void atomic_dec(ptr)
- void atomic_add(ptr, val)
- void atomic_sub(ptr, val)
- void atomic_and(ptr, val)
- void atomic_or(ptr, val)
-
- typeof(*ptr) atomic_fetch_inc(ptr)
- typeof(*ptr) atomic_fetch_dec(ptr)
- typeof(*ptr) atomic_fetch_add(ptr, val)
- typeof(*ptr) atomic_fetch_sub(ptr, val)
- typeof(*ptr) atomic_fetch_and(ptr, val)
- typeof(*ptr) atomic_fetch_or(ptr, val)
- typeof(*ptr) atomic_fetch_xor(ptr, val)
- typeof(*ptr) atomic_fetch_inc_nonzero(ptr)
- typeof(*ptr) atomic_xchg(ptr, val)
- typeof(*ptr) atomic_cmpxchg(ptr, old, new)
+ void qatomic_inc(ptr)
+ void qatomic_dec(ptr)
+ void qatomic_add(ptr, val)
+ void qatomic_sub(ptr, val)
+ void qatomic_and(ptr, val)
+ void qatomic_or(ptr, val)
+
+ typeof(*ptr) qatomic_fetch_inc(ptr)
+ typeof(*ptr) qatomic_fetch_dec(ptr)
+ typeof(*ptr) qatomic_fetch_add(ptr, val)
+ typeof(*ptr) qatomic_fetch_sub(ptr, val)
+ typeof(*ptr) qatomic_fetch_and(ptr, val)
+ typeof(*ptr) qatomic_fetch_or(ptr, val)
+ typeof(*ptr) qatomic_fetch_xor(ptr, val)
+ typeof(*ptr) qatomic_fetch_inc_nonzero(ptr)
+ typeof(*ptr) qatomic_xchg(ptr, val)
+ typeof(*ptr) qatomic_cmpxchg(ptr, old, new)
all of which return the old value of ``*ptr``. These operations are
polymorphic; they operate on any type that is as wide as a pointer or
@@ -91,19 +91,19 @@ smaller.
Similar operations return the new value of ``*ptr``::
- typeof(*ptr) atomic_inc_fetch(ptr)
- typeof(*ptr) atomic_dec_fetch(ptr)
- typeof(*ptr) atomic_add_fetch(ptr, val)
- typeof(*ptr) atomic_sub_fetch(ptr, val)
- typeof(*ptr) atomic_and_fetch(ptr, val)
- typeof(*ptr) atomic_or_fetch(ptr, val)
- typeof(*ptr) atomic_xor_fetch(ptr, val)
+ typeof(*ptr) qatomic_inc_fetch(ptr)
+ typeof(*ptr) qatomic_dec_fetch(ptr)
+ typeof(*ptr) qatomic_add_fetch(ptr, val)
+ typeof(*ptr) qatomic_sub_fetch(ptr, val)
+ typeof(*ptr) qatomic_and_fetch(ptr, val)
+ typeof(*ptr) qatomic_or_fetch(ptr, val)
+ typeof(*ptr) qatomic_xor_fetch(ptr, val)
``qemu/atomic.h`` also provides loads and stores that cannot be reordered
with each other::
- typeof(*ptr) atomic_mb_read(ptr)
- void atomic_mb_set(ptr, val)
+ typeof(*ptr) qatomic_mb_read(ptr)
+ void qatomic_mb_set(ptr, val)
However these do not provide sequential consistency and, in particular,
they do not participate in the total ordering enforced by
@@ -115,11 +115,11 @@ easiest to hardest):
- lightweight synchronization primitives such as ``QemuEvent``
-- RCU operations (``atomic_rcu_read``, ``atomic_rcu_set``) when publishing
+- RCU operations (``qatomic_rcu_read``, ``qatomic_rcu_set``) when publishing
or accessing a new version of a data structure
-- other atomic accesses: ``atomic_read`` and ``atomic_load_acquire`` for
- loads, ``atomic_set`` and ``atomic_store_release`` for stores, ``smp_mb``
+- other atomic accesses: ``qatomic_read`` and ``qatomic_load_acquire`` for
+ loads, ``qatomic_set`` and ``qatomic_store_release`` for stores, ``smp_mb``
to forbid reordering subsequent loads before a store.
@@ -149,22 +149,22 @@ The only guarantees that you can rely upon in this case are:
When using this model, variables are accessed with:
-- ``atomic_read()`` and ``atomic_set()``; these prevent the compiler from
+- ``qatomic_read()`` and ``qatomic_set()``; these prevent the compiler from
optimizing accesses out of existence and creating unsolicited
accesses, but do not otherwise impose any ordering on loads and
stores: both the compiler and the processor are free to reorder
them.
-- ``atomic_load_acquire()``, which guarantees the LOAD to appear to
+- ``qatomic_load_acquire()``, which guarantees the LOAD to appear to
happen, with respect to the other components of the system,
before all the LOAD or STORE operations specified afterwards.
- Operations coming before ``atomic_load_acquire()`` can still be
+ Operations coming before ``qatomic_load_acquire()`` can still be
reordered after it.
-- ``atomic_store_release()``, which guarantees the STORE to appear to
+- ``qatomic_store_release()``, which guarantees the STORE to appear to
happen, with respect to the other components of the system,
after all the LOAD or STORE operations specified before.
- Operations coming after ``atomic_store_release()`` can still be
+ Operations coming after ``qatomic_store_release()`` can still be
reordered before it.
Restrictions to the ordering of accesses can also be specified
@@ -229,7 +229,7 @@ They come in six kinds:
dependency and a full read barrier or better is required.
-Memory barriers and ``atomic_load_acquire``/``atomic_store_release`` are
+Memory barriers and ``qatomic_load_acquire``/``qatomic_store_release`` are
mostly used when a data structure has one thread that is always a writer
and one thread that is always a reader:
@@ -238,8 +238,8 @@ and one thread that is always a reader:
+==================================+==================================+
| :: | :: |
| | |
- | atomic_store_release(&a, x); | y = atomic_load_acquire(&b); |
- | atomic_store_release(&b, y); | x = atomic_load_acquire(&a); |
+ | qatomic_store_release(&a, x); | y = qatomic_load_acquire(&b); |
+ | qatomic_store_release(&b, y); | x = qatomic_load_acquire(&a); |
+----------------------------------+----------------------------------+
In this case, correctness is easy to check for using the "pairing"
@@ -258,14 +258,14 @@ outside a loop. For example:
| | |
| n = 0; | n = 0; |
| for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) |
- | n += atomic_load_acquire(&a[i]); | n += atomic_read(&a[i]); |
+ | n += qatomic_load_acquire(&a[i]); | n += qatomic_read(&a[i]); |
| | smp_mb_acquire(); |
+------------------------------------------+----------------------------------+
| :: | :: |
| | |
| | smp_mb_release(); |
| for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) |
- | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); |
+ | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); |
+------------------------------------------+----------------------------------+
Splitting a loop can also be useful to reduce the number of barriers:
@@ -277,11 +277,11 @@ Splitting a loop can also be useful to reduce the number of barriers:
| | |
| n = 0; | smp_mb_release(); |
| for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) |
- | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); |
+ | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); |
| smp_mb(); | smb_mb(); |
- | n += atomic_read(&b[i]); | n = 0; |
+ | n += qatomic_read(&b[i]); | n = 0; |
| } | for (i = 0; i < 10; i++) |
- | | n += atomic_read(&b[i]); |
+ | | n += qatomic_read(&b[i]); |
+------------------------------------------+----------------------------------+
In this case, a ``smp_mb_release()`` is also replaced with a (possibly cheaper, and clearer
@@ -294,10 +294,10 @@ as well) ``smp_wmb()``:
| | |
| | smp_mb_release(); |
| for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) |
- | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); |
- | atomic_store_release(&b[i], false); | smb_wmb(); |
+ | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); |
+ | qatomic_store_release(&b[i], false); | smb_wmb(); |
| } | for (i = 0; i < 10; i++) |
- | | atomic_set(&b[i], false); |
+ | | qatomic_set(&b[i], false); |
+------------------------------------------+----------------------------------+
@@ -306,7 +306,7 @@ as well) ``smp_wmb()``:
Acquire/release pairing and the *synchronizes-with* relation
------------------------------------------------------------
-Atomic operations other than ``atomic_set()`` and ``atomic_read()`` have
+Atomic operations other than ``qatomic_set()`` and ``qatomic_read()`` have
either *acquire* or *release* semantics [#rmw]_. This has two effects:
.. [#rmw] Read-modify-write operations can have both---acquire applies to the
@@ -357,16 +357,16 @@ thread 2 is relying on the *synchronizes-with* relation between ``pthread_exit``
Synchronization between threads basically descends from this pairing of
a release operation and an acquire operation. Therefore, atomic operations
-other than ``atomic_set()`` and ``atomic_read()`` will almost always be
+other than ``qatomic_set()`` and ``qatomic_read()`` will almost always be
paired with another operation of the opposite kind: an acquire operation
will pair with a release operation and vice versa. This rule of thumb is
extremely useful; in the case of QEMU, however, note that the other
operation may actually be in a driver that runs in the guest!
``smp_read_barrier_depends()``, ``smp_rmb()``, ``smp_mb_acquire()``,
-``atomic_load_acquire()`` and ``atomic_rcu_read()`` all count
+``qatomic_load_acquire()`` and ``qatomic_rcu_read()`` all count
as acquire operations. ``smp_wmb()``, ``smp_mb_release()``,
-``atomic_store_release()`` and ``atomic_rcu_set()`` all count as release
+``qatomic_store_release()`` and ``qatomic_rcu_set()`` all count as release
operations. ``smp_mb()`` counts as both acquire and release, therefore
it can pair with any other atomic operation. Here is an example:
@@ -375,11 +375,11 @@ it can pair with any other atomic operation. Here is an example:
+======================+==============================+
| :: | :: |
| | |
- | atomic_set(&a, 1); | |
+ | qatomic_set(&a, 1);| |
| smp_wmb(); | |
- | atomic_set(&b, 2); | x = atomic_read(&b); |
+ | qatomic_set(&b, 2);| x = qatomic_read(&b); |
| | smp_rmb(); |
- | | y = atomic_read(&a); |
+ | | y = qatomic_read(&a); |
+----------------------+------------------------------+
Note that a load-store pair only counts if the two operations access the
@@ -393,9 +393,9 @@ correct synchronization:
+================================+================================+
| :: | :: |
| | |
- | atomic_set(&a, 1); | |
- | atomic_store_release(&b, 2); | x = atomic_load_acquire(&b); |
- | | y = atomic_read(&a); |
+ | qatomic_set(&a, 1); | |
+ | qatomic_store_release(&b, 2);| x = qatomic_load_acquire(&b);|
+ | | y = qatomic_read(&a); |
+--------------------------------+--------------------------------+
Acquire and release semantics of higher-level primitives can also be
@@ -421,7 +421,7 @@ cannot be a data race:
| smp_wmb(); | |
| x->i = 2; | |
| smp_wmb(); | |
- | atomic_set(&a, x); | x = atomic_read(&a); |
+ | qatomic_set(&a, x);| x = qatomic_read(&a); |
| | smp_read_barrier_depends(); |
| | y = x->i; |
| | smp_read_barrier_depends(); |
@@ -442,7 +442,7 @@ and memory barriers, and the equivalents in QEMU:
at all. Linux 4.1 updated them to implement volatile
semantics via ``ACCESS_ONCE`` (or the more recent ``READ``/``WRITE_ONCE``).
- QEMU's ``atomic_read`` and ``atomic_set`` implement C11 atomic relaxed
+ QEMU's ``qatomic_read`` and ``qatomic_set`` implement C11 atomic relaxed
semantics if the compiler supports it, and volatile semantics otherwise.
Both semantics prevent the compiler from doing certain transformations;
the difference is that atomic accesses are guaranteed to be atomic,
@@ -451,8 +451,8 @@ and memory barriers, and the equivalents in QEMU:
since we assume the variables passed are machine-word sized and
properly aligned.
- No barriers are implied by ``atomic_read`` and ``atomic_set`` in either Linux
- or QEMU.
+ No barriers are implied by ``qatomic_read`` and ``qatomic_set`` in either
+ Linux or QEMU.
- atomic read-modify-write operations in Linux are of three kinds:
@@ -469,7 +469,7 @@ and memory barriers, and the equivalents in QEMU:
a different set of memory barriers; in QEMU, all of them enforce
sequential consistency.
-- in QEMU, ``atomic_read()`` and ``atomic_set()`` do not participate in
+- in QEMU, ``qatomic_read()`` and ``qatomic_set()`` do not participate in
the total ordering enforced by sequentially-consistent operations.
This is because QEMU uses the C11 memory model. The following example
is correct in Linux but not in QEMU:
@@ -479,8 +479,8 @@ and memory barriers, and the equivalents in QEMU:
+==================================+================================+
| :: | :: |
| | |
- | a = atomic_fetch_add(&x, 2); | a = atomic_fetch_add(&x, 2); |
- | b = READ_ONCE(&y); | b = atomic_read(&y); |
+ | a = atomic_fetch_add(&x, 2); | a = qatomic_fetch_add(&x, 2);|
+ | b = READ_ONCE(&y); | b = qatomic_read(&y); |
+----------------------------------+--------------------------------+
because the read of ``y`` can be moved (by either the processor or the
@@ -495,10 +495,10 @@ and memory barriers, and the equivalents in QEMU:
+================================+
| :: |
| |
- | a = atomic_read(&x); |
- | atomic_set(&x, a + 2); |
+ | a = qatomic_read(&x); |
+ | qatomic_set(&x, a + 2); |
| smp_mb(); |
- | b = atomic_read(&y); |
+ | b = qatomic_read(&y); |
+--------------------------------+
Sources
diff --git a/docs/devel/lockcnt.txt b/docs/devel/lockcnt.txt
index 7c099bc6c8..2d85462fe3 100644
--- a/docs/devel/lockcnt.txt
+++ b/docs/devel/lockcnt.txt
@@ -95,7 +95,7 @@ not just frees, though there could be cases where this is not necessary.
Reads, instead, can be done without taking the mutex, as long as the
readers and writers use the same macros that are used for RCU, for
-example atomic_rcu_read, atomic_rcu_set, QLIST_FOREACH_RCU, etc. This is
+example qatomic_rcu_read, qatomic_rcu_set, QLIST_FOREACH_RCU, etc. This is
because the reads are done outside a lock and a set or QLIST_INSERT_HEAD
can happen concurrently with the read. The RCU API ensures that the
processor and the compiler see all required memory barriers.
@@ -189,7 +189,7 @@ qemu_lockcnt_lock and qemu_lockcnt_unlock:
if (!xyz) {
new_xyz = g_new(XYZ, 1);
...
- atomic_rcu_set(&xyz, new_xyz);
+ qatomic_rcu_set(&xyz, new_xyz);
}
qemu_lockcnt_unlock(&xyz_lockcnt);
@@ -198,7 +198,7 @@ qemu_lockcnt_dec:
qemu_lockcnt_inc(&xyz_lockcnt);
if (xyz) {
- XYZ *p = atomic_rcu_read(&xyz);
+ XYZ *p = qatomic_rcu_read(&xyz);
...
/* Accesses can now be done through "p". */
}
@@ -222,7 +222,7 @@ the decrement, the locking and the check on count as follows:
qemu_lockcnt_inc(&xyz_lockcnt);
if (xyz) {
- XYZ *p = atomic_rcu_read(&xyz);
+ XYZ *p = qatomic_rcu_read(&xyz);
...
/* Accesses can now be done through "p". */
}
diff --git a/docs/devel/rcu.txt b/docs/devel/rcu.txt
index 0ce15ba198..cdf002edd8 100644
--- a/docs/devel/rcu.txt
+++ b/docs/devel/rcu.txt
@@ -130,13 +130,13 @@ The core RCU API is small:
g_free_rcu(&foo, rcu);
- typeof(*p) atomic_rcu_read(p);
+ typeof(*p) qatomic_rcu_read(p);
- atomic_rcu_read() is similar to atomic_load_acquire(), but it makes
+ qatomic_rcu_read() is similar to qatomic_load_acquire(), but it makes
some assumptions on the code that calls it. This allows a more
optimized implementation.
- atomic_rcu_read assumes that whenever a single RCU critical
+ qatomic_rcu_read assumes that whenever a single RCU critical
section reads multiple shared data, these reads are either
data-dependent or need no ordering. This is almost always the
case when using RCU, because read-side critical sections typically
@@ -144,7 +144,7 @@ The core RCU API is small:
every update) until reaching a data structure of interest,
and then read from there.
- RCU read-side critical sections must use atomic_rcu_read() to
+ RCU read-side critical sections must use qatomic_rcu_read() to
read data, unless concurrent writes are prevented by another
synchronization mechanism.
@@ -152,18 +152,18 @@ The core RCU API is small:
data structure in a single direction, opposite to the direction
in which the updater initializes it.
- void atomic_rcu_set(p, typeof(*p) v);
+ void qatomic_rcu_set(p, typeof(*p) v);
- atomic_rcu_set() is similar to atomic_store_release(), though it also
+ qatomic_rcu_set() is similar to qatomic_store_release(), though it also
makes assumptions on the code that calls it in order to allow a more
optimized implementation.
- In particular, atomic_rcu_set() suffices for synchronization
+ In particular, qatomic_rcu_set() suffices for synchronization
with readers, if the updater never mutates a field within a
data item that is already accessible to readers. This is the
case when initializing a new copy of the RCU-protected data
structure; just ensure that initialization of *p is carried out
- before atomic_rcu_set() makes the data item visible to readers.
+ before qatomic_rcu_set() makes the data item visible to readers.
If this rule is observed, writes will happen in the opposite
order as reads in the RCU read-side critical sections (or if
there is just one update), and there will be no need for other
@@ -212,7 +212,7 @@ DIFFERENCES WITH LINUX
programming; not allowing this would prevent upgrading an RCU read-side
critical section to become an updater.
-- atomic_rcu_read and atomic_rcu_set replace rcu_dereference and
+- qatomic_rcu_read and qatomic_rcu_set replace rcu_dereference and
rcu_assign_pointer. They take a _pointer_ to the variable being accessed.
- call_rcu is a macro that has an extra argument (the name of the first
@@ -257,7 +257,7 @@ may be used as a restricted reference-counting mechanism. For example,
consider the following code fragment:
rcu_read_lock();
- p = atomic_rcu_read(&foo);
+ p = qatomic_rcu_read(&foo);
/* do something with p. */
rcu_read_unlock();
@@ -268,7 +268,7 @@ The write side looks simply like this (with appropriate locking):
qemu_mutex_lock(&foo_mutex);
old = foo;
- atomic_rcu_set(&foo, new);
+ qatomic_rcu_set(&foo, new);
qemu_mutex_unlock(&foo_mutex);
synchronize_rcu();
free(old);
@@ -277,7 +277,7 @@ If the processing cannot be done purely within the critical section, it
is possible to combine this idiom with a "real" reference count:
rcu_read_lock();
- p = atomic_rcu_read(&foo);
+ p = qatomic_rcu_read(&foo);
foo_ref(p);
rcu_read_unlock();
/* do something with p. */
@@ -287,7 +287,7 @@ The write side can be like this:
qemu_mutex_lock(&foo_mutex);
old = foo;
- atomic_rcu_set(&foo, new);
+ qatomic_rcu_set(&foo, new);
qemu_mutex_unlock(&foo_mutex);
synchronize_rcu();
foo_unref(old);
@@ -296,7 +296,7 @@ or with call_rcu:
qemu_mutex_lock(&foo_mutex);
old = foo;
- atomic_rcu_set(&foo, new);
+ qatomic_rcu_set(&foo, new);
qemu_mutex_unlock(&foo_mutex);
call_rcu(foo_unref, old, rcu);
@@ -307,7 +307,7 @@ last reference may be dropped on the read side. Hence you can
use call_rcu() instead:
foo_unref(struct foo *p) {
- if (atomic_fetch_dec(&p->refcount) == 1) {
+ if (qatomic_fetch_dec(&p->refcount) == 1) {
call_rcu(foo_destroy, p, rcu);
}
}
@@ -375,7 +375,7 @@ Instead, we store the size of the array with the array itself:
read side:
rcu_read_lock();
- struct arr *array = atomic_rcu_read(&global_array);
+ struct arr *array = qatomic_rcu_read(&global_array);
x = i < array->size ? array->data[i] : -1;
rcu_read_unlock();
return x;
@@ -392,7 +392,7 @@ Instead, we store the size of the array with the array itself:
/* Removal phase. */
old_array = global_array;
- atomic_rcu_set(&new_array->data, new_array);
+ qatomic_rcu_set(&new_array->data, new_array);
synchronize_rcu();
/* Reclamation phase. */
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index fb95d2ecc4..8b3ab5bcf1 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -3,10 +3,11 @@ Deprecated features
In general features are intended to be supported indefinitely once
introduced into QEMU. In the event that a feature needs to be removed,
-it will be listed in this section. The feature will remain functional
-for 2 releases prior to actual removal. Deprecated features may also
-generate warnings on the console when QEMU starts up, or if activated
-via a monitor command, however, this is not a mandatory requirement.
+it will be listed in this section. The feature will remain functional for the
+release in which it was deprecated and one further release. After these two
+releases, the feature is liable to be removed. Deprecated features may also
+generate warnings on the console when QEMU starts up, or if activated via a
+monitor command, however, this is not a mandatory requirement.
Prior to the 2.10.0 release there was no official policy on how
long features would be deprecated prior to their removal, nor