mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-05 08:44:14 +02:00
Merge 7.2-rc7 into usb-next
We need the USB fixes in here as well to build on top of. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -72,6 +72,7 @@ Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@nvidia.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maxim@isovalent.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <alice@isovalent.com>
|
||||
Aloka Dixit <quic_alokad@quicinc.com> <alokad@codeaurora.org>
|
||||
Alvin Šipraga <alvin.sipraga@analog.com> <alsi@bang-olufsen.dk>
|
||||
Al Viro <viro@ftp.linux.org.uk>
|
||||
Al Viro <viro@zenIV.linux.org.uk>
|
||||
Amit Blay <quic_ablay@quicinc.com> <ablay@codeaurora.org>
|
||||
@@ -170,12 +171,14 @@ Boris Brezillon <bbrezillon@kernel.org> <b.brezillon@overkiz.com>
|
||||
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
|
||||
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@free-electrons.com>
|
||||
Brendan Higgins <brendan.higgins@linux.dev> <brendanhiggins@google.com>
|
||||
Brendan Jackman <brendan.jackman@linux.dev> <jackmanb@google.com>
|
||||
Brian Avery <b.avery@hp.com>
|
||||
Brian Cain <bcain@kernel.org> <brian.cain@oss.qualcomm.com>
|
||||
Brian Cain <bcain@kernel.org> <bcain@quicinc.com>
|
||||
Brian King <brking@us.ibm.com>
|
||||
Brian Silverman <bsilver16384@gmail.com> <brian.silverman@bluerivertech.com>
|
||||
Bryan Tan <bryan-bt.tan@broadcom.com> <bryantan@vmware.com>
|
||||
Burak Emir <burak.emir@gmail.com> <bqe@google.com>
|
||||
Cai Huoqing <cai.huoqing@linux.dev> <caihuoqing@baidu.com>
|
||||
Casey Connolly <casey.connolly@linaro.org> <caleb.connolly@linaro.org>
|
||||
Casey Connolly <casey.connolly@linaro.org> <caleb@connolly.tech>
|
||||
@@ -231,6 +234,8 @@ Daniel Lezcano <daniel.lezcano@kernel.org> <daniel.lezcano@linexp.org>
|
||||
Daniel Lezcano <daniel.lezcano@kernel.org> <dlezcano@fr.ibm.com>
|
||||
Daniel Thompson <danielt@kernel.org> <daniel.thompson@linaro.org>
|
||||
Daniele Alessandrelli <daniele.alessandrelli@gmail.com> <daniele.alessandrelli@intel.com>
|
||||
Danila Tikhonov <danila@mainlining.org> <danila@jiaxyga.com>
|
||||
Danila Tikhonov <danila@mainlining.org> <JIaxyga@protonmail.com>
|
||||
Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com>
|
||||
David Brownell <david-b@pacbell.net>
|
||||
David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org>
|
||||
@@ -296,6 +301,7 @@ Frank Rowand <frowand.list@gmail.com> <frank.rowand@sony.com>
|
||||
Frank Rowand <frowand.list@gmail.com> <frank.rowand@sonymobile.com>
|
||||
Frank Rowand <frowand.list@gmail.com> <frowand@mvista.com>
|
||||
Frank Zago <fzago@systemfabricworks.com>
|
||||
Fuad Tabba <fuad.tabba@linux.dev> <tabba@google.com>
|
||||
Gao Xiang <xiang@kernel.org> <gaoxiang25@huawei.com>
|
||||
Gao Xiang <xiang@kernel.org> <hsiangkao@aol.com>
|
||||
Gao Xiang <xiang@kernel.org> <hsiangkao@linux.alibaba.com>
|
||||
@@ -648,6 +654,7 @@ Nicholas Piggin <npiggin@gmail.com> <npiggin@suse.de>
|
||||
Nicholas Piggin <npiggin@gmail.com> <nickpiggin@yahoo.com.au>
|
||||
Nicholas Piggin <npiggin@gmail.com> <piggin@cyberone.com.au>
|
||||
Nicolas Ferre <nicolas.ferre@microchip.com> <nicolas.ferre@atmel.com>
|
||||
Nico Pache <nico.pache@linux.dev> <npache@redhat.com>
|
||||
Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org>
|
||||
Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org>
|
||||
Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de>
|
||||
@@ -695,6 +702,7 @@ Paulo Alcantara <pc@manguebit.org> <palcantara@suse.com>
|
||||
Paulo Alcantara <pc@manguebit.org> <pc@manguebit.com>
|
||||
Pavankumar Kondeti <quic_pkondeti@quicinc.com> <pkondeti@codeaurora.org>
|
||||
Peter A Jonsson <pj@ludd.ltu.se>
|
||||
Peter Collingbourne <peter@pcc.me.uk> <pcc@google.com>
|
||||
Peter Hilber <peter.hilber@oss.qualcomm.com> <quic_philber@quicinc.com>
|
||||
Peter Oruba <peter.oruba@amd.com>
|
||||
Peter Oruba <peter@oruba.de>
|
||||
|
||||
@@ -10,3 +10,4 @@ Description:
|
||||
0 no adjustment of input current limit. This
|
||||
helps for more unusual power sources like
|
||||
solar modules.
|
||||
============ ===========================================
|
||||
|
||||
@@ -2239,9 +2239,12 @@ IO Latency
|
||||
~~~~~~~~~~
|
||||
|
||||
This is a cgroup v2 controller for IO workload protection. You provide a group
|
||||
with a latency target, and if the average latency exceeds that target the
|
||||
controller will throttle any peers that have a lower latency target than the
|
||||
protected workload.
|
||||
with a latency target, and if the group misses its target the controller will
|
||||
throttle any peers that have a lower latency target than the protected
|
||||
workload. How a miss is detected depends on the device: on rotational devices
|
||||
the average latency over the window must exceed the target, while on
|
||||
non-rotational devices a miss is counted once enough of the IOs in the window
|
||||
individually exceed the target.
|
||||
|
||||
The limits are only applied at the peer level in the hierarchy. This means that
|
||||
in the diagram below, only groups A, B, and C will influence each other, and
|
||||
@@ -2258,10 +2261,12 @@ So the ideal way to configure this is to set io.latency in groups A, B, and C.
|
||||
Generally you do not want to set a value lower than the latency your device
|
||||
supports. Experiment to find the value that works best for your workload.
|
||||
Start at higher than the expected latency for your device and, with
|
||||
blkcg_debug_stats enabled, watch the avg_lat value in io.stat for your
|
||||
workload group to get an idea of the latency you see during normal operation.
|
||||
Use the avg_lat value as a basis for your real setting, setting at 10-15%
|
||||
higher than the value in io.stat.
|
||||
blkcg_debug_stats enabled, observe io.stat for your workload group to get an
|
||||
idea of the latency you see during normal operation. On rotational devices,
|
||||
use the avg_lat value as a basis for your real setting, setting it 10-15%
|
||||
higher. On non-rotational devices io.stat reports no average latency; set
|
||||
the target based on your device and use the missed/total fields to verify it
|
||||
is being met.
|
||||
|
||||
How IO Latency Throttling Works
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -2303,19 +2308,36 @@ IO Latency Interface Files
|
||||
the blkcg_debug_stats module parameter is enabled (it is disabled by
|
||||
default).
|
||||
|
||||
The reported latency fields depend on the device. Rotational devices
|
||||
report avg_lat and win; non-rotational devices report missed and total
|
||||
instead. missed and total are live counters for the current window and
|
||||
may change between reads.
|
||||
|
||||
depth
|
||||
This is the current queue depth for the group.
|
||||
|
||||
avg_lat
|
||||
This is an exponential moving average with a decay rate of 1/exp
|
||||
bound by the sampling interval. The decay rate interval can be
|
||||
calculated by multiplying the win value in io.stat by the
|
||||
corresponding number of samples based on the win value.
|
||||
(Rotational devices only.) This is an exponential moving
|
||||
average with a decay rate of 1/exp bound by the sampling
|
||||
interval. The decay rate interval can be calculated by
|
||||
multiplying the win value in io.stat by the corresponding number
|
||||
of samples based on the win value.
|
||||
|
||||
win
|
||||
The sampling window size in milliseconds. This is the minimum
|
||||
duration of time between evaluation events. Windows only elapse
|
||||
with IO activity. Idle periods extend the most recent window.
|
||||
(Rotational devices only.) The sampling window size in
|
||||
milliseconds. This is the minimum duration of time between
|
||||
evaluation events. Windows only elapse with IO activity. Idle
|
||||
periods extend the most recent window.
|
||||
|
||||
missed
|
||||
(Non-rotational devices only.) The number of IOs in the
|
||||
current window whose latency exceeded the target. A group is
|
||||
considered to be missing its target once missed reaches a
|
||||
certain ratio of total.
|
||||
|
||||
total
|
||||
(Non-rotational devices only.) The total number of IOs
|
||||
accounted in the current window.
|
||||
|
||||
IO Priority
|
||||
~~~~~~~~~~~
|
||||
|
||||
@@ -8169,6 +8169,11 @@ Kernel parameters
|
||||
q = USB_QUIRK_FORCE_ONE_CONFIG (Device
|
||||
claims zero configurations,
|
||||
forcing to 1);
|
||||
r = USB_QUIRK_WINDOWS_CONFIG_REQ_SIZE (Device
|
||||
fails during initialization when asked for
|
||||
9-bytes configuration descriptor request.
|
||||
Ask for 255-bytes request instead to mirror
|
||||
Windows' behavior);
|
||||
Example: quirks=0781:5580:bk,0a5c:5834:gij
|
||||
|
||||
usbhid.mousepoll=
|
||||
|
||||
@@ -55,10 +55,14 @@ stable kernels.
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Ampere | AmpereOne | AC03_CPU_38 | AMPERE_ERRATUM_AC03_CPU_38 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Ampere | AmpereOne | AC03_CPU_57 | N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Ampere | AmpereOne AC04 | AC04_CPU_10 | AMPERE_ERRATUM_AC03_CPU_38 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Ampere | AmpereOne AC04 | AC04_CPU_23 | AMPERE_ERRATUM_AC04_CPU_23 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Ampere | AmpereOne AC04 | AC04_CPU_29 | N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
|
||||
@@ -135,7 +135,6 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -18,7 +18,14 @@ properties:
|
||||
- const: qcom,sa8255p-ufshc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: std
|
||||
- const: mcq
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
@@ -118,12 +118,16 @@ attribute-sets:
|
||||
doc: >-
|
||||
The number of seconds after which a keep alive message is sent to the
|
||||
peer
|
||||
checks:
|
||||
max: 86400
|
||||
-
|
||||
name: keepalive-timeout
|
||||
type: u32
|
||||
doc: >-
|
||||
The number of seconds from the last activity after which the peer is
|
||||
assumed dead
|
||||
checks:
|
||||
max: 86400
|
||||
-
|
||||
name: del-reason
|
||||
type: u32
|
||||
|
||||
@@ -43,12 +43,13 @@ UMEM also has two rings: the FILL ring and the COMPLETION ring. The
|
||||
FILL ring is used by the application to send down addr for the kernel
|
||||
to fill in with RX packet data. References to these frames will then
|
||||
appear in the RX ring once each packet has been received. The
|
||||
COMPLETION ring, on the other hand, contains frame addr that the
|
||||
kernel has transmitted completely and can now be used again by user
|
||||
space, for either TX or RX. Thus, the frame addrs appearing in the
|
||||
COMPLETION ring are addrs that were previously transmitted using the
|
||||
TX ring. In summary, the RX and FILL rings are used for the RX path
|
||||
and the TX and COMPLETION rings are used for the TX path.
|
||||
COMPLETION ring, on the other hand, contains frame addresses from Tx
|
||||
descriptors that the kernel has finished processing and that can now be
|
||||
used again by user space, for either Tx or Rx. This includes frames whose
|
||||
transmission has completed as well as frames referenced by invalid Tx
|
||||
descriptors rejected by the kernel. A completion therefore returns
|
||||
ownership of a frame to user space, but does not by itself guarantee that
|
||||
the packet was successfully transmitted.
|
||||
|
||||
The socket is then finally bound with a bind() call to a device and a
|
||||
specific queue id on that device, and it is not until bind is
|
||||
@@ -169,14 +170,15 @@ chunks mode, then the incoming addr will be left untouched.
|
||||
UMEM Completion Ring
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The COMPLETION Ring is used transfer ownership of UMEM frames from
|
||||
The COMPLETION Ring is used to transfer ownership of UMEM frames from
|
||||
kernel-space to user-space. Just like the FILL ring, UMEM indices are
|
||||
used.
|
||||
|
||||
Frames passed from the kernel to user-space are frames that has been
|
||||
sent (TX ring) and can be used by user-space again.
|
||||
|
||||
The user application consumes UMEM addrs from this ring.
|
||||
used. Frames passed from the kernel to user-space are frames referenced
|
||||
by Tx descriptors that the kernel has finished processing and can be
|
||||
used by user-space again. This includes both frames whose transmission
|
||||
has completed and frames referenced by invalid Tx descriptors that were
|
||||
rejected and reclaimed by the kernel. A completion entry does not
|
||||
guarantee successful packet transmission. The user application consumes
|
||||
UMEM addrs from this ring.
|
||||
|
||||
|
||||
RX Ring
|
||||
@@ -504,21 +506,25 @@ will be treated as an invalid descriptor.
|
||||
These are the semantics for producing packets onto AF_XDP Tx ring
|
||||
consisting of multiple frames:
|
||||
|
||||
* When an invalid descriptor is found, all the other
|
||||
descriptors/frames of this packet are marked as invalid and not
|
||||
completed. The next descriptor is treated as the start of a new
|
||||
packet, even if this was not the intent (because we cannot guess
|
||||
the intent). As before, if your program is producing invalid
|
||||
descriptors you have a bug that must be fixed.
|
||||
* When an invalid descriptor is found, the complete packet is treated as
|
||||
invalid. The kernel consumes descriptors through the descriptor marking
|
||||
the end of the packet and returns all their frame addresses through the
|
||||
COMPLETION ring. A standalone invalid descriptor is treated as a
|
||||
one-descriptor invalid packet. The descriptor following the end of the
|
||||
invalid packet is treated as the start of a new packet. As before, if
|
||||
your program is producing invalid descriptors you have a bug that must
|
||||
be fixed. Rejected descriptors are reported in the ``tx_invalid_descs``
|
||||
statistic.
|
||||
|
||||
* Zero length descriptors are treated as invalid descriptors.
|
||||
|
||||
* For copy mode, the maximum supported number of frames in a packet is
|
||||
equal to CONFIG_MAX_SKB_FRAGS + 1. If it is exceeded, all
|
||||
descriptors accumulated so far are dropped and treated as
|
||||
invalid. To produce an application that will work on any system
|
||||
regardless of this config setting, limit the number of frags to 18,
|
||||
as the minimum value of the config is 17.
|
||||
equal to CONFIG_MAX_SKB_FRAGS + 1. If it is exceeded, all descriptors
|
||||
through the end of the oversized packet are consumed, treated as invalid,
|
||||
and their frame addresses are returned through the COMPLETION ring. To
|
||||
produce an application that will work on any system regardless of this
|
||||
config setting, limit the number of frags to 18, as the minimum value of
|
||||
the config is 17.
|
||||
|
||||
* For zero-copy mode, the limit is up to what the NIC HW
|
||||
supports. Usually at least five on the NICs we have checked. We
|
||||
|
||||
@@ -57,3 +57,40 @@ Basic development tools (git, gcc, make, editors) should not be listed.
|
||||
Example::
|
||||
|
||||
Assisted-by: Claude:claude-3-opus coccinelle sparse
|
||||
|
||||
Procedure for finding and fixing bugs
|
||||
=====================================
|
||||
|
||||
When an AI assistant is used to find and fix bugs, it **MUST** follow at least
|
||||
these steps:
|
||||
|
||||
1. Before starting, read the whole process documentation listed above, as well
|
||||
as any other document mentioned in the request. Do not rely on isolated
|
||||
parts found by keyword search.
|
||||
2. Note the commit ID and Locate a bug as instructed.
|
||||
3. For any bug found that is not trivial, verify that it looks real by
|
||||
attempting to create a reproducer to demonstrate it. Lacking it may cause
|
||||
the report to be ignored, as many unverified bug reports sent to maintainers
|
||||
happen to be invalid. Stop here if it finally looks wrong.
|
||||
4. Write a fix for the bug. This part is not optional: except in a few very
|
||||
rare cases, an AI assistant able to find a bug is able to fix it. Note that
|
||||
fixes written in the same session as used to find the bug will generally
|
||||
lead to better and more accurate fixes as the LLM's reasoning context
|
||||
remains present.
|
||||
5. Build and verify that the fix works either using the reproducer or by
|
||||
re-running a complete analysis; drop any fix that doesn't work and try
|
||||
another one. The fix must not add build warnings and must pass the
|
||||
checkpatch.pl checks (see submitting-patches.rst).
|
||||
6. Commit the working fix with a detailed message describing the problem, the
|
||||
solution and a Fixes tag. Do not add a Signed-off-by tag, and add an
|
||||
Assisted-by tag, as described above.
|
||||
7. Identify the maintainers and lists using scripts/get_maintainer.pl.
|
||||
Documentation/process/security-bugs.rst shows how to do that.
|
||||
8. Indicate what could not be done. If the fix could not be built or tested, or
|
||||
if no reproducer could be produced, say so explicitly: maintainers currently
|
||||
waste too much time analyzing unverified reports and untested fixes.
|
||||
9. Read Documentation/process/threat-model.rst to determine whether the bug is
|
||||
a vulnerability or a regular bug, and leave the result to the reporter for
|
||||
review (the assistant must never send anything itself). Regular bugs are
|
||||
submitted as described in Documentation/process/submitting-patches.rst,
|
||||
vulnerabilities as described in Documentation/process/security-bugs.rst.
|
||||
|
||||
@@ -18,6 +18,10 @@ information is helpful. The following information are absolutely necessary in
|
||||
**any** security bug report:
|
||||
|
||||
* **affected kernel version range**: with no version indication, your report
|
||||
will not be processed. Note that a time-dependent version such as "latest
|
||||
mainline" is not acceptable. A stable identifier such as a commit ID or an
|
||||
exact version is required. Versions designating kernels not coming from
|
||||
kernel.org (such as distro kernels) are meaningless to maintainers and
|
||||
will not be processed. A significant part of reports are for bugs that
|
||||
have already been fixed, so it is extremely important that vulnerabilities
|
||||
are verified on recent versions (development tree or latest stable
|
||||
@@ -225,6 +229,28 @@ there is no need to consume a maintainer's time with an unimportant report. If
|
||||
the issue is clearly trivial and publicly discoverable, you should report it
|
||||
directly to the public mailing lists.
|
||||
|
||||
At the very least, when using an AI assistant to find and report bugs, make the
|
||||
assistant read this file and threat-model.rst before proceeding, and have it
|
||||
follow the procedure described in coding-assistants.rst: work on an up-to-date
|
||||
mainline tree and note the commit ID, verify the bug is real, write a fix,
|
||||
build it warning-free and checkpatch-clean, commit it with a Fixes tag, and
|
||||
identify the maintainers with get_maintainer.pl.
|
||||
|
||||
On top of that procedure, the AI assistant **MUST**:
|
||||
|
||||
1. Prepare a plain-text report explaining the problem. It must contain the
|
||||
four items listed at the top of this file as absolutely necessary: the
|
||||
affected version or commit ID noted while following the procedure above,
|
||||
the description of the problem, the reproducer or its status, and the
|
||||
triggering conditions.
|
||||
2. Start the report with a temporary section listing the recipients' addresses
|
||||
(maintainers+list for the patch, maintainers only for the report and
|
||||
reproducer), and with instructions reminding the reporter to check that
|
||||
their email client is properly setup (see email-clients.rst), and leave it
|
||||
to the reporter to remove that temporary section.
|
||||
|
||||
A more detailed process is covered at https://github.com/masoncl/kres.git.
|
||||
|
||||
Sending the report
|
||||
------------------
|
||||
|
||||
|
||||
@@ -98,11 +98,11 @@ measures whose purpose is to avoid crossing a security boundary when certain
|
||||
classes of bugs are found, but a failure of these extra protections do not
|
||||
constitute a vulnerability alone.
|
||||
|
||||
What does not constitute a security bug
|
||||
---------------------------------------
|
||||
What classes of problems are not considered vulnerabilities
|
||||
-----------------------------------------------------------
|
||||
|
||||
In the Linux kernel's threat model, the following classes of problems are
|
||||
**NOT** considered as Linux Kernel security bugs. However, when it is believed
|
||||
**NOT** considered Linux Kernel vulnerabilities. However, when it is believed
|
||||
that the kernel could do better, they should be reported, so that they can be
|
||||
reviewed and fixed where reasonably possible, but they will be handled as any
|
||||
regular bug:
|
||||
@@ -111,8 +111,8 @@ regular bug:
|
||||
|
||||
* outdated kernels and particularly end-of-life branches are out of the scope
|
||||
of the kernel's threat model: administrators are responsible for keeping
|
||||
their system up to date. For a bug to qualify as a security bug, it must be
|
||||
demonstrated that it affects actively maintained versions.
|
||||
their system up to date. For a bug to qualify as a vulnerability, it must
|
||||
be demonstrated that it affects actively maintained versions.
|
||||
|
||||
* build-level: changes to the kernel configuration that are explicitly
|
||||
documented as lowering the security level (e.g. ``CONFIG_NOMMU``), or
|
||||
@@ -178,9 +178,6 @@ regular bug:
|
||||
involving tens of millions of threads, tens of thousands of CPUs,
|
||||
unrealistic CPU frequencies, RAM sizes or disk capacities, network speeds).
|
||||
|
||||
* issues whose reproduction requires hardware modification or emulation,
|
||||
including fake USB devices that pretend to be another one.
|
||||
|
||||
* as well as issues that can be triggered at a cost that is orders of
|
||||
magnitude higher than the expected benefits (e.g. fully functional keyboard
|
||||
emulator only to retrieve 7 uninitialized bytes in a structure, or
|
||||
@@ -208,19 +205,27 @@ regular bug:
|
||||
messages.
|
||||
|
||||
* Leaks of kernel memory addresses/pointers do not constitute an immediately
|
||||
exploitable vector and are not security bugs, though they must be reported
|
||||
and fixed.
|
||||
exploitable vector and are not vulnerabilities, though they must be
|
||||
reported and fixed.
|
||||
|
||||
* **Crafted file system images**:
|
||||
* **Non-conforming devices and media**:
|
||||
|
||||
Drivers are implemented against a specification. When a device or a storage
|
||||
medium violates the specification its driver was written against, the
|
||||
resulting misbehaviour is a regular bug to be fixed, not a vulnerability,
|
||||
unless the driver is specifically documented as being hardened against
|
||||
hostile inputs. The following are therefore not considered vulnerabilities:
|
||||
|
||||
* bugs triggered by mounting a corrupted or maliciously crafted file system
|
||||
image are generally not security bugs, as the kernel assumes the underlying
|
||||
storage media is under the administrator's control, unless the filesystem
|
||||
driver is specifically documented as being hardened against untrusted media.
|
||||
|
||||
* issues that are resolved, mitigated, or detected by running a filesystem
|
||||
image: mounting a block device is a privileged operation (see above), and
|
||||
the administrator is responsible for the media they mount. This includes
|
||||
issues that are resolved, mitigated, or detected by running a filesystem
|
||||
consistency check (fsck) on the image prior to mounting.
|
||||
|
||||
* bugs whose reproduction requires hardware modification or emulation,
|
||||
including fake USB devices that pretend to be another one, or devices
|
||||
reporting values outside their documented ranges.
|
||||
|
||||
* **Physical access**:
|
||||
|
||||
Issues that require physical access to the machine, hardware modification, or
|
||||
@@ -232,4 +237,4 @@ regular bug:
|
||||
* **Functional and performance regressions**:
|
||||
|
||||
Any issue that can be mitigated by setting proper permissions and limits
|
||||
doesn't qualify as a security bug.
|
||||
doesn't qualify as a vulnerability.
|
||||
|
||||
@@ -8414,6 +8414,12 @@ When this capability is enabled all memory in memslots must be mapped as
|
||||
attempts to create a memslot with an invalid mmap will result in an
|
||||
-EINVAL return.
|
||||
|
||||
``guest_memfd``, even though it is an anonymous file, is not supported with MTE.
|
||||
Attempting to create a memslot backed by ``guest_memfd`` when the MTE capability
|
||||
is enabled, or attempting to enable the MTE capability after
|
||||
``guest_memfd``-backed memslots have been created, will result in an -EINVAL
|
||||
return.
|
||||
|
||||
When enabled the VMM may make use of the ``KVM_ARM_MTE_COPY_TAGS`` ioctl to
|
||||
perform a bulk copy of tags to/from the guest.
|
||||
|
||||
|
||||
@@ -112,9 +112,20 @@ Groups:
|
||||
mask or unmask the adapter, as specified in mask
|
||||
|
||||
KVM_S390_IO_ADAPTER_MAP
|
||||
This is now a no-op. The mapping is purely done by the irq route.
|
||||
Map an adapter indicator or summary page for long-term pinning so that
|
||||
interrupt injection can be performed in atomic context. If long-term
|
||||
pinning is not possible (e.g. file-backed memory), the page is verified
|
||||
via a short-term pin and the ioctl returns success; interrupt injection
|
||||
will use the non-atomic irqfd path with short-term pinning on each
|
||||
interrupt. In Secure Execution mode this is a no-op and the ioctl
|
||||
returns success.
|
||||
|
||||
KVM_S390_IO_ADAPTER_UNMAP
|
||||
This is now a no-op. The mapping is purely done by the irq route.
|
||||
Unmap a previously mapped adapter indicator or summary page and release
|
||||
the long-term pin. If the page was not long-term pinned (e.g. file-backed
|
||||
memory), the map entry is removed and success is returned; if no prior
|
||||
map entry exists, -ENOENT is returned. In Secure Execution mode this is
|
||||
a no-op and the ioctl returns success.
|
||||
|
||||
KVM_DEV_FLIC_AISM
|
||||
modify the adapter-interruption-suppression mode for a given isc if the
|
||||
|
||||
+25
-23
@@ -2676,6 +2676,8 @@ F: drivers/irqchip/irq-aspeed-i2c-ic.c
|
||||
ARM/ASPEED MACHINE SUPPORT
|
||||
M: Joel Stanley <joel@jms.id.au>
|
||||
M: Andrew Jeffery <andrew@codeconstruct.com.au>
|
||||
R: Ryan Chen <ryan_chen@aspeedtech.com>
|
||||
R: Billy Tsai <billy_tsai@aspeedtech.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
@@ -2881,7 +2883,7 @@ W: http://www.armlinux.org.uk/
|
||||
F: arch/arm/include/asm/hardware/dec21285.h
|
||||
F: arch/arm/mach-footbridge/
|
||||
|
||||
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
|
||||
ARM/FREESCALE IMX / MXC / LAYERSCAPE ARM ARCHITECTURE
|
||||
M: Frank Li <Frank.Li@nxp.com>
|
||||
M: Sascha Hauer <s.hauer@pengutronix.de>
|
||||
R: Pengutronix Kernel Team <kernel@pengutronix.de>
|
||||
@@ -2895,22 +2897,11 @@ F: Documentation/devicetree/bindings/firmware/nxp*
|
||||
F: arch/arm/boot/dts/nxp/
|
||||
F: arch/arm64/boot/dts/freescale/
|
||||
X: Documentation/devicetree/bindings/media/i2c/
|
||||
X: arch/arm64/boot/dts/freescale/fsl-*
|
||||
X: arch/arm64/boot/dts/freescale/qoriq-*
|
||||
X: drivers/media/i2c/
|
||||
N: imx
|
||||
N: mxs
|
||||
N: \bmxc[^\d]
|
||||
|
||||
ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE
|
||||
M: Frank Li <Frank.Li@nxp.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux.git
|
||||
F: arch/arm/boot/dts/nxp/ls/
|
||||
F: arch/arm64/boot/dts/freescale/fsl-*
|
||||
F: arch/arm64/boot/dts/freescale/qoriq-*
|
||||
|
||||
ARM/FREESCALE VYBRID ARM ARCHITECTURE
|
||||
M: Frank Li <Frank.Li@nxp.com>
|
||||
M: Sascha Hauer <s.hauer@pengutronix.de>
|
||||
@@ -4634,7 +4625,7 @@ F: rust/helpers/cpumask.c
|
||||
|
||||
BITMAP API [RUST]
|
||||
M: Alice Ryhl <aliceryhl@google.com>
|
||||
M: Burak Emir <bqe@google.com>
|
||||
M: Burak Emir <burak.emir@gmail.com>
|
||||
R: Yury Norov <yury.norov@gmail.com>
|
||||
S: Maintained
|
||||
F: lib/find_bit_benchmark_rust.rs
|
||||
@@ -9617,7 +9608,7 @@ M: Chao Yu <chao@kernel.org>
|
||||
R: Yue Hu <zbestahu@gmail.com>
|
||||
R: Jeffle Xu <jefflexu@linux.alibaba.com>
|
||||
R: Sandeep Dhavale <dhavale@google.com>
|
||||
R: Hongbo Li <lihongbo22@huawei.com>
|
||||
R: Hongbo Li <hongbohbli@tencent.com>
|
||||
R: Chunhai Guo <guochunhai@vivo.com>
|
||||
L: linux-erofs@lists.ozlabs.org
|
||||
S: Maintained
|
||||
@@ -10134,6 +10125,11 @@ F: drivers/base/firmware_loader/
|
||||
F: rust/kernel/firmware.rs
|
||||
F: include/linux/firmware.h
|
||||
|
||||
FIXED-LAYOUT NVMEM LAYOUT DRIVER
|
||||
M: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
|
||||
S: Maintained
|
||||
F: drivers/nvmem/layouts/fixed-layout.c
|
||||
|
||||
FLEXTIMER FTM-QUADDEC DRIVER
|
||||
M: Patrick Havelange <patrick.havelange@essensium.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -11743,6 +11739,7 @@ F: drivers/net/ethernet/hisilicon/hibmcge/
|
||||
|
||||
HISILICON NETWORK SUBSYSTEM DRIVER
|
||||
M: Jian Shen <shenjian15@huawei.com>
|
||||
M: Jijie Shao <shaojijie@huawei.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.hisilicon.com
|
||||
@@ -14193,7 +14190,7 @@ F: virt/kvm/*
|
||||
KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
|
||||
M: Marc Zyngier <maz@kernel.org>
|
||||
M: Oliver Upton <oupton@kernel.org>
|
||||
R: Fuad Tabba <tabba@google.com>
|
||||
R: Fuad Tabba <fuad.tabba@linux.dev>
|
||||
R: Joey Gouly <joey.gouly@arm.com>
|
||||
R: Steffen Eiden <seiden@linux.ibm.com>
|
||||
R: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
@@ -14887,7 +14884,7 @@ X: drivers/macintosh/via-macii.c
|
||||
|
||||
LINUX FOR POWERPC (32-BIT AND 64-BIT)
|
||||
M: Madhavan Srinivasan <maddy@linux.ibm.com>
|
||||
M: Michael Ellerman <mpe@ellerman.id.au>
|
||||
R: Michael Ellerman <mpe@ellerman.id.au>
|
||||
R: Nicholas Piggin <npiggin@gmail.com>
|
||||
R: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
@@ -17160,7 +17157,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Suren Baghdasaryan <surenb@google.com>
|
||||
R: Michal Hocko <mhocko@suse.com>
|
||||
R: Brendan Jackman <jackmanb@google.com>
|
||||
R: Brendan Jackman <brendan.jackman@linux.dev>
|
||||
R: Johannes Weiner <hannes@cmpxchg.org>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
L: linux-mm@kvack.org
|
||||
@@ -17253,7 +17250,7 @@ M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
R: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Nico Pache <npache@redhat.com>
|
||||
R: Nico Pache <nico.pache@linux.dev>
|
||||
R: Ryan Roberts <ryan.roberts@arm.com>
|
||||
R: Dev Jain <dev.jain@arm.com>
|
||||
R: Barry Song <baohua@kernel.org>
|
||||
@@ -17846,7 +17843,7 @@ F: drivers/net/wireless/microchip/
|
||||
|
||||
MICROCHIP ZL3073X DRIVER
|
||||
M: Ivan Vecera <ivecera@redhat.com>
|
||||
M: Prathosh Satish <Prathosh.Satish@microchip.com>
|
||||
M: Min Li <min.li@microchip.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml
|
||||
@@ -20692,7 +20689,6 @@ F: include/linux/switchtec.h
|
||||
F: include/uapi/linux/switchtec_ioctl.h
|
||||
|
||||
PCI DRIVER FOR MOBIVEIL PCIE IP
|
||||
M: Karthikeyan Mitran <m.karthikeyan@mobiveil.co.in>
|
||||
M: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Supported
|
||||
@@ -22736,7 +22732,8 @@ F: drivers/watchdog/realtek_otto_wdt.c
|
||||
|
||||
REALTEK RTL83xx SMI DSA ROUTER CHIPS
|
||||
M: Linus Walleij <linusw@kernel.org>
|
||||
M: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
M: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
R: Alvin Šipraga <alvin.sipraga@analog.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
F: drivers/net/dsa/realtek/*
|
||||
@@ -24633,8 +24630,7 @@ SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
|
||||
M: D. Wythe <alibuda@linux.alibaba.com>
|
||||
M: Dust Li <dust.li@linux.alibaba.com>
|
||||
M: Sidraya Jayagond <sidraya@linux.ibm.com>
|
||||
M: Wenjia Zhang <wenjia@linux.ibm.com>
|
||||
R: Mahanta Jambigi <mjambigi@linux.ibm.com>
|
||||
M: Mahanta Jambigi <mjambigi@linux.ibm.com>
|
||||
R: Tony Lu <tonylu@linux.alibaba.com>
|
||||
R: Wen Gu <guwen@linux.alibaba.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
@@ -25430,6 +25426,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/i2c/spacemit,k1-i2c.yaml
|
||||
F: drivers/i2c/busses/i2c-k1.c
|
||||
|
||||
SPACEMIT K1/K3 I2S DRIVER
|
||||
M: Troy Mitchell <troy.mitchell@linux.spacemit.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
|
||||
F: sound/soc/spacemit/k1_i2s.c
|
||||
|
||||
SPANISH DOCUMENTATION
|
||||
M: Carlos Bilbao <carlos.bilbao@kernel.org>
|
||||
R: Avadhut Naik <avadhut.naik@amd.com>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@@ -700,13 +700,11 @@ filechk_makefile = { \
|
||||
echo "include $(abs_srctree)/Makefile"; \
|
||||
}
|
||||
|
||||
$(objtree)/Makefile: FORCE
|
||||
PHONY += $(CURDIR)/Makefile
|
||||
$(CURDIR)/Makefile: FORCE
|
||||
$(call filechk,makefile)
|
||||
|
||||
# Prevent $(srcroot)/Makefile from inhibiting the rule to run.
|
||||
PHONY += $(objtree)/Makefile
|
||||
|
||||
outputmakefile: $(objtree)/Makefile
|
||||
outputmakefile: $(CURDIR)/Makefile
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
@if [ -f $(srctree)/.config -o \
|
||||
-d $(srctree)/include/config -o \
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
|
||||
/* PCIe Controller 2 */
|
||||
<0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x00014000 1 &gic GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
nvram@1c080000 {
|
||||
compatible = "brcm,nvram";
|
||||
reg = <0x1c080000 0x180000>;
|
||||
reg = <0x1c080000 0x100000>;
|
||||
|
||||
et2macaddr: et2macaddr {
|
||||
#nvmem-cell-cells = <1>;
|
||||
|
||||
@@ -32,6 +32,7 @@ static int npcm7xx_smp_boot_secondary(unsigned int cpu,
|
||||
goto out;
|
||||
}
|
||||
gcr_base = of_iomap(gcr_np, 0);
|
||||
of_node_put(gcr_np);
|
||||
if (!gcr_base) {
|
||||
pr_err("could not iomap gcr");
|
||||
ret = -ENOMEM;
|
||||
@@ -60,6 +61,7 @@ static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
|
||||
return;
|
||||
}
|
||||
scu_base = of_iomap(scu_np, 0);
|
||||
of_node_put(scu_np);
|
||||
if (!scu_base) {
|
||||
pr_err("could not iomap scu");
|
||||
return;
|
||||
|
||||
@@ -678,8 +678,6 @@
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
|
||||
IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
|
||||
IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
|
||||
IRQ_TYPE_LEVEL_LOW)>;
|
||||
};
|
||||
|
||||
|
||||
@@ -2559,7 +2559,7 @@
|
||||
"dsi_pll";
|
||||
|
||||
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK>;
|
||||
<&bi_tcxo_div2>;
|
||||
clock-names = "iface",
|
||||
"ref";
|
||||
|
||||
|
||||
@@ -1876,7 +1876,7 @@
|
||||
spi0: spi@b80000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b80000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1052 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 92 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -1903,7 +1903,7 @@
|
||||
i2c1: i2c@b84000 {
|
||||
compatible = "qcom,geni-i2c";
|
||||
reg = <0x0 0x00b84000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1053 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -1930,7 +1930,7 @@
|
||||
spi1: spi@b84000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b84000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1053 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -1957,7 +1957,7 @@
|
||||
i2c2: i2c@b88000 {
|
||||
compatible = "qcom,geni-i2c";
|
||||
reg = <0x0 0x00b88000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -1984,7 +1984,7 @@
|
||||
spi2: spi@b88000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b88000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2011,7 +2011,7 @@
|
||||
uart2: serial@b88000 {
|
||||
compatible = "qcom,geni-uart";
|
||||
reg = <0x0 0x00b88000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1054 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2056,7 +2056,7 @@
|
||||
spi3: spi@b8c000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b8c000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1055 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 95 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2110,7 +2110,7 @@
|
||||
spi4: spi@b90000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b90000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1056 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 96 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2164,7 +2164,7 @@
|
||||
spi5: spi@b94000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b94000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1057 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2191,7 +2191,7 @@
|
||||
i2c6: i2c@b98000 {
|
||||
compatible = "qcom,geni-i2c";
|
||||
reg = <0x0 0x00b98000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1058 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2218,7 +2218,7 @@
|
||||
spi6: spi@b98000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b98000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1058 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2245,7 +2245,7 @@
|
||||
i2c7: i2c@b9c000 {
|
||||
compatible = "qcom,geni-i2c";
|
||||
reg = <0x0 0x00b9c000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1059 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 99 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -2272,7 +2272,7 @@
|
||||
spi7: spi@b9c000 {
|
||||
compatible = "qcom,geni-spi";
|
||||
reg = <0x0 0x00b9c000 0x0 0x4000>;
|
||||
interrupts = <GIC_SPI 1059 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 99 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
|
||||
clock-names = "se";
|
||||
interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
|
||||
@@ -6874,9 +6874,9 @@
|
||||
pcie_smmu: iommu@15480000 {
|
||||
compatible = "arm,smmu-v3";
|
||||
reg = <0x0 0x15480000 0x0 0x20000>;
|
||||
interrupts = <GIC_SPI 964 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 962 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 960 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_ESPI 4 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_ESPI 2 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_ESPI 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "eventq", "cmdq-sync", "gerror";
|
||||
dma-coherent;
|
||||
#iommu-cells = <1>;
|
||||
|
||||
@@ -7384,6 +7384,7 @@
|
||||
interrupt-controller;
|
||||
#redistributor-regions = <1>;
|
||||
redistributor-stride = <0x0 0x20000>;
|
||||
#address-cells = <0>;
|
||||
};
|
||||
|
||||
watchdog@17c10000 {
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
&gpu {
|
||||
compatible = "qcom,adreno-43030c00", "qcom,adreno";
|
||||
|
||||
iommus = <&adreno_smmu 0 0x0>;
|
||||
|
||||
nvmem-cells = <&gpu_speed_bin>;
|
||||
nvmem-cell-names = "speed_bin";
|
||||
|
||||
|
||||
@@ -637,7 +637,7 @@
|
||||
compatible = "huawei,gaokun3-ec";
|
||||
reg = <0x38>;
|
||||
|
||||
interrupts-extended = <&tlmm 107 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupts-extended = <&tlmm 103 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
@@ -5356,7 +5356,7 @@
|
||||
<211 699 1>,
|
||||
<212 705 1>,
|
||||
<213 450 1>,
|
||||
<214 643 1>,
|
||||
<214 643 2>,
|
||||
<216 646 5>,
|
||||
<221 390 5>,
|
||||
<226 700 3>,
|
||||
@@ -5379,7 +5379,7 @@
|
||||
<252 798 1>,
|
||||
<253 765 1>,
|
||||
<254 763 1>,
|
||||
<255 454 1>,
|
||||
<255 454 3>,
|
||||
<258 139 1>,
|
||||
<259 786 2>,
|
||||
<261 370 2>,
|
||||
|
||||
@@ -347,6 +347,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&cluster_sleep_0 {
|
||||
arm,psci-suspend-param = <0x41008244>;
|
||||
};
|
||||
|
||||
&gcc {
|
||||
protected-clocks = <GCC_QSPI_CORE_CLK>,
|
||||
<GCC_QSPI_CORE_CLK_SRC>,
|
||||
|
||||
@@ -7091,8 +7091,8 @@
|
||||
|
||||
ranges = <0 0 0x14680000 0x2c000>;
|
||||
|
||||
ipa_modem_tables: modem-tables@8000 {
|
||||
reg = <0x8000 0x2000>;
|
||||
ipa_modem_tables: modem-tables@3000 {
|
||||
reg = <0x3000 0x2000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
enum hyp_enter_exit_reason {
|
||||
HYP_REASON_SMC,
|
||||
HYP_REASON_HVC,
|
||||
HYP_REASON_SYS,
|
||||
HYP_REASON_PSCI,
|
||||
HYP_REASON_HOST_ABORT,
|
||||
HYP_REASON_GUEST_EXIT,
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#include <linux/ptdump.h>
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(arm64_ptdump_lock_key);
|
||||
|
||||
#ifdef CONFIG_PTDUMP
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright 2023 Google LLC
|
||||
// Authors: Ard Biesheuvel <ardb@google.com>
|
||||
// Peter Collingbourne <pcc@google.com>
|
||||
// Peter Collingbourne <peter@pcc.me.uk>
|
||||
|
||||
#include <linux/elf.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
+19
-6
@@ -149,14 +149,27 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
|
||||
set_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
|
||||
&kvm->arch.flags);
|
||||
break;
|
||||
case KVM_CAP_ARM_MTE:
|
||||
mutex_lock(&kvm->lock);
|
||||
if (system_supports_mte() && !kvm->created_vcpus) {
|
||||
r = 0;
|
||||
set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags);
|
||||
case KVM_CAP_ARM_MTE: {
|
||||
struct kvm_memory_slot *memslot;
|
||||
int bkt;
|
||||
|
||||
guard(mutex)(&kvm->lock);
|
||||
if (!system_supports_mte() || kvm->created_vcpus)
|
||||
break;
|
||||
|
||||
r = 0;
|
||||
guard(mutex)(&kvm->slots_lock);
|
||||
kvm_for_each_memslot(memslot, bkt, kvm_memslots(kvm)) {
|
||||
if (kvm_slot_has_gmem(memslot)) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
if (r == 0)
|
||||
set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags);
|
||||
break;
|
||||
|
||||
}
|
||||
case KVM_CAP_ARM_SYSTEM_SUSPEND:
|
||||
r = 0;
|
||||
set_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags);
|
||||
|
||||
@@ -932,6 +932,7 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
|
||||
handle_host_mem_abort(host_ctxt);
|
||||
break;
|
||||
case ESR_ELx_EC_SYS64:
|
||||
trace_hyp_enter(host_ctxt, HYP_REASON_SYS);
|
||||
if (handle_host_mte(esr))
|
||||
break;
|
||||
fallthrough;
|
||||
|
||||
+24
-12
@@ -37,8 +37,6 @@ static struct hyp_trace_clock {
|
||||
u32 shift;
|
||||
struct delayed_work work;
|
||||
struct completion ready;
|
||||
struct mutex lock;
|
||||
bool running;
|
||||
} hyp_clock;
|
||||
|
||||
static void __hyp_clock_work(struct work_struct *work)
|
||||
@@ -110,12 +108,9 @@ static void hyp_trace_clock_enable(struct hyp_trace_clock *hyp_clock, bool enabl
|
||||
{
|
||||
struct system_time_snapshot snap;
|
||||
|
||||
if (hyp_clock->running == enable)
|
||||
return;
|
||||
|
||||
if (!enable) {
|
||||
cancel_delayed_work_sync(&hyp_clock->work);
|
||||
hyp_clock->running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
|
||||
@@ -128,7 +123,6 @@ static void hyp_trace_clock_enable(struct hyp_trace_clock *hyp_clock, bool enabl
|
||||
INIT_DELAYED_WORK(&hyp_clock->work, __hyp_clock_work);
|
||||
schedule_delayed_work(&hyp_clock->work, msecs_to_jiffies(CLOCK_INIT_MS));
|
||||
wait_for_completion(&hyp_clock->ready);
|
||||
hyp_clock->running = true;
|
||||
}
|
||||
|
||||
/* Access to this struct within the trace_remote_callbacks are protected by the trace_remote lock */
|
||||
@@ -160,6 +154,7 @@ static int hyp_trace_buffer_alloc_bpages_backing(struct hyp_trace_buffer *trace_
|
||||
int nr_bpages = (PAGE_ALIGN(size) / PAGE_SIZE) + 1;
|
||||
size_t backing_size;
|
||||
void *start;
|
||||
int ret;
|
||||
|
||||
backing_size = PAGE_ALIGN(sizeof(struct simple_buffer_page) * nr_bpages *
|
||||
num_possible_cpus());
|
||||
@@ -168,10 +163,16 @@ static int hyp_trace_buffer_alloc_bpages_backing(struct hyp_trace_buffer *trace_
|
||||
if (!start)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = __map_hyp(start, backing_size);
|
||||
if (ret) {
|
||||
free_pages_exact(start, backing_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
trace_buffer->desc->bpages_backing_start = (unsigned long)start;
|
||||
trace_buffer->desc->bpages_backing_size = backing_size;
|
||||
|
||||
return __map_hyp(start, backing_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hyp_trace_buffer_free_bpages_backing(struct hyp_trace_buffer *trace_buffer)
|
||||
@@ -228,18 +229,22 @@ static int hyp_trace_buffer_share_hyp(struct hyp_trace_buffer *trace_buffer)
|
||||
static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
|
||||
{
|
||||
struct hyp_trace_buffer *trace_buffer = priv;
|
||||
size_t desc_size, tb_desc_size;
|
||||
struct hyp_trace_desc *desc;
|
||||
size_t desc_size;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(trace_buffer->desc))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
desc_size = trace_buffer_desc_size(size, num_possible_cpus());
|
||||
tb_desc_size = trace_buffer_desc_size(size, num_possible_cpus());
|
||||
desc_size = size_add(tb_desc_size, offsetof(struct hyp_trace_desc, trace_buffer_desc));
|
||||
if (desc_size == SIZE_MAX)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
desc_size = PAGE_ALIGN(desc_size);
|
||||
if (!desc_size)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
desc = (struct hyp_trace_desc *)alloc_pages_exact(desc_size, GFP_KERNEL);
|
||||
if (!desc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -255,7 +260,7 @@ static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
|
||||
if (ret)
|
||||
goto err_free_desc;
|
||||
|
||||
ret = trace_remote_alloc_buffer(&desc->trace_buffer_desc, desc_size, size,
|
||||
ret = trace_remote_alloc_buffer(&desc->trace_buffer_desc, tb_desc_size, size,
|
||||
cpu_possible_mask);
|
||||
if (ret)
|
||||
goto err_free_backing;
|
||||
@@ -304,9 +309,15 @@ static void hyp_trace_unload(struct trace_buffer_desc *desc, void *priv)
|
||||
|
||||
static int hyp_trace_enable_tracing(bool enable, void *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hyp_trace_clock_enable(&hyp_clock, enable);
|
||||
|
||||
return kvm_call_hyp_nvhe(__tracing_enable, enable);
|
||||
ret = kvm_call_hyp_nvhe(__tracing_enable, enable);
|
||||
if (ret)
|
||||
hyp_trace_clock_enable(&hyp_clock, !enable);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hyp_trace_swap_reader_page(unsigned int cpu, void *priv)
|
||||
@@ -398,6 +409,7 @@ static const char *__hyp_enter_exit_reason_str(u8 reason)
|
||||
static const char strs[][12] = {
|
||||
"smc",
|
||||
"hvc",
|
||||
"sys",
|
||||
"psci",
|
||||
"host_abort",
|
||||
"guest_exit",
|
||||
|
||||
@@ -2652,6 +2652,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
if (kvm_slot_has_gmem(new) && !kvm_memslot_is_gmem_only(new))
|
||||
return -EINVAL;
|
||||
|
||||
/* guest_memfd is incompatible with MTE. */
|
||||
if (kvm_slot_has_gmem(new) && kvm_has_mte(kvm))
|
||||
return -EINVAL;
|
||||
|
||||
hva = new->userspace_addr;
|
||||
reg_end = hva + (new->npages << PAGE_SHIFT);
|
||||
|
||||
|
||||
@@ -116,18 +116,27 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
|
||||
kfree(irq);
|
||||
irq = oldirq;
|
||||
} else {
|
||||
ret = xa_err(__xa_store(&dist->lpi_xa, intid, irq, 0));
|
||||
/*
|
||||
* The entry is either empty or contains a dead LPI (refcount=0)
|
||||
* from the deferred release path, pending cleanup by
|
||||
* vgic_release_deleted_lpis(). Evict and free it if present.
|
||||
*/
|
||||
oldirq = __xa_store(&dist->lpi_xa, intid, irq,
|
||||
GFP_NOWAIT | __GFP_ACCOUNT);
|
||||
ret = xa_err(oldirq);
|
||||
if (ret) {
|
||||
xa_unlock_irqrestore(&dist->lpi_xa, flags);
|
||||
kfree(irq);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (oldirq && !WARN_ON_ONCE(refcount_read(&oldirq->refcount)))
|
||||
kfree_rcu(oldirq, rcu);
|
||||
}
|
||||
|
||||
xa_unlock_irqrestore(&dist->lpi_xa, flags);
|
||||
|
||||
if (ret) {
|
||||
xa_release(&dist->lpi_xa, intid);
|
||||
kfree(irq);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* We "cache" the configuration table entries in our struct vgic_irq's.
|
||||
* However we only have those structs for mapped IRQs, so we read in
|
||||
|
||||
@@ -275,7 +275,13 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
|
||||
lr = vgic_v3_compute_lr(vcpu, irq) & ~ICH_LR_ACTIVE_BIT;
|
||||
}
|
||||
|
||||
if (lr & ICH_LR_HW)
|
||||
/*
|
||||
* In the nested state, the irq has already been deactivated via the HW
|
||||
* bit in the LR. Deactivating again would be harmless except AmpereOne
|
||||
* errata AC03_CPU_57, AC04_CPU_29 could cause irq delivery to break if
|
||||
* the deactivation hits the highest priority pending irq.
|
||||
*/
|
||||
if ((lr & ICH_LR_HW) && !vgic_state_is_nested(vcpu))
|
||||
vgic_v3_deactivate_phys(FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
|
||||
|
||||
vgic_v3_fold_lr(vcpu, lr);
|
||||
|
||||
@@ -146,11 +146,7 @@ static __must_check bool __vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
|
||||
|
||||
static __must_check bool vgic_put_irq_norelease(struct kvm *kvm, struct vgic_irq *irq)
|
||||
{
|
||||
if (!__vgic_put_irq(kvm, irq))
|
||||
return false;
|
||||
|
||||
irq->pending_release = true;
|
||||
return true;
|
||||
return __vgic_put_irq(kvm, irq);
|
||||
}
|
||||
|
||||
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
|
||||
@@ -167,12 +163,14 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
|
||||
guard(spinlock_irqsave)(&dist->lpi_xa.xa_lock);
|
||||
}
|
||||
|
||||
if (!__vgic_put_irq(kvm, irq))
|
||||
if (!irq_is_lpi(kvm, irq->intid))
|
||||
return;
|
||||
|
||||
xa_lock_irqsave(&dist->lpi_xa, flags);
|
||||
vgic_release_lpi_locked(dist, irq);
|
||||
xa_unlock_irqrestore(&dist->lpi_xa, flags);
|
||||
if (refcount_dec_and_lock_irqsave(&irq->refcount,
|
||||
&dist->lpi_xa.xa_lock, &flags)) {
|
||||
vgic_release_lpi_locked(dist, irq);
|
||||
xa_unlock_irqrestore(&dist->lpi_xa, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void vgic_release_deleted_lpis(struct kvm *kvm)
|
||||
@@ -184,7 +182,7 @@ static void vgic_release_deleted_lpis(struct kvm *kvm)
|
||||
xa_lock_irqsave(&dist->lpi_xa, flags);
|
||||
|
||||
xa_for_each(&dist->lpi_xa, intid, irq) {
|
||||
if (irq->pending_release)
|
||||
if (!refcount_read(&irq->refcount))
|
||||
vgic_release_lpi_locked(dist, irq);
|
||||
}
|
||||
|
||||
|
||||
+4
-39
@@ -49,8 +49,6 @@
|
||||
#define NO_CONT_MAPPINGS BIT(1)
|
||||
#define NO_EXEC_MAPPINGS BIT(2) /* assumes FEAT_HPDS is not used */
|
||||
|
||||
DEFINE_STATIC_KEY_FALSE(arm64_ptdump_lock_key);
|
||||
|
||||
u64 kimage_voffset __ro_after_init;
|
||||
EXPORT_SYMBOL(kimage_voffset);
|
||||
|
||||
@@ -1864,8 +1862,7 @@ int pmd_clear_huge(pmd_t *pmdp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __pmd_free_pte_page(pmd_t *pmdp, unsigned long addr,
|
||||
bool acquire_mmap_lock)
|
||||
int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
|
||||
{
|
||||
pte_t *table;
|
||||
pmd_t pmd;
|
||||
@@ -1877,25 +1874,13 @@ static int __pmd_free_pte_page(pmd_t *pmdp, unsigned long addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* See comment in pud_free_pmd_page for static key logic */
|
||||
table = pte_offset_kernel(pmdp, addr);
|
||||
pmd_clear(pmdp);
|
||||
__flush_tlb_kernel_pgtable(addr);
|
||||
if (static_branch_unlikely(&arm64_ptdump_lock_key) && acquire_mmap_lock) {
|
||||
mmap_read_lock(&init_mm);
|
||||
mmap_read_unlock(&init_mm);
|
||||
}
|
||||
|
||||
pte_free_kernel(NULL, table);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
|
||||
{
|
||||
/* If ptdump is walking the pagetables, acquire init_mm.mmap_lock */
|
||||
return __pmd_free_pte_page(pmdp, addr, /* acquire_mmap_lock = */ true);
|
||||
}
|
||||
|
||||
int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
|
||||
{
|
||||
pmd_t *table;
|
||||
@@ -1911,36 +1896,16 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
|
||||
}
|
||||
|
||||
table = pmd_offset(pudp, addr);
|
||||
|
||||
/*
|
||||
* Our objective is to prevent ptdump from reading a PMD table which has
|
||||
* been freed. In this race, if pud_free_pmd_page observes the key on
|
||||
* (which got flipped by ptdump) then the mmap lock sequence here will,
|
||||
* as a result of the mmap write lock/unlock sequence in ptdump, give
|
||||
* us the correct synchronization. If not, this means that ptdump has
|
||||
* yet not started walking the pagetables - the sequence of barriers
|
||||
* issued by __flush_tlb_kernel_pgtable() guarantees that ptdump will
|
||||
* observe an empty PUD.
|
||||
*/
|
||||
pud_clear(pudp);
|
||||
__flush_tlb_kernel_pgtable(addr);
|
||||
if (static_branch_unlikely(&arm64_ptdump_lock_key)) {
|
||||
mmap_read_lock(&init_mm);
|
||||
mmap_read_unlock(&init_mm);
|
||||
}
|
||||
|
||||
pmdp = table;
|
||||
next = addr;
|
||||
end = addr + PUD_SIZE;
|
||||
do {
|
||||
if (pmd_present(pmdp_get(pmdp)))
|
||||
/*
|
||||
* PMD has been isolated, so ptdump won't see it. No
|
||||
* need to acquire init_mm.mmap_lock.
|
||||
*/
|
||||
__pmd_free_pte_page(pmdp, next, /* acquire_mmap_lock = */ false);
|
||||
pmd_free_pte_page(pmdp, next);
|
||||
} while (pmdp++, next += PMD_SIZE, next != end);
|
||||
|
||||
pud_clear(pudp);
|
||||
__flush_tlb_kernel_pgtable(addr);
|
||||
pmd_free(NULL, table);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -283,13 +283,6 @@ void note_page_flush(struct ptdump_state *pt_st)
|
||||
note_page(pt_st, 0, -1, pte_val(pte_zero));
|
||||
}
|
||||
|
||||
static void arm64_ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm)
|
||||
{
|
||||
static_branch_inc(&arm64_ptdump_lock_key);
|
||||
ptdump_walk_pgd(st, mm, NULL);
|
||||
static_branch_dec(&arm64_ptdump_lock_key);
|
||||
}
|
||||
|
||||
void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
|
||||
{
|
||||
unsigned long end = ~0UL;
|
||||
@@ -318,7 +311,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
|
||||
}
|
||||
};
|
||||
|
||||
arm64_ptdump_walk_pgd(&st.ptdump, info->mm);
|
||||
ptdump_walk_pgd(&st.ptdump, info->mm, NULL);
|
||||
}
|
||||
|
||||
static void __init ptdump_initialize(void)
|
||||
@@ -360,7 +353,7 @@ bool ptdump_check_wx(void)
|
||||
}
|
||||
};
|
||||
|
||||
arm64_ptdump_walk_pgd(&st.ptdump, &init_mm);
|
||||
ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
|
||||
|
||||
if (st.wx_pages || st.uxn_pages) {
|
||||
pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n",
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <asm/processor.h>
|
||||
|
||||
.section .data
|
||||
/* The MMU requires a page aligned page directory. */
|
||||
.align 12
|
||||
.global swapper_pg_dir
|
||||
swapper_pg_dir:
|
||||
.space PAGE_SIZE
|
||||
|
||||
@@ -68,7 +68,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
|
||||
/* finally, setup the timebase */
|
||||
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
|
||||
"cpu", sizeof("cpu"));
|
||||
if (!node)
|
||||
if (node < 0)
|
||||
fatal("Cannot find cpu node\n");
|
||||
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
|
||||
if (timebase && (size == 4))
|
||||
|
||||
@@ -146,7 +146,7 @@ void platform_init(char *userdata)
|
||||
|
||||
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
|
||||
"cpu", sizeof("cpu"));
|
||||
if (!node)
|
||||
if (node < 0)
|
||||
fatal("Cannot find cpu node\n");
|
||||
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
|
||||
if (timebase && (size == 4))
|
||||
|
||||
@@ -102,7 +102,7 @@ void platform_init(void)
|
||||
|
||||
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
|
||||
"cpu", sizeof("cpu"));
|
||||
if (!node)
|
||||
if (node < 0)
|
||||
fatal("Cannot find cpu node\n");
|
||||
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
|
||||
if (timebase && (size == 4))
|
||||
|
||||
@@ -66,6 +66,13 @@ static inline void srr_regs_clobbered(void)
|
||||
static inline void nap_adjust_return(struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_PPC_970_NAP
|
||||
/*
|
||||
* Adjust the nap return address before irq_exit_rcu(). irq_exit_rcu()
|
||||
* may invoke softirqs with interrupts re-enabled, allowing a nested
|
||||
* async interrupt to arrive. If _TLF_NAPPING is still set at that
|
||||
* point, the nested interrupt would erroneously redirect its own
|
||||
* return address to power4_idle_nap_return, corrupting the stack.
|
||||
*/
|
||||
if (unlikely(test_thread_local_flags(_TLF_NAPPING))) {
|
||||
/* Can avoid a test-and-clear because NMIs do not call this */
|
||||
clear_thread_local_flags(_TLF_NAPPING);
|
||||
@@ -286,14 +293,6 @@ static inline void arch_interrupt_async_enter_prepare(struct pt_regs *regs)
|
||||
|
||||
static inline void arch_interrupt_async_exit_prepare(struct pt_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Adjust at exit so the main handler sees the true NIA. This must
|
||||
* come before irq_exit() because irq_exit can enable interrupts, and
|
||||
* if another interrupt is taken before nap_adjust_return has run
|
||||
* here, then that interrupt would return directly to idle nap return.
|
||||
*/
|
||||
nap_adjust_return(regs);
|
||||
|
||||
arch_interrupt_exit_prepare(regs);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,6 +246,7 @@ interrupt_handler void func(struct pt_regs *regs) \
|
||||
instrumentation_begin(); \
|
||||
irq_enter_rcu(); \
|
||||
____##func (regs); \
|
||||
nap_adjust_return(regs); \
|
||||
irq_exit_rcu(); \
|
||||
instrumentation_end(); \
|
||||
arch_interrupt_async_exit_prepare(regs); \
|
||||
|
||||
@@ -53,9 +53,6 @@ struct pt_regs
|
||||
unsigned long esr;
|
||||
};
|
||||
unsigned long result;
|
||||
unsigned long exit_flags;
|
||||
/* Maintain 16 byte interrupt stack alignment */
|
||||
unsigned long __pt_regs_pad[3];
|
||||
};
|
||||
};
|
||||
#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_KUAP)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
*/
|
||||
#ifndef _ASM_POWERPC_SERIAL_H
|
||||
#define _ASM_POWERPC_SERIAL_H
|
||||
|
||||
@@ -18,4 +16,4 @@ extern void find_legacy_serial_ports(void);
|
||||
#define find_legacy_serial_ports() do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _PPC64_SERIAL_H */
|
||||
#endif /* _ASM_POWERPC_SERIAL_H */
|
||||
|
||||
@@ -57,6 +57,7 @@ struct thread_info {
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int cpu;
|
||||
#endif
|
||||
unsigned long exit_flags; /* Exit Flags for entry/exit */
|
||||
unsigned long syscall_work; /* SYSCALL_WORK_ flags */
|
||||
unsigned long local_flags; /* private flags for thread */
|
||||
#ifdef CONFIG_LIVEPATCH_64
|
||||
|
||||
@@ -55,8 +55,6 @@ struct pt_regs
|
||||
unsigned long dar; /* Fault registers */
|
||||
unsigned long dsisr; /* on 4xx/Book-E used for ESR */
|
||||
unsigned long result; /* Result of a system call */
|
||||
unsigned long exit_flags; /* System call exit flags */
|
||||
unsigned long __pt_regs_pad[3]; /* Maintain 16 byte interrupt stack alignment */
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
@@ -116,12 +114,10 @@ struct pt_regs
|
||||
#define PT_DAR 41
|
||||
#define PT_DSISR 42
|
||||
#define PT_RESULT 43
|
||||
#define PT_EXIT_FLAGS 44
|
||||
#define PT_PAD 47 /* 3 times */
|
||||
#define PT_DSCR 48
|
||||
#define PT_REGS_COUNT 48
|
||||
#define PT_DSCR 44
|
||||
#define PT_REGS_COUNT 44
|
||||
|
||||
#define PT_FPR0 (PT_REGS_COUNT + 4) /* each FP reg occupies 2 slots in this space */
|
||||
#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
|
||||
|
||||
#ifndef __powerpc64__
|
||||
|
||||
@@ -133,7 +129,7 @@ struct pt_regs
|
||||
#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */
|
||||
|
||||
|
||||
#define PT_VR0 (PT_FPSCR + 2) /* <82> each Vector reg occupies 2 slots in 64-bit */
|
||||
#define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */
|
||||
#define PT_VSCR (PT_VR0 + 32*2 + 1)
|
||||
#define PT_VRSAVE (PT_VR0 + 33*2)
|
||||
|
||||
@@ -141,7 +137,7 @@ struct pt_regs
|
||||
/*
|
||||
* Only store first 32 VSRs here. The second 32 VSRs in VR0-31
|
||||
*/
|
||||
#define PT_VSR0 (PT_VRSAVE + 2) /* each VSR reg occupies 2 slots in 64-bit */
|
||||
#define PT_VSR0 150 /* each VSR reg occupies 2 slots in 64-bit */
|
||||
#define PT_VSR31 (PT_VSR0 + 2*31)
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
|
||||
@@ -89,15 +89,17 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
|
||||
long scv)
|
||||
{
|
||||
unsigned long ti_flags;
|
||||
unsigned long ret = 0;
|
||||
bool is_not_scv = !IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !scv;
|
||||
|
||||
kuap_assert_locked();
|
||||
|
||||
regs->result = r3;
|
||||
regs->exit_flags = 0;
|
||||
|
||||
/* Clear exit_flags so only flags set during this exit are visible */
|
||||
current->thread_info.exit_flags = 0;
|
||||
|
||||
ti_flags = read_thread_flags();
|
||||
|
||||
if (unlikely(r3 >= (unsigned long)-MAX_ERRNO) && is_not_scv) {
|
||||
if (likely(!(ti_flags & (_TIF_NOERROR | _TIF_RESTOREALL)))) {
|
||||
r3 = -r3;
|
||||
@@ -107,7 +109,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
|
||||
|
||||
if (unlikely(ti_flags & _TIF_PERSYSCALL_MASK)) {
|
||||
if (ti_flags & _TIF_RESTOREALL)
|
||||
regs->exit_flags = _TIF_RESTOREALL;
|
||||
ret = _TIF_RESTOREALL;
|
||||
else
|
||||
regs->gpr[3] = r3;
|
||||
clear_bits(_TIF_PERSYSCALL_MASK, ¤t_thread_info()->flags);
|
||||
@@ -116,7 +118,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
|
||||
}
|
||||
|
||||
if (unlikely(ti_flags & _TIF_SYSCALL_DOTRACE)) {
|
||||
regs->exit_flags |= _TIF_RESTOREALL;
|
||||
ret |= _TIF_RESTOREALL;
|
||||
}
|
||||
|
||||
syscall_exit_to_user_mode(regs);
|
||||
@@ -132,17 +134,19 @@ again:
|
||||
|
||||
/* Restore user access locks last */
|
||||
kuap_user_restore(regs);
|
||||
|
||||
ret |= current->thread_info.exit_flags;
|
||||
#ifdef CONFIG_PPC64
|
||||
regs->exit_result = regs->exit_flags;
|
||||
regs->exit_result = ret;
|
||||
#endif
|
||||
|
||||
return regs->exit_flags;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
notrace unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
/*
|
||||
* This is called when detecting a soft-pending interrupt as well as
|
||||
* an alternate-return interrupt. So we can't just have the alternate
|
||||
@@ -167,9 +171,11 @@ again:
|
||||
}
|
||||
|
||||
kuap_user_restore(regs);
|
||||
regs->exit_result |= regs->exit_flags;
|
||||
ret = current_thread_info()->exit_flags & _TIF_RESTOREALL;
|
||||
current_thread_info()->exit_flags &= ~_TIF_RESTOREALL;
|
||||
regs->exit_result |= ret;
|
||||
|
||||
return regs->exit_result;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -186,8 +192,10 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
|
||||
*/
|
||||
kuap_assert_locked();
|
||||
|
||||
/* Clear exit_flags so only flags set during this exit are visible */
|
||||
current_thread_info()->exit_flags = 0;
|
||||
|
||||
local_irq_disable();
|
||||
regs->exit_flags = 0;
|
||||
again:
|
||||
check_return_regs_valid(regs);
|
||||
user_enter_irqoff();
|
||||
@@ -200,9 +208,7 @@ again:
|
||||
|
||||
/* Restore user access locks last */
|
||||
kuap_user_restore(regs);
|
||||
|
||||
ret = regs->exit_flags;
|
||||
|
||||
ret = current_thread_info()->exit_flags & _TIF_RESTOREALL;
|
||||
#ifdef CONFIG_PPC64
|
||||
regs->exit_result = ret;
|
||||
#endif
|
||||
|
||||
@@ -291,7 +291,6 @@ void __init pt_regs_check(void)
|
||||
CHECK_REG(PT_DAR, dar);
|
||||
CHECK_REG(PT_DSISR, dsisr);
|
||||
CHECK_REG(PT_RESULT, result);
|
||||
CHECK_REG(PT_EXIT_FLAGS, exit_flags);
|
||||
#undef CHECK_REG
|
||||
|
||||
BUILD_BUG_ON(PT_REGS_COUNT != sizeof(struct user_pt_regs) / sizeof(unsigned long));
|
||||
|
||||
@@ -356,6 +356,6 @@ void signal_fault(struct task_struct *tsk, struct pt_regs *regs,
|
||||
void arch_do_signal_or_restart(struct pt_regs *regs)
|
||||
{
|
||||
BUG_ON(regs != current->thread.regs);
|
||||
regs->exit_flags |= _TIF_RESTOREALL;
|
||||
current_thread_info()->exit_flags |= _TIF_RESTOREALL;
|
||||
do_signal(current);
|
||||
}
|
||||
|
||||
@@ -1023,10 +1023,7 @@ static int thread_imc_event_init(struct perf_event *event)
|
||||
|
||||
static bool is_thread_imc_pmu(struct perf_event *event)
|
||||
{
|
||||
if (!strncmp(event->pmu->name, "thread_imc", strlen("thread_imc")))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return strstarts(event->pmu->name, "thread_imc");
|
||||
}
|
||||
|
||||
static __be64 *get_event_base_addr(struct perf_event *event)
|
||||
|
||||
@@ -615,6 +615,7 @@ static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
|
||||
|
||||
fail_map:
|
||||
for (iopage--; 0 <= iopage; iopage--) {
|
||||
offset = (1 << r->page_size) * iopage;
|
||||
lv1_put_iopte(0,
|
||||
c->bus_addr + offset,
|
||||
c->lpar_addr + offset,
|
||||
|
||||
@@ -191,8 +191,6 @@ static void spu_unmap(struct spu *spu)
|
||||
|
||||
static int __init setup_areas(struct spu *spu)
|
||||
{
|
||||
struct table {char* name; unsigned long addr; unsigned long size;};
|
||||
|
||||
spu_pdata(spu)->shadow = ioremap_prot(spu_pdata(spu)->shadow_addr,
|
||||
sizeof(struct spe_shadow),
|
||||
pgprot_noncached_wc(PAGE_KERNEL_RO));
|
||||
|
||||
@@ -20,12 +20,15 @@
|
||||
void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
|
||||
{
|
||||
/*
|
||||
* Don't risk a hypervisor call if we're crashing
|
||||
* XXX: Why? The hypervisor is not crashing. It might be better
|
||||
* to at least attempt unregister to avoid the hypervisor stepping
|
||||
* on our memory.
|
||||
* Ensure vpa/slb_shadow/dtl cleanup even while we are crashing.
|
||||
* Why? The hypervisor is not crashing so at least attempt unregister to
|
||||
* avoid the hypervisor stepping on our memory. If hypervisor or kexec
|
||||
* kernel steps on the old memory allocated to these areas before the
|
||||
* new kexec-kernel happens to allocate and register new areas,
|
||||
* the hypervisor will see invalid content which may cause
|
||||
* unexpected behavior.
|
||||
*/
|
||||
if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
|
||||
if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
|
||||
int ret;
|
||||
int cpu = smp_processor_id();
|
||||
int hwcpu = hard_smp_processor_id();
|
||||
|
||||
@@ -699,7 +699,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
|
||||
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
|
||||
return -EINVAL;
|
||||
|
||||
if (count > sizeof(kbuf))
|
||||
if (count == 0 || count > sizeof(kbuf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(kbuf, buf, count))
|
||||
|
||||
@@ -230,10 +230,17 @@ static long papr_phy_attest_create_handle(struct papr_phy_attest_io_block __user
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(¶ms->cmd, ulc,
|
||||
sizeof(struct papr_phy_attest_io_block)))
|
||||
sizeof(struct papr_phy_attest_io_block))) {
|
||||
kfree(params);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
params->cmd_len = be32_to_cpu(params->cmd.length);
|
||||
if (params->cmd_len == 0 || params->cmd_len > sizeof(params->cmd)) {
|
||||
kfree(params);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
seq = (struct papr_rtas_sequence) {
|
||||
.begin = phy_attest_sequence_begin,
|
||||
.end = phy_attest_sequence_end,
|
||||
@@ -246,6 +253,9 @@ static long papr_phy_attest_create_handle(struct papr_phy_attest_io_block __user
|
||||
&papr_phy_attest_handle_ops,
|
||||
"[papr-physical-attestation]");
|
||||
|
||||
if (fd < 0)
|
||||
kfree(params);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ static int pseries_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
|
||||
|
||||
/* First integer stores max config */
|
||||
max_config_vfs = of_read_number(&max_vfs[0], 1);
|
||||
if (max_config_vfs < num_vfs && num_vfs > MAX_VFS_FOR_MAP_PE) {
|
||||
if (max_config_vfs < num_vfs || num_vfs > MAX_VFS_FOR_MAP_PE) {
|
||||
dev_err(&pdev->dev,
|
||||
"Num VFs %x > %x Configurable VFs\n",
|
||||
num_vfs, (num_vfs > MAX_VFS_FOR_MAP_PE) ?
|
||||
|
||||
@@ -128,7 +128,12 @@ static void smp_setup_cpu(int cpu)
|
||||
else if (cpu != boot_cpuid)
|
||||
xics_setup_cpu();
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_SPLPAR))
|
||||
/*
|
||||
* Initialize VPA on non-boot cpus since boot-cpu vpa was
|
||||
* already initialized in pSeries_setup_arch()
|
||||
*/
|
||||
if (firmware_has_feature(FW_FEATURE_SPLPAR) &&
|
||||
cpu != boot_cpuid)
|
||||
vpa_init(cpu);
|
||||
|
||||
cpumask_clear_cpu(cpu, of_spin_mask);
|
||||
|
||||
+1
-1
@@ -168,7 +168,7 @@ vdso_prepare: prepare0
|
||||
endif
|
||||
endif
|
||||
|
||||
vdso-install-y += arch/riscv/kernel/vdso/vdso.so.dbg
|
||||
vdso-install-$(CONFIG_MMU) += arch/riscv/kernel/vdso/vdso.so.dbg
|
||||
vdso-install-$(CONFIG_RISCV_USER_CFI) += arch/riscv/kernel/vdso_cfi/vdso-cfi.so.dbg
|
||||
vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg
|
||||
|
||||
|
||||
@@ -93,10 +93,8 @@ void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
||||
for (alt = begin; alt < end; alt++) {
|
||||
if (alt->vendor_id != SIFIVE_VENDOR_ID)
|
||||
continue;
|
||||
if (alt->patch_id >= ERRATA_SIFIVE_NUMBER) {
|
||||
WARN(1, "This errata id:%d is not in kernel errata list", alt->patch_id);
|
||||
if (alt->patch_id >= ERRATA_SIFIVE_NUMBER)
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp = (1U << alt->patch_id);
|
||||
if (cpu_req_errata & tmp) {
|
||||
|
||||
@@ -22,13 +22,13 @@ static inline cycles_t get_cycles(void)
|
||||
#else /* !CONFIG_64BIT */
|
||||
static inline u32 get_cycles(void)
|
||||
{
|
||||
return readl_relaxed(((u32 *)clint_time_val));
|
||||
return readl_relaxed(((u32 __iomem *)clint_time_val));
|
||||
}
|
||||
#define get_cycles get_cycles
|
||||
|
||||
static inline u32 get_cycles_hi(void)
|
||||
{
|
||||
return readl_relaxed(((u32 *)clint_time_val) + 1);
|
||||
return readl_relaxed(((u32 __iomem *)clint_time_val) + 1);
|
||||
}
|
||||
#define get_cycles_hi get_cycles_hi
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
@@ -289,7 +289,7 @@ free:
|
||||
}
|
||||
|
||||
/* Measure unaligned access speed on all CPUs present at boot in parallel. */
|
||||
static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused)
|
||||
static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused)
|
||||
{
|
||||
schedule_on_each_cpu(check_vector_unaligned_access);
|
||||
riscv_hwprobe_complete_async_probe();
|
||||
@@ -297,7 +297,7 @@ static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __alway
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */
|
||||
static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused)
|
||||
static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
+16
-8
@@ -63,7 +63,8 @@ EXPORT_SYMBOL(phys_ram_base);
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
#define VMEMMAP_ADDR_ALIGN max(1ULL << SECTION_SIZE_BITS, \
|
||||
MAX_FOLIO_VMEMMAP_ALIGN)
|
||||
PFN_PHYS(MAX_FOLIO_VMEMMAP_ALIGN / \
|
||||
sizeof(struct page)))
|
||||
|
||||
unsigned long vmemmap_start_pfn __ro_after_init;
|
||||
EXPORT_SYMBOL(vmemmap_start_pfn);
|
||||
@@ -164,7 +165,9 @@ static void print_vm_layout(void) { }
|
||||
|
||||
void __init arch_mm_preinit(void)
|
||||
{
|
||||
bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit);
|
||||
bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit) &&
|
||||
memblock_start_of_DRAM() < dma32_phys_limit;
|
||||
unsigned int swiotlb_flags = SWIOTLB_VERBOSE;
|
||||
#ifdef CONFIG_FLATMEM
|
||||
BUG_ON(!mem_map);
|
||||
#endif /* CONFIG_FLATMEM */
|
||||
@@ -172,17 +175,22 @@ void __init arch_mm_preinit(void)
|
||||
if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
|
||||
dma_cache_alignment != 1) {
|
||||
/*
|
||||
* If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb
|
||||
* buffer per 1GB of RAM for kmalloc() bouncing on
|
||||
* non-coherent platforms.
|
||||
* No 32-bit DMA bouncing needed (either all DRAM is within
|
||||
* the 32-bit limit, or it all starts above it), but
|
||||
* kmalloc() buffers whose sizes are not cache-line-aligned
|
||||
* still require bouncing for non-coherent DMA. Use
|
||||
* SWIOTLB_ANY so that the buffer can be allocated from high
|
||||
* memory when DRAM starts above dma32_phys_limit. Allocate
|
||||
* ~1 MB per 1 GB of RAM.
|
||||
*/
|
||||
unsigned long size =
|
||||
DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
|
||||
swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
|
||||
swiotlb = true;
|
||||
swiotlb_flags |= SWIOTLB_ANY;
|
||||
}
|
||||
|
||||
swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
|
||||
swiotlb_init(swiotlb, swiotlb_flags);
|
||||
|
||||
print_vm_layout();
|
||||
}
|
||||
@@ -1618,7 +1626,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
|
||||
|
||||
for (; addr < end; addr = next) {
|
||||
next = pud_addr_end(addr, end);
|
||||
pudp = pud_base + pud_index(addr);
|
||||
pudp = pgtable_l4_enabled ? pud_base + pud_index(addr) : pud_base;
|
||||
pud = pudp_get(pudp);
|
||||
if (!pud_present(pud))
|
||||
continue;
|
||||
@@ -1649,7 +1657,7 @@ static void __meminit remove_p4d_mapping(p4d_t *p4d_base, unsigned long addr, un
|
||||
|
||||
for (; addr < end; addr = next) {
|
||||
next = p4d_addr_end(addr, end);
|
||||
p4dp = p4d_base + p4d_index(addr);
|
||||
p4dp = pgtable_l5_enabled ? p4d_base + p4d_index(addr) : p4d_base;
|
||||
p4d = p4dp_get(p4dp);
|
||||
if (!p4d_present(p4d))
|
||||
continue;
|
||||
|
||||
@@ -440,6 +440,7 @@ struct kvm_vcpu_arch {
|
||||
bool skey_enabled;
|
||||
/* Indicator if the access registers have been loaded from guest */
|
||||
bool acrs_loaded;
|
||||
bool initialized;
|
||||
struct kvm_s390_pv_vcpu pv;
|
||||
union diag318_info diag318_info;
|
||||
struct kvm_s390_mmu_cache *mc;
|
||||
@@ -476,6 +477,11 @@ struct s390_map_info {
|
||||
__u64 guest_addr;
|
||||
__u64 addr;
|
||||
struct page *page;
|
||||
/*
|
||||
* True if the page is long-term pinned. False if long-term pinning
|
||||
* failed and this entry exists only to preserve MAP/UNMAP symmetry.
|
||||
*/
|
||||
bool pinned;
|
||||
};
|
||||
|
||||
struct s390_io_adapter {
|
||||
|
||||
+16
-7
@@ -755,13 +755,15 @@ int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gf
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dat_reset_reference_bit(union asce asce, gfn_t gfn)
|
||||
int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey)
|
||||
{
|
||||
union pgste pgste, old;
|
||||
union crste *crstep;
|
||||
union pte *ptep;
|
||||
int rc;
|
||||
|
||||
skey->skey = 0;
|
||||
|
||||
rc = dat_entry_walk(NULL, gfn, asce, DAT_WALK_ANY, TABLE_TYPE_PAGE_TABLE, &crstep, &ptep);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -771,21 +773,23 @@ int dat_reset_reference_bit(union asce asce, gfn_t gfn)
|
||||
|
||||
if (!crste.h.fc || !crste.s.fc1.pr)
|
||||
return 0;
|
||||
return page_reset_referenced(large_crste_to_phys(*crstep, gfn));
|
||||
skey->skey = page_reset_referenced(large_crste_to_phys(*crstep, gfn)) << 1;
|
||||
return 0;
|
||||
}
|
||||
old = pgste_get_lock(ptep);
|
||||
pgste = old;
|
||||
|
||||
if (!ptep->h.i) {
|
||||
rc = page_reset_referenced(pte_origin(*ptep));
|
||||
pgste.hr = rc >> 1;
|
||||
skey->skey = page_reset_referenced(pte_origin(*ptep)) << 1;
|
||||
pgste.hr = skey->r;
|
||||
}
|
||||
rc |= (pgste.gr << 1) | pgste.gc;
|
||||
skey->r |= pgste.gr;
|
||||
skey->c |= pgste.gc;
|
||||
pgste.gr = 0;
|
||||
|
||||
dat_update_ptep_sd(old, pgste, ptep);
|
||||
pgste_set_unlock(ptep, pgste);
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dat_reset_skeys_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
|
||||
@@ -846,6 +850,7 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
|
||||
struct slot_priv *p = walk->priv;
|
||||
union crste dummy = { .val = p->token };
|
||||
union pte new_pte, pte = READ_ONCE(*ptep);
|
||||
union pgste pgste;
|
||||
|
||||
new_pte = _PTE_TOK(dummy.tok.type, dummy.tok.par);
|
||||
|
||||
@@ -853,7 +858,11 @@ static long _dat_slot_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_wal
|
||||
if (pte.val == new_pte.val)
|
||||
return 0;
|
||||
|
||||
dat_ptep_xchg(ptep, new_pte, gfn, walk->asce, false);
|
||||
pgste = pgste_get_lock(ptep);
|
||||
pgste = __dat_ptep_xchg(ptep, pgste, new_pte, gfn, walk->asce, false);
|
||||
pgste.cmma_d = 0;
|
||||
pgste_set_unlock(ptep, pgste);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -537,7 +537,7 @@ int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gf
|
||||
union skey skey, bool nq);
|
||||
int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,
|
||||
union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);
|
||||
int dat_reset_reference_bit(union asce asce, gfn_t gfn);
|
||||
int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);
|
||||
long dat_reset_skeys(union asce asce, gfn_t start);
|
||||
|
||||
unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);
|
||||
|
||||
@@ -91,9 +91,9 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
|
||||
/* Access outside memory, addressing exception. */
|
||||
if (is_noslot_pfn(f->pfn))
|
||||
return PGM_ADDRESSING;
|
||||
/* Signal pending: try again. */
|
||||
if (f->pfn == KVM_PFN_ERR_SIGPENDING)
|
||||
return -EAGAIN;
|
||||
/* Fatal signal pending: bail out. */
|
||||
if (is_sigpending_pfn(f->pfn))
|
||||
return -EINTR;
|
||||
/* Check if it's read-only memory; don't try to actually handle that case. */
|
||||
if (f->pfn == KVM_PFN_ERR_RO_FAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
+56
-19
@@ -45,13 +45,16 @@ static struct kvm_s390_gib *gib;
|
||||
static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
|
||||
{
|
||||
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||
union esca_sigp_ctrl sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||
union esca_sigp_ctrl sigp_ctrl;
|
||||
|
||||
if (!kvm_s390_test_cpuflags(vcpu, CPUSTAT_ECALL_PEND))
|
||||
return 0;
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return 0;
|
||||
|
||||
BUG_ON(!kvm_s390_use_sca_entries());
|
||||
|
||||
sigp_ctrl = sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||
if (src_id)
|
||||
*src_id = sigp_ctrl.scn;
|
||||
|
||||
@@ -60,13 +63,16 @@ static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
|
||||
|
||||
static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
|
||||
{
|
||||
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||
union esca_sigp_ctrl old_val, new_val = {.scn = src_id, .c = 1};
|
||||
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||
union esca_sigp_ctrl *sigp_ctrl;
|
||||
int expect, rc;
|
||||
|
||||
BUG_ON(!kvm_s390_use_sca_entries());
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return -EINVAL;
|
||||
|
||||
sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||
old_val = READ_ONCE(*sigp_ctrl);
|
||||
old_val.c = 0;
|
||||
|
||||
@@ -84,10 +90,13 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
|
||||
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||
union esca_sigp_ctrl *sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||
union esca_sigp_ctrl *sigp_ctrl;
|
||||
|
||||
if (!kvm_s390_use_sca_entries())
|
||||
if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized || kvm_is_ucontrol(vcpu->kvm))
|
||||
return;
|
||||
|
||||
/* Initialize after the above check, to prevent going out of bounds */
|
||||
sigp_ctrl = &sca->cpu[vcpu->vcpu_id].sigp_ctrl;
|
||||
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
|
||||
|
||||
WRITE_ONCE(sigp_ctrl->value, 0);
|
||||
@@ -2520,8 +2529,22 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
|
||||
map->addr = host_addr;
|
||||
map->page = pin_map_page(kvm, host_addr, FOLL_LONGTERM);
|
||||
if (!map->page) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
/*
|
||||
* Long-term pinning may fail for memory types such as file-backed
|
||||
* memory. Verify that short-term pinning succeeds so that the
|
||||
* non-atomic irqfd path can handle interrupt injection.
|
||||
*/
|
||||
map->page = pin_map_page(kvm, host_addr, 0);
|
||||
if (!map->page) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
unpin_user_page(map->page);
|
||||
map->page = NULL;
|
||||
map->pinned = false;
|
||||
/* Add an entry to preserve MAP/UNMAP symmetry. */
|
||||
} else {
|
||||
map->pinned = true;
|
||||
}
|
||||
spin_lock_irqsave(&adapter->maps_lock, flags);
|
||||
if (adapter->nr_maps < MAX_S390_ADAPTER_MAPS) {
|
||||
@@ -2532,7 +2555,7 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->maps_lock, flags);
|
||||
if (ret)
|
||||
if (ret && map->page)
|
||||
unpin_user_page(map->page);
|
||||
out:
|
||||
if (ret)
|
||||
@@ -2546,6 +2569,7 @@ static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
|
||||
struct s390_map_info *map, *tmp, *map_to_free;
|
||||
struct page *map_page_to_put = NULL;
|
||||
u64 map_addr_to_mark = 0;
|
||||
bool map_pinned = false;
|
||||
unsigned long flags;
|
||||
int found = 0, idx;
|
||||
|
||||
@@ -2560,6 +2584,7 @@ static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
|
||||
list_del(&map->list);
|
||||
map_page_to_put = map->page;
|
||||
map_addr_to_mark = map->guest_addr;
|
||||
map_pinned = map->pinned;
|
||||
map_to_free = map;
|
||||
break;
|
||||
}
|
||||
@@ -2568,11 +2593,18 @@ static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
|
||||
|
||||
if (found) {
|
||||
kfree(map_to_free);
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
mark_page_dirty(kvm, map_addr_to_mark >> PAGE_SHIFT);
|
||||
set_page_dirty_lock(map_page_to_put);
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
unpin_user_page(map_page_to_put);
|
||||
if (map_pinned) {
|
||||
/*
|
||||
* Only long-term pinned pages need to be marked dirty
|
||||
* and released. Fallback entries exist only for
|
||||
* MAP/UNMAP symmetry.
|
||||
*/
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
mark_page_dirty(kvm, map_addr_to_mark >> PAGE_SHIFT);
|
||||
set_page_dirty_lock(map_page_to_put);
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
unpin_user_page(map_page_to_put);
|
||||
}
|
||||
}
|
||||
|
||||
return found ? 0 : -ENOENT;
|
||||
@@ -2598,11 +2630,13 @@ void kvm_s390_unmap_all_adapters(struct kvm *kvm)
|
||||
|
||||
list_for_each_entry_safe(map, tmp, &local_list, list) {
|
||||
list_del(&map->list);
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
mark_page_dirty(kvm, map->guest_addr >> PAGE_SHIFT);
|
||||
set_page_dirty_lock(map->page);
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
unpin_user_page(map->page);
|
||||
if (map->pinned) {
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
mark_page_dirty(kvm, map->guest_addr >> PAGE_SHIFT);
|
||||
set_page_dirty_lock(map->page);
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
unpin_user_page(map->page);
|
||||
}
|
||||
kfree(map);
|
||||
}
|
||||
}
|
||||
@@ -2929,8 +2963,11 @@ static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter,
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(map, &adapter->maps, list) {
|
||||
if (map->addr == addr)
|
||||
if (map->addr == addr) {
|
||||
if (!map->pinned)
|
||||
return NULL;
|
||||
return map;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+81
-44
@@ -571,7 +571,7 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
|
||||
switch (op) {
|
||||
case KVM_S390_KEYOP_SSKE:
|
||||
r = dat_cond_set_storage_key(mc, asce, gfn, skey, &skey, 0, 0, 0);
|
||||
if (r >= 0)
|
||||
if (r == 0 || r == 1)
|
||||
return skey.skey;
|
||||
break;
|
||||
case KVM_S390_KEYOP_ISKE:
|
||||
@@ -580,14 +580,14 @@ static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op
|
||||
return skey.skey;
|
||||
break;
|
||||
case KVM_S390_KEYOP_RRBE:
|
||||
r = dat_reset_reference_bit(asce, gfn);
|
||||
if (r > 0)
|
||||
return r << 1;
|
||||
r = dat_reset_reference_bit(asce, gfn, &skey);
|
||||
if (!r)
|
||||
return skey.skey;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return r;
|
||||
return r > 0 ? -EFAULT : r;
|
||||
}
|
||||
|
||||
/* Section: device related */
|
||||
@@ -1219,8 +1219,8 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
|
||||
|
||||
/*
|
||||
* Must be called with kvm->srcu held to avoid races on memslots, and with
|
||||
* kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
|
||||
* and kvm_s390_get_cmma_bits().
|
||||
* kvm->slots_arch_lock to avoid races with ourselves,
|
||||
* kvm_s390_vm_stop_migration(), and kvm_s390_get_cmma_bits().
|
||||
*/
|
||||
static int kvm_s390_vm_start_migration(struct kvm *kvm)
|
||||
{
|
||||
@@ -1265,7 +1265,7 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called with kvm->slots_lock to avoid races with ourselves,
|
||||
* Must be called with kvm->slots_arch_lock to avoid races with ourselves,
|
||||
* kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
|
||||
*/
|
||||
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
|
||||
@@ -1300,7 +1300,9 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
|
||||
{
|
||||
int res = -ENXIO;
|
||||
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
guard(srcu)(&kvm->srcu);
|
||||
guard(mutex)(&kvm->slots_arch_lock);
|
||||
|
||||
switch (attr->attr) {
|
||||
case KVM_S390_VM_MIGRATION_START:
|
||||
res = kvm_s390_vm_start_migration(kvm);
|
||||
@@ -1311,7 +1313,6 @@ static int kvm_s390_vm_set_migration(struct kvm *kvm,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&kvm->slots_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -2214,7 +2215,7 @@ static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
|
||||
}
|
||||
|
||||
kvfree(keys);
|
||||
return r;
|
||||
return r <= 0 ? r : -EFAULT;
|
||||
}
|
||||
|
||||
static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
|
||||
@@ -2276,7 +2277,7 @@ static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
|
||||
kvm_s390_free_mmu_cache(mc);
|
||||
out:
|
||||
kvfree(keys);
|
||||
return r;
|
||||
return r <= 0 ? r : -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2386,7 +2387,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
|
||||
|
||||
set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
|
||||
|
||||
return r;
|
||||
return r <= 0 ? r : -EFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2934,6 +2935,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
|
||||
case KVM_S390_INTERRUPT: {
|
||||
struct kvm_s390_interrupt s390int;
|
||||
|
||||
r = -EINVAL;
|
||||
if (kvm_is_ucontrol(kvm))
|
||||
break;
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&s390int, argp, sizeof(s390int)))
|
||||
break;
|
||||
@@ -2998,9 +3002,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&args, argp, sizeof(args)))
|
||||
break;
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
r = kvm_s390_get_cmma_bits(kvm, &args);
|
||||
mutex_unlock(&kvm->slots_lock);
|
||||
scoped_guard(mutex, &kvm->slots_arch_lock)
|
||||
r = kvm_s390_get_cmma_bits(kvm, &args);
|
||||
if (!r) {
|
||||
r = copy_to_user(argp, &args, sizeof(args));
|
||||
if (r)
|
||||
@@ -3014,9 +3017,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&args, argp, sizeof(args)))
|
||||
break;
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
mutex_lock(&kvm->slots_arch_lock);
|
||||
r = kvm_s390_set_cmma_bits(kvm, &args);
|
||||
mutex_unlock(&kvm->slots_lock);
|
||||
mutex_unlock(&kvm->slots_arch_lock);
|
||||
break;
|
||||
}
|
||||
case KVM_S390_PV_COMMAND: {
|
||||
@@ -3247,7 +3250,8 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
|
||||
|
||||
static void sca_dispose(struct kvm *kvm)
|
||||
{
|
||||
free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
|
||||
if (kvm->arch.sca)
|
||||
free_pages_exact(kvm->arch.sca, sizeof(*kvm->arch.sca));
|
||||
kvm->arch.sca = NULL;
|
||||
}
|
||||
|
||||
@@ -3461,7 +3465,7 @@ static void sca_del_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct esca_block *sca = vcpu->kvm->arch.sca;
|
||||
|
||||
if (!kvm_s390_use_sca_entries())
|
||||
if (!kvm_s390_use_sca_entries() || !vcpu->arch.initialized)
|
||||
return;
|
||||
|
||||
clear_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
|
||||
@@ -3481,8 +3485,8 @@ static void sca_add_vcpu(struct kvm_vcpu *vcpu)
|
||||
if (!kvm_s390_use_sca_entries())
|
||||
return;
|
||||
|
||||
WRITE_ONCE(sca->cpu[vcpu->vcpu_id].sda, virt_to_phys(vcpu->arch.sie_block));
|
||||
set_bit_inv(vcpu->vcpu_id, (unsigned long *)sca->mcn);
|
||||
sca->cpu[vcpu->vcpu_id].sda = virt_to_phys(vcpu->arch.sie_block);
|
||||
}
|
||||
|
||||
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
|
||||
@@ -3613,6 +3617,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
|
||||
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
|
||||
vcpu->kvm->arch.user_operexec)
|
||||
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
|
||||
|
||||
/* Pairs with smp_load_acquire() in kvm_arch_vcpu_ioctl_run() and kvm_arch_vcpu_ioctl() */
|
||||
smp_store_release(&vcpu->arch.initialized, true);
|
||||
}
|
||||
|
||||
static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
|
||||
@@ -3674,7 +3681,8 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
|
||||
|
||||
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
|
||||
if (vcpu->arch.sie_block->cbrlo)
|
||||
free_page((unsigned long)phys_to_virt(vcpu->arch.sie_block->cbrlo));
|
||||
vcpu->arch.sie_block->cbrlo = 0;
|
||||
}
|
||||
|
||||
@@ -3792,21 +3800,21 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_FREE(sie_page, struct sie_page *, if (_T) free_page((unsigned long)(_T)))
|
||||
|
||||
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct sie_page *sie_page;
|
||||
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
|
||||
struct sie_page *sie_page __free(sie_page) = NULL;
|
||||
int rc;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
|
||||
vcpu->arch.mc = kvm_s390_new_mmu_cache();
|
||||
if (!vcpu->arch.mc)
|
||||
mc = kvm_s390_new_mmu_cache();
|
||||
if (!mc)
|
||||
return -ENOMEM;
|
||||
sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL_ACCOUNT);
|
||||
if (!sie_page) {
|
||||
kvm_s390_free_mmu_cache(vcpu->arch.mc);
|
||||
vcpu->arch.mc = NULL;
|
||||
if (!sie_page)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
vcpu->arch.sie_block = &sie_page->sie_block;
|
||||
vcpu->arch.sie_block->itdba = virt_to_phys(&sie_page->itdb);
|
||||
@@ -3848,10 +3856,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
|
||||
|
||||
if (kvm_is_ucontrol(vcpu->kvm)) {
|
||||
rc = -ENOMEM;
|
||||
vcpu->arch.gmap = gmap_new_child(vcpu->kvm->arch.gmap, -1UL);
|
||||
if (!vcpu->arch.gmap)
|
||||
goto out_free_sie_block;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%p, sie block at 0x%p",
|
||||
@@ -3859,20 +3866,19 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
|
||||
|
||||
rc = kvm_s390_vcpu_setup(vcpu);
|
||||
if (rc)
|
||||
goto out_ucontrol_uninit;
|
||||
if (rc) {
|
||||
if (kvm_is_ucontrol(vcpu->kvm)) {
|
||||
scoped_guard(spinlock, &vcpu->kvm->arch.gmap->children_lock)
|
||||
gmap_remove_child(vcpu->arch.gmap);
|
||||
vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
vcpu->arch.mc = no_free_ptr(mc);
|
||||
sie_page = NULL;
|
||||
kvm_s390_update_topology_change_report(vcpu->kvm, 1);
|
||||
return 0;
|
||||
|
||||
out_ucontrol_uninit:
|
||||
if (kvm_is_ucontrol(vcpu->kvm)) {
|
||||
gmap_remove_child(vcpu->arch.gmap);
|
||||
vcpu->arch.gmap = gmap_put(vcpu->arch.gmap);
|
||||
}
|
||||
out_free_sie_block:
|
||||
free_page((unsigned long)(vcpu->arch.sie_block));
|
||||
return rc;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
|
||||
@@ -5039,6 +5045,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
||||
kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS)
|
||||
return -EINVAL;
|
||||
|
||||
/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
|
||||
if (!smp_load_acquire(&vcpu->arch.initialized))
|
||||
return -EINVAL;
|
||||
|
||||
vcpu_load(vcpu);
|
||||
|
||||
if (guestdbg_exit_pending(vcpu)) {
|
||||
@@ -5447,6 +5457,8 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
|
||||
struct kvm_s390_interrupt s390int;
|
||||
struct kvm_s390_irq s390irq = {};
|
||||
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&s390int, argp, sizeof(s390int)))
|
||||
return -EFAULT;
|
||||
if (s390int_to_s390irq(&s390int, &s390irq))
|
||||
@@ -5523,6 +5535,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
|
||||
long r;
|
||||
u16 rc, rrc;
|
||||
|
||||
/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
|
||||
if (!smp_load_acquire(&vcpu->arch.initialized))
|
||||
return -EINVAL;
|
||||
|
||||
vcpu_load(vcpu);
|
||||
|
||||
switch (ioctl) {
|
||||
@@ -5794,14 +5810,30 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
|
||||
{
|
||||
union pgste pgste;
|
||||
|
||||
pgste = pgste_get_lock(ptep);
|
||||
if (pgste.cmma_d) {
|
||||
pgste.cmma_d = 0;
|
||||
atomic64_dec(walk->priv);
|
||||
}
|
||||
pgste_set_unlock(ptep, pgste);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_commit_memory_region(struct kvm *kvm,
|
||||
struct kvm_memory_slot *old,
|
||||
const struct kvm_memory_slot *new,
|
||||
enum kvm_mr_change change)
|
||||
{
|
||||
struct kvm_s390_mmu_cache *mc = NULL;
|
||||
const struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, };
|
||||
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
|
||||
int rc = 0;
|
||||
|
||||
guard(mutex)(&kvm->slots_arch_lock);
|
||||
|
||||
if (change == KVM_MR_FLAGS_ONLY)
|
||||
return;
|
||||
|
||||
@@ -5812,6 +5844,12 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
|
||||
}
|
||||
|
||||
scoped_guard(write_lock, &kvm->mmu_lock) {
|
||||
if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
|
||||
_dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages,
|
||||
kvm->arch.gmap->asce, &ops, DAT_WALK_IGN_HOLES,
|
||||
&kvm->arch.cmma_dirty_pages);
|
||||
}
|
||||
|
||||
switch (change) {
|
||||
case KVM_MR_DELETE:
|
||||
rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages);
|
||||
@@ -5833,7 +5871,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
|
||||
out:
|
||||
if (rc)
|
||||
pr_warn("failed to commit memory region\n");
|
||||
kvm_s390_free_mmu_cache(mc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+86
-21
@@ -190,40 +190,61 @@ static int kvm_zpci_clear_airq(struct zpci_dev *zdev)
|
||||
return cc ? -EIO : 0;
|
||||
}
|
||||
|
||||
static inline void unaccount_mem(unsigned long nr_pages)
|
||||
static inline void unaccount_mem(struct kvm_zdev *kzdev, unsigned long nr_pages)
|
||||
{
|
||||
struct user_struct *user = get_uid(current_user());
|
||||
struct user_struct *user = kzdev->user_account;
|
||||
struct mm_struct *mm_account = kzdev->mm_account;
|
||||
|
||||
if (user)
|
||||
if (user) {
|
||||
atomic_long_sub(nr_pages, &user->locked_vm);
|
||||
if (current->mm)
|
||||
atomic64_sub(nr_pages, ¤t->mm->pinned_vm);
|
||||
free_uid(user);
|
||||
kzdev->user_account = NULL;
|
||||
}
|
||||
|
||||
if (mm_account) {
|
||||
atomic64_sub(nr_pages, &mm_account->pinned_vm);
|
||||
mmdrop(mm_account);
|
||||
kzdev->mm_account = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int account_mem(unsigned long nr_pages)
|
||||
static inline int account_mem(struct kvm_zdev *kzdev, unsigned long nr_pages)
|
||||
{
|
||||
struct user_struct *user = get_uid(current_user());
|
||||
unsigned long page_limit, cur_pages, new_pages;
|
||||
int rc = 0;
|
||||
|
||||
page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
|
||||
|
||||
cur_pages = atomic_long_read(&user->locked_vm);
|
||||
do {
|
||||
new_pages = cur_pages + nr_pages;
|
||||
if (new_pages > page_limit)
|
||||
return -ENOMEM;
|
||||
if (new_pages > page_limit) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
} while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages));
|
||||
|
||||
atomic64_add(nr_pages, ¤t->mm->pinned_vm);
|
||||
if (current->mm) {
|
||||
mmgrab(current->mm);
|
||||
atomic64_add(nr_pages, ¤t->mm->pinned_vm);
|
||||
}
|
||||
|
||||
kzdev->user_account = user;
|
||||
kzdev->mm_account = current->mm;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
free_uid(user);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
bool assist)
|
||||
{
|
||||
struct page *pages[1], *aibv_page, *aisb_page = NULL;
|
||||
unsigned int msi_vecs, idx;
|
||||
unsigned int msi_vecs, idx, size;
|
||||
struct zpci_gaite *gaite;
|
||||
unsigned long hva, bit;
|
||||
struct kvm *kvm;
|
||||
@@ -237,6 +258,10 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
if (zdev->gisa == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* AIF already enabled for the device */
|
||||
if (zdev->kzdev->fib.fmt0.aibv != 0)
|
||||
return -EINVAL;
|
||||
|
||||
kvm = zdev->kzdev->kvm;
|
||||
msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi);
|
||||
|
||||
@@ -246,6 +271,14 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
return gisc;
|
||||
|
||||
/* Replace AIBV address */
|
||||
size = BITS_TO_LONGS(msi_vecs + fib->fmt0.aibvo) * sizeof(unsigned long);
|
||||
npages = DIV_ROUND_UP((fib->fmt0.aibv & ~PAGE_MASK) + size, PAGE_SIZE);
|
||||
/* AIBV cannot span more than 1 page */
|
||||
if (npages > 1) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv));
|
||||
npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages);
|
||||
@@ -261,6 +294,12 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
|
||||
/* Pin the guest AISB if one was specified */
|
||||
if (fib->fmt0.sum == 1) {
|
||||
/* AISB must be dword aligned */
|
||||
if (fib->fmt0.aisb & 0x7) {
|
||||
rc = -EINVAL;
|
||||
goto unpin1;
|
||||
}
|
||||
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb));
|
||||
npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM,
|
||||
@@ -275,20 +314,28 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
}
|
||||
|
||||
/* Account for pinned pages, roll back on failure */
|
||||
if (account_mem(pcount))
|
||||
rc = account_mem(zdev->kzdev, pcount);
|
||||
if (rc)
|
||||
goto unpin2;
|
||||
|
||||
/* AISB must be allocated before we can fill in GAITE */
|
||||
mutex_lock(&aift->aift_lock);
|
||||
bit = airq_iv_alloc_bit(aift->sbv);
|
||||
if (bit == -1UL)
|
||||
if (bit == -1UL) {
|
||||
rc = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
zdev->aisb = bit; /* store the summary bit number */
|
||||
zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA |
|
||||
AIRQ_IV_BITLOCK |
|
||||
AIRQ_IV_GUESTVEC,
|
||||
phys_to_virt(fib->fmt0.aibv));
|
||||
|
||||
if (!zdev->aibv) {
|
||||
rc = -ENOMEM;
|
||||
goto free_aisb;
|
||||
}
|
||||
|
||||
spin_lock_irq(&aift->gait_lock);
|
||||
gaite = aift->gait + zdev->aisb;
|
||||
|
||||
@@ -311,21 +358,39 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
aift->kzdev[zdev->aisb] = zdev->kzdev;
|
||||
spin_unlock_irq(&aift->gait_lock);
|
||||
|
||||
/* Update guest FIB for re-issue */
|
||||
fib->fmt0.aisbo = zdev->aisb & 63;
|
||||
fib->fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8;
|
||||
fib->fmt0.isc = gisc;
|
||||
|
||||
/* Save some guest fib values in the host for later use */
|
||||
zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc;
|
||||
zdev->kzdev->fib.fmt0.isc = gisc;
|
||||
zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv;
|
||||
mutex_unlock(&aift->aift_lock);
|
||||
|
||||
/* Issue the clp to setup the irq now */
|
||||
rc = kvm_zpci_set_airq(zdev);
|
||||
return rc;
|
||||
if (!rc) {
|
||||
mutex_unlock(&aift->aift_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Start cleanup */
|
||||
zdev->kzdev->fib.fmt0.isc = 0;
|
||||
zdev->kzdev->fib.fmt0.aibv = 0;
|
||||
|
||||
spin_lock_irq(&aift->gait_lock);
|
||||
gaite->count--;
|
||||
gaite->aisb = 0;
|
||||
gaite->gisc = 0;
|
||||
gaite->aisbo = 0;
|
||||
gaite->gisa = 0;
|
||||
aift->kzdev[zdev->aisb] = NULL;
|
||||
spin_unlock_irq(&aift->gait_lock);
|
||||
|
||||
airq_iv_release(zdev->aibv);
|
||||
zdev->aibv = NULL;
|
||||
|
||||
free_aisb:
|
||||
airq_iv_free_bit(aift->sbv, zdev->aisb);
|
||||
zdev->aisb = 0;
|
||||
unlock:
|
||||
if (pcount > 0)
|
||||
unaccount_mem(zdev->kzdev, pcount);
|
||||
mutex_unlock(&aift->aift_lock);
|
||||
unpin2:
|
||||
if (fib->fmt0.sum == 1)
|
||||
@@ -396,7 +461,7 @@ static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force)
|
||||
pcount++;
|
||||
}
|
||||
if (pcount > 0)
|
||||
unaccount_mem(pcount);
|
||||
unaccount_mem(kzdev, pcount);
|
||||
out:
|
||||
mutex_unlock(&aift->aift_lock);
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ struct kvm_zdev {
|
||||
struct kvm *kvm;
|
||||
struct zpci_fib fib;
|
||||
struct list_head entry;
|
||||
struct user_struct *user_account;
|
||||
struct mm_struct *mm_account;
|
||||
};
|
||||
|
||||
struct zpci_gaite {
|
||||
|
||||
@@ -289,6 +289,7 @@ static int handle_iske(struct kvm_vcpu *vcpu)
|
||||
static int handle_rrbe(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long gaddr;
|
||||
union skey skey;
|
||||
int reg1, reg2;
|
||||
int rc;
|
||||
|
||||
@@ -307,12 +308,12 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)
|
||||
gaddr = kvm_s390_logical_to_effective(vcpu, gaddr);
|
||||
gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
|
||||
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
|
||||
rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr));
|
||||
rc = dat_reset_reference_bit(vcpu->arch.gmap->asce, gpa_to_gfn(gaddr), &skey);
|
||||
if (rc > 0)
|
||||
return kvm_s390_inject_program_int(vcpu, rc);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
kvm_s390_set_psw_cc(vcpu, rc);
|
||||
kvm_s390_set_psw_cc(vcpu, (skey.skey >> 1) & 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1260,8 +1261,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)
|
||||
/* Retry the ESSA instruction */
|
||||
kvm_s390_retry_instr(vcpu);
|
||||
} else {
|
||||
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
|
||||
i = __do_essa(vcpu, orc);
|
||||
scoped_guard(mutex, &vcpu->kvm->slots_arch_lock)
|
||||
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
|
||||
i = __do_essa(vcpu, orc);
|
||||
if (i < 0)
|
||||
return i;
|
||||
/* Account for the possible extra cbrl entry */
|
||||
|
||||
+22
-21
@@ -244,6 +244,24 @@ static void kvm_s390_clear_pv_state(struct kvm *kvm)
|
||||
kvm->arch.pv.stor_var = NULL;
|
||||
}
|
||||
|
||||
static void kvm_s390_pv_dispose_cpu(struct kvm_vcpu *vcpu, bool free_stor_base)
|
||||
{
|
||||
if (free_stor_base)
|
||||
free_pages(vcpu->arch.pv.stor_base, get_order(uv_info.guest_cpu_stor_len));
|
||||
free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
|
||||
vcpu->arch.sie_block->pv_handle_cpu = 0;
|
||||
vcpu->arch.sie_block->pv_handle_config = 0;
|
||||
memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
|
||||
vcpu->arch.sie_block->sdf = 0;
|
||||
/*
|
||||
* The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
|
||||
* Use the reset value of gbea to avoid leaking the kernel pointer of
|
||||
* the just freed sida.
|
||||
*/
|
||||
vcpu->arch.sie_block->gbea = 1;
|
||||
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
|
||||
}
|
||||
|
||||
int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
|
||||
{
|
||||
int cc;
|
||||
@@ -258,24 +276,9 @@ int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
|
||||
WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc);
|
||||
|
||||
/* Intended memory leak for something that should never happen. */
|
||||
if (!cc)
|
||||
free_pages(vcpu->arch.pv.stor_base,
|
||||
get_order(uv_info.guest_cpu_stor_len));
|
||||
kvm_s390_pv_dispose_cpu(vcpu, !cc);
|
||||
|
||||
free_page((unsigned long)sida_addr(vcpu->arch.sie_block));
|
||||
vcpu->arch.sie_block->pv_handle_cpu = 0;
|
||||
vcpu->arch.sie_block->pv_handle_config = 0;
|
||||
memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
|
||||
vcpu->arch.sie_block->sdf = 0;
|
||||
/*
|
||||
* The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
|
||||
* Use the reset value of gbea to avoid leaking the kernel pointer of
|
||||
* the just freed sida.
|
||||
*/
|
||||
vcpu->arch.sie_block->gbea = 1;
|
||||
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
|
||||
|
||||
return cc ? EIO : 0;
|
||||
return cc ? -EIO : 0;
|
||||
}
|
||||
|
||||
int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
|
||||
@@ -319,9 +322,7 @@ int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
|
||||
uvcb.header.rrc);
|
||||
|
||||
if (cc) {
|
||||
u16 dummy;
|
||||
|
||||
kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
|
||||
kvm_s390_pv_dispose_cpu(vcpu, true);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -809,7 +810,7 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (ret && ret != -EAGAIN)
|
||||
if (ret && ret != -EAGAIN && ret != -EINTR)
|
||||
KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x",
|
||||
uvcb.gaddr, *rc, *rrc);
|
||||
return ret;
|
||||
|
||||
@@ -188,6 +188,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr,
|
||||
goto out_unlock_mmap;
|
||||
}
|
||||
|
||||
ret = -EFAULT;
|
||||
io_addr = (void __iomem *)((args.pfn << PAGE_SHIFT) |
|
||||
(mmio_addr & ~PAGE_MASK));
|
||||
|
||||
|
||||
@@ -995,6 +995,9 @@ static int vector_mmsg_rx(struct vector_private *vp, int budget)
|
||||
*/
|
||||
dev_kfree_skb_irq(skb);
|
||||
vp->estats.rx_encaps_errors++;
|
||||
(*skbuff_vector) = NULL;
|
||||
mmsg_vector++;
|
||||
skbuff_vector++;
|
||||
continue;
|
||||
}
|
||||
if (header_check > 0) {
|
||||
|
||||
@@ -32,8 +32,15 @@
|
||||
int memcmp(const void *s1, const void *s2, size_t len)
|
||||
{
|
||||
bool diff;
|
||||
asm("repe cmpsb"
|
||||
: "=@ccnz" (diff), "+D" (s1), "+S" (s2), "+c" (len));
|
||||
|
||||
/*
|
||||
* Make sure ZF is properly set in the len==0 case because in it,
|
||||
* RCX==0 and the REPE; CMPSB won't get executed.
|
||||
*/
|
||||
asm volatile("test %3, %3\n\t"
|
||||
"repe cmpsb"
|
||||
: "=@ccnz" (diff), "+D" (s1), "+S" (s2), "+c" (len)
|
||||
: : "cc", "memory");
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
@@ -937,6 +937,8 @@ SYM_CODE_START(paranoid_entry)
|
||||
IBRS_ENTER save_reg=%r15
|
||||
UNTRAIN_RET_FROM_CALL
|
||||
|
||||
HANDLE_INTR_SAFERET 8(%rsp)
|
||||
|
||||
RET
|
||||
SYM_CODE_END(paranoid_entry)
|
||||
|
||||
@@ -1039,6 +1041,11 @@ SYM_CODE_START(error_entry)
|
||||
movl %ecx, %eax /* zero extend */
|
||||
cmpq %rax, RIP+8(%rsp)
|
||||
je .Lbstep_iret
|
||||
|
||||
VALIDATE_UNRET_END
|
||||
|
||||
HANDLE_INTR_SAFERET 8(%rsp)
|
||||
|
||||
cmpq $.Lgs_change, RIP+8(%rsp)
|
||||
jne .Lerror_entry_done_lfence
|
||||
|
||||
@@ -1057,7 +1064,6 @@ SYM_CODE_START(error_entry)
|
||||
FENCE_SWAPGS_KERNEL_ENTRY
|
||||
CALL_DEPTH_ACCOUNT
|
||||
leaq 8(%rsp), %rax /* return pt_regs pointer */
|
||||
VALIDATE_UNRET_END
|
||||
RET
|
||||
|
||||
.Lbstep_iret:
|
||||
|
||||
@@ -1858,7 +1858,7 @@ struct kvm_x86_ops {
|
||||
* Can potentially get non-canonical addresses through INVLPGs, which
|
||||
* the implementation may choose to ignore if appropriate.
|
||||
*/
|
||||
void (*flush_tlb_gva)(struct kvm_vcpu *vcpu, gva_t addr);
|
||||
void (*flush_tlb_gva)(struct kvm_vcpu *vcpu, gva_t addr, bool *full);
|
||||
|
||||
/*
|
||||
* Flush any TLB entries created by the guest. Like tlb_flush_gva(),
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <asm/msr-index.h>
|
||||
#include <asm/unwind_hints.h>
|
||||
#include <asm/percpu.h>
|
||||
#include <asm/ptrace-abi.h>
|
||||
|
||||
/*
|
||||
* Call depth tracking for Intel SKL CPUs to address the RSB underflow
|
||||
@@ -176,6 +177,50 @@
|
||||
add $(BITS_PER_LONG/8), %_ASM_SP; \
|
||||
lfence;
|
||||
|
||||
/*
|
||||
* Helper for detecting if an interrupt occurred at an unsafe location within
|
||||
* Safe-RET. If Safe-RET is interrupted after the CALL or LEA the RSB may get
|
||||
* poisoned by the interrupt handler.
|
||||
*
|
||||
* The Safe-RET sequence is:
|
||||
*
|
||||
* CALL
|
||||
* LEA 8(%RSP), %RSP
|
||||
* RET
|
||||
*
|
||||
* The two CMPs below check whether RIP points to after the CALL or after the
|
||||
* LEA.
|
||||
*
|
||||
* The LFENCE below is to address this particular speculation case:
|
||||
*
|
||||
* 1. Userspace runs and poisons the BTB around the safe-RET routine
|
||||
*
|
||||
* 2. Userspace triggers some kind of exception
|
||||
*
|
||||
* 3. Kernel executes error_entry() and mis-speculates the branch into thinking
|
||||
* it actually came from kernel space
|
||||
*
|
||||
* 4. The kernel then further mis-speculates that the exception occurred due
|
||||
* to an interrupted safe-RET
|
||||
*
|
||||
* 5. The handle_interrupted_saferet() routine speculatively executes and
|
||||
* speculatively does a safe-RET. But this is unsafe since it was never
|
||||
* untrained.
|
||||
*
|
||||
* The LFENCE fixes this by ensuring step 5 is never reached speculatively.
|
||||
* Note that this LFENCE only occurs if safe-RET was actually interrupted (so
|
||||
* it's outside of the normal path).
|
||||
*/
|
||||
#define __HANDLE_INTR_SAFERET(name, pt_regs) \
|
||||
cmpq $(name), RIP+pt_regs; \
|
||||
jb 1f; \
|
||||
cmpq $(name)+5, RIP+pt_regs; \
|
||||
ja 1f; \
|
||||
lfence; \
|
||||
leaq pt_regs, %rdi; \
|
||||
call handle_interrupted_saferet; \
|
||||
1:
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
/*
|
||||
@@ -293,6 +338,14 @@
|
||||
#define UNTRAIN_RET_FROM_CALL \
|
||||
__UNTRAIN_RET X86_FEATURE_ENTRY_IBPB, __stringify(RESET_CALL_DEPTH_FROM_CALL)
|
||||
|
||||
.macro HANDLE_INTR_SAFERET pt_regs
|
||||
#ifdef CONFIG_MITIGATION_SRSO
|
||||
ALTERNATIVE_2 "", \
|
||||
__stringify(__HANDLE_INTR_SAFERET(srso_safe_ret, \pt_regs)), X86_FEATURE_SRSO, \
|
||||
__stringify(__HANDLE_INTR_SAFERET(srso_alias_safe_ret, \pt_regs)), X86_FEATURE_SRSO_ALIAS
|
||||
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro CALL_DEPTH_ACCOUNT
|
||||
#ifdef CONFIG_MITIGATION_CALL_DEPTH_TRACKING
|
||||
@@ -625,6 +678,10 @@ static __always_inline void x86_idle_clear_cpu_buffers(void)
|
||||
x86_clear_cpu_buffers();
|
||||
}
|
||||
|
||||
void srso_safe_ret(void);
|
||||
void srso_alias_safe_ret(void);
|
||||
void handle_interrupted_saferet(struct pt_regs *regs);
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* _ASM_X86_NOSPEC_BRANCH_H_ */
|
||||
|
||||
@@ -515,11 +515,13 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
|
||||
case 0x00 ... 0x2f:
|
||||
case 0x40 ... 0x4f:
|
||||
case 0x60 ... 0x7f:
|
||||
case 0xd0 ... 0xd7:
|
||||
setup_force_cpu_cap(X86_FEATURE_ZEN5);
|
||||
break;
|
||||
case 0x50 ... 0x5f:
|
||||
case 0x80 ... 0xaf:
|
||||
case 0xc0 ... 0xef:
|
||||
case 0xc0 ... 0xcf:
|
||||
case 0xd8 ... 0xef:
|
||||
setup_force_cpu_cap(X86_FEATURE_ZEN6);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -3775,3 +3775,42 @@ void __warn_thunk(void)
|
||||
{
|
||||
WARN_ONCE(1, "Unpatched return thunk in use. This should not happen!\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MITIGATION_SRSO
|
||||
/*
|
||||
* Called during exception/interrupt entry if interrupted during the
|
||||
* safe-RET sequence. The safe-RET sequence consists of 3 instructions:
|
||||
*
|
||||
* CALL
|
||||
* LEA 8(%RSP), %RSP
|
||||
* RET
|
||||
*
|
||||
* An interrupt after the CALL or after the LEA could potentially lead
|
||||
* to branch predictor poisoning and results in the sequence not being
|
||||
* able to be safely resumed.
|
||||
*
|
||||
* Therefore, modify the regs state as if the remaining part of the
|
||||
* safe-RET sequence executed so the interrupt returns back to the
|
||||
* desired return target, instead of the to the safe-RET sequence.
|
||||
*/
|
||||
void noinstr handle_interrupted_saferet(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long rip = regs->ip;
|
||||
|
||||
if (rip == (unsigned long) srso_safe_ret ||
|
||||
rip == (unsigned long) srso_alias_safe_ret) {
|
||||
/* Modify stack pointer as if LEA executed: */
|
||||
regs->sp += 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust registers as if RET executed:
|
||||
*
|
||||
* 1. Read the return address off the stack and into rIP:
|
||||
*/
|
||||
regs->ip = *(unsigned long *)(regs->sp);
|
||||
|
||||
/* 2. Pop rIP off the stack: */
|
||||
regs->sp += 8;
|
||||
}
|
||||
#endif /* CONFIG_MITIGATION_SRSO */
|
||||
|
||||
@@ -2266,10 +2266,10 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
|
||||
|
||||
mca_cfg.initialized = 1;
|
||||
|
||||
__mcheck_cpu_setup_timer();
|
||||
__mcheck_cpu_init_generic();
|
||||
__mcheck_cpu_init_vendor(c);
|
||||
__mcheck_cpu_init_prepare_banks();
|
||||
__mcheck_cpu_setup_timer();
|
||||
cr4_set_bits(X86_CR4_MCE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1974,6 +1974,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
u64 entries[KVM_HV_TLB_FLUSH_FIFO_SIZE];
|
||||
int i, j, count;
|
||||
gva_t gva;
|
||||
bool full = false;
|
||||
|
||||
if (!tdp_enabled || !hv_vcpu)
|
||||
return -EINVAL;
|
||||
@@ -1982,7 +1983,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
|
||||
count = kfifo_out(&tlb_flush_fifo->entries, entries, KVM_HV_TLB_FLUSH_FIFO_SIZE);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 0; i < count && !full; i++) {
|
||||
if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY)
|
||||
goto out_flush_all;
|
||||
|
||||
@@ -1991,11 +1992,11 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
* pages to flush.
|
||||
*/
|
||||
gva = entries[i] & PAGE_MASK;
|
||||
for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++) {
|
||||
for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1 && !full; j++) {
|
||||
if (is_noncanonical_invlpg_address(gva + j * PAGE_SIZE, vcpu))
|
||||
continue;
|
||||
|
||||
kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE);
|
||||
kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE, &full);
|
||||
}
|
||||
|
||||
++vcpu->stat.tlb_flush;
|
||||
|
||||
+25
-2
@@ -722,6 +722,26 @@ static struct kvm_lpage_info *lpage_info_slot(gfn_t gfn,
|
||||
return &slot->arch.lpage_info[level - 2][idx];
|
||||
}
|
||||
|
||||
static bool kvm_gfn_is_lpage_allowed(struct kvm *kvm,
|
||||
const struct kvm_memory_slot *slot,
|
||||
gfn_t gfn, int level)
|
||||
{
|
||||
const struct kvm_memory_slot *other_slot;
|
||||
|
||||
BUILD_BUG_ON(KVM_MAX_NR_ADDRESS_SPACES > 2);
|
||||
|
||||
if (lpage_info_slot(gfn, slot, level)->disallow_lpage)
|
||||
return false;
|
||||
|
||||
if (kvm_arch_nr_memslot_as_ids(kvm) > 1) {
|
||||
other_slot = __gfn_to_memslot(__kvm_memslots(kvm, slot->as_id ^ 1), gfn);
|
||||
if (other_slot && lpage_info_slot(gfn, other_slot, level)->disallow_lpage)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The most significant bit in disallow_lpage tracks whether or not memory
|
||||
* attributes are mixed, i.e. not identical for all gfns at the current level.
|
||||
@@ -2422,6 +2442,9 @@ static union kvm_mmu_page_role kvm_mmu_child_role(u64 *sptep, bool direct,
|
||||
role.direct = direct;
|
||||
role.passthrough = 0;
|
||||
|
||||
WARN_ON_ONCE(role.invalid);
|
||||
role.invalid = 0;
|
||||
|
||||
/*
|
||||
* If the guest has 4-byte PTEs then that means it's using 32-bit,
|
||||
* 2-level, non-PAE paging. KVM shadows such guests with PAE paging
|
||||
@@ -2968,7 +2991,7 @@ int mmu_try_to_unsync_pages(struct kvm *kvm, const struct kvm_memory_slot *slot,
|
||||
* write-protected (see above), thus if the gfn can be mapped with a
|
||||
* hugepage and isn't write-tracked, it can't have a shadow page.
|
||||
*/
|
||||
if (!lpage_info_slot(gfn, slot, PG_LEVEL_2M)->disallow_lpage)
|
||||
if (kvm_gfn_is_lpage_allowed(kvm, slot, gfn, PG_LEVEL_2M))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@@ -6632,7 +6655,7 @@ void kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
if (is_noncanonical_invlpg_address(addr, vcpu))
|
||||
return;
|
||||
|
||||
kvm_x86_call(flush_tlb_gva)(vcpu, addr);
|
||||
kvm_x86_call(flush_tlb_gva)(vcpu, addr, NULL);
|
||||
}
|
||||
|
||||
if (!mmu->sync_spte)
|
||||
|
||||
@@ -130,13 +130,23 @@ void __kvm_write_track_remove_gfn(struct kvm *kvm,
|
||||
kvm_mmu_gfn_allow_lpage(slot, gfn);
|
||||
}
|
||||
|
||||
/*
|
||||
* check if the corresponding access on the specified guest page is tracked.
|
||||
*/
|
||||
static bool __kvm_gfn_is_write_tracked(const struct kvm_memory_slot *slot,
|
||||
gfn_t gfn)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (!slot)
|
||||
return false;
|
||||
|
||||
index = gfn_to_index(gfn, slot->base_gfn, PG_LEVEL_4K);
|
||||
return !!READ_ONCE(slot->arch.gfn_write_track[index]);
|
||||
}
|
||||
|
||||
/* check if write access is tracked on the specified guest page. */
|
||||
bool kvm_gfn_is_write_tracked(struct kvm *kvm,
|
||||
const struct kvm_memory_slot *slot, gfn_t gfn)
|
||||
{
|
||||
int index;
|
||||
const struct kvm_memory_slot *other_slot;
|
||||
|
||||
if (!slot)
|
||||
return false;
|
||||
@@ -144,8 +154,18 @@ bool kvm_gfn_is_write_tracked(struct kvm *kvm,
|
||||
if (!kvm_page_track_write_tracking_enabled(kvm))
|
||||
return false;
|
||||
|
||||
index = gfn_to_index(gfn, slot->base_gfn, PG_LEVEL_4K);
|
||||
return !!READ_ONCE(slot->arch.gfn_write_track[index]);
|
||||
BUILD_BUG_ON(KVM_MAX_NR_ADDRESS_SPACES > 2);
|
||||
|
||||
if (__kvm_gfn_is_write_tracked(slot, gfn))
|
||||
return true;
|
||||
|
||||
if (kvm_arch_nr_memslot_as_ids(kvm) > 1) {
|
||||
other_slot = __gfn_to_memslot(__kvm_memslots(kvm, slot->as_id ^ 1), gfn);
|
||||
if (__kvm_gfn_is_write_tracked(other_slot, gfn))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
|
||||
|
||||
@@ -240,14 +240,6 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm)
|
||||
if (!is_sev_es_guest(&svm->vcpu))
|
||||
svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
|
||||
|
||||
/*
|
||||
* If running nested and the guest uses its own MSR bitmap, there
|
||||
* is no need to update L0's msr bitmap
|
||||
*/
|
||||
if (is_guest_mode(&svm->vcpu) &&
|
||||
vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT))
|
||||
return;
|
||||
|
||||
/* Enabling MSR intercept for x2APIC registers */
|
||||
avic_set_x2apic_msr_interception(svm, true);
|
||||
}
|
||||
|
||||
+25
-9
@@ -97,6 +97,8 @@ static u64 sev_supported_vmsa_features __ro_after_init;
|
||||
static u8 sev_enc_bit;
|
||||
static DECLARE_RWSEM(sev_deactivate_lock);
|
||||
static DEFINE_MUTEX(sev_bitmap_lock);
|
||||
/* Protects kvm_sev_info's enc_context_owner, mirror_vms and mirror_entry. */
|
||||
static DEFINE_MUTEX(sev_mirror_lock);
|
||||
unsigned int max_sev_asid;
|
||||
static unsigned int min_sev_asid;
|
||||
static unsigned int max_sev_es_asid;
|
||||
@@ -2018,7 +2020,6 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
|
||||
dst->asid = src->asid;
|
||||
dst->handle = src->handle;
|
||||
dst->pages_locked = src->pages_locked;
|
||||
dst->enc_context_owner = src->enc_context_owner;
|
||||
dst->es_active = src->es_active;
|
||||
dst->vmsa_features = src->vmsa_features;
|
||||
|
||||
@@ -2026,11 +2027,12 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
|
||||
src->active = false;
|
||||
src->handle = 0;
|
||||
src->pages_locked = 0;
|
||||
src->enc_context_owner = NULL;
|
||||
src->es_active = false;
|
||||
|
||||
list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list);
|
||||
|
||||
mutex_lock(&sev_mirror_lock);
|
||||
|
||||
/*
|
||||
* If this VM has mirrors, "transfer" each mirror's refcount of the
|
||||
* source to the destination (this KVM). The caller holds a reference
|
||||
@@ -2047,12 +2049,15 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
|
||||
* If this VM is a mirror, remove the old mirror from the owners list
|
||||
* and add the new mirror to the list.
|
||||
*/
|
||||
if (is_mirroring_enc_context(dst_kvm)) {
|
||||
struct kvm_sev_info *owner_sev_info = to_kvm_sev_info(dst->enc_context_owner);
|
||||
if (is_mirroring_enc_context(src_kvm)) {
|
||||
struct kvm_sev_info *owner_sev_info = to_kvm_sev_info(src->enc_context_owner);
|
||||
|
||||
dst->enc_context_owner = src->enc_context_owner;
|
||||
src->enc_context_owner = NULL;
|
||||
list_del(&src->mirror_entry);
|
||||
list_add_tail(&dst->mirror_entry, &owner_sev_info->mirror_vms);
|
||||
}
|
||||
mutex_unlock(&sev_mirror_lock);
|
||||
|
||||
kvm_for_each_vcpu(i, dst_vcpu, dst_kvm) {
|
||||
dst_svm = to_svm(dst_vcpu);
|
||||
@@ -2871,11 +2876,14 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||
* disappear until we're done with it
|
||||
*/
|
||||
source_sev = to_kvm_sev_info(source_kvm);
|
||||
kvm_get_kvm(source_kvm);
|
||||
list_add_tail(&mirror_sev->mirror_entry, &source_sev->mirror_vms);
|
||||
|
||||
/* Set enc_context_owner and copy its encryption context over */
|
||||
mutex_lock(&sev_mirror_lock);
|
||||
kvm_get_kvm(source_kvm);
|
||||
list_add_tail(&mirror_sev->mirror_entry, &source_sev->mirror_vms);
|
||||
mirror_sev->enc_context_owner = source_kvm;
|
||||
mutex_unlock(&sev_mirror_lock);
|
||||
|
||||
mirror_sev->active = true;
|
||||
mirror_sev->asid = source_sev->asid;
|
||||
mirror_sev->fd = source_sev->fd;
|
||||
@@ -2963,11 +2971,19 @@ void sev_vm_destroy(struct kvm *kvm)
|
||||
* Note, mirror VMs don't support registering encrypted regions.
|
||||
*/
|
||||
if (is_mirroring_enc_context(kvm)) {
|
||||
struct kvm *owner_kvm = sev->enc_context_owner;
|
||||
struct kvm *owner_kvm;
|
||||
|
||||
mutex_lock(&owner_kvm->lock);
|
||||
mutex_lock(&sev_mirror_lock);
|
||||
owner_kvm = sev->enc_context_owner;
|
||||
list_del(&sev->mirror_entry);
|
||||
mutex_unlock(&owner_kvm->lock);
|
||||
sev->enc_context_owner = NULL;
|
||||
|
||||
/*
|
||||
* The reference to owner_kvm cannot move after sev_mirror_lock is
|
||||
* released. Release it before kvm_put_kvm() so that owner_kvm is
|
||||
* never destroyed inside sev_mirror_lock.
|
||||
*/
|
||||
mutex_unlock(&sev_mirror_lock);
|
||||
kvm_put_kvm(owner_kvm);
|
||||
return;
|
||||
}
|
||||
|
||||
+20
-7
@@ -4227,13 +4227,6 @@ static void svm_flush_tlb_all(struct kvm_vcpu *vcpu)
|
||||
svm_flush_tlb_asid(vcpu);
|
||||
}
|
||||
|
||||
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
invlpga(gva, svm->vmcb->control.asid);
|
||||
}
|
||||
|
||||
static void svm_flush_tlb_guest(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvm_register_mark_dirty(vcpu, VCPU_REG_ERAPS);
|
||||
@@ -4241,6 +4234,26 @@ static void svm_flush_tlb_guest(struct kvm_vcpu *vcpu)
|
||||
svm_flush_tlb_asid(vcpu);
|
||||
}
|
||||
|
||||
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva, bool *full)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
/*
|
||||
* INVLPGA has had errata on Genoa and Turin, and even on older
|
||||
* generations there were reports of Windows BSODs if INVLPGA
|
||||
* was used for Hyper-V tlbflush. Use it only for shadow paging
|
||||
* where it seems to be okay.
|
||||
*/
|
||||
if (!npt_enabled) {
|
||||
invlpga(gva, svm->vmcb->control.asid);
|
||||
return;
|
||||
}
|
||||
|
||||
svm_flush_tlb_guest(vcpu);
|
||||
if (full)
|
||||
*full = true;
|
||||
}
|
||||
|
||||
static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
@@ -109,6 +109,7 @@ struct kvm_sev_info {
|
||||
u64 ap_jump_table; /* SEV-ES AP Jump Table address */
|
||||
u64 vmsa_features;
|
||||
u16 ghcb_version; /* Highest guest GHCB protocol version allowed */
|
||||
/* The three fields below are protected by sev_mirror_lock */
|
||||
struct kvm *enc_context_owner; /* Owner of copied encryption context */
|
||||
struct list_head mirror_vms; /* List of VMs mirroring */
|
||||
struct list_head mirror_entry; /* Use as a list entry of mirrors */
|
||||
|
||||
@@ -535,12 +535,12 @@ static void vt_flush_tlb_current(struct kvm_vcpu *vcpu)
|
||||
vmx_flush_tlb_current(vcpu);
|
||||
}
|
||||
|
||||
static void vt_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
|
||||
static void vt_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr, bool *full)
|
||||
{
|
||||
if (is_td_vcpu(vcpu))
|
||||
return;
|
||||
|
||||
vmx_flush_tlb_gva(vcpu, addr);
|
||||
vmx_flush_tlb_gva(vcpu, addr, full);
|
||||
}
|
||||
|
||||
static void vt_flush_tlb_guest(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -3361,7 +3361,7 @@ void vmx_flush_tlb_current(struct kvm_vcpu *vcpu)
|
||||
vpid_sync_context(vmx_get_current_vpid(vcpu));
|
||||
}
|
||||
|
||||
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
|
||||
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr, bool *full)
|
||||
{
|
||||
/*
|
||||
* vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in
|
||||
|
||||
@@ -101,7 +101,7 @@ static __always_inline unsigned long __vmcs_readl(unsigned long field)
|
||||
|
||||
: [output] "=r" (value)
|
||||
: [field] "r" (field)
|
||||
: "cc"
|
||||
: "cc", "memory"
|
||||
: do_fail, do_exception);
|
||||
|
||||
return value;
|
||||
@@ -145,7 +145,7 @@ do_exception:
|
||||
|
||||
: ASM_CALL_CONSTRAINT, [output] "=&r" (value)
|
||||
: [field] "r" (field)
|
||||
: "cc");
|
||||
: "cc", "memory");
|
||||
return value;
|
||||
|
||||
#endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
|
||||
@@ -192,7 +192,7 @@ do { \
|
||||
asm goto("1: " __stringify(insn) " %0\n\t" \
|
||||
"jna %l[error]\n\t" \
|
||||
_ASM_EXTABLE(1b, %l[fault]) \
|
||||
: : op1 : "cc" : error, fault); \
|
||||
: : op1 : "cc", "memory" : error, fault); \
|
||||
return; \
|
||||
error: \
|
||||
instrumentation_begin(); \
|
||||
@@ -208,7 +208,7 @@ do { \
|
||||
asm goto("1: " __stringify(insn) " %1, %0\n\t" \
|
||||
"jna %l[error]\n\t" \
|
||||
_ASM_EXTABLE(1b, %l[fault]) \
|
||||
: : op1, op2 : "cc" : error, fault); \
|
||||
: : op1, op2 : "cc", "memory" : error, fault);\
|
||||
return; \
|
||||
error: \
|
||||
instrumentation_begin(); \
|
||||
|
||||
@@ -82,7 +82,7 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
|
||||
bool vmx_get_if_flag(struct kvm_vcpu *vcpu);
|
||||
void vmx_flush_tlb_all(struct kvm_vcpu *vcpu);
|
||||
void vmx_flush_tlb_current(struct kvm_vcpu *vcpu);
|
||||
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr);
|
||||
void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr, bool *full);
|
||||
void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu);
|
||||
void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask);
|
||||
u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -13429,9 +13429,15 @@ void kvm_arch_pre_destroy_vm(struct kvm *kvm)
|
||||
* iterating over vCPUs in a different task while vCPUs are being freed
|
||||
* is unsafe, i.e. will lead to use-after-free. The PIT also needs to
|
||||
* be stopped before IRQ routing is freed.
|
||||
*
|
||||
* Do NOT free the in-kernel PIC or I/O APIC here (but as above, make
|
||||
* sure to flush any background work), as KVM expects interrupt routing
|
||||
* structures to be valid until vCPUs are destroyed.
|
||||
*/
|
||||
#ifdef CONFIG_KVM_IOAPIC
|
||||
kvm_free_pit(kvm);
|
||||
if (kvm->arch.vioapic)
|
||||
cancel_delayed_work_sync(&kvm->arch.vioapic->eoi_inject);
|
||||
#endif
|
||||
|
||||
kvm_mmu_pre_destroy_vm(kvm);
|
||||
|
||||
@@ -207,10 +207,24 @@ __EXPORT_THUNK(srso_alias_untrain_ret)
|
||||
|
||||
.pushsection .text..__x86.rethunk_safe
|
||||
SYM_CODE_START_NOALIGN(srso_alias_safe_ret)
|
||||
|
||||
/*
|
||||
* Tell objtool that those are not function pointers referenced by
|
||||
* __HANDLE_INTR_SAFERET(). Below too.
|
||||
*/
|
||||
ANNOTATE_NOENDBR
|
||||
|
||||
/*
|
||||
* Safe-RET sequence. If you need to change it, adjust
|
||||
* handle_interrupted_saferet() too.
|
||||
*/
|
||||
lea 8(%_ASM_SP), %_ASM_SP
|
||||
UNWIND_HINT_FUNC
|
||||
|
||||
ANNOTATE_NOENDBR
|
||||
ANNOTATE_UNRET_SAFE
|
||||
ret
|
||||
/* End of Safe-RET sequence */
|
||||
int3
|
||||
SYM_FUNC_END(srso_alias_safe_ret)
|
||||
|
||||
@@ -245,8 +259,14 @@ SYM_CODE_START_LOCAL_NOALIGN(srso_untrain_ret)
|
||||
* the stack.
|
||||
*/
|
||||
SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL)
|
||||
/*
|
||||
* Safe-RET sequence. If you need to change it, adjust
|
||||
* handle_interrupted_saferet() too.
|
||||
*/
|
||||
lea 8(%_ASM_SP), %_ASM_SP
|
||||
ret
|
||||
/* End of Safe-RET sequence */
|
||||
|
||||
int3
|
||||
int3
|
||||
/* end of movabs */
|
||||
|
||||
+8
-4
@@ -1281,14 +1281,18 @@ static void disk_release(struct device *dev)
|
||||
/*
|
||||
* To undo the all initialization from blk_mq_init_allocated_queue in
|
||||
* case of a probe failure where add_disk is never called we have to
|
||||
* call blk_mq_exit_queue here. We can't do this for the more common
|
||||
* teardown case (yet) as the tagset can be gone by the time the disk
|
||||
* is released once it was added.
|
||||
* call blk_mq_exit_queue here, after stopping the timer and work items
|
||||
* that I/O issued before add_disk may have left pending. We can't do
|
||||
* this for the more common teardown case (yet) as the tagset can be
|
||||
* gone by the time the disk is released once it was added.
|
||||
*/
|
||||
if (queue_is_mq(disk->queue) &&
|
||||
test_bit(GD_OWNS_QUEUE, &disk->state) &&
|
||||
!test_bit(GD_ADDED, &disk->state))
|
||||
!test_bit(GD_ADDED, &disk->state)) {
|
||||
blk_sync_queue(disk->queue);
|
||||
blk_mq_cancel_work_sync(disk->queue);
|
||||
blk_mq_exit_queue(disk->queue);
|
||||
}
|
||||
|
||||
blkcg_exit_disk(disk);
|
||||
|
||||
|
||||
@@ -436,6 +436,23 @@ static void amdxdna_gem_dev_obj_free(struct drm_gem_object *gobj)
|
||||
amdxdna_gem_destroy_obj(abo);
|
||||
}
|
||||
|
||||
static void amdxdna_mark_mapp_invalid(struct amdxdna_gem_obj *abo,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
struct amdxdna_umap *mapp;
|
||||
|
||||
down_write(&xdna->notifier_lock);
|
||||
abo->mem.map_invalid = true;
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
|
||||
mapp->invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_write(&xdna->notifier_lock);
|
||||
}
|
||||
|
||||
static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
@@ -450,26 +467,17 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
||||
XDNA_ERR(xdna, "Failed shmem mmap %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The buffer is based on memory pages. Fix the flag. */
|
||||
vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
|
||||
ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages,
|
||||
&num_pages);
|
||||
} else {
|
||||
vma->vm_private_data = NULL;
|
||||
vma->vm_ops = NULL;
|
||||
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Failed insert pages %d", ret);
|
||||
vma->vm_ops->close(vma);
|
||||
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
vma->vm_private_data = NULL;
|
||||
vma->vm_ops = NULL;
|
||||
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
|
||||
return ret;
|
||||
/* Drop the reference drm_gem_mmap_obj() acquired.*/
|
||||
drm_gem_object_put(to_gobj(abo));
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -478,17 +486,14 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
||||
fault_ret = handle_mm_fault(vma, vma->vm_start + offset,
|
||||
FAULT_FLAG_WRITE, NULL);
|
||||
if (fault_ret & VM_FAULT_ERROR) {
|
||||
vma->vm_ops->close(vma);
|
||||
XDNA_ERR(xdna, "Fault in page failed");
|
||||
return -EFAULT;
|
||||
amdxdna_mark_mapp_invalid(abo, vma);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += PAGE_SIZE;
|
||||
} while (--num_pages);
|
||||
|
||||
/* Drop the reference drm_gem_mmap_obj() acquired.*/
|
||||
drm_gem_object_put(to_gobj(abo));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user