mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
KVM/ARM updates for 4.13
- vcpu request overhaul - allow timer and PMU to have their interrupt number selected from userspace - workaround for Cavium erratum 30115 - handling of memory poisonning - the usual crop of fixes and cleanups -----BEGIN PGP SIGNATURE----- iQJJBAABCAAzFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAllWCM0VHG1hcmMuenlu Z2llckBhcm0uY29tAAoJECPQ0LrRPXpDjJ0QAI16x6+trKhH31lTSYekYfqm4hZ2 Fp7IbALW9KNCaY35tZov2Zuh99qGRduxTh7ewqhKpON8kkU+UKj0F7zH22+vfN4m yas/+uNr8R9VLyvea4ysPsgx8Q8v1Ix9setohHYNZIL9/klVqtaHpYvArHVF/mzq p2j/NxRS2dlp9r2TtoMRMhA05u6r0wolhUuh+z9v2ipib0gfOBIG24jsqCTEcD9n 5A/cVd+ztYshkrV95h3y9peahwt3zOA4QBGzrQ2K25jp0s54nqhmC7JTNSa8dtar YGW2MuAMoIFTwCFAlpwCzrwpOJFzF3Q6A8bOxei2fjclzjPMgT1xQxuhOoe4ntFa lTPxSHalm5W6dFTW90YSo2DBcPe+N7sQkhjR0cCeY3GYsOFhXMLTlOl5Pt1YK1or +3FAI74tFRKvVmb9mhZeGTvuzhDgRvtf3Qq5rjwlGzKc2BBOEgtMyj/Wgwo4N6Dz IjOnoRaUGELoBCWoTorMxLpsPBdPVSUxNyJTdAhqZ/ZtT1xqjhFNLZcrVWmOTzDM 1cav+jZkla4sLmJSNDD54aCSvvtPHis0nZn9PRlh12xgOyYiAVx4K++MNuWP0P37 hbh1gbPT+FcoVxPurUsX/pjNlTucPZcBwFytZDQlpwtPBpEFzJiImLYe/PldRb0f 9WQOH1Y1+q14MF+N =6hNK -----END PGP SIGNATURE----- Merge tag 'kvmarm-for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD KVM/ARM updates for 4.13 - vcpu request overhaul - allow timer and PMU to have their interrupt number selected from userspace - workaround for Cavium erratum 30115 - handling of memory poisonning - the usual crop of fixes and cleanups Conflicts: arch/s390/include/asm/kvm_host.h
This commit is contained in:
commit
04a7ea04d5
59 changed files with 2077 additions and 326 deletions
|
|
@ -16,7 +16,9 @@ Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt is a
|
|||
Returns: -EBUSY: The PMU overflow interrupt is already set
|
||||
-ENXIO: The overflow interrupt not set when attempting to get it
|
||||
-ENODEV: PMUv3 not supported
|
||||
-EINVAL: Invalid PMU overflow interrupt number supplied
|
||||
-EINVAL: Invalid PMU overflow interrupt number supplied or
|
||||
trying to set the IRQ number without using an in-kernel
|
||||
irqchip.
|
||||
|
||||
A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
|
||||
number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
|
||||
|
|
@ -25,11 +27,36 @@ all vcpus, while as an SPI it must be a separate number per vcpu.
|
|||
|
||||
1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
|
||||
Parameters: no additional parameter in kvm_device_attr.addr
|
||||
Returns: -ENODEV: PMUv3 not supported
|
||||
-ENXIO: PMUv3 not properly configured as required prior to calling this
|
||||
attribute
|
||||
Returns: -ENODEV: PMUv3 not supported or GIC not initialized
|
||||
-ENXIO: PMUv3 not properly configured or in-kernel irqchip not
|
||||
configured as required prior to calling this attribute
|
||||
-EBUSY: PMUv3 already initialized
|
||||
|
||||
Request the initialization of the PMUv3. This must be done after creating the
|
||||
in-kernel irqchip. Creating a PMU with a userspace irqchip is currently not
|
||||
supported.
|
||||
Request the initialization of the PMUv3. If using the PMUv3 with an in-kernel
|
||||
virtual GIC implementation, this must be done after initializing the in-kernel
|
||||
irqchip.
|
||||
|
||||
|
||||
2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
|
||||
Architectures: ARM,ARM64
|
||||
|
||||
2.1. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_VTIMER
|
||||
2.2. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_PTIMER
|
||||
Parameters: in kvm_device_attr.addr the address for the timer interrupt is a
|
||||
pointer to an int
|
||||
Returns: -EINVAL: Invalid timer interrupt number
|
||||
-EBUSY: One or more VCPUs has already run
|
||||
|
||||
A value describing the architected timer interrupt number when connected to an
|
||||
in-kernel virtual GIC. These must be a PPI (16 <= intid < 32). Setting the
|
||||
attribute overrides the default values (see below).
|
||||
|
||||
KVM_ARM_VCPU_TIMER_IRQ_VTIMER: The EL1 virtual timer intid (default: 27)
|
||||
KVM_ARM_VCPU_TIMER_IRQ_PTIMER: The EL1 physical timer intid (default: 30)
|
||||
|
||||
Setting the same PPI for different timers will prevent the VCPUs from running.
|
||||
Setting the interrupt number on a VCPU configures all VCPUs created at that
|
||||
time to use the number provided for a given timer, overwriting any previously
|
||||
configured values on other VCPUs. Userspace should configure the interrupt
|
||||
numbers on at least one VCPU after creating all VCPUs and before running any
|
||||
VCPUs.
|
||||
|
|
|
|||
307
Documentation/virtual/kvm/vcpu-requests.rst
Normal file
307
Documentation/virtual/kvm/vcpu-requests.rst
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
=================
|
||||
KVM VCPU Requests
|
||||
=================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
KVM supports an internal API enabling threads to request a VCPU thread to
|
||||
perform some activity. For example, a thread may request a VCPU to flush
|
||||
its TLB with a VCPU request. The API consists of the following functions::
|
||||
|
||||
/* Check if any requests are pending for VCPU @vcpu. */
|
||||
bool kvm_request_pending(struct kvm_vcpu *vcpu);
|
||||
|
||||
/* Check if VCPU @vcpu has request @req pending. */
|
||||
bool kvm_test_request(int req, struct kvm_vcpu *vcpu);
|
||||
|
||||
/* Clear request @req for VCPU @vcpu. */
|
||||
void kvm_clear_request(int req, struct kvm_vcpu *vcpu);
|
||||
|
||||
/*
|
||||
* Check if VCPU @vcpu has request @req pending. When the request is
|
||||
* pending it will be cleared and a memory barrier, which pairs with
|
||||
* another in kvm_make_request(), will be issued.
|
||||
*/
|
||||
bool kvm_check_request(int req, struct kvm_vcpu *vcpu);
|
||||
|
||||
/*
|
||||
* Make request @req of VCPU @vcpu. Issues a memory barrier, which pairs
|
||||
* with another in kvm_check_request(), prior to setting the request.
|
||||
*/
|
||||
void kvm_make_request(int req, struct kvm_vcpu *vcpu);
|
||||
|
||||
/* Make request @req of all VCPUs of the VM with struct kvm @kvm. */
|
||||
bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
|
||||
|
||||
Typically a requester wants the VCPU to perform the activity as soon
|
||||
as possible after making the request. This means most requests
|
||||
(kvm_make_request() calls) are followed by a call to kvm_vcpu_kick(),
|
||||
and kvm_make_all_cpus_request() has the kicking of all VCPUs built
|
||||
into it.
|
||||
|
||||
VCPU Kicks
|
||||
----------
|
||||
|
||||
The goal of a VCPU kick is to bring a VCPU thread out of guest mode in
|
||||
order to perform some KVM maintenance. To do so, an IPI is sent, forcing
|
||||
a guest mode exit. However, a VCPU thread may not be in guest mode at the
|
||||
time of the kick. Therefore, depending on the mode and state of the VCPU
|
||||
thread, there are two other actions a kick may take. All three actions
|
||||
are listed below:
|
||||
|
||||
1) Send an IPI. This forces a guest mode exit.
|
||||
2) Waking a sleeping VCPU. Sleeping VCPUs are VCPU threads outside guest
|
||||
mode that wait on waitqueues. Waking them removes the threads from
|
||||
the waitqueues, allowing the threads to run again. This behavior
|
||||
may be suppressed, see KVM_REQUEST_NO_WAKEUP below.
|
||||
3) Nothing. When the VCPU is not in guest mode and the VCPU thread is not
|
||||
sleeping, then there is nothing to do.
|
||||
|
||||
VCPU Mode
|
||||
---------
|
||||
|
||||
VCPUs have a mode state, ``vcpu->mode``, that is used to track whether the
|
||||
guest is running in guest mode or not, as well as some specific
|
||||
outside guest mode states. The architecture may use ``vcpu->mode`` to
|
||||
ensure VCPU requests are seen by VCPUs (see "Ensuring Requests Are Seen"),
|
||||
as well as to avoid sending unnecessary IPIs (see "IPI Reduction"), and
|
||||
even to ensure IPI acknowledgements are waited upon (see "Waiting for
|
||||
Acknowledgements"). The following modes are defined:
|
||||
|
||||
OUTSIDE_GUEST_MODE
|
||||
|
||||
The VCPU thread is outside guest mode.
|
||||
|
||||
IN_GUEST_MODE
|
||||
|
||||
The VCPU thread is in guest mode.
|
||||
|
||||
EXITING_GUEST_MODE
|
||||
|
||||
The VCPU thread is transitioning from IN_GUEST_MODE to
|
||||
OUTSIDE_GUEST_MODE.
|
||||
|
||||
READING_SHADOW_PAGE_TABLES
|
||||
|
||||
The VCPU thread is outside guest mode, but it wants the sender of
|
||||
certain VCPU requests, namely KVM_REQ_TLB_FLUSH, to wait until the VCPU
|
||||
thread is done reading the page tables.
|
||||
|
||||
VCPU Request Internals
|
||||
======================
|
||||
|
||||
VCPU requests are simply bit indices of the ``vcpu->requests`` bitmap.
|
||||
This means general bitops, like those documented in [atomic-ops]_ could
|
||||
also be used, e.g. ::
|
||||
|
||||
clear_bit(KVM_REQ_UNHALT & KVM_REQUEST_MASK, &vcpu->requests);
|
||||
|
||||
However, VCPU request users should refrain from doing so, as it would
|
||||
break the abstraction. The first 8 bits are reserved for architecture
|
||||
independent requests, all additional bits are available for architecture
|
||||
dependent requests.
|
||||
|
||||
Architecture Independent Requests
|
||||
---------------------------------
|
||||
|
||||
KVM_REQ_TLB_FLUSH
|
||||
|
||||
KVM's common MMU notifier may need to flush all of a guest's TLB
|
||||
entries, calling kvm_flush_remote_tlbs() to do so. Architectures that
|
||||
choose to use the common kvm_flush_remote_tlbs() implementation will
|
||||
need to handle this VCPU request.
|
||||
|
||||
KVM_REQ_MMU_RELOAD
|
||||
|
||||
When shadow page tables are used and memory slots are removed it's
|
||||
necessary to inform each VCPU to completely refresh the tables. This
|
||||
request is used for that.
|
||||
|
||||
KVM_REQ_PENDING_TIMER
|
||||
|
||||
This request may be made from a timer handler run on the host on behalf
|
||||
of a VCPU. It informs the VCPU thread to inject a timer interrupt.
|
||||
|
||||
KVM_REQ_UNHALT
|
||||
|
||||
This request may be made from the KVM common function kvm_vcpu_block(),
|
||||
which is used to emulate an instruction that causes a CPU to halt until
|
||||
one of an architectural specific set of events and/or interrupts is
|
||||
received (determined by checking kvm_arch_vcpu_runnable()). When that
|
||||
event or interrupt arrives kvm_vcpu_block() makes the request. This is
|
||||
in contrast to when kvm_vcpu_block() returns due to any other reason,
|
||||
such as a pending signal, which does not indicate the VCPU's halt
|
||||
emulation should stop, and therefore does not make the request.
|
||||
|
||||
KVM_REQUEST_MASK
|
||||
----------------
|
||||
|
||||
VCPU requests should be masked by KVM_REQUEST_MASK before using them with
|
||||
bitops. This is because only the lower 8 bits are used to represent the
|
||||
request's number. The upper bits are used as flags. Currently only two
|
||||
flags are defined.
|
||||
|
||||
VCPU Request Flags
|
||||
------------------
|
||||
|
||||
KVM_REQUEST_NO_WAKEUP
|
||||
|
||||
This flag is applied to requests that only need immediate attention
|
||||
from VCPUs running in guest mode. That is, sleeping VCPUs do not need
|
||||
to be awaken for these requests. Sleeping VCPUs will handle the
|
||||
requests when they are awaken later for some other reason.
|
||||
|
||||
KVM_REQUEST_WAIT
|
||||
|
||||
When requests with this flag are made with kvm_make_all_cpus_request(),
|
||||
then the caller will wait for each VCPU to acknowledge its IPI before
|
||||
proceeding. This flag only applies to VCPUs that would receive IPIs.
|
||||
If, for example, the VCPU is sleeping, so no IPI is necessary, then
|
||||
the requesting thread does not wait. This means that this flag may be
|
||||
safely combined with KVM_REQUEST_NO_WAKEUP. See "Waiting for
|
||||
Acknowledgements" for more information about requests with
|
||||
KVM_REQUEST_WAIT.
|
||||
|
||||
VCPU Requests with Associated State
|
||||
===================================
|
||||
|
||||
Requesters that want the receiving VCPU to handle new state need to ensure
|
||||
the newly written state is observable to the receiving VCPU thread's CPU
|
||||
by the time it observes the request. This means a write memory barrier
|
||||
must be inserted after writing the new state and before setting the VCPU
|
||||
request bit. Additionally, on the receiving VCPU thread's side, a
|
||||
corresponding read barrier must be inserted after reading the request bit
|
||||
and before proceeding to read the new state associated with it. See
|
||||
scenario 3, Message and Flag, of [lwn-mb]_ and the kernel documentation
|
||||
[memory-barriers]_.
|
||||
|
||||
The pair of functions, kvm_check_request() and kvm_make_request(), provide
|
||||
the memory barriers, allowing this requirement to be handled internally by
|
||||
the API.
|
||||
|
||||
Ensuring Requests Are Seen
|
||||
==========================
|
||||
|
||||
When making requests to VCPUs, we want to avoid the receiving VCPU
|
||||
executing in guest mode for an arbitrary long time without handling the
|
||||
request. We can be sure this won't happen as long as we ensure the VCPU
|
||||
thread checks kvm_request_pending() before entering guest mode and that a
|
||||
kick will send an IPI to force an exit from guest mode when necessary.
|
||||
Extra care must be taken to cover the period after the VCPU thread's last
|
||||
kvm_request_pending() check and before it has entered guest mode, as kick
|
||||
IPIs will only trigger guest mode exits for VCPU threads that are in guest
|
||||
mode or at least have already disabled interrupts in order to prepare to
|
||||
enter guest mode. This means that an optimized implementation (see "IPI
|
||||
Reduction") must be certain when it's safe to not send the IPI. One
|
||||
solution, which all architectures except s390 apply, is to:
|
||||
|
||||
- set ``vcpu->mode`` to IN_GUEST_MODE between disabling the interrupts and
|
||||
the last kvm_request_pending() check;
|
||||
- enable interrupts atomically when entering the guest.
|
||||
|
||||
This solution also requires memory barriers to be placed carefully in both
|
||||
the requesting thread and the receiving VCPU. With the memory barriers we
|
||||
can exclude the possibility of a VCPU thread observing
|
||||
!kvm_request_pending() on its last check and then not receiving an IPI for
|
||||
the next request made of it, even if the request is made immediately after
|
||||
the check. This is done by way of the Dekker memory barrier pattern
|
||||
(scenario 10 of [lwn-mb]_). As the Dekker pattern requires two variables,
|
||||
this solution pairs ``vcpu->mode`` with ``vcpu->requests``. Substituting
|
||||
them into the pattern gives::
|
||||
|
||||
CPU1 CPU2
|
||||
================= =================
|
||||
local_irq_disable();
|
||||
WRITE_ONCE(vcpu->mode, IN_GUEST_MODE); kvm_make_request(REQ, vcpu);
|
||||
smp_mb(); smp_mb();
|
||||
if (kvm_request_pending(vcpu)) { if (READ_ONCE(vcpu->mode) ==
|
||||
IN_GUEST_MODE) {
|
||||
...abort guest entry... ...send IPI...
|
||||
} }
|
||||
|
||||
As stated above, the IPI is only useful for VCPU threads in guest mode or
|
||||
that have already disabled interrupts. This is why this specific case of
|
||||
the Dekker pattern has been extended to disable interrupts before setting
|
||||
``vcpu->mode`` to IN_GUEST_MODE. WRITE_ONCE() and READ_ONCE() are used to
|
||||
pedantically implement the memory barrier pattern, guaranteeing the
|
||||
compiler doesn't interfere with ``vcpu->mode``'s carefully planned
|
||||
accesses.
|
||||
|
||||
IPI Reduction
|
||||
-------------
|
||||
|
||||
As only one IPI is needed to get a VCPU to check for any/all requests,
|
||||
then they may be coalesced. This is easily done by having the first IPI
|
||||
sending kick also change the VCPU mode to something !IN_GUEST_MODE. The
|
||||
transitional state, EXITING_GUEST_MODE, is used for this purpose.
|
||||
|
||||
Waiting for Acknowledgements
|
||||
----------------------------
|
||||
|
||||
Some requests, those with the KVM_REQUEST_WAIT flag set, require IPIs to
|
||||
be sent, and the acknowledgements to be waited upon, even when the target
|
||||
VCPU threads are in modes other than IN_GUEST_MODE. For example, one case
|
||||
is when a target VCPU thread is in READING_SHADOW_PAGE_TABLES mode, which
|
||||
is set after disabling interrupts. To support these cases, the
|
||||
KVM_REQUEST_WAIT flag changes the condition for sending an IPI from
|
||||
checking that the VCPU is IN_GUEST_MODE to checking that it is not
|
||||
OUTSIDE_GUEST_MODE.
|
||||
|
||||
Request-less VCPU Kicks
|
||||
-----------------------
|
||||
|
||||
As the determination of whether or not to send an IPI depends on the
|
||||
two-variable Dekker memory barrier pattern, then it's clear that
|
||||
request-less VCPU kicks are almost never correct. Without the assurance
|
||||
that a non-IPI generating kick will still result in an action by the
|
||||
receiving VCPU, as the final kvm_request_pending() check does for
|
||||
request-accompanying kicks, then the kick may not do anything useful at
|
||||
all. If, for instance, a request-less kick was made to a VCPU that was
|
||||
just about to set its mode to IN_GUEST_MODE, meaning no IPI is sent, then
|
||||
the VCPU thread may continue its entry without actually having done
|
||||
whatever it was the kick was meant to initiate.
|
||||
|
||||
One exception is x86's posted interrupt mechanism. In this case, however,
|
||||
even the request-less VCPU kick is coupled with the same
|
||||
local_irq_disable() + smp_mb() pattern described above; the ON bit
|
||||
(Outstanding Notification) in the posted interrupt descriptor takes the
|
||||
role of ``vcpu->requests``. When sending a posted interrupt, PIR.ON is
|
||||
set before reading ``vcpu->mode``; dually, in the VCPU thread,
|
||||
vmx_sync_pir_to_irr() reads PIR after setting ``vcpu->mode`` to
|
||||
IN_GUEST_MODE.
|
||||
|
||||
Additional Considerations
|
||||
=========================
|
||||
|
||||
Sleeping VCPUs
|
||||
--------------
|
||||
|
||||
VCPU threads may need to consider requests before and/or after calling
|
||||
functions that may put them to sleep, e.g. kvm_vcpu_block(). Whether they
|
||||
do or not, and, if they do, which requests need consideration, is
|
||||
architecture dependent. kvm_vcpu_block() calls kvm_arch_vcpu_runnable()
|
||||
to check if it should awaken. One reason to do so is to provide
|
||||
architectures a function where requests may be checked if necessary.
|
||||
|
||||
Clearing Requests
|
||||
-----------------
|
||||
|
||||
Generally it only makes sense for the receiving VCPU thread to clear a
|
||||
request. However, in some circumstances, such as when the requesting
|
||||
thread and the receiving VCPU thread are executed serially, such as when
|
||||
they are the same thread, or when they are using some form of concurrency
|
||||
control to temporarily execute synchronously, then it's possible to know
|
||||
that the request may be cleared immediately, rather than waiting for the
|
||||
receiving VCPU thread to handle the request in VCPU RUN. The only current
|
||||
examples of this are kvm_vcpu_block() calls made by VCPUs to block
|
||||
themselves. A possible side-effect of that call is to make the
|
||||
KVM_REQ_UNHALT request, which may then be cleared immediately when the
|
||||
VCPU returns from the call.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [atomic-ops] Documentation/core-api/atomic_ops.rst
|
||||
.. [memory-barriers] Documentation/memory-barriers.txt
|
||||
.. [lwn-mb] https://lwn.net/Articles/573436/
|
||||
Loading…
Reference in a new issue