mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 23:59:33 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.2-rc4). No conflicts. Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
5
.mailmap
5
.mailmap
@@ -399,6 +399,7 @@ Jens Axboe <axboe@kernel.dk> <jens.axboe@oracle.com>
|
||||
Jens Axboe <axboe@kernel.dk> <axboe@fb.com>
|
||||
Jens Axboe <axboe@kernel.dk> <axboe@meta.com>
|
||||
Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
|
||||
Jens Wiklander <jenswi@kernel.org> <jens.wiklander@linaro.org>
|
||||
Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
|
||||
Jesper Dangaard Brouer <hawk@kernel.org> <brouer@redhat.com>
|
||||
Jesper Dangaard Brouer <hawk@kernel.org> <hawk@comx.dk>
|
||||
@@ -825,8 +826,8 @@ Sriram Yagnaraman <sriram.yagnaraman@ericsson.com> <sriram.yagnaraman@est.tech>
|
||||
Stanislav Fomichev <sdf@fomichev.me> <sdf@google.com>
|
||||
Stanislav Fomichev <sdf@fomichev.me> <stfomichev@gmail.com>
|
||||
Stefan Wahren <wahrenst@gmx.net> <stefan.wahren@i2se.com>
|
||||
Stéphane Grosjean <stephane.grosjean@hms-networks.com> <s.grosjean@peak-system.com>
|
||||
Stéphane Grosjean <stephane.grosjean@hms-networks.com> <stephane.grosjean@free.fr>
|
||||
Stéphane Grosjean <s.grosjean@peak-system.fr> <s.grosjean@peak-system.com>
|
||||
Stéphane Grosjean <s.grosjean@peak-system.fr> <stephane.grosjean@free.fr>
|
||||
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
|
||||
Stephen Hemminger <stephen@networkplumber.org> <shemminger@linux-foundation.org>
|
||||
Stephen Hemminger <stephen@networkplumber.org> <shemminger@osdl.org>
|
||||
|
||||
@@ -22,7 +22,7 @@ Description:
|
||||
|
||||
Reading this attribute gives the state of the DbC. It
|
||||
can be one of the following states: disabled, enabled,
|
||||
initialized, connected or configured.
|
||||
initialized, connected, configured or suspended.
|
||||
|
||||
What: /sys/bus/pci/drivers/xhci_hcd/.../dbc_idVendor
|
||||
Date: March 2023
|
||||
|
||||
@@ -9,6 +9,7 @@ RDMA Controller
|
||||
1-2. Why RDMA controller needed?
|
||||
1-3. How is RDMA controller implemented?
|
||||
2. Usage Examples
|
||||
3. RDMA Interface Files
|
||||
|
||||
1. Overview
|
||||
===========
|
||||
@@ -115,3 +116,68 @@ Following resources can be accounted by rdma controller.
|
||||
(d) Delete resource limit::
|
||||
|
||||
echo mlx4_0 hca_handle=max hca_object=max > /sys/fs/cgroup/rdma/1/rdma.max
|
||||
|
||||
3. RDMA Interface Files
|
||||
========================
|
||||
|
||||
The following interface files are available in each non-root RDMA cgroup.
|
||||
|
||||
rdma.max
|
||||
A read-write file which describes the configured resource limit
|
||||
for an RDMA/IB device. See the Usage Examples above.
|
||||
|
||||
rdma.current
|
||||
A read-only file which describes the current resource usage.
|
||||
|
||||
rdma.peak
|
||||
A read-only nested-keyed file which shows the historical high
|
||||
watermark of resource usage per device since the cgroup was created.
|
||||
|
||||
An example for mlx4 and ocrdma device follows::
|
||||
|
||||
mlx4_0 hca_handle=1 hca_object=20
|
||||
ocrdma1 hca_handle=0 hca_object=23
|
||||
|
||||
rdma.events
|
||||
A read-only nested-keyed file which exists on non-root cgroups
|
||||
and contains the following keys:
|
||||
|
||||
max
|
||||
The number of times a process in this cgroup or its
|
||||
descendants attempted an RDMA resource allocation that
|
||||
was rejected because a rdma.max limit in the subtree
|
||||
was reached. This is a hierarchical counter propagated
|
||||
upward to all ancestor cgroups. A value change in this
|
||||
file generates a file modified event.
|
||||
|
||||
alloc_fail
|
||||
The number of RDMA resource allocation attempts that
|
||||
originated in this cgroup or its descendants and failed
|
||||
due to a rdma.max limit being reached. This is a
|
||||
hierarchical counter propagated upward.
|
||||
|
||||
An example for mlx4 device follows::
|
||||
|
||||
mlx4_0 hca_handle.max=5 hca_handle.alloc_fail=3 hca_object.max=0 hca_object.alloc_fail=0
|
||||
|
||||
rdma.events.local
|
||||
Similar to rdma.events but the fields are local to the cgroup,
|
||||
i.e. not hierarchical. The file modified event generated on this
|
||||
file reflects only the local events.
|
||||
|
||||
The following nested keys are defined.
|
||||
|
||||
max
|
||||
The number of times a process in this cgroup or its
|
||||
descendants attempted an RDMA resource allocation that
|
||||
was rejected because this cgroup's own rdma.max limit
|
||||
was reached.
|
||||
|
||||
alloc_fail
|
||||
The number of RDMA resource allocation attempts
|
||||
originating from this cgroup that failed due to this
|
||||
cgroup's or an ancestor's rdma.max limit.
|
||||
|
||||
An example for mlx4 device follows::
|
||||
|
||||
mlx4_0 hca_handle.max=5 hca_handle.alloc_fail=0 hca_object.max=0 hca_object.alloc_fail=0
|
||||
|
||||
@@ -1570,7 +1570,7 @@ The following nested keys are defined.
|
||||
sock (npn)
|
||||
Amount of memory used in network transmission buffers
|
||||
|
||||
vmalloc (npn)
|
||||
vmalloc
|
||||
Amount of memory used for vmap backed memory.
|
||||
|
||||
shmem
|
||||
@@ -1735,7 +1735,7 @@ The following nested keys are defined.
|
||||
Number of pages written from zswap to swap.
|
||||
|
||||
zswap_incomp
|
||||
Number of incompressible pages currently stored in zswap
|
||||
Amount of memory used by incompressible pages currently stored in zswap
|
||||
without compression. These pages could not be compressed to
|
||||
a size smaller than PAGE_SIZE, so they are stored as-is.
|
||||
|
||||
@@ -2257,10 +2257,11 @@ groups D and F will influence each other. Group G will influence nobody::
|
||||
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 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.
|
||||
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.
|
||||
|
||||
How IO Latency Throttling Works
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -2298,7 +2299,9 @@ IO Latency Interface Files
|
||||
|
||||
io.stat
|
||||
If the controller is enabled you will see extra stats in io.stat in
|
||||
addition to the normal ones.
|
||||
addition to the normal ones. These debug stats are only emitted when
|
||||
the blkcg_debug_stats module parameter is enabled (it is disabled by
|
||||
default).
|
||||
|
||||
depth
|
||||
This is the current queue depth for the group.
|
||||
@@ -2934,7 +2937,8 @@ include/linux/misc_cgroup.h.
|
||||
Misc Interface Files
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Miscellaneous controller provides 3 interface files. If two misc resources (res_a and res_b) are registered then:
|
||||
Miscellaneous controller provides the following interface files. If two misc
|
||||
resources (res_a and res_b) are registered then:
|
||||
|
||||
misc.capacity
|
||||
A read-only flat-keyed file shown only in the root cgroup. It shows
|
||||
|
||||
@@ -47,11 +47,12 @@ ever have can be described at boot. There are no power-domain considerations
|
||||
as such devices are emulated.
|
||||
|
||||
CPU Hotplug on virtual systems is supported. It is distinct from physical
|
||||
CPU Hotplug as all resources are described as ``present``, but CPUs may be
|
||||
marked as disabled by firmware. Only the CPU's online/offline behaviour is
|
||||
influenced by firmware. An example is where a virtual machine boots with a
|
||||
single CPU, and additional CPUs are added once a cloud orchestrator deploys
|
||||
the workload.
|
||||
CPU Hotplug as all vCPU resources are statically described in the firmware
|
||||
configuration tables (e.g. MADT), meaning their maximum possible count is
|
||||
known at boot. However, vCPUs that are not enabled at boot are not marked
|
||||
as ``present`` by the kernel until they are hotplugged. An example is where
|
||||
a virtual machine boots with a single CPU, and additional CPUs are added
|
||||
once a cloud orchestrator deploys the workload.
|
||||
|
||||
For a virtual machine, the VMM (e.g. Qemu) plays the part of firmware.
|
||||
|
||||
@@ -60,16 +61,19 @@ brought online. Firmware can enforce its policy via PSCI's return codes. e.g.
|
||||
``DENIED``.
|
||||
|
||||
The ACPI tables must describe all the resources of the virtual machine. CPUs
|
||||
that firmware wishes to disable either from boot (or later) should not be
|
||||
``enabled`` in the MADT GICC structures, but should have the ``online capable``
|
||||
bit set, to indicate they can be enabled later. The boot CPU must be marked as
|
||||
``enabled``. The 'always on' GICR structure must be used to describe the
|
||||
redistributors.
|
||||
that are hot-pluggable must have the ``online capable`` bit set and the
|
||||
``enabled`` bit cleared in the MADT GICC structures to indicate they can be
|
||||
enabled later. The boot CPU must be marked as ``enabled`` with its
|
||||
``online capable`` bit cleared. The 'always on' GICR structure must be used
|
||||
to describe the redistributors.
|
||||
|
||||
CPUs described as ``online capable`` but not ``enabled`` can be set to enabled
|
||||
by the DSDT's Processor object's _STA method. On virtual systems the _STA method
|
||||
must always report the CPU as ``present``. Changes to the firmware policy can
|
||||
be notified to the OS via device-check or eject-request.
|
||||
must always set the ``ACPI_STA_DEVICE_PRESENT`` bit, while toggling the
|
||||
``ACPI_STA_DEVICE_ENABLED`` bit to reflect its plug status. The kernel will
|
||||
then dynamically mark the vCPU as ``present`` within the OS when the
|
||||
``ACPI_STA_DEVICE_ENABLED`` bit becomes set during hot-add. Changes to the
|
||||
firmware policy can be notified to the OS via device-check or eject-request.
|
||||
|
||||
CPUs described as ``enabled`` in the static table, should not have their _STA
|
||||
modified dynamically by firmware. Soft-restart features such as kexec will
|
||||
|
||||
@@ -82,121 +82,121 @@ The following keys are defined:
|
||||
version 1.0 of the RISC-V Vector extension manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBA`: The Zba address generation extension is
|
||||
supported, as defined in version 1.0 of the Bit-Manipulation ISA
|
||||
extensions.
|
||||
supported, as defined in version 1.0 of the Bit-Manipulation ISA
|
||||
extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBB`: The Zbb extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOZ`: The Zicboz extension is supported, as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBC` The Zbc extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBKB` The Zbkb extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBKC` The Zbkc extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBKX` The Zbkx extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKND` The Zknd extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKNE` The Zkne extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKNH` The Zknh extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKSED` The Zksed extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKSH` The Zksh extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKT` The Zkt extension is supported, as defined
|
||||
in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVBB`: The Zvbb extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVBC`: The Zvbc extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKB`: The Zvkb extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKG`: The Zvkg extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKNED`: The Zvkned extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKNHA`: The Zvknha extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKNHB`: The Zvknhb extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKSED`: The Zvksed extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKSH`: The Zvksh extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKT`: The Zvkt extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFH`: The Zfh extension version 1.0 is supported
|
||||
as defined in the RISC-V ISA manual.
|
||||
as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFHMIN`: The Zfhmin extension version 1.0 is
|
||||
supported as defined in the RISC-V ISA manual.
|
||||
supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIHINTNTL`: The Zihintntl extension version 1.0
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFH`: The Zvfh extension is supported as
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFHMIN`: The Zvfhmin extension is supported as
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFA`: The Zfa extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 056b6ff467c7
|
||||
("Zfa is ratified").
|
||||
defined in the RISC-V ISA manual starting from commit 056b6ff467c7
|
||||
("Zfa is ratified").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZTSO`: The Ztso extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 5618fb5a216b
|
||||
("Ztso is now ratified.")
|
||||
defined in the RISC-V ISA manual starting from commit 5618fb5a216b
|
||||
("Ztso is now ratified.")
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZACAS`: The Zacas extension is supported as
|
||||
defined in the Atomic Compare-and-Swap (CAS) instructions manual starting
|
||||
from commit 5059e0ca641c ("update to ratified").
|
||||
defined in the Atomic Compare-and-Swap (CAS) instructions manual starting
|
||||
from commit 5059e0ca641c ("update to ratified").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICNTR`: The Zicntr extension version 2.0
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICOND`: The Zicond extension is supported as
|
||||
defined in the RISC-V Integer Conditional (Zicond) operations extension
|
||||
manual starting from commit 95cf1f9 ("Add changes requested by Ved
|
||||
during signoff")
|
||||
defined in the RISC-V Integer Conditional (Zicond) operations extension
|
||||
manual starting from commit 95cf1f9 ("Add changes requested by Ved
|
||||
during signoff")
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIHINTPAUSE`: The Zihintpause extension is
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
d8ab5c78c207 ("Zihintpause is ratified").
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
d8ab5c78c207 ("Zihintpause is ratified").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIHPM`: The Zihpm extension version 2.0
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVE32X`: The Vector sub-extension Zve32x is
|
||||
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
|
||||
@@ -214,84 +214,89 @@ The following keys are defined:
|
||||
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIMOP`: The Zimop May-Be-Operations extension is
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
58220614a5f ("Zimop is ratified/1.0").
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
58220614a5f ("Zimop is ratified/1.0").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCA`: The Zca extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCB`: The Zcb extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCD`: The Zcd extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCF`: The Zcf extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCMOP`: The Zcmop May-Be-Operations extension is
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
c732a4f39a4 ("Zcmop is ratified/1.0").
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
c732a4f39a4 ("Zcmop is ratified/1.0").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZAWRS`: The Zawrs extension is supported as
|
||||
ratified in commit 98918c844281 ("Merge pull request #1217 from
|
||||
riscv/zawrs") of riscv-isa-manual.
|
||||
ratified in commit 98918c844281 ("Merge pull request #1217 from
|
||||
riscv/zawrs") of riscv-isa-manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZAAMO`: The Zaamo extension is supported as
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZALASR`: The Zalasr extension is supported as
|
||||
frozen at commit 194f0094 ("Version 0.9 for freeze") of riscv-zalasr.
|
||||
frozen at commit 194f0094 ("Version 0.9 for freeze") of riscv-zalasr.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZALRSC`: The Zalrsc extension is supported as
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_SUPM`: The Supm extension is supported as
|
||||
defined in version 1.0 of the RISC-V Pointer Masking extensions.
|
||||
defined in version 1.0 of the RISC-V Pointer Masking extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFBFMIN`: The Zfbfmin extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFBFMIN`: The Zvfbfmin extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFBFWMA`: The Zvfbfwma extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOM`: The Zicbom extension is supported, as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZABHA`: The Zabha extension is supported as
|
||||
ratified in commit 49f49c842ff9 ("Update to Rafified state") of
|
||||
riscv-zabha.
|
||||
ratified in commit 49f49c842ff9 ("Update to Rafified state") of
|
||||
riscv-zabha.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOP`: The Zicbop extension is supported, as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZILSD`: The Zilsd extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCLSD`: The Zclsd extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICFILP`: The Zicfilp extension is supported,
|
||||
as defined in version 1.0 of the RISC-V Control-flow Integrity (CFI)
|
||||
extensions specification, ratified in commit 302a2d45c243
|
||||
("Update build-pdf.yml") of riscv-cfi.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to
|
||||
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
|
||||
mistakenly classified as a bitmask rather than a value.
|
||||
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
|
||||
mistakenly classified as a bitmask rather than a value.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`: An enum value describing
|
||||
the performance of misaligned scalar native word accesses on the selected set
|
||||
@@ -326,7 +331,7 @@ The following keys are defined:
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_TIME_CSR_FREQ`: Frequency (in Hz) of `time CSR`.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF`: An enum value describing the
|
||||
performance of misaligned vector accesses on the selected set of processors.
|
||||
performance of misaligned vector accesses on the selected set of processors.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN`: The performance of misaligned
|
||||
vector accesses is unknown.
|
||||
@@ -348,7 +353,7 @@ The following keys are defined:
|
||||
* MIPS
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XMIPSEXECTL`: The xmipsexectl vendor
|
||||
extension is supported in the MIPS ISA extensions spec.
|
||||
extension is supported in the MIPS ISA extensions spec.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0`: A bitmask containing the
|
||||
thead vendor extensions that are compatible with the
|
||||
@@ -357,8 +362,8 @@ The following keys are defined:
|
||||
* T-HEAD
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XTHEADVECTOR`: The xtheadvector vendor
|
||||
extension is supported in the T-Head ISA extensions spec starting from
|
||||
commit a18c801634 ("Add T-Head VECTOR vendor extension. ").
|
||||
extension is supported in the T-Head ISA extensions spec starting from
|
||||
commit a18c801634 ("Add T-Head VECTOR vendor extension. ").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE`: An unsigned int which
|
||||
represents the size of the Zicbom block in bytes.
|
||||
@@ -370,20 +375,20 @@ The following keys are defined:
|
||||
* SIFIVE
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVQMACCDOD`: The Xsfqmaccdod vendor
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Extensions Specification.
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVQMACCQOQ`: The Xsfqmaccqoq vendor
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Instruction Extensions Specification.
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Instruction Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFNRCLIPXFQF`: The Xsfvfnrclipxfqf
|
||||
vendor extension is supported in version 1.0 of SiFive FP32-to-int8 Ranged
|
||||
Clip Instructions Extensions Specification.
|
||||
vendor extension is supported in version 1.0 of SiFive FP32-to-int8 Ranged
|
||||
Clip Instructions Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
|
||||
vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
|
||||
Instruction Extensions Specification.
|
||||
vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
|
||||
Instruction Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which
|
||||
represents the size of the Zicbop block in bytes.
|
||||
@@ -391,3 +396,8 @@ The following keys are defined:
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_1`: A bitmask containing additional
|
||||
extensions that are compatible with the
|
||||
:c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: base system behavior.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICFISS`: The Zicfiss extension is supported,
|
||||
as defined in version 1.0 of the RISC-V Control-flow Integrity (CFI)
|
||||
extensions specification, ratified in commit 302a2d45c243
|
||||
("Update build-pdf.yml") of riscv-cfi.
|
||||
|
||||
@@ -193,7 +193,6 @@ allOf:
|
||||
- mediatek,mt8183-mmc
|
||||
- mediatek,mt8186-mmc
|
||||
- mediatek,mt8188-mmc
|
||||
- mediatek,mt8189-mmc
|
||||
- mediatek,mt8195-mmc
|
||||
- mediatek,mt8196-mmc
|
||||
- mediatek,mt8516-mmc
|
||||
@@ -348,6 +347,34 @@ allOf:
|
||||
- const: axi_cg
|
||||
- const: ahb_cg
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: mediatek,mt8189-mmc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 6
|
||||
items:
|
||||
- description: source clock
|
||||
- description: HCLK which used for host
|
||||
- description: independent source clock gate
|
||||
- description: bus clock used for internal register access
|
||||
- description: peripheral bus clock gate
|
||||
- description: AXI bus clock gate
|
||||
- description: crypto clock used for data encrypt/decrypt (optional)
|
||||
clock-names:
|
||||
minItems: 6
|
||||
items:
|
||||
- const: source
|
||||
- const: hclk
|
||||
- const: source_cg
|
||||
- const: bus_clk
|
||||
- const: pclk_cg
|
||||
- const: axi_cg
|
||||
- const: crypto
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
||||
@@ -457,6 +457,13 @@ properties:
|
||||
merged in the riscv-isa-manual by commit dbc79cf28a2 ("Initial seed
|
||||
of zc.adoc to src tree.").
|
||||
|
||||
- const: zclsd
|
||||
description:
|
||||
The Zclsd extension implements the compressed (16-bit) version of the
|
||||
Load/Store Pair for RV32. As with Zilsd, this extension was ratified
|
||||
in commit f88abf1 ("Integrating load/store pair for RV32 with the
|
||||
main manual") of riscv-isa-manual.
|
||||
|
||||
- const: zcmop
|
||||
description:
|
||||
The standard Zcmop extension version 1.0, as ratified in commit
|
||||
@@ -487,6 +494,22 @@ properties:
|
||||
in commit 64074bc ("Update version numbers for Zfh/Zfinx") of
|
||||
riscv-isa-manual.
|
||||
|
||||
- const: zicbom
|
||||
description:
|
||||
The standard Zicbom extension for base cache management operations as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicbop
|
||||
description:
|
||||
The standard Zicbop extension for cache-block prefetch instructions
|
||||
as ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of
|
||||
riscv-CMOs.
|
||||
|
||||
- const: zicboz
|
||||
description:
|
||||
The standard Zicboz extension for cache-block zeroing as ratified
|
||||
in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: ziccamoa
|
||||
description:
|
||||
The standard Ziccamoa extension for main memory (cacheability and
|
||||
@@ -514,6 +537,66 @@ properties:
|
||||
guarantee on LR/SC sequences, as ratified in commit b1d806605f87
|
||||
("Updated to ratified state.") of the riscv profiles specification.
|
||||
|
||||
- const: zicfilp
|
||||
description: |
|
||||
The standard Zicfilp extension for enforcing forward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicfiss
|
||||
description: |
|
||||
The standard Zicfiss extension for enforcing backward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicntr
|
||||
description:
|
||||
The standard Zicntr extension for base counters and timers, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zicond
|
||||
description:
|
||||
The standard Zicond extension for conditional arithmetic and
|
||||
conditional-select/move operations as ratified in commit 95cf1f9
|
||||
("Add changes requested by Ved during signoff") of riscv-zicond.
|
||||
|
||||
- const: zicsr
|
||||
description: |
|
||||
The standard Zicsr extension for control and status register
|
||||
instructions, as ratified in the 20191213 version of the
|
||||
unprivileged ISA specification.
|
||||
|
||||
This does not include Chapter 10, "Counters", which documents
|
||||
special case read-only CSRs, that were moved into the Zicntr and
|
||||
Zihpm extensions after the ratification of the 20191213 version of
|
||||
the unprivileged specification.
|
||||
|
||||
- const: zifencei
|
||||
description:
|
||||
The standard Zifencei extension for instruction-fetch fence, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zihintntl
|
||||
description:
|
||||
The standard Zihintntl extension for non-temporal locality hints, as
|
||||
ratified in commit 0dc91f5 ("Zihintntl is ratified") of the
|
||||
riscv-isa-manual.
|
||||
|
||||
- const: zihintpause
|
||||
description:
|
||||
The standard Zihintpause extension for pause hints, as ratified in
|
||||
commit d8ab5c7 ("Zihintpause is ratified") of the riscv-isa-manual.
|
||||
|
||||
- const: zihpm
|
||||
description:
|
||||
The standard Zihpm extension for hardware performance counters, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zilsd
|
||||
description:
|
||||
The standard Zilsd extension which provides support for aligned
|
||||
@@ -521,12 +604,10 @@ properties:
|
||||
encodings, as ratified in commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of riscv-isa-manual.
|
||||
|
||||
- const: zclsd
|
||||
- const: zimop
|
||||
description:
|
||||
The Zclsd extension implements the compressed (16-bit) version of the
|
||||
Load/Store Pair for RV32. As with Zilsd, this extension was ratified
|
||||
in commit f88abf1 ("Integrating load/store pair for RV32 with the
|
||||
main manual") of riscv-isa-manual.
|
||||
The standard Zimop extension version 1.0, as ratified in commit
|
||||
58220614a5f ("Zimop is ratified/1.0") of the riscv-isa-manual.
|
||||
|
||||
- const: zk
|
||||
description:
|
||||
@@ -590,87 +671,6 @@ properties:
|
||||
in version 1.0 of RISC-V Cryptography Extensions Volume I
|
||||
specification.
|
||||
|
||||
- const: zicbom
|
||||
description:
|
||||
The standard Zicbom extension for base cache management operations as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicbop
|
||||
description:
|
||||
The standard Zicbop extension for cache-block prefetch instructions
|
||||
as ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of
|
||||
riscv-CMOs.
|
||||
|
||||
- const: zicboz
|
||||
description:
|
||||
The standard Zicboz extension for cache-block zeroing as ratified
|
||||
in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicfilp
|
||||
description: |
|
||||
The standard Zicfilp extension for enforcing forward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicfiss
|
||||
description: |
|
||||
The standard Zicfiss extension for enforcing backward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicntr
|
||||
description:
|
||||
The standard Zicntr extension for base counters and timers, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zicond
|
||||
description:
|
||||
The standard Zicond extension for conditional arithmetic and
|
||||
conditional-select/move operations as ratified in commit 95cf1f9
|
||||
("Add changes requested by Ved during signoff") of riscv-zicond.
|
||||
|
||||
- const: zicsr
|
||||
description: |
|
||||
The standard Zicsr extension for control and status register
|
||||
instructions, as ratified in the 20191213 version of the
|
||||
unprivileged ISA specification.
|
||||
|
||||
This does not include Chapter 10, "Counters", which documents
|
||||
special case read-only CSRs, that were moved into the Zicntr and
|
||||
Zihpm extensions after the ratification of the 20191213 version of
|
||||
the unprivileged specification.
|
||||
|
||||
- const: zifencei
|
||||
description:
|
||||
The standard Zifencei extension for instruction-fetch fence, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zihintpause
|
||||
description:
|
||||
The standard Zihintpause extension for pause hints, as ratified in
|
||||
commit d8ab5c7 ("Zihintpause is ratified") of the riscv-isa-manual.
|
||||
|
||||
- const: zihintntl
|
||||
description:
|
||||
The standard Zihintntl extension for non-temporal locality hints, as
|
||||
ratified in commit 0dc91f5 ("Zihintntl is ratified") of the
|
||||
riscv-isa-manual.
|
||||
|
||||
- const: zihpm
|
||||
description:
|
||||
The standard Zihpm extension for hardware performance counters, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zimop
|
||||
description:
|
||||
The standard Zimop extension version 1.0, as ratified in commit
|
||||
58220614a5f ("Zimop is ratified/1.0") of the riscv-isa-manual.
|
||||
|
||||
- const: ztso
|
||||
description:
|
||||
The standard Ztso extension for total store ordering, as ratified
|
||||
@@ -809,18 +809,18 @@ properties:
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvksh
|
||||
description: |
|
||||
The standard Zvksh extension for ShangMi suite: SM3 secure hash
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvksg
|
||||
description:
|
||||
The standard Zvksg extension for ShangMi algorithm suite with GCM
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvksh
|
||||
description: |
|
||||
The standard Zvksh extension for ShangMi suite: SM3 secure hash
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvkt
|
||||
description:
|
||||
The standard Zvkt extension for vector data-independent execution
|
||||
|
||||
@@ -21,6 +21,7 @@ properties:
|
||||
- qcom,sc8280xp-lpass-rx-macro
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-lpass-rx-macro
|
||||
- qcom,kaanapali-lpass-rx-macro
|
||||
- qcom,sm8650-lpass-rx-macro
|
||||
- qcom,sm8750-lpass-rx-macro
|
||||
|
||||
@@ -21,6 +21,7 @@ properties:
|
||||
- qcom,sc8280xp-lpass-tx-macro
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-lpass-tx-macro
|
||||
- qcom,kaanapali-lpass-tx-macro
|
||||
- qcom,sm8650-lpass-tx-macro
|
||||
- qcom,sm8750-lpass-tx-macro
|
||||
|
||||
@@ -21,6 +21,7 @@ properties:
|
||||
- qcom,sc8280xp-lpass-va-macro
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-lpass-va-macro
|
||||
- qcom,glymur-lpass-va-macro
|
||||
- qcom,kaanapali-lpass-va-macro
|
||||
- qcom,sm8650-lpass-va-macro
|
||||
|
||||
@@ -20,6 +20,7 @@ properties:
|
||||
- qcom,sc8280xp-lpass-wsa-macro
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-lpass-wsa-macro
|
||||
- qcom,glymur-lpass-wsa-macro
|
||||
- qcom,kaanapali-lpass-wsa-macro
|
||||
- qcom,sm8650-lpass-wsa-macro
|
||||
|
||||
@@ -23,6 +23,7 @@ properties:
|
||||
- const: qcom,sdm845-sndcard
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-sndcard
|
||||
- qcom,kaanapali-sndcard
|
||||
- qcom,sm8550-sndcard
|
||||
- qcom,sm8650-sndcard
|
||||
|
||||
@@ -493,8 +493,9 @@ a freshly woken up task gets on a CPU.
|
||||
Where to Look
|
||||
=============
|
||||
|
||||
* ``include/linux/sched/ext.h`` defines the core data structures, ops table
|
||||
and constants.
|
||||
* ``include/linux/sched/ext.h`` defines the core data structures and
|
||||
constants, while the ops table (``struct sched_ext_ops``) is defined in
|
||||
``kernel/sched/ext/internal.h``.
|
||||
|
||||
* ``kernel/sched/ext/ext.c`` contains sched_ext core implementation and helpers.
|
||||
The functions prefixed with ``scx_bpf_`` can be called from the BPF
|
||||
@@ -555,7 +556,8 @@ ABI Instability
|
||||
===============
|
||||
|
||||
The APIs provided by sched_ext to BPF schedulers programs have no stability
|
||||
guarantees. This includes the ops table callbacks and constants defined in
|
||||
guarantees. This includes the ops table callbacks defined in
|
||||
``kernel/sched/ext/internal.h`` and the constants defined in
|
||||
``include/linux/sched/ext.h``, as well as the ``scx_bpf_`` kfuncs defined in
|
||||
``kernel/sched/ext/ext.c`` and ``kernel/sched/ext/idle.c``.
|
||||
|
||||
|
||||
15
MAINTAINERS
15
MAINTAINERS
@@ -2767,12 +2767,12 @@ F: arch/arm/mach-ep93xx/
|
||||
F: drivers/iio/adc/ep93xx_adc.c
|
||||
|
||||
ARM/CIX SOC SUPPORT
|
||||
M: Peter Chen <peter.chen@cixtech.com>
|
||||
M: Gary Yang <gary.yang@cixtech.com>
|
||||
M: Fugang Duan <fugang.duan@cixtech.com>
|
||||
R: CIX Linux Kernel Upstream Group <cix-kernel-upstream@cixtech.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/peter.chen/cix.git
|
||||
T: git https://github.com/cixtech/linux-mainline.git
|
||||
F: Documentation/devicetree/bindings/arm/cix.yaml
|
||||
F: Documentation/devicetree/bindings/mailbox/cix,sky1-mbox.yaml
|
||||
F: arch/arm64/boot/dts/cix/
|
||||
@@ -6209,6 +6209,7 @@ F: include/dt-bindings/sound/cs*
|
||||
F: include/linux/mfd/cs42l43*
|
||||
F: include/sound/cs*
|
||||
F: sound/hda/codecs/cirrus*
|
||||
F: sound/hda/codecs/side-codecs/cirrus*
|
||||
F: sound/hda/codecs/side-codecs/cs*
|
||||
F: sound/hda/codecs/side-codecs/hda_component*
|
||||
F: sound/soc/codecs/cs*
|
||||
@@ -14186,6 +14187,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: Joey Gouly <joey.gouly@arm.com>
|
||||
R: Steffen Eiden <seiden@linux.ibm.com>
|
||||
R: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
@@ -20190,7 +20192,7 @@ W: http://www.onsemi.com
|
||||
F: drivers/net/phy/ncn*
|
||||
|
||||
OP-TEE DRIVER
|
||||
M: Jens Wiklander <jens.wiklander@linaro.org>
|
||||
M: Jens Wiklander <jenswi@kernel.org>
|
||||
L: op-tee@lists.trustedfirmware.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-optee-devices
|
||||
@@ -23308,7 +23310,7 @@ L: spacemit@lists.linux.dev
|
||||
S: Maintained
|
||||
W: https://github.com/spacemit-com/linux/wiki
|
||||
C: irc://irc.libera.chat/spacemit
|
||||
T: git https://github.com/spacemit-com/linux
|
||||
T: https://git.kernel.org/pub/scm/linux/kernel/git/spacemit/linux.git
|
||||
F: arch/riscv/boot/dts/spacemit/
|
||||
N: spacemit
|
||||
K: spacemit
|
||||
@@ -23567,7 +23569,7 @@ F: Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml
|
||||
F: drivers/media/platform/sunxi/sun8i-rotate/
|
||||
|
||||
RPMB SUBSYSTEM
|
||||
M: Jens Wiklander <jens.wiklander@linaro.org>
|
||||
M: Jens Wiklander <jenswi@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/misc/rpmb-core.c
|
||||
@@ -26521,7 +26523,7 @@ F: drivers/media/i2c/tw9910.c
|
||||
F: include/media/i2c/tw9910.h
|
||||
|
||||
TEE SUBSYSTEM
|
||||
M: Jens Wiklander <jens.wiklander@linaro.org>
|
||||
M: Jens Wiklander <jenswi@kernel.org>
|
||||
R: Sumit Garg <sumit.garg@kernel.org>
|
||||
L: op-tee@lists.trustedfirmware.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
@@ -28050,6 +28052,7 @@ F: include/dt-bindings/usb/
|
||||
F: include/linux/usb.h
|
||||
F: include/linux/usb/
|
||||
F: include/uapi/linux/usb/
|
||||
F: rust/kernel/usb.rs
|
||||
|
||||
USB TYPEC BUS FOR ALTERNATE MODES
|
||||
M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
|
||||
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc2
|
||||
EXTRAVERSION = -rc3
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -14,6 +14,5 @@ menuconfig ARCH_IXP4XX
|
||||
select IXP4XX_TIMER
|
||||
select USB_EHCI_BIG_ENDIAN_DESC
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
||||
select USE_OF
|
||||
help
|
||||
Support for Intel's IXP4XX (XScale) family of processors.
|
||||
|
||||
@@ -22,7 +22,6 @@ config MACH_PXA25X_DT
|
||||
select PINCTRL
|
||||
select POWER_SUPPLY
|
||||
select PXA25x
|
||||
select USE_OF
|
||||
help
|
||||
Include support for Marvell PXA25x based platforms using
|
||||
the device tree. Needn't select any other machine while
|
||||
@@ -33,7 +32,6 @@ config MACH_PXA27X_DT
|
||||
select PINCTRL
|
||||
select POWER_SUPPLY
|
||||
select PXA27x
|
||||
select USE_OF
|
||||
help
|
||||
Include support for Marvell PXA27x based platforms using
|
||||
the device tree. Needn't select any other machine while
|
||||
@@ -47,7 +45,6 @@ config MACH_PXA3XX_DT
|
||||
select PINCTRL
|
||||
select POWER_SUPPLY
|
||||
select PXA3xx
|
||||
select USE_OF
|
||||
help
|
||||
Include support for Marvell PXA3xx based platforms using
|
||||
the device tree. Needn't select any other machine while
|
||||
|
||||
@@ -5355,7 +5355,7 @@ cpus {
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu0_0: cpu@0 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x00000>;
|
||||
|
||||
@@ -5374,7 +5374,7 @@ cpu0_0: cpu@0 {
|
||||
};
|
||||
|
||||
cpu0_1: cpu@100 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x00100>;
|
||||
|
||||
@@ -5393,7 +5393,7 @@ cpu0_1: cpu@100 {
|
||||
};
|
||||
|
||||
cpu0_2: cpu@200 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x00200>;
|
||||
|
||||
@@ -5412,7 +5412,7 @@ cpu0_2: cpu@200 {
|
||||
};
|
||||
|
||||
cpu0_3: cpu@300 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x00300>;
|
||||
|
||||
@@ -5431,7 +5431,7 @@ cpu0_3: cpu@300 {
|
||||
};
|
||||
|
||||
cpu1_0: cpu@10000 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x10000>;
|
||||
|
||||
@@ -5450,7 +5450,7 @@ cpu1_0: cpu@10000 {
|
||||
};
|
||||
|
||||
cpu1_1: cpu@10100 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x10100>;
|
||||
|
||||
@@ -5469,7 +5469,7 @@ cpu1_1: cpu@10100 {
|
||||
};
|
||||
|
||||
cpu1_2: cpu@10200 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x10200>;
|
||||
|
||||
@@ -5488,7 +5488,7 @@ cpu1_2: cpu@10200 {
|
||||
};
|
||||
|
||||
cpu1_3: cpu@10300 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x10300>;
|
||||
|
||||
@@ -5507,7 +5507,7 @@ cpu1_3: cpu@10300 {
|
||||
};
|
||||
|
||||
cpu2_0: cpu@20000 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x20000>;
|
||||
|
||||
@@ -5526,7 +5526,7 @@ cpu2_0: cpu@20000 {
|
||||
};
|
||||
|
||||
cpu2_1: cpu@20100 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x20100>;
|
||||
|
||||
@@ -5545,7 +5545,7 @@ cpu2_1: cpu@20100 {
|
||||
};
|
||||
|
||||
cpu2_2: cpu@20200 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x20200>;
|
||||
|
||||
@@ -5564,7 +5564,7 @@ cpu2_2: cpu@20200 {
|
||||
};
|
||||
|
||||
cpu2_3: cpu@20300 {
|
||||
compatible = "arm,cortex-a78";
|
||||
compatible = "arm,cortex-a78ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x20300>;
|
||||
|
||||
|
||||
@@ -3208,7 +3208,7 @@ agic_page5: interrupt-controller@99b0000 {
|
||||
};
|
||||
|
||||
gpcdma: dma-controller@8400000 {
|
||||
compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma";
|
||||
compatible = "nvidia,tegra264-gpcdma";
|
||||
reg = <0x0 0x08400000 0x0 0x210000>;
|
||||
interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>,
|
||||
@@ -4070,7 +4070,7 @@ cpu0: cpu@0 {
|
||||
d-cache-sets = <256>;
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
cpu1: cpu@10000 {
|
||||
compatible = "arm,neoverse-v3ae";
|
||||
device_type = "cpu";
|
||||
reg = <0x10000>;
|
||||
|
||||
@@ -107,6 +107,47 @@ tee@8c400000 {
|
||||
reg = <0x0 0x8c400000 0x0 0x02000000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
/* DRAM controller inline ECC areas */
|
||||
ecc@10cccc0000 {
|
||||
reg = <0x10 0xcccc0000 0x0 0x33340000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@12cccc0000 {
|
||||
reg = <0x12 0xcccc0000 0x0 0x33340000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@14cccc0000 {
|
||||
reg = <0x14 0xcccc0000 0x0 0x33340000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@16cccc0000 {
|
||||
reg = <0x16 0xcccc0000 0x0 0x33340000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@18cccc0000 {
|
||||
reg = <0x18 0xcccc0000 0x0 0x33340000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@1a66660000 {
|
||||
reg = <0x1a 0x66660000 0x0 0x999a0000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@1c66660000 {
|
||||
reg = <0x1c 0x66660000 0x0 0x999a0000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
ecc@1e66660000 {
|
||||
reg = <0x1e 0x66660000 0x0 0x999a0000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -388,6 +388,14 @@ struct s1_walk_result {
|
||||
bool failed;
|
||||
};
|
||||
|
||||
static inline void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool s1ptw)
|
||||
{
|
||||
wr->fst = fst;
|
||||
wr->ptw = s1ptw;
|
||||
wr->s2 = s1ptw;
|
||||
wr->failed = true;
|
||||
}
|
||||
|
||||
int __kvm_translate_va(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
|
||||
struct s1_walk_result *wr, u64 va);
|
||||
int __kvm_find_s1_desc_level(struct kvm_vcpu *vcpu, u64 va, u64 ipa,
|
||||
|
||||
@@ -2,17 +2,11 @@
|
||||
#ifndef _ARCH_ARM64_TLBBATCH_H
|
||||
#define _ARCH_ARM64_TLBBATCH_H
|
||||
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
struct arch_tlbflush_unmap_batch {
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
/*
|
||||
* Track CPUs that need SME DVMSync on completion of this batch.
|
||||
* Otherwise, the arm64 HW can do tlb shootdown, so we don't need to
|
||||
* record cpumask for sending IPI
|
||||
* For arm64, HW can do TLB shootdown, so we don't need to record a
|
||||
* cpumask for sending IPIs.
|
||||
*/
|
||||
cpumask_var_t cpumask;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _ARCH_ARM64_TLBBATCH_H */
|
||||
|
||||
@@ -82,6 +82,8 @@ static inline unsigned long get_trans_granule(void)
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
extern cpumask_t sme_active_cpus;
|
||||
|
||||
void sme_do_dvmsync(const struct cpumask *mask);
|
||||
|
||||
static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
@@ -92,42 +94,12 @@ static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
sme_do_dvmsync(mm_cpumask(mm));
|
||||
}
|
||||
|
||||
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
|
||||
struct mm_struct *mm)
|
||||
static inline void sme_dvmsync_batch(void)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Order the mm_cpumask() read after the hardware DVMSync.
|
||||
*/
|
||||
dsb(ish);
|
||||
if (cpumask_empty(mm_cpumask(mm)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Allocate the batch cpumask on first use. Fall back to an immediate
|
||||
* IPI for this mm in case of failure.
|
||||
*/
|
||||
if (!cpumask_available(batch->cpumask) &&
|
||||
!zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) {
|
||||
sme_do_dvmsync(mm_cpumask(mm));
|
||||
return;
|
||||
}
|
||||
|
||||
cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm));
|
||||
}
|
||||
|
||||
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
if (!cpumask_available(batch->cpumask))
|
||||
return;
|
||||
|
||||
sme_do_dvmsync(batch->cpumask);
|
||||
cpumask_clear(batch->cpumask);
|
||||
sme_do_dvmsync(&sme_active_cpus);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -135,11 +107,7 @@ static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
static inline void sme_dvmsync_batch(void)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -285,11 +253,11 @@ static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
|
||||
sme_dvmsync(mm);
|
||||
}
|
||||
|
||||
static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
static inline void __tlbi_sync_s1ish_batch(void)
|
||||
{
|
||||
dsb(ish);
|
||||
__repeat_tlbi_sync(vale1is, 0);
|
||||
sme_dvmsync_batch(batch);
|
||||
sme_dvmsync_batch();
|
||||
}
|
||||
|
||||
static inline void __tlbi_sync_s1ish_kernel(void)
|
||||
@@ -434,7 +402,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
|
||||
*/
|
||||
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
__tlbi_sync_s1ish_batch(batch);
|
||||
__tlbi_sync_s1ish_batch();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -722,7 +690,6 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b
|
||||
|
||||
__flush_tlb_range(&vma, start, end, PAGE_SIZE, 3,
|
||||
TLBF_NOWALKCACHE | TLBF_NOSYNC);
|
||||
sme_dvmsync_add_pending(batch, mm);
|
||||
}
|
||||
|
||||
static inline bool __pte_flags_need_flush(ptval_t oldval, ptval_t newval)
|
||||
|
||||
@@ -448,12 +448,14 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id,
|
||||
return *pcpu;
|
||||
}
|
||||
|
||||
set_cpu_present(*pcpu, true);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_map_cpu);
|
||||
|
||||
int acpi_unmap_cpu(int cpu)
|
||||
{
|
||||
set_cpu_present(cpu, false);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_unmap_cpu);
|
||||
|
||||
@@ -1355,6 +1355,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
|
||||
* SME/CME erratum handling.
|
||||
*/
|
||||
static cpumask_t sme_dvmsync_cpus;
|
||||
cpumask_t sme_active_cpus;
|
||||
|
||||
/*
|
||||
* These helpers are only called from non-preemptible contexts, so
|
||||
@@ -1368,13 +1369,15 @@ void sme_set_active(void)
|
||||
return;
|
||||
|
||||
cpumask_set_cpu(cpu, mm_cpumask(current->mm));
|
||||
cpumask_set_cpu(cpu, &sme_active_cpus);
|
||||
|
||||
/*
|
||||
* A subsequent (post ERET) SME access may use a stale address
|
||||
* translation. On C1-Pro, a TLBI+DSB on a different CPU will wait for
|
||||
* the completion of cpumask_set_cpu() above as it appears in program
|
||||
* order before the SME access. The post-TLBI+DSB read of mm_cpumask()
|
||||
* will lead to the IPI being issued.
|
||||
* the completion of the cpumask_set_cpu() operations above as they
|
||||
* appear in program order before the SME access. The post-TLBI+DSB
|
||||
* read of mm_cpumask() or sme_active_cpus will lead to the IPI being
|
||||
* issued.
|
||||
*
|
||||
* https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3
|
||||
*/
|
||||
@@ -1392,6 +1395,7 @@ void sme_clear_active(void)
|
||||
* completed on entering EL1.
|
||||
*/
|
||||
cpumask_clear_cpu(cpu, mm_cpumask(current->mm));
|
||||
cpumask_clear_cpu(cpu, &sme_active_cpus);
|
||||
}
|
||||
|
||||
static void sme_dvmsync_ipi(void *unused)
|
||||
|
||||
@@ -341,41 +341,8 @@ void flush_thread(void)
|
||||
flush_gcs();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
static void arch_dup_tlbbatch_mask(struct task_struct *dst)
|
||||
{
|
||||
/*
|
||||
* Clear the inherited cpumask with memset() to cover both cases where
|
||||
* cpumask_var_t is a pointer or an array. It will be allocated lazily
|
||||
* in sme_dvmsync_add_pending() if CPUMASK_OFFSTACK=y.
|
||||
*/
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
memset(&dst->tlb_ubc.arch.cpumask, 0,
|
||||
sizeof(dst->tlb_ubc.arch.cpumask));
|
||||
}
|
||||
|
||||
static void arch_release_tlbbatch_mask(struct task_struct *tsk)
|
||||
{
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
free_cpumask_var(tsk->tlb_ubc.arch.cpumask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void arch_dup_tlbbatch_mask(struct task_struct *dst)
|
||||
{
|
||||
}
|
||||
|
||||
static void arch_release_tlbbatch_mask(struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM64_ERRATUM_4193714 */
|
||||
|
||||
void arch_release_task_struct(struct task_struct *tsk)
|
||||
{
|
||||
arch_release_tlbbatch_mask(tsk);
|
||||
fpsimd_release_task(tsk);
|
||||
}
|
||||
|
||||
@@ -391,8 +358,6 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
||||
|
||||
*dst = *src;
|
||||
|
||||
arch_dup_tlbbatch_mask(dst);
|
||||
|
||||
/*
|
||||
* Drop stale reference to src's sve_state and convert dst to
|
||||
* non-streaming FPSIMD mode.
|
||||
|
||||
@@ -535,23 +535,13 @@ void arch_unregister_cpu(int cpu)
|
||||
{
|
||||
acpi_handle acpi_handle = acpi_get_processor_handle(cpu);
|
||||
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
||||
acpi_status status;
|
||||
unsigned long long sta;
|
||||
|
||||
if (!acpi_handle) {
|
||||
pr_err_once("Removing a CPU without associated ACPI handle\n");
|
||||
return;
|
||||
}
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(acpi_handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status))
|
||||
return;
|
||||
|
||||
/* For now do not allow anything that looks like physical CPU HP */
|
||||
if (cpu_present(cpu) && !(sta & ACPI_STA_DEVICE_PRESENT)) {
|
||||
if (!ACPI_FAILURE(status) &&
|
||||
cpu_present(cpu) && !(sta & ACPI_STA_DEVICE_PRESENT))
|
||||
pr_err_once("Changing CPU present bit is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unregister_cpu(c);
|
||||
}
|
||||
@@ -566,6 +556,11 @@ struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_cpu_get_madt_gicc);
|
||||
|
||||
static bool acpi_cpu_is_present(int cpu)
|
||||
{
|
||||
return acpi_cpu_get_madt_gicc(cpu)->flags & ACPI_MADT_ENABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* acpi_map_gic_cpu_interface - parse processor MADT entry
|
||||
*
|
||||
@@ -670,6 +665,10 @@ static void __init acpi_parse_and_init_cpus(void)
|
||||
early_map_cpu_to_node(i, acpi_numa_get_nid(i));
|
||||
}
|
||||
#else
|
||||
static bool acpi_cpu_is_present(int cpu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#define acpi_parse_and_init_cpus(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
@@ -814,7 +813,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
set_cpu_present(cpu, true);
|
||||
if (acpi_disabled || acpi_cpu_is_present(cpu))
|
||||
set_cpu_present(cpu, true);
|
||||
numa_store_cpu_info(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,6 @@
|
||||
#include <asm/kvm_mmu.h>
|
||||
#include <asm/lsui.h>
|
||||
|
||||
static void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool s1ptw)
|
||||
{
|
||||
wr->fst = fst;
|
||||
wr->ptw = s1ptw;
|
||||
wr->s2 = s1ptw;
|
||||
wr->failed = true;
|
||||
}
|
||||
|
||||
#define S1_MMU_DISABLED (-127)
|
||||
|
||||
static int get_ia_size(struct s1_walk_info *wi)
|
||||
|
||||
@@ -2746,17 +2746,33 @@ static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)
|
||||
(spsr & PSR_MODE32_BIT) ||
|
||||
(vcpu_el2_tge_is_set(vcpu) && (mode == PSR_MODE_EL1t ||
|
||||
mode == PSR_MODE_EL1h))) {
|
||||
/*
|
||||
* The guest is playing with our nerves. Preserve EL, SP,
|
||||
* masks, flags from the existing PSTATE, and set IL.
|
||||
* The HW will then generate an Illegal State Exception
|
||||
* immediately after ERET.
|
||||
*/
|
||||
spsr = *vcpu_cpsr(vcpu);
|
||||
u64 mask;
|
||||
|
||||
spsr &= (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT |
|
||||
PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT |
|
||||
PSR_MODE_MASK | PSR_MODE32_BIT);
|
||||
/*
|
||||
* On an illegal exception return, the flags and masks are
|
||||
* taken from the SPSR while PSTATE.{EL,SP,nRW} and, if
|
||||
* FEAT_GCS, PSTATE.EXLOCK are unchanged (R_VWJHB). Set IL
|
||||
* so the HW generates an Illegal State Exception right
|
||||
* after ERET.
|
||||
*/
|
||||
mask = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT |
|
||||
PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT;
|
||||
|
||||
if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, PAN, IMP))
|
||||
mask |= PSR_PAN_BIT;
|
||||
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, NMI, IMP))
|
||||
mask |= ALLINT_ALLINT;
|
||||
/* FEAT_SPE_EXC and FEAT_TRBE_EXC also gate PSTATE.PM one day... */
|
||||
if (kvm_has_feat(vcpu->kvm, ID_AA64DFR1_EL1, EBEP, IMP))
|
||||
mask |= BIT_ULL(32); /* SPSR_ELx.PM */
|
||||
|
||||
spsr &= mask;
|
||||
|
||||
mask = PSR_MODE_MASK | PSR_MODE32_BIT;
|
||||
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, GCS, IMP))
|
||||
mask |= BIT_ULL(34); /* PSTATE.EXLOCK */
|
||||
|
||||
spsr |= *vcpu_cpsr(vcpu) & mask;
|
||||
spsr |= PSR_IL_BIT;
|
||||
}
|
||||
|
||||
@@ -2784,7 +2800,7 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
|
||||
* ERET handling, and the guest will have a little surprise.
|
||||
*/
|
||||
if (kvm_has_pauth(vcpu->kvm, FPACCOMBINE) && !(spsr & PSR_IL_BIT)) {
|
||||
esr &= ESR_ELx_ERET_ISS_ERETA;
|
||||
esr &= (ESR_ELx_ERET_ISS_ERETA | ESR_ELx_IL);
|
||||
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_FPAC);
|
||||
kvm_inject_nested_sync(vcpu, esr);
|
||||
return;
|
||||
@@ -2826,6 +2842,7 @@ static void kvm_inject_el2_exception(struct kvm_vcpu *vcpu, u64 esr_el2,
|
||||
break;
|
||||
case except_type_serror:
|
||||
kvm_pend_exception(vcpu, EXCEPT_AA64_EL2_SERR);
|
||||
vcpu_write_sys_reg(vcpu, esr_el2, ESR_EL2);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Unsupported EL2 exception injection %d\n", type);
|
||||
@@ -2950,6 +2967,6 @@ int kvm_inject_nested_serror(struct kvm_vcpu *vcpu, u64 esr)
|
||||
* vSError injection. Manually populate EC for an emulated SError
|
||||
* exception.
|
||||
*/
|
||||
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR);
|
||||
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR) | ESR_ELx_IL;
|
||||
return kvm_inject_nested(vcpu, esr, except_type_serror);
|
||||
}
|
||||
|
||||
@@ -448,16 +448,19 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
|
||||
|
||||
static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
{
|
||||
u64 spsr;
|
||||
|
||||
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
|
||||
arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
|
||||
write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
|
||||
|
||||
/*
|
||||
* Finish potential single step before executing the prologue
|
||||
* instruction.
|
||||
* instruction. Modify the hardware SPSR_EL2 directly, as vcpu_cpsr()
|
||||
* may hold a synthetic (vEL2) value for a guest hypervisor.
|
||||
*/
|
||||
*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
|
||||
write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
|
||||
spsr = read_sysreg_el2(SYS_SPSR);
|
||||
write_sysreg_el2(spsr & ~DBG_SPSR_SS, SYS_SPSR);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -602,8 +605,6 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
|
||||
return false;
|
||||
break;
|
||||
case ESR_ELx_EC_SYS64:
|
||||
if (WARN_ON_ONCE(!is_hyp_ctxt(vcpu)))
|
||||
return false;
|
||||
fallthrough;
|
||||
case ESR_ELx_EC_SVE:
|
||||
if (!sve_guest)
|
||||
|
||||
@@ -352,7 +352,7 @@ static u32 __ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges,
|
||||
u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE;
|
||||
u64 pfn = hyp_phys_to_pfn(range->address);
|
||||
|
||||
if (!PAGE_ALIGNED(sz))
|
||||
if (!PAGE_ALIGNED(sz | range->address))
|
||||
break;
|
||||
|
||||
if (__pkvm_host_share_ffa(pfn, sz / PAGE_SIZE))
|
||||
@@ -372,7 +372,7 @@ static u32 __ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges,
|
||||
u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE;
|
||||
u64 pfn = hyp_phys_to_pfn(range->address);
|
||||
|
||||
if (!PAGE_ALIGNED(sz))
|
||||
if (!PAGE_ALIGNED(sz | range->address))
|
||||
break;
|
||||
|
||||
if (__pkvm_host_unshare_ffa(pfn, sz / PAGE_SIZE))
|
||||
@@ -476,11 +476,12 @@ static void __do_ffa_mem_xfer(const u64 func_id,
|
||||
DECLARE_REG(u32, fraglen, ctxt, 2);
|
||||
DECLARE_REG(u64, addr_mbz, ctxt, 3);
|
||||
DECLARE_REG(u32, npages_mbz, ctxt, 4);
|
||||
u32 offset, nr_ranges, checked_offset, em_mem_access_off;
|
||||
struct ffa_mem_region_attributes *ep_mem_access;
|
||||
struct ffa_composite_mem_region *reg;
|
||||
struct ffa_mem_region *buf;
|
||||
u32 offset, nr_ranges, checked_offset;
|
||||
int ret = 0;
|
||||
size_t mem_region_len = FFA_MEM_REGION_SZ(hyp_ffa_version);
|
||||
|
||||
if (addr_mbz || npages_mbz || fraglen > len ||
|
||||
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
|
||||
@@ -488,8 +489,7 @@ static void __do_ffa_mem_xfer(const u64 func_id,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fraglen < sizeof(struct ffa_mem_region) +
|
||||
sizeof(struct ffa_mem_region_attributes)) {
|
||||
if (fraglen < mem_region_len + ffa_emad_size_get(hyp_ffa_version)) {
|
||||
ret = FFA_RET_INVALID_PARAMETERS;
|
||||
goto out;
|
||||
}
|
||||
@@ -508,8 +508,13 @@ static void __do_ffa_mem_xfer(const u64 func_id,
|
||||
buf = hyp_buffers.tx;
|
||||
memcpy(buf, host_buffers.tx, fraglen);
|
||||
|
||||
ep_mem_access = (void *)buf +
|
||||
ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
|
||||
em_mem_access_off = ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
|
||||
if ((u64)em_mem_access_off + ffa_emad_size_get(hyp_ffa_version) > fraglen) {
|
||||
ret = FFA_RET_INVALID_PARAMETERS;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ep_mem_access = (void *)buf + em_mem_access_off;
|
||||
offset = ep_mem_access->composite_off;
|
||||
if (!offset || buf->ep_count != 1 || buf->sender_id != HOST_FFA_ID) {
|
||||
ret = FFA_RET_INVALID_PARAMETERS;
|
||||
@@ -574,9 +579,9 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
|
||||
DECLARE_REG(u32, handle_lo, ctxt, 1);
|
||||
DECLARE_REG(u32, handle_hi, ctxt, 2);
|
||||
DECLARE_REG(u32, flags, ctxt, 3);
|
||||
u32 offset, len, fraglen, fragoff, em_mem_access_off;
|
||||
struct ffa_mem_region_attributes *ep_mem_access;
|
||||
struct ffa_composite_mem_region *reg;
|
||||
u32 offset, len, fraglen, fragoff;
|
||||
struct ffa_mem_region *buf;
|
||||
int ret = 0;
|
||||
u64 handle;
|
||||
@@ -599,16 +604,22 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
|
||||
len = res->a1;
|
||||
fraglen = res->a2;
|
||||
|
||||
ep_mem_access = (void *)buf +
|
||||
ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
|
||||
em_mem_access_off = ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
|
||||
if ((u64)em_mem_access_off + ffa_emad_size_get(hyp_ffa_version) > fraglen) {
|
||||
ret = FFA_RET_INVALID_PARAMETERS;
|
||||
ffa_rx_release(res);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ep_mem_access = (void *)buf + em_mem_access_off;
|
||||
offset = ep_mem_access->composite_off;
|
||||
/*
|
||||
* We can trust the SPMD to get this right, but let's at least
|
||||
* check that we end up with something that doesn't look _completely_
|
||||
* bogus.
|
||||
*/
|
||||
if (WARN_ON(offset > len ||
|
||||
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
|
||||
if (offset + CONSTITUENTS_OFFSET(0) > len ||
|
||||
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
|
||||
ret = FFA_RET_ABORTED;
|
||||
ffa_rx_release(res);
|
||||
goto out_unlock;
|
||||
@@ -636,11 +647,16 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
|
||||
ffa_rx_release(res);
|
||||
}
|
||||
|
||||
reg = (void *)buf + offset;
|
||||
if (offset + CONSTITUENTS_OFFSET(reg->addr_range_cnt) > len) {
|
||||
ret = FFA_RET_ABORTED;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ffa_mem_reclaim(res, handle_lo, handle_hi, flags);
|
||||
if (res->a0 != FFA_SUCCESS)
|
||||
goto out_unlock;
|
||||
|
||||
reg = (void *)buf + offset;
|
||||
/* If the SPMD was happy, then we should be too. */
|
||||
WARN_ON(ffa_host_unshare_ranges(reg->constituents,
|
||||
reg->addr_range_cnt));
|
||||
@@ -864,7 +880,7 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
|
||||
|
||||
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
|
||||
{
|
||||
struct arm_smccc_1_2_regs res;
|
||||
struct arm_smccc_1_2_regs res = {0};
|
||||
|
||||
/*
|
||||
* There's no way we can tell what a non-standard SMC call might
|
||||
|
||||
@@ -1056,7 +1056,8 @@ static u64 __pkvm_memshare_page_req(struct kvm_vcpu *vcpu, u64 ipa)
|
||||
|
||||
/* Fake up a data abort (level 3 translation fault on write) */
|
||||
vcpu->arch.fault.esr_el2 = (ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT) |
|
||||
ESR_ELx_WNR | ESR_ELx_FSC_FAULT |
|
||||
ESR_ELx_IL | ESR_ELx_WNR |
|
||||
ESR_ELx_FSC_FAULT |
|
||||
FIELD_PREP(ESR_ELx_FSC_LEVEL, 3);
|
||||
|
||||
/* Shuffle the IPA around into the HPFAR */
|
||||
|
||||
@@ -268,6 +268,7 @@ static void inject_sync64(struct kvm_vcpu *vcpu, u64 esr)
|
||||
|
||||
write_sysreg_el1(esr, SYS_ESR);
|
||||
write_sysreg_el1(read_sysreg_el2(SYS_ELR), SYS_ELR);
|
||||
write_sysreg_el1(read_sysreg_el2(SYS_SPSR), SYS_SPSR);
|
||||
write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
|
||||
write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
|
||||
}
|
||||
@@ -278,7 +279,7 @@ static void inject_sync64(struct kvm_vcpu *vcpu, u64 esr)
|
||||
*/
|
||||
static void inject_undef64(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
inject_sync64(vcpu, (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT));
|
||||
inject_sync64(vcpu, (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT) | ESR_ELx_IL);
|
||||
}
|
||||
|
||||
static u64 read_id_reg(const struct kvm_vcpu *vcpu,
|
||||
|
||||
@@ -1370,16 +1370,19 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
|
||||
if (prot & KVM_PGTABLE_PROT_W)
|
||||
set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
|
||||
|
||||
ret = stage2_set_xn_attr(prot, &xn);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (prot & KVM_PGTABLE_PROT_X) {
|
||||
ret = stage2_set_xn_attr(prot, &xn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set |= xn & KVM_PTE_LEAF_ATTR_HI_S2_XN;
|
||||
clr |= ~xn & KVM_PTE_LEAF_ATTR_HI_S2_XN;
|
||||
set |= xn & KVM_PTE_LEAF_ATTR_HI_S2_XN;
|
||||
clr |= ~xn & KVM_PTE_LEAF_ATTR_HI_S2_XN;
|
||||
}
|
||||
|
||||
ret = stage2_update_leaf_attrs(pgt, addr, 1, set, clr, NULL, &level, flags);
|
||||
if (!ret || ret == -EAGAIN)
|
||||
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, level);
|
||||
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr,
|
||||
(ret == -EAGAIN) ? TLBI_TTL_UNKNOWN : level);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,11 +138,10 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
|
||||
pend_sync_exception(vcpu);
|
||||
|
||||
/*
|
||||
* Build an {i,d}abort, depending on the level and the
|
||||
* instruction set. Report an external synchronous abort.
|
||||
* Build an {i,d}abort, depending on the level.
|
||||
* Report an external synchronous abort.
|
||||
*/
|
||||
if (kvm_vcpu_trap_il_is32bit(vcpu))
|
||||
esr |= ESR_ELx_IL;
|
||||
esr |= ESR_ELx_IL;
|
||||
|
||||
/*
|
||||
* Here, the guest runs in AArch64 mode when in EL1. If we get
|
||||
@@ -170,14 +169,7 @@ void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr)
|
||||
|
||||
static void inject_undef64(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
|
||||
|
||||
/*
|
||||
* Build an unknown exception, depending on the instruction
|
||||
* set.
|
||||
*/
|
||||
if (kvm_vcpu_trap_il_is32bit(vcpu))
|
||||
esr |= ESR_ELx_IL;
|
||||
u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT) | ESR_ELx_IL;
|
||||
|
||||
kvm_inject_sync(vcpu, esr);
|
||||
}
|
||||
@@ -389,7 +381,7 @@ int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr)
|
||||
*/
|
||||
if (!serror_is_masked(vcpu)) {
|
||||
pend_serror_exception(vcpu);
|
||||
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR);
|
||||
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR) | ESR_ELx_IL;
|
||||
vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,10 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
|
||||
len = kvm_vcpu_dabt_get_as(vcpu);
|
||||
data = kvm_mmio_read_buf(run->mmio.data, len);
|
||||
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
|
||||
&data);
|
||||
data = vcpu_data_host_to_guest(vcpu, data, len);
|
||||
|
||||
if (kvm_vcpu_dabt_issext(vcpu) &&
|
||||
len < sizeof(unsigned long)) {
|
||||
mask = 1U << ((len * 8) - 1);
|
||||
@@ -135,9 +139,6 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
|
||||
if (!kvm_vcpu_dabt_issf(vcpu))
|
||||
data = data & 0xffffffff;
|
||||
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
|
||||
&data);
|
||||
data = vcpu_data_host_to_guest(vcpu, data, len);
|
||||
vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ struct vncr_tlb {
|
||||
struct s1_walk_result wr;
|
||||
|
||||
u64 hpa;
|
||||
bool hpa_writable;
|
||||
|
||||
/* -1 when not mapped on a CPU */
|
||||
int cpu;
|
||||
@@ -1401,15 +1402,19 @@ static int kvm_translate_vncr(struct kvm_vcpu *vcpu, bool *is_gmem)
|
||||
|
||||
gfn = vt->wr.pa >> PAGE_SHIFT;
|
||||
memslot = gfn_to_memslot(vcpu->kvm, gfn);
|
||||
if (!memslot)
|
||||
if (!memslot) {
|
||||
fail_s1_walk(&vt->wr, ESR_ELx_FSC_EXTABT, false);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*is_gmem = kvm_slot_has_gmem(memslot);
|
||||
if (!*is_gmem) {
|
||||
pfn = __kvm_faultin_pfn(memslot, gfn, write_fault ? FOLL_WRITE : 0,
|
||||
&writable, &page);
|
||||
if (is_error_noslot_pfn(pfn) || (write_fault && !writable))
|
||||
if (is_error_noslot_pfn(pfn)) {
|
||||
fail_s1_walk(&vt->wr, ESR_ELx_FSC_EXTABT, false);
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
ret = kvm_gmem_get_pfn(vcpu->kvm, memslot, gfn, &pfn, &page, NULL);
|
||||
if (ret) {
|
||||
@@ -1417,6 +1422,19 @@ static int kvm_translate_vncr(struct kvm_vcpu *vcpu, bool *is_gmem)
|
||||
write_fault, false, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
writable = !(memslot->flags & KVM_MEM_READONLY);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This check is too restrictive as KVM allows cacheable memory
|
||||
* attributes for PFNMAP VMAs that have cacheable attributes in host
|
||||
* stage-1.
|
||||
*/
|
||||
if (!pfn_is_map_memory(pfn)) {
|
||||
kvm_release_faultin_page(vcpu->kvm, page, true, false);
|
||||
fail_s1_walk(&vt->wr, ESR_ELx_FSC_EXTABT, false);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scoped_guard(write_lock, &vcpu->kvm->mmu_lock) {
|
||||
@@ -1427,116 +1445,100 @@ static int kvm_translate_vncr(struct kvm_vcpu *vcpu, bool *is_gmem)
|
||||
|
||||
vt->gva = va;
|
||||
vt->hpa = pfn << PAGE_SHIFT;
|
||||
vt->hpa_writable = writable;
|
||||
vt->valid = true;
|
||||
vt->cpu = -1;
|
||||
|
||||
kvm_make_request(KVM_REQ_MAP_L1_VNCR_EL2, vcpu);
|
||||
kvm_release_faultin_page(vcpu->kvm, page, false, vt->wr.pw);
|
||||
kvm_release_faultin_page(vcpu->kvm, page, false, vt->wr.pw && vt->hpa_writable);
|
||||
}
|
||||
|
||||
if (vt->wr.pw)
|
||||
if (vt->wr.pw && vt->hpa_writable)
|
||||
mark_page_dirty(vcpu->kvm, gfn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void inject_vncr_perm(struct kvm_vcpu *vcpu)
|
||||
static void handle_vncr_perm(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vncr_tlb *vt = vcpu->arch.vncr_tlb;
|
||||
u64 esr = kvm_vcpu_get_esr(vcpu);
|
||||
u64 fsc;
|
||||
|
||||
/*
|
||||
* Promote to an external abort if the stage-1 permits writes but the
|
||||
* HPA is read-only (e.g. RO memslot).
|
||||
*/
|
||||
if (kvm_is_write_fault(vcpu) && vt->wr.pw && !vt->hpa_writable)
|
||||
fsc = ESR_ELx_FSC_EXTABT;
|
||||
/*
|
||||
* Otherwise, inject a permission fault using the guest's translation
|
||||
* level rather than the host's.
|
||||
*/
|
||||
else
|
||||
fsc = ESR_ELx_FSC_PERM_L(vt->wr.level);
|
||||
|
||||
/* Adjust the fault level to reflect that of the guest's */
|
||||
esr &= ~ESR_ELx_FSC;
|
||||
esr |= FIELD_PREP(ESR_ELx_FSC,
|
||||
ESR_ELx_FSC_PERM_L(vt->wr.level));
|
||||
esr |= FIELD_PREP(ESR_ELx_FSC, fsc);
|
||||
|
||||
kvm_inject_nested_sync(vcpu, esr);
|
||||
}
|
||||
|
||||
static bool kvm_vncr_tlb_lookup(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vncr_tlb *vt = vcpu->arch.vncr_tlb;
|
||||
|
||||
lockdep_assert_held_read(&vcpu->kvm->mmu_lock);
|
||||
|
||||
if (!vt->valid)
|
||||
return false;
|
||||
|
||||
if (read_vncr_el2(vcpu) != vt->gva)
|
||||
return false;
|
||||
|
||||
if (vt->wr.nG)
|
||||
return get_asid_by_regime(vcpu, TR_EL20) == vt->wr.asid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int kvm_handle_vncr_abort(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vncr_tlb *vt = vcpu->arch.vncr_tlb;
|
||||
u64 esr = kvm_vcpu_get_esr(vcpu);
|
||||
bool is_gmem = false;
|
||||
bool perm;
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(!(esr & ESR_ELx_VNCR));
|
||||
|
||||
if (kvm_vcpu_abt_issea(vcpu))
|
||||
return kvm_handle_guest_sea(vcpu);
|
||||
|
||||
if (esr_fsc_is_permission_fault(esr)) {
|
||||
inject_vncr_perm(vcpu);
|
||||
} else if (esr_fsc_is_translation_fault(esr)) {
|
||||
bool valid, is_gmem = false;
|
||||
int ret;
|
||||
if (!esr_fsc_is_translation_fault(esr) && !esr_fsc_is_permission_fault(esr)) {
|
||||
KVM_BUG(1, vcpu->kvm, "Unhandled VNCR abort, ESR=%llx\n", esr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
|
||||
valid = kvm_vncr_tlb_lookup(vcpu);
|
||||
ret = kvm_translate_vncr(vcpu, &is_gmem);
|
||||
switch (ret) {
|
||||
case -EAGAIN:
|
||||
/* Let's try again... */
|
||||
return 1;
|
||||
case -ENOMEM:
|
||||
/*
|
||||
* For guest_memfd, this indicates that it failed to
|
||||
* create a folio to back the memory. Inform userspace.
|
||||
*/
|
||||
if (is_gmem)
|
||||
return 0;
|
||||
/* Otherwise, let's try again... */
|
||||
break;
|
||||
case -EFAULT:
|
||||
case -EIO:
|
||||
case -EHWPOISON:
|
||||
if (is_gmem)
|
||||
return 0;
|
||||
fallthrough;
|
||||
case -EINVAL:
|
||||
case -ENOENT:
|
||||
case -EACCES:
|
||||
/*
|
||||
* Translation failed, inject the corresponding
|
||||
* exception back to EL2.
|
||||
*/
|
||||
esr &= ~ESR_ELx_FSC;
|
||||
esr |= FIELD_PREP(ESR_ELx_FSC, vt->wr.fst);
|
||||
|
||||
if (!valid)
|
||||
ret = kvm_translate_vncr(vcpu, &is_gmem);
|
||||
else
|
||||
ret = -EPERM;
|
||||
|
||||
switch (ret) {
|
||||
case -EAGAIN:
|
||||
/* Let's try again... */
|
||||
break;
|
||||
case -ENOMEM:
|
||||
/*
|
||||
* For guest_memfd, this indicates that it failed to
|
||||
* create a folio to back the memory. Inform userspace.
|
||||
*/
|
||||
if (is_gmem)
|
||||
return 0;
|
||||
/* Otherwise, let's try again... */
|
||||
break;
|
||||
case -EFAULT:
|
||||
case -EIO:
|
||||
case -EHWPOISON:
|
||||
if (is_gmem)
|
||||
return 0;
|
||||
fallthrough;
|
||||
case -EINVAL:
|
||||
case -ENOENT:
|
||||
case -EACCES:
|
||||
/*
|
||||
* Translation failed, inject the corresponding
|
||||
* exception back to EL2.
|
||||
*/
|
||||
BUG_ON(!vt->wr.failed);
|
||||
|
||||
esr &= ~ESR_ELx_FSC;
|
||||
esr |= FIELD_PREP(ESR_ELx_FSC, vt->wr.fst);
|
||||
|
||||
kvm_inject_nested_sync(vcpu, esr);
|
||||
break;
|
||||
case -EPERM:
|
||||
/* Hack to deal with POE until we get kernel support */
|
||||
inject_vncr_perm(vcpu);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
WARN_ONCE(1, "Unhandled VNCR abort, ESR=%llx\n", esr);
|
||||
kvm_inject_nested_sync(vcpu, esr);
|
||||
break;
|
||||
case 0:
|
||||
perm = kvm_is_write_fault(vcpu) ? vt->wr.pw && vt->hpa_writable : vt->wr.pr;
|
||||
if (!perm)
|
||||
handle_vncr_perm(vcpu);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1574,7 +1576,7 @@ static void kvm_map_l1_vncr(struct kvm_vcpu *vcpu)
|
||||
|
||||
vt->cpu = smp_processor_id();
|
||||
|
||||
if (vt->wr.pw && vt->wr.pr)
|
||||
if (vt->hpa_writable && vt->wr.pw && vt->wr.pr)
|
||||
prot = PAGE_KERNEL;
|
||||
else if (vt->wr.pr)
|
||||
prot = PAGE_KERNEL_RO;
|
||||
|
||||
@@ -352,7 +352,7 @@ static int __pkvm_pgtable_stage2_reclaim(struct kvm_pgtable *pgt, u64 start, u64
|
||||
page = pfn_to_page(mapping->pfn);
|
||||
WARN_ON_ONCE(mapping->nr_pages != 1);
|
||||
unpin_user_pages_dirty_lock(&page, 1, true);
|
||||
account_locked_vm(current->mm, 1, false);
|
||||
account_locked_vm(kvm->mm, 1, false);
|
||||
pkvm_mapping_remove(mapping, &pgt->pkvm_mappings);
|
||||
kfree(mapping);
|
||||
}
|
||||
|
||||
@@ -508,6 +508,8 @@ static struct vgic_its *__vgic_doorbell_to_its(struct kvm *kvm, gpa_t db)
|
||||
struct kvm_io_device *kvm_io_dev;
|
||||
struct vgic_io_device *iodev;
|
||||
|
||||
guard(srcu)(&kvm->srcu);
|
||||
|
||||
kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, db);
|
||||
if (!kvm_io_dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
@@ -203,6 +203,7 @@ void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
|
||||
list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
|
||||
if (irq_is_lpi(vcpu->kvm, irq->intid)) {
|
||||
raw_spin_lock(&irq->irq_lock);
|
||||
irq->pending_latch = false;
|
||||
list_del(&irq->ap_list);
|
||||
irq->vcpu = NULL;
|
||||
raw_spin_unlock(&irq->irq_lock);
|
||||
@@ -792,7 +793,11 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This interrupt looks like it has to be migrated. */
|
||||
/*
|
||||
* This interrupt looks like it has to be migrated,
|
||||
* make sure it is kept alive while locks are dropped.
|
||||
*/
|
||||
vgic_get_irq_ref(irq);
|
||||
|
||||
raw_spin_unlock(&irq->irq_lock);
|
||||
raw_spin_unlock(&vgic_cpu->ap_list_lock);
|
||||
@@ -815,15 +820,16 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
|
||||
raw_spin_lock(&irq->irq_lock);
|
||||
|
||||
/*
|
||||
* If the affinity has been preserved, move the
|
||||
* interrupt around. Otherwise, it means things have
|
||||
* changed while the interrupt was unlocked, and we
|
||||
* need to replay this.
|
||||
* If the interrupt is still ours and its affinity has
|
||||
* been preserved, move it around. Otherwise, it means
|
||||
* things have changed while the interrupt was unlocked
|
||||
* (it may even have been taken off the list with its
|
||||
* affinity left untouched), and we need to replay this.
|
||||
*
|
||||
* In all cases, we cannot trust the list not to have
|
||||
* changed, so we restart from the beginning.
|
||||
*/
|
||||
if (target_vcpu == vgic_target_oracle(irq)) {
|
||||
if (irq->vcpu == vcpu && target_vcpu == vgic_target_oracle(irq)) {
|
||||
struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
|
||||
|
||||
list_del(&irq->ap_list);
|
||||
@@ -836,6 +842,8 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
|
||||
raw_spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
|
||||
raw_spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
|
||||
|
||||
deleted_lpis |= vgic_put_irq_norelease(vcpu->kvm, irq);
|
||||
|
||||
if (target_vcpu_needs_kick) {
|
||||
kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
|
||||
kvm_vcpu_kick(target_vcpu);
|
||||
|
||||
@@ -1515,7 +1515,13 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
|
||||
if (free_mapped) {
|
||||
/* CONT blocks are not supported in the vmemmap */
|
||||
WARN_ON(pmd_cont(pmd));
|
||||
flush_tlb_kernel_range(addr, addr + PMD_SIZE);
|
||||
/*
|
||||
* Invalidating a block entry requires just
|
||||
* a single overlapping TLB invalidation,
|
||||
* so limit the range of the flush to a single
|
||||
* page.
|
||||
*/
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
|
||||
free_hotplug_page_range(pmd_page(pmd),
|
||||
PMD_SIZE, altmap);
|
||||
}
|
||||
@@ -1545,7 +1551,8 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
|
||||
if (pud_leaf(pud)) {
|
||||
pud_clear(pudp);
|
||||
if (free_mapped) {
|
||||
flush_tlb_kernel_range(addr, addr + PUD_SIZE);
|
||||
/* See comment in unmap_hotplug_pmd_range(). */
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
|
||||
free_hotplug_page_range(pud_page(pud),
|
||||
PUD_SIZE, altmap);
|
||||
}
|
||||
|
||||
@@ -1806,7 +1806,7 @@ Res0 15:8
|
||||
UnsignedEnum 7:4 BWE
|
||||
0b0000 NI
|
||||
0b0001 FEAT_BWE
|
||||
0b0002 FEAT_BWE2
|
||||
0b0010 FEAT_BWE2
|
||||
EndEnum
|
||||
UnsignedEnum 3:0 STEP
|
||||
0b0000 NI
|
||||
|
||||
@@ -79,7 +79,7 @@ static void __init m523x_i2c_init(void)
|
||||
static void __init m523x_fec_init(void)
|
||||
{
|
||||
/* Set multi-function pins to ethernet use */
|
||||
mcf_write8(read8(MCFGPIO_PAR_FECI2C) | 0xf0, MCFGPIO_PAR_FECI2C);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PAR_FECI2C) | 0xf0, MCFGPIO_PAR_FECI2C);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
@@ -113,11 +113,11 @@ void wildfiremod_halt(void)
|
||||
mcf_write16(read16(MCFGPIO_PEPAR) & ~(1 << (5 * 2)), MCFGPIO_PEPAR);
|
||||
|
||||
/* Make portE.5 an output */
|
||||
mcf_write8(read8(MCFGPIO_PDDR_E) | (1 << 5), MCFGPIO_PDDR_E);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PDDR_E) | (1 << 5), MCFGPIO_PDDR_E);
|
||||
|
||||
/* Now toggle portE.5 from low to high */
|
||||
mcf_write8(read8(MCFGPIO_PODR_E) & ~(1 << 5), MCFGPIO_PODR_E);
|
||||
mcf_write8(read8(MCFGPIO_PODR_E) | (1 << 5), MCFGPIO_PODR_E);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PODR_E) & ~(1 << 5), MCFGPIO_PODR_E);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PODR_E) | (1 << 5), MCFGPIO_PODR_E);
|
||||
|
||||
printk(KERN_EMERG "Failed to hibernate. Halting!\n");
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_POWERPC_PREEMPT_H
|
||||
#define __ASM_POWERPC_PREEMPT_H
|
||||
|
||||
#include <asm-generic/preempt.h>
|
||||
|
||||
#if defined(CONFIG_PREEMPT_DYNAMIC)
|
||||
#include <linux/jump_label.h>
|
||||
DECLARE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched);
|
||||
#define need_irq_preemption() \
|
||||
(static_branch_unlikely(&sk_dynamic_irqentry_exit_cond_resched))
|
||||
#else
|
||||
#define need_irq_preemption() (IS_ENABLED(CONFIG_PREEMPTION))
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_POWERPC_PREEMPT_H */
|
||||
@@ -537,7 +537,7 @@ static inline void __user *mask_user_address(const void __user *ptr)
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC64))
|
||||
return mask_user_address_simple(ptr);
|
||||
if (IS_ENABLED(CONFIG_E500))
|
||||
if (IS_ENABLED(CONFIG_PPC_E500))
|
||||
return mask_user_address_isel(ptr);
|
||||
if (TASK_SIZE <= UL(SZ_2G) && border >= UL(SZ_2G))
|
||||
return mask_user_address_simple(ptr);
|
||||
|
||||
@@ -704,6 +704,15 @@ static void __init cpufeatures_setup_start(u32 isa)
|
||||
if (isa >= ISA_V3_1) {
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_31;
|
||||
cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_1;
|
||||
|
||||
/*
|
||||
* CPU_FTR_P11_PVR is a kernel-internal flag to identify
|
||||
* Power11 and later processors. While ISA v3.1 is supported
|
||||
* by Power10+, this flag specifically indicates Power11+
|
||||
* for code that needs to distinguish between P10 and P11.
|
||||
*/
|
||||
if (PVR_VER(mfspr(SPRN_PVR)) >= PVR_POWER11)
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_P11_PVR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -377,7 +377,6 @@ void vtime_task_switch(struct task_struct *prev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
/**
|
||||
* vtime_reset - Fast forward vtime entry clocks
|
||||
*
|
||||
@@ -394,6 +393,7 @@ void vtime_reset(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_HZ_COMMON
|
||||
/**
|
||||
* vtime_dyntick_start - Inform vtime about entry to idle-dynticks
|
||||
*
|
||||
@@ -933,6 +933,7 @@ static void __init set_decrementer_max(void)
|
||||
static void __init init_decrementer_clockevent(void)
|
||||
{
|
||||
register_decrementer_clockevent(smp_processor_id());
|
||||
vtime_reset();
|
||||
}
|
||||
|
||||
void secondary_cpu_time_init(void)
|
||||
@@ -948,6 +949,7 @@ void secondary_cpu_time_init(void)
|
||||
/* FIME: Should make unrelated change to move snapshot_timebase
|
||||
* call here ! */
|
||||
register_decrementer_clockevent(smp_processor_id());
|
||||
vtime_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,7 +46,7 @@ int exit_vmx_usercopy(void)
|
||||
* set and we are preemptible. The hack here is to schedule a
|
||||
* decrementer to fire here and reschedule for us if necessary.
|
||||
*/
|
||||
if (need_irq_preemption() && need_resched())
|
||||
if (need_resched())
|
||||
set_dec(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ static const struct of_device_id mpc85xx_common_ids[] __initconst = {
|
||||
{ .compatible = "fsl,qoriq-pcie-v2.3", },
|
||||
{ .compatible = "fsl,qoriq-pcie-v2.2", },
|
||||
{ .compatible = "fsl,fman", },
|
||||
/* IFC NAND and NOR controllers */
|
||||
{ .compatible = "fsl,ifc", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -268,10 +268,12 @@ static int spufs_mem_mmap_access(struct vm_area_struct *vma,
|
||||
|
||||
if (write && !(vma->vm_flags & VM_WRITE))
|
||||
return -EACCES;
|
||||
if (offset >= LS_SIZE)
|
||||
return -EFAULT;
|
||||
if (spu_acquire(ctx))
|
||||
return -EINTR;
|
||||
if ((offset + len) > vma->vm_end)
|
||||
len = vma->vm_end - offset;
|
||||
if ((offset + len) > LS_SIZE)
|
||||
len = LS_SIZE - offset;
|
||||
local_store = ctx->ops->get_ls(ctx);
|
||||
if (write)
|
||||
memcpy_toio(local_store + offset, buf, len);
|
||||
|
||||
@@ -154,6 +154,7 @@ config HV_PERF_CTRS
|
||||
config VPA_PMU
|
||||
tristate "VPA PMU events"
|
||||
depends on KVM_BOOK3S_64_HV && HV_PERF_CTRS
|
||||
default m
|
||||
help
|
||||
Enable access to the VPA PMU counters via perf. This enables
|
||||
code that support measurement for KVM on PowerVM(KoP) feature.
|
||||
|
||||
@@ -271,11 +271,9 @@ static int __init papr_init(void)
|
||||
esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * max_esi_attrs);
|
||||
|
||||
temp_esi_buf = krealloc(esi_buf, esi_buf_size, GFP_KERNEL);
|
||||
if (temp_esi_buf)
|
||||
esi_buf = temp_esi_buf;
|
||||
else
|
||||
return -ENOMEM;
|
||||
|
||||
if (!temp_esi_buf)
|
||||
goto out_free_esi_buf;
|
||||
esi_buf = temp_esi_buf;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,12 @@ config ARCH_THEAD
|
||||
help
|
||||
This enables support for the RISC-V based T-HEAD SoCs.
|
||||
|
||||
config ARCH_ULTRARISC
|
||||
bool "UltraRISC RISC-V SoCs"
|
||||
help
|
||||
This enables support for UltraRISC SoC platform hardware,
|
||||
including boards based on the UR-DP1000.
|
||||
|
||||
config ARCH_VIRT
|
||||
bool "QEMU Virt Machine"
|
||||
select POWER_RESET
|
||||
|
||||
@@ -33,6 +33,7 @@ CONFIG_SOC_STARFIVE=y
|
||||
CONFIG_ARCH_SUNXI=y
|
||||
CONFIG_ARCH_TENSTORRENT=y
|
||||
CONFIG_ARCH_THEAD=y
|
||||
CONFIG_ARCH_ULTRARISC=y
|
||||
CONFIG_ARCH_VIRT=y
|
||||
CONFIG_ARCH_CANAAN=y
|
||||
CONFIG_SMP=y
|
||||
|
||||
@@ -41,6 +41,9 @@ machine_kexec_prepare(struct kimage *image)
|
||||
if (image->segment[i].memsz <= sizeof(fdt))
|
||||
continue;
|
||||
|
||||
if (!image->segment[i].buf)
|
||||
continue;
|
||||
|
||||
if (image->file_mode)
|
||||
memcpy(&fdt, image->segment[i].buf, sizeof(fdt));
|
||||
else if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt)))
|
||||
|
||||
@@ -190,17 +190,18 @@ static int memtop_get_stride_len(unsigned long *res)
|
||||
static int memtop_get_page_count(unsigned long *res, unsigned long level)
|
||||
{
|
||||
static unsigned long memtop_pages[DIAG310_LEVELMAX];
|
||||
unsigned long pages;
|
||||
unsigned long pages, idx;
|
||||
int rc;
|
||||
|
||||
if (level > DIAG310_LEVELMAX || level < DIAG310_LEVELMIN)
|
||||
return -EINVAL;
|
||||
pages = READ_ONCE(memtop_pages[level - 1]);
|
||||
idx = array_index_nospec(level - 1, ARRAY_SIZE(memtop_pages));
|
||||
pages = READ_ONCE(memtop_pages[idx]);
|
||||
if (!pages) {
|
||||
rc = diag310_get_memtop_size(&pages, level);
|
||||
if (rc)
|
||||
return rc;
|
||||
WRITE_ONCE(memtop_pages[level - 1], pages);
|
||||
WRITE_ONCE(memtop_pages[idx], pages);
|
||||
}
|
||||
*res = pages;
|
||||
return 0;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Here we can supply some information useful to userland.
|
||||
*/
|
||||
|
||||
#include <linux/build-salt.h>
|
||||
#include <linux/uts.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/elfnote.h>
|
||||
@@ -11,3 +12,5 @@
|
||||
ELFNOTE_START(Linux, 0, "a")
|
||||
.long LINUX_VERSION_CODE
|
||||
ELFNOTE_END
|
||||
|
||||
BUILD_SALT
|
||||
|
||||
@@ -570,6 +570,8 @@ static long dat_crste_walk_range(gfn_t start, gfn_t end, struct crst_table *tabl
|
||||
else if (walk->ops->pte_entry)
|
||||
rc = dat_pte_walk_range(max(start, cur), min(end, next),
|
||||
dereference_pmd(crste.pmd), walk);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
||||
@@ -1374,8 +1374,13 @@ struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *pare
|
||||
/* Only allow one real-space gmap shadow. */
|
||||
list_for_each_entry(sg, &parent->children, list) {
|
||||
if (sg->guest_asce.r) {
|
||||
scoped_guard(write_lock, &parent->kvm->mmu_lock)
|
||||
if (write_trylock(&parent->kvm->mmu_lock)) {
|
||||
gmap_unshadow(sg);
|
||||
write_unlock(&parent->kvm->mmu_lock);
|
||||
} else {
|
||||
gmap_put(new);
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1280,8 +1280,10 @@ static int kvm_s390_vm_stop_migration(struct kvm *kvm)
|
||||
* PGSTEs might have cmma_d set.
|
||||
*/
|
||||
WRITE_ONCE(kvm->arch.migration_mode, 0);
|
||||
if (kvm->arch.use_cmma)
|
||||
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
|
||||
if (!kvm->arch.use_cmma)
|
||||
return 0;
|
||||
|
||||
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
|
||||
/* Clear cmma_d on all existing PGSTEs and set cmma_dirty_pages to 0. */
|
||||
gmap_set_cmma_all_clean(kvm->arch.gmap);
|
||||
atomic64_set(&kvm->arch.cmma_dirty_pages, 0);
|
||||
|
||||
@@ -300,9 +300,14 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
|
||||
gaite->gisc = fib->fmt0.isc;
|
||||
gaite->count++;
|
||||
gaite->aisbo = fib->fmt0.aisbo;
|
||||
gaite->aisb = virt_to_phys(page_address(aisb_page) + (fib->fmt0.aisb &
|
||||
~PAGE_MASK));
|
||||
if (fib->fmt0.sum == 1) {
|
||||
gaite->aisbo = fib->fmt0.aisbo;
|
||||
gaite->aisb = virt_to_phys(page_address(aisb_page) +
|
||||
(fib->fmt0.aisb & ~PAGE_MASK));
|
||||
} else {
|
||||
gaite->aisbo = 0;
|
||||
gaite->aisb = 0;
|
||||
}
|
||||
aift->kzdev[zdev->aisb] = zdev->kzdev;
|
||||
spin_unlock_irq(&aift->gait_lock);
|
||||
|
||||
@@ -328,6 +333,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
unpin1:
|
||||
unpin_user_page(aibv_page);
|
||||
out:
|
||||
kvm_s390_gisc_unregister(kvm, fib->fmt0.isc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ static inline unsigned long mmap_base(unsigned long rnd,
|
||||
return PAGE_ALIGN(STACK_TOP - gap - rnd);
|
||||
}
|
||||
|
||||
static int get_align_mask(struct file *filp, unsigned long flags)
|
||||
static unsigned long get_align_mask(struct file *filp, unsigned long flags)
|
||||
{
|
||||
if (filp && is_file_hugepages(filp))
|
||||
return huge_page_mask_align(filp);
|
||||
|
||||
@@ -259,13 +259,13 @@ void amd_brs_disable_all(void)
|
||||
amd_brs_disable();
|
||||
}
|
||||
|
||||
static bool amd_brs_match_plm(struct perf_event *event, u64 to)
|
||||
static bool amd_brs_match_plm(struct perf_event *event, u64 from, u64 to)
|
||||
{
|
||||
int type = event->attr.branch_sample_type;
|
||||
int plm_k = PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV;
|
||||
int plm_u = PERF_SAMPLE_BRANCH_USER;
|
||||
|
||||
if (!(type & plm_k) && kernel_ip(to))
|
||||
if (!(type & plm_k) && (kernel_ip(to) || kernel_ip(from)))
|
||||
return 0;
|
||||
|
||||
if (!(type & plm_u) && !kernel_ip(to))
|
||||
@@ -338,11 +338,11 @@ void amd_brs_drain(void)
|
||||
*/
|
||||
to = (u64)(((s64)to << shift) >> shift);
|
||||
|
||||
if (!amd_brs_match_plm(event, to))
|
||||
continue;
|
||||
|
||||
rdmsrq(brs_from(brs_idx), from);
|
||||
|
||||
if (!amd_brs_match_plm(event, from, to))
|
||||
continue;
|
||||
|
||||
perf_clear_branch_entry_bitfields(br+nr);
|
||||
|
||||
br[nr].from = from;
|
||||
|
||||
@@ -754,13 +754,11 @@ static void amd_pmu_enable_event(struct perf_event *event)
|
||||
x86_pmu_enable_event(event);
|
||||
}
|
||||
|
||||
static void amd_pmu_enable_all(int added)
|
||||
static void __amd_pmu_enable_all(void)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
int idx;
|
||||
|
||||
amd_brs_enable_all();
|
||||
|
||||
for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
|
||||
/* only activate events which are marked as active */
|
||||
if (!test_bit(idx, cpuc->active_mask))
|
||||
@@ -775,6 +773,12 @@ static void amd_pmu_enable_all(int added)
|
||||
}
|
||||
}
|
||||
|
||||
static void amd_pmu_enable_all(int added)
|
||||
{
|
||||
amd_brs_enable_all();
|
||||
__amd_pmu_enable_all();
|
||||
}
|
||||
|
||||
static void amd_pmu_v2_enable_event(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
@@ -1561,7 +1565,7 @@ static inline void amd_pmu_reload_virt(void)
|
||||
* set global enable bits once again
|
||||
*/
|
||||
amd_pmu_v2_disable_all();
|
||||
amd_pmu_enable_all(0);
|
||||
__amd_pmu_enable_all();
|
||||
amd_pmu_v2_enable_all(0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ static void amd_pmu_lbr_filter(void)
|
||||
}
|
||||
|
||||
/* If type does not correspond, then discard */
|
||||
if (type == X86_BR_NONE || (br_sel & type) != type) {
|
||||
if (type == X86_BR_NONE || (br_sel & type) != type ||
|
||||
(!(br_sel & X86_BR_KERNEL) && kernel_ip(cpuc->lbr_entries[i].from))) {
|
||||
cpuc->lbr_entries[i].from = 0; /* mark invalid */
|
||||
compress = true;
|
||||
}
|
||||
|
||||
@@ -488,8 +488,10 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
|
||||
|
||||
if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
|
||||
ret = kvm_pi_update_irte(irqfd, &irqfd->irq_entry);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
kvm->arch.nr_possible_bypass_irqs--;
|
||||
irqfd->producer = NULL;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&kvm->irqfds.lock);
|
||||
|
||||
|
||||
@@ -3371,6 +3371,12 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
|
||||
struct kvm_lapic *apic)
|
||||
{
|
||||
int vector;
|
||||
|
||||
if (unlikely(!pv_eoi_enabled(vcpu))) {
|
||||
__clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PV EOI state is derived from KVM_APIC_PV_EOI_PENDING in host
|
||||
* and KVM_PV_EOI_ENABLED in guest memory as follows:
|
||||
@@ -3382,8 +3388,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
|
||||
* KVM_APIC_PV_EOI_PENDING is set, KVM_PV_EOI_ENABLED is unset:
|
||||
* -> host enabled PV EOI, guest executed EOI.
|
||||
*/
|
||||
BUG_ON(!pv_eoi_enabled(vcpu));
|
||||
|
||||
if (pv_eoi_test_and_clr_pending(vcpu))
|
||||
return;
|
||||
vector = apic_set_eoi(apic);
|
||||
|
||||
@@ -2129,8 +2129,9 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Do not allow SNP VM migration until additional state transfer is implemented */
|
||||
if (kvm->arch.vm_type != source_kvm->arch.vm_type ||
|
||||
sev_guest(kvm) || !sev_guest(source_kvm)) {
|
||||
sev_guest(kvm) || !sev_guest(source_kvm) || sev_snp_guest(source_kvm)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -2851,8 +2852,9 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||
* disallow out-of-band SEV/SEV-ES init if the target is already an
|
||||
* SEV guest, or if vCPUs have been created. KVM relies on vCPUs being
|
||||
* created after SEV/SEV-ES initialization, e.g. to init intercepts.
|
||||
* Also do not allow SNP VM mirroring until additional state transfer is implemented.
|
||||
*/
|
||||
if (sev_guest(kvm) || !sev_guest(source_kvm) ||
|
||||
if (sev_guest(kvm) || !sev_guest(source_kvm) || sev_snp_guest(source_kvm) ||
|
||||
is_mirroring_enc_context(source_kvm) || kvm->created_vcpus) {
|
||||
ret = -EINVAL;
|
||||
goto e_unlock;
|
||||
|
||||
@@ -571,7 +571,12 @@ static int svm_enable_virtualization_cpu(void)
|
||||
return r;
|
||||
|
||||
sd = per_cpu_ptr(&svm_data, me);
|
||||
sd->asid_generation = 1;
|
||||
/*
|
||||
* Bump the current asid_generation value to ensure any vCPU that
|
||||
* previously ran on this CPU sees a stale generation and is forced
|
||||
* to acquire a new ASID, preventing a latent ASID collision.
|
||||
*/
|
||||
sd->asid_generation++;
|
||||
sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
|
||||
sd->next_asid = sd->max_asid + 1;
|
||||
sd->min_asid = max_sev_asid + 1;
|
||||
|
||||
@@ -490,7 +490,7 @@ TRACE_EVENT(kvm_inj_exception,
|
||||
TP_printk("%s%s%s%s%s",
|
||||
__print_symbolic(__entry->exception, kvm_trace_sym_exc),
|
||||
!__entry->has_error ? "" : " (",
|
||||
!__entry->has_error ? "" : __print_symbolic(__entry->error_code, { }),
|
||||
!__entry->has_error ? "" : __print_symbolic(__entry->error_code),
|
||||
!__entry->has_error ? "" : ")",
|
||||
__entry->reinjected ? " [reinjected]" : "")
|
||||
);
|
||||
|
||||
@@ -582,6 +582,9 @@ static int nested_vmx_check_msr_bitmap_controls(struct kvm_vcpu *vcpu,
|
||||
static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu,
|
||||
struct vmcs12 *vmcs12)
|
||||
{
|
||||
gpa_t vtpr_gpa = vmcs12->virtual_apic_page_addr + APIC_TASKPRI;
|
||||
u32 vtpr;
|
||||
|
||||
if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
|
||||
return 0;
|
||||
|
||||
@@ -591,6 +594,32 @@ static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu,
|
||||
if (CC(!nested_cpu_has_vid(vmcs12) && vmcs12->tpr_threshold >> 4))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Do the illegal vTPR vs. TPR Threshold consistency check if and only
|
||||
* if KVM is configured to WARN on missed consistency checks, otherwise
|
||||
* it's a waste of time. KVM needs to rely on hardware to fully detect
|
||||
* an illegal combination due to the vTPR being writable by L1 at all
|
||||
* times (it's an in-memory value, not a VMCS field). I.e. even if the
|
||||
* check passes now, it might fail at the actual VM-Enter.
|
||||
*
|
||||
* If reading guest memory fails, skip the check as KVM's de facto ABI
|
||||
* for VMX instruction accesses to non-existent memory is to provide
|
||||
* PCI Bus Error semantics (reads return 0xFFs), in which case the vTPR
|
||||
* is guaranteed to greater than or equal to the threshold.
|
||||
*
|
||||
* Note! Deliberately use the VM-scoped API when reading guest memory,
|
||||
* to ensure the read doesn't hit SMRAM when restoring L2 state on RSM,
|
||||
* and only perform the check when in KVM_RUN, to avoid a false failure
|
||||
* if userspace hasn't yet configured memslots during state restore.
|
||||
*/
|
||||
if (warn_on_missed_cc && vcpu->wants_to_run &&
|
||||
nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW) &&
|
||||
!nested_cpu_has_vid(vmcs12) &&
|
||||
!nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
|
||||
!kvm_read_guest(vcpu->kvm, vtpr_gpa, &vtpr, sizeof(vtpr)) &&
|
||||
CC((vmcs12->tpr_threshold & GENMASK(3, 0)) > ((vtpr >> 4) & GENMASK(3, 0))))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3104,38 +3133,6 @@ static int nested_vmx_check_controls(struct kvm_vcpu *vcpu,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nested_vmx_check_controls_late(struct kvm_vcpu *vcpu,
|
||||
struct vmcs12 *vmcs12)
|
||||
{
|
||||
void *vapic = to_vmx(vcpu)->nested.virtual_apic_map.hva;
|
||||
u32 vtpr = vapic ? (*(u32 *)(vapic + APIC_TASKPRI)) >> 4 : 0;
|
||||
|
||||
/*
|
||||
* Don't bother with the consistency checks if KVM isn't configured to
|
||||
* WARN on missed consistency checks, as KVM needs to rely on hardware
|
||||
* to fully detect an illegal vTPR vs. TRP Threshold combination due to
|
||||
* the vTPR being writable by L1 at all times (it's an in-memory value,
|
||||
* not a VMCS field). I.e. even if the check passes now, it might fail
|
||||
* at the actual VM-Enter.
|
||||
*
|
||||
* Keying off the module param also allows treating an invalid vAPIC
|
||||
* mapping as a consistency check failure without increasing the risk
|
||||
* of breaking a "real" VM.
|
||||
*/
|
||||
if (!warn_on_missed_cc)
|
||||
return 0;
|
||||
|
||||
if ((exec_controls_get(to_vmx(vcpu)) & CPU_BASED_TPR_SHADOW) &&
|
||||
nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW) &&
|
||||
!nested_cpu_has_vid(vmcs12) &&
|
||||
!nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
|
||||
(CC(!vapic) ||
|
||||
CC((vmcs12->tpr_threshold & GENMASK(3, 0)) > (vtpr & GENMASK(3, 0)))))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu,
|
||||
struct vmcs12 *vmcs12)
|
||||
{
|
||||
@@ -3661,19 +3658,14 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
|
||||
&vmx->nested.pre_vmenter_ssp_tbl);
|
||||
|
||||
/*
|
||||
* Overwrite vmcs01.GUEST_CR3 with L1's CR3 if EPT is disabled. In the
|
||||
* event of a "late" VM-Fail, i.e. a VM-Fail detected by hardware but
|
||||
* not KVM, KVM must unwind its software model to the pre-VM-Entry host
|
||||
* state. When EPT is disabled, GUEST_CR3 holds KVM's shadow CR3, not
|
||||
* L1's "real" CR3, which causes nested_vmx_restore_host_state() to
|
||||
* corrupt vcpu->arch.cr3. Stuffing vmcs01.GUEST_CR3 results in the
|
||||
* unwind naturally setting arch.cr3 to the correct value. Smashing
|
||||
* vmcs01.GUEST_CR3 is safe because nested VM-Exits, and the unwind,
|
||||
* reset KVM's MMU, i.e. vmcs01.GUEST_CR3 is guaranteed to be
|
||||
* overwritten with a shadow CR3 prior to re-entering L1.
|
||||
* Stash L1's CR3, so that in the event of a "late" VM-Fail, i.e. a
|
||||
* VM-Fail detected by hardware but not KVM, KVM can unwind its
|
||||
* software model to the pre-VM-Entry host state. When EPT is
|
||||
* disabled, GUEST_CR3 holds KVM's shadow CR3, not L1's "real" CR3,
|
||||
* and so simply restoring from vmcs01.GUEST_CR3 would corrupt
|
||||
* vcpu->arch.cr3.
|
||||
*/
|
||||
if (!enable_ept)
|
||||
vmcs_writel(GUEST_CR3, vcpu->arch.cr3);
|
||||
vmx->nested.pre_vmenter_cr3 = kvm_read_cr3(vcpu);
|
||||
|
||||
vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
|
||||
|
||||
@@ -3685,11 +3677,6 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
|
||||
return NVMX_VMENTRY_KVM_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (nested_vmx_check_controls_late(vcpu, vmcs12)) {
|
||||
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
|
||||
return NVMX_VMENTRY_VMFAIL;
|
||||
}
|
||||
|
||||
if (nested_vmx_check_guest_state(vcpu, vmcs12,
|
||||
&entry_failure_code)) {
|
||||
exit_reason.basic = EXIT_REASON_INVALID_STATE;
|
||||
@@ -3774,6 +3761,8 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
|
||||
if (!from_vmentry)
|
||||
return NVMX_VMENTRY_VMEXIT;
|
||||
|
||||
nested_put_vmcs12_pages(vcpu);
|
||||
|
||||
load_vmcs12_host_state(vcpu, vmcs12);
|
||||
vmcs12->vm_exit_reason = exit_reason.full;
|
||||
if (enable_shadow_vmcs || nested_vmx_is_evmptr12_valid(vmx))
|
||||
@@ -4990,7 +4979,7 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
|
||||
vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW));
|
||||
|
||||
nested_ept_uninit_mmu_context(vcpu);
|
||||
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
|
||||
vcpu->arch.cr3 = vmx->nested.pre_vmenter_cr3;
|
||||
kvm_register_mark_available(vcpu, VCPU_REG_CR3);
|
||||
|
||||
/*
|
||||
|
||||
@@ -2797,7 +2797,11 @@ static int tdx_td_init(struct kvm *kvm, struct kvm_tdx_cmd *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (init_vm->cpuid.padding) {
|
||||
/*
|
||||
* Reject the request if userspace changes cpuid.nent between the
|
||||
* initial read and the subsequent copy.
|
||||
*/
|
||||
if (init_vm->cpuid.padding || init_vm->cpuid.nent != nr_user_entries) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,13 @@ struct nested_vmx {
|
||||
bool has_preemption_timer_deadline;
|
||||
bool preemption_timer_expired;
|
||||
|
||||
/*
|
||||
* Used to restore L1's CR3 if hardware detects a VM-Fail Consistency
|
||||
* Check that KVM does not, in which case KVM needs to unwind CR3 back
|
||||
* to its pre-VM-Enter state, NOT to vmcs01.HOST_CR3.
|
||||
*/
|
||||
unsigned long pre_vmenter_cr3;
|
||||
|
||||
/*
|
||||
* Used to snapshot MSRs that are conditionally loaded on VM-Enter in
|
||||
* order to propagate the guest's pre-VM-Enter value into vmcs02. For
|
||||
|
||||
@@ -43,21 +43,26 @@ bool video_is_primary_device(struct device *dev)
|
||||
if (!pci_is_display(pdev))
|
||||
return false;
|
||||
|
||||
if (pdev == vga_default_device())
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_SCREEN_INFO
|
||||
numres = screen_info_resources(si, res, ARRAY_SIZE(res));
|
||||
for (i = 0; i < numres; ++i) {
|
||||
if (!(res[i].flags & IORESOURCE_MEM))
|
||||
continue;
|
||||
if (numres > 0) {
|
||||
for (i = 0; i < numres; ++i) {
|
||||
if (!(res[i].flags & IORESOURCE_MEM))
|
||||
continue;
|
||||
|
||||
if (pci_find_resource(pdev, &res[i]))
|
||||
return true;
|
||||
if (pci_find_resource(pdev, &res[i]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
/*
|
||||
* No framebuffer was set up by the firmware/bootloader, so fall back
|
||||
* to the default VGA device.
|
||||
*/
|
||||
return pdev == vga_default_device();
|
||||
}
|
||||
EXPORT_SYMBOL(video_is_primary_device);
|
||||
|
||||
|
||||
@@ -536,6 +536,8 @@ int snp_prepare(void)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
wbinvd_on_all_cpus();
|
||||
|
||||
/*
|
||||
* MtrrFixDramModEn is not shared between threads on a core,
|
||||
* therefore it must be set on all CPUs prior to enabling SNP.
|
||||
|
||||
@@ -5218,6 +5218,7 @@ static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
||||
struct io_comp_batch *iob, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
unsigned long timeout = jiffies + 2;
|
||||
|
||||
do {
|
||||
ret = q->mq_ops->poll(hctx, iob);
|
||||
@@ -5228,7 +5229,7 @@ static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
||||
if (ret < 0 || (flags & BLK_POLL_ONESHOT))
|
||||
break;
|
||||
cpu_relax();
|
||||
} while (!need_resched());
|
||||
} while (!need_resched() && time_before(jiffies, timeout));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -813,6 +813,21 @@ static void wbt_queue_depth_changed(struct rq_qos *rqos)
|
||||
wbt_update_limits(RQWB(rqos));
|
||||
}
|
||||
|
||||
static bool wbt_set_lat_changed(struct request_queue *q, u64 val)
|
||||
{
|
||||
struct rq_qos *rqos = wbt_rq_qos(q);
|
||||
struct rq_wb *rwb;
|
||||
|
||||
if (!rqos)
|
||||
return true;
|
||||
|
||||
rwb = RQWB(rqos);
|
||||
if (rwb->min_lat_nsec != val)
|
||||
return true;
|
||||
|
||||
return rwb_enabled(rwb) != !!val;
|
||||
}
|
||||
|
||||
static void wbt_exit(struct rq_qos *rqos)
|
||||
{
|
||||
struct rq_wb *rwb = RQWB(rqos);
|
||||
@@ -1005,8 +1020,12 @@ int wbt_set_lat(struct gendisk *disk, s64 val)
|
||||
else if (val >= 0)
|
||||
val *= 1000ULL;
|
||||
|
||||
if (wbt_get_min_lat(q) == val)
|
||||
mutex_lock(&disk->rqos_state_mutex);
|
||||
if (!wbt_set_lat_changed(q, val)) {
|
||||
mutex_unlock(&disk->rqos_state_mutex);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&disk->rqos_state_mutex);
|
||||
|
||||
blk_mq_quiesce_queue(q);
|
||||
|
||||
|
||||
@@ -1923,11 +1923,20 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
|
||||
if (!disk->zone_wplugs_pool)
|
||||
goto free_hash;
|
||||
|
||||
disk->zone_wplugs_wq =
|
||||
alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU,
|
||||
pool_size, disk->disk_name);
|
||||
if (!disk->zone_wplugs_wq)
|
||||
goto destroy_pool;
|
||||
/*
|
||||
* We may already have a zone write plug workqueue as this function may
|
||||
* be called after disk_free_zone_resources(), which does not destroy
|
||||
* the workqueue (the zone write plugs workqueue is destroyed at
|
||||
* disk_release() time).
|
||||
*/
|
||||
if (!disk->zone_wplugs_wq) {
|
||||
disk->zone_wplugs_wq =
|
||||
alloc_workqueue("%s_zwplugs",
|
||||
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU,
|
||||
pool_size, disk->disk_name);
|
||||
if (!disk->zone_wplugs_wq)
|
||||
goto destroy_pool;
|
||||
}
|
||||
|
||||
disk->zone_wplugs_worker =
|
||||
kthread_create(disk_zone_wplugs_worker, disk,
|
||||
@@ -1935,15 +1944,12 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
|
||||
if (IS_ERR(disk->zone_wplugs_worker)) {
|
||||
ret = PTR_ERR(disk->zone_wplugs_worker);
|
||||
disk->zone_wplugs_worker = NULL;
|
||||
goto destroy_wq;
|
||||
goto destroy_pool;
|
||||
}
|
||||
wake_up_process(disk->zone_wplugs_worker);
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_wq:
|
||||
destroy_workqueue(disk->zone_wplugs_wq);
|
||||
disk->zone_wplugs_wq = NULL;
|
||||
destroy_pool:
|
||||
mempool_destroy(disk->zone_wplugs_pool);
|
||||
disk->zone_wplugs_pool = NULL;
|
||||
@@ -1999,7 +2005,7 @@ static void disk_set_zones_cond_array(struct gendisk *disk, u8 *zones_cond)
|
||||
kfree_rcu_mightsleep(zones_cond);
|
||||
}
|
||||
|
||||
void disk_free_zone_resources(struct gendisk *disk)
|
||||
static void disk_free_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
if (disk->zone_wplugs_worker) {
|
||||
kthread_stop(disk->zone_wplugs_worker);
|
||||
@@ -2007,10 +2013,8 @@ void disk_free_zone_resources(struct gendisk *disk)
|
||||
}
|
||||
WARN_ON_ONCE(!list_empty(&disk->zone_wplugs_list));
|
||||
|
||||
if (disk->zone_wplugs_wq) {
|
||||
destroy_workqueue(disk->zone_wplugs_wq);
|
||||
disk->zone_wplugs_wq = NULL;
|
||||
}
|
||||
if (disk->zone_wplugs_wq)
|
||||
drain_workqueue(disk->zone_wplugs_wq);
|
||||
|
||||
disk_destroy_zone_wplugs_hash_table(disk);
|
||||
|
||||
@@ -2020,6 +2024,16 @@ void disk_free_zone_resources(struct gendisk *disk)
|
||||
disk->nr_zones = 0;
|
||||
}
|
||||
|
||||
void disk_release_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
if (disk->zone_wplugs_wq) {
|
||||
destroy_workqueue(disk->zone_wplugs_wq);
|
||||
disk->zone_wplugs_wq = NULL;
|
||||
}
|
||||
|
||||
disk_free_zone_resources(disk);
|
||||
}
|
||||
|
||||
struct blk_revalidate_zone_args {
|
||||
struct gendisk *disk;
|
||||
u8 *zones_cond;
|
||||
|
||||
@@ -528,7 +528,7 @@ static inline void ioc_clear_queue(struct request_queue *q)
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
void disk_init_zone_resources(struct gendisk *disk);
|
||||
void disk_free_zone_resources(struct gendisk *disk);
|
||||
void disk_release_zone_resources(struct gendisk *disk);
|
||||
static inline bool bio_zone_write_plugging(struct bio *bio)
|
||||
{
|
||||
return bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING);
|
||||
@@ -581,7 +581,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
|
||||
static inline void disk_init_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
static inline void disk_free_zone_resources(struct gendisk *disk)
|
||||
static inline void disk_release_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
static inline bool bio_zone_write_plugging(struct bio *bio)
|
||||
|
||||
@@ -407,10 +407,6 @@ static void add_disk_final(struct gendisk *disk)
|
||||
struct device *ddev = disk_to_dev(disk);
|
||||
|
||||
if (!(disk->flags & GENHD_FL_HIDDEN)) {
|
||||
/* Make sure the first partition scan will be proceed */
|
||||
if (get_capacity(disk) && disk_has_partscan(disk))
|
||||
set_bit(GD_NEED_PART_SCAN, &disk->state);
|
||||
|
||||
bdev_add(disk->part0, ddev->devt);
|
||||
if (get_capacity(disk))
|
||||
disk_scan_partitions(disk, BLK_OPEN_READ);
|
||||
@@ -1300,7 +1296,7 @@ static void disk_release(struct device *dev)
|
||||
|
||||
disk_release_events(disk);
|
||||
kfree(disk->random);
|
||||
disk_free_zone_resources(disk);
|
||||
disk_release_zone_resources(disk);
|
||||
xa_destroy(&disk->part_tbl);
|
||||
|
||||
kobject_put(&disk->queue_kobj);
|
||||
|
||||
@@ -875,7 +875,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
||||
if (!hwctx->cus)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret)
|
||||
goto free_cus;
|
||||
|
||||
@@ -900,13 +900,16 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
||||
static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq)
|
||||
{
|
||||
struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq);
|
||||
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
||||
|
||||
if (!out_fence) {
|
||||
XDNA_ERR(hwctx->client->xdna, "Failed to get fence");
|
||||
XDNA_ERR(xdna, "Failed to get fence");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
dma_fence_put(out_fence);
|
||||
}
|
||||
|
||||
@@ -1039,7 +1042,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
|
||||
found = false;
|
||||
down_write(&xdna->notifier_lock);
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (mapp->invalid) {
|
||||
if (mapp->invalid && kref_get_unless_zero(&mapp->refcnt)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -1050,11 +1053,9 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
|
||||
up_write(&xdna->notifier_lock);
|
||||
return 0;
|
||||
}
|
||||
kref_get(&mapp->refcnt);
|
||||
|
||||
up_write(&xdna->notifier_lock);
|
||||
|
||||
XDNA_DBG(xdna, "populate memory range %lx %lx",
|
||||
mapp->vma->vm_start, mapp->vma->vm_end);
|
||||
mm = mapp->notifier.mm;
|
||||
if (!mmget_not_zero(mm)) {
|
||||
amdxdna_umap_put(mapp);
|
||||
@@ -1221,10 +1222,6 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
|
||||
u64 addr;
|
||||
int ret;
|
||||
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
addr = amdxdna_obj_dma_addr(heap);
|
||||
ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
|
||||
addr, heap->mem.size);
|
||||
@@ -1233,7 +1230,5 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
|
||||
hwctx->name, heap->mem.size, ret);
|
||||
}
|
||||
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -840,7 +840,7 @@ static struct aie2_exec_msg_ops npu_exec_message_ops = {
|
||||
static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
|
||||
size_t *size, u32 *msg_op)
|
||||
{
|
||||
struct amdxdna_dev *xdna = cmd_abo->client->xdna;
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
|
||||
int ret;
|
||||
u32 op;
|
||||
|
||||
@@ -874,7 +874,7 @@ static int
|
||||
aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
|
||||
size_t *size, u32 *cmd_op)
|
||||
{
|
||||
struct amdxdna_dev *xdna = cmd_abo->client->xdna;
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
|
||||
int ret;
|
||||
u32 op;
|
||||
|
||||
|
||||
@@ -310,6 +310,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
|
||||
if (!drm_dev_enter(dev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&xdna->client_lock);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
hwctx = xa_erase(&client->hwctx_xa, args->handle);
|
||||
if (!hwctx) {
|
||||
@@ -328,6 +329,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
|
||||
XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
|
||||
out:
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
mutex_unlock(&xdna->client_lock);
|
||||
drm_dev_exit(idx);
|
||||
return ret;
|
||||
}
|
||||
@@ -382,16 +384,27 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Resume failed, ret %d", ret);
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
mutex_lock(&xdna->client_lock);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
hwctx = xa_load(&client->hwctx_xa, args->handle);
|
||||
if (!hwctx) {
|
||||
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
|
||||
ret = -EINVAL;
|
||||
goto free_buf;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
mutex_unlock(&xdna->client_lock);
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
free_buf:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
@@ -412,16 +425,27 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
|
||||
if (!gobj)
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Resume failed, ret %d", ret);
|
||||
goto put_obj;
|
||||
}
|
||||
|
||||
abo = to_xdna_obj(gobj);
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
mutex_lock(&xdna->client_lock);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
|
||||
if (!hwctx) {
|
||||
ret = -EINVAL;
|
||||
goto put_obj;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
mutex_unlock(&xdna->client_lock);
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
return ret;
|
||||
@@ -448,9 +472,7 @@ static int amdxdna_hwctx_expand_heap(struct amdxdna_hwctx *hwctx)
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&client->mm_lock);
|
||||
ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);
|
||||
mutex_lock(&client->mm_lock);
|
||||
if (ret) {
|
||||
amdxdna_gem_unpin(heap);
|
||||
drm_gem_object_put(to_gobj(heap));
|
||||
@@ -469,18 +491,26 @@ int amdxdna_update_heap(struct amdxdna_client *client, struct amdxdna_hwctx *hwc
|
||||
unsigned long hwctx_id;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&client->mm_lock);
|
||||
ret = amdxdna_pm_resume_get_locked(client->xdna);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hwctx)
|
||||
return amdxdna_hwctx_expand_heap(hwctx);
|
||||
mutex_lock(&client->mm_lock);
|
||||
|
||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
||||
if (hwctx) {
|
||||
ret = amdxdna_hwctx_expand_heap(hwctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
||||
ret = amdxdna_hwctx_expand_heap(hwctx);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&client->mm_lock);
|
||||
|
||||
return 0;
|
||||
amdxdna_pm_suspend_put(client->xdna);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -198,6 +198,7 @@ amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
|
||||
*/
|
||||
void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
|
||||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
|
||||
int ret;
|
||||
|
||||
@@ -210,7 +211,7 @@ void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
|
||||
if (!abo->mem.kva) {
|
||||
ret = drm_gem_vmap(to_gobj(abo), &map);
|
||||
if (ret)
|
||||
XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
|
||||
XDNA_ERR(xdna, "Vmap bo failed, ret %d", ret);
|
||||
else
|
||||
abo->mem.kva = map.vaddr;
|
||||
}
|
||||
@@ -254,7 +255,7 @@ static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
|
||||
|
||||
xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
XDNA_DBG(xdna, "Invalidating range 0x%lx, 0x%lx, type %d",
|
||||
mapp->vma->vm_start, mapp->vma->vm_end, abo->type);
|
||||
mapp->range.start, mapp->range.end, abo->type);
|
||||
|
||||
if (!mmu_notifier_range_blockable(range))
|
||||
return false;
|
||||
@@ -284,15 +285,23 @@ static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = {
|
||||
.invalidate = amdxdna_hmm_invalidate,
|
||||
};
|
||||
|
||||
static inline bool compare_range(struct amdxdna_umap *mapp,
|
||||
struct mm_struct *mm,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
return (!mapp->unmapped && mapp->notifier.mm == mm &&
|
||||
mapp->range.start == start && mapp->range.end == end);
|
||||
}
|
||||
|
||||
static void amdxdna_hmm_unregister(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_read(&xdna->notifier_lock);
|
||||
down_write(&xdna->notifier_lock);
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (!vma || mapp->vma == vma) {
|
||||
if (!vma || compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
|
||||
if (!mapp->unmapped) {
|
||||
queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
|
||||
mapp->unmapped = true;
|
||||
@@ -301,19 +310,16 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_read(&xdna->notifier_lock);
|
||||
up_write(&xdna->notifier_lock);
|
||||
}
|
||||
|
||||
static void amdxdna_umap_release(struct kref *ref)
|
||||
{
|
||||
struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
|
||||
struct amdxdna_gem_obj *abo = mapp->abo;
|
||||
struct vm_area_struct *vma = mapp->vma;
|
||||
struct amdxdna_dev *xdna;
|
||||
|
||||
mmu_interval_notifier_remove(&mapp->notifier);
|
||||
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
|
||||
mapping_clear_unevictable(vma->vm_file->f_mapping);
|
||||
|
||||
xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
|
||||
down_write(&xdna->notifier_lock);
|
||||
@@ -346,15 +352,30 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
|
||||
unsigned long len = vma->vm_end - vma->vm_start;
|
||||
unsigned long addr = vma->vm_start;
|
||||
struct amdxdna_umap *mapp;
|
||||
u32 nr_pages;
|
||||
unsigned long nr_pages;
|
||||
int ret;
|
||||
|
||||
if (!amdxdna_pasid_on(abo->client)) {
|
||||
/*
|
||||
* When PASID is off, amdxdna_gem_obj_open() called amdxdna_dma_map_bo()
|
||||
* and mem.dma_addr is valid; use the DMA address directly and skip HMM.
|
||||
* Avoid dereferencing abo->client which may be NULL (cleared in close())
|
||||
* while internal kernel references are still held.
|
||||
*/
|
||||
if (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) {
|
||||
/* Need to set uva for heap uva validation */
|
||||
abo->mem.uva = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
down_read(&xdna->notifier_lock);
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (compare_range(mapp, current->mm, addr, addr + len)) {
|
||||
up_read(&xdna->notifier_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
up_read(&xdna->notifier_lock);
|
||||
|
||||
mapp = kzalloc_obj(*mapp);
|
||||
if (!mapp)
|
||||
return -ENOMEM;
|
||||
@@ -380,13 +401,10 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
|
||||
mapp->range.start = vma->vm_start;
|
||||
mapp->range.end = vma->vm_end;
|
||||
mapp->range.default_flags = HMM_PFN_REQ_FAULT;
|
||||
mapp->vma = vma;
|
||||
mapp->abo = abo;
|
||||
kref_init(&mapp->refcnt);
|
||||
|
||||
INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
|
||||
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
|
||||
mapping_set_unevictable(vma->vm_file->f_mapping);
|
||||
|
||||
down_write(&xdna->notifier_lock);
|
||||
if (list_empty(&abo->mem.umap_list))
|
||||
@@ -527,6 +545,7 @@ static int amdxdna_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struc
|
||||
|
||||
close_vma:
|
||||
vma->vm_ops->close(vma);
|
||||
return ret;
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
return ret;
|
||||
@@ -652,8 +671,11 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi
|
||||
/* No need to set up dma addr mapping in PASID mode. */
|
||||
if (!amdxdna_pasid_on(abo->client)) {
|
||||
ret = amdxdna_dma_map_bo(xdna, abo);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
abo->open_ref--;
|
||||
abo->client = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
amdxdna_gem_add_bo_usage(abo);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "amdxdna_pci_drv.h"
|
||||
|
||||
struct amdxdna_umap {
|
||||
struct vm_area_struct *vma;
|
||||
struct mmu_interval_notifier notifier;
|
||||
struct hmm_range range;
|
||||
struct work_struct hmm_unreg_work;
|
||||
@@ -89,12 +88,19 @@ u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
|
||||
|
||||
static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
|
||||
{
|
||||
return amdxdna_gem_dev_addr(abo) - abo->client->xdna->dev_info->dev_mem_base;
|
||||
return amdxdna_gem_dev_addr(abo) - to_xdna_dev(to_gobj(abo)->dev)->dev_info->dev_mem_base;
|
||||
}
|
||||
|
||||
static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
|
||||
{
|
||||
return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;
|
||||
/*
|
||||
* amdxdna_gem_obj_open() calls amdxdna_dma_map_bo() only when PASID is
|
||||
* off, leaving mem.dma_addr at AMDXDNA_INVALID_ADDR when PASID is on.
|
||||
* Avoid dereferencing abo->client, which is cleared to NULL by
|
||||
* amdxdna_gem_obj_close() while internal kernel references remain.
|
||||
*/
|
||||
return (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) ?
|
||||
abo->mem.dma_addr : amdxdna_gem_uva(abo);
|
||||
}
|
||||
|
||||
void amdxdna_umap_put(struct amdxdna_umap *mapp);
|
||||
|
||||
@@ -109,11 +109,16 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
||||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(ddev);
|
||||
struct amdxdna_client *client;
|
||||
int ret;
|
||||
|
||||
client = kzalloc_obj(*client);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = init_srcu_struct(&client->hwctx_srcu);
|
||||
if (ret)
|
||||
goto free_client;
|
||||
|
||||
client->pid = pid_nr(rcu_access_pointer(filp->pid));
|
||||
client->xdna = xdna;
|
||||
client->pasid = IOMMU_PASID_INVALID;
|
||||
@@ -125,13 +130,12 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
||||
XDNA_WARN(xdna, "PASID not available for pid %d", client->pid);
|
||||
if (!amdxdna_use_carveout(xdna)) {
|
||||
XDNA_ERR(xdna, "PASID unavailable and carveout not configured");
|
||||
kfree(client);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto cleanup_srcu;
|
||||
}
|
||||
}
|
||||
}
|
||||
mmgrab(client->mm);
|
||||
init_srcu_struct(&client->hwctx_srcu);
|
||||
xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
|
||||
xa_init_flags(&client->dev_heap_xa, XA_FLAGS_ALLOC);
|
||||
drm_mm_init(&client->dev_heap_mm, xdna->dev_info->dev_mem_base,
|
||||
@@ -149,6 +153,12 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
||||
|
||||
XDNA_DBG(xdna, "pid %d opened", client->pid);
|
||||
return 0;
|
||||
|
||||
cleanup_srcu:
|
||||
cleanup_srcu_struct(&client->hwctx_srcu);
|
||||
free_client:
|
||||
kfree(client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void amdxdna_client_cleanup(struct amdxdna_client *client)
|
||||
@@ -373,7 +383,10 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drmm_mutex_init(ddev, &xdna->dev_lock);
|
||||
ret = drmm_mutex_init(ddev, &xdna->dev_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
init_rwsem(&xdna->notifier_lock);
|
||||
INIT_LIST_HEAD(&xdna->client_list);
|
||||
pci_set_drvdata(pdev, xdna);
|
||||
|
||||
@@ -1658,7 +1658,20 @@ static void binder_txn_latency_free(struct binder_transaction *t)
|
||||
|
||||
static void binder_free_transaction(struct binder_transaction *t)
|
||||
{
|
||||
struct binder_proc *target_proc = t->to_proc;
|
||||
struct binder_thread *target_thread;
|
||||
struct binder_proc *target_proc;
|
||||
|
||||
spin_lock(&t->lock);
|
||||
target_proc = t->to_proc;
|
||||
target_thread = t->to_thread;
|
||||
/*
|
||||
* Pin target_thread to keep target_proc alive. Undelivered
|
||||
* transactions with !target_thread are safe, as target_proc
|
||||
* can only be the current context there.
|
||||
*/
|
||||
if (target_thread)
|
||||
atomic_inc(&target_thread->tmp_ref);
|
||||
spin_unlock(&t->lock);
|
||||
|
||||
if (target_proc) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
@@ -1672,6 +1685,10 @@ static void binder_free_transaction(struct binder_transaction *t)
|
||||
t->buffer->transaction = NULL;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
}
|
||||
|
||||
if (target_thread)
|
||||
binder_thread_dec_tmpref(target_thread);
|
||||
|
||||
if (trace_binder_txn_latency_free_enabled())
|
||||
binder_txn_latency_free(t);
|
||||
/*
|
||||
@@ -3080,6 +3097,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
int t_debug_id = atomic_inc_return(&binder_last_id);
|
||||
ktime_t t_start_time = ktime_get();
|
||||
struct lsm_context lsmctx = { };
|
||||
size_t lsmctx_aligned_size = 0;
|
||||
LIST_HEAD(sgc_head);
|
||||
LIST_HEAD(pf_head);
|
||||
const void __user *user_buffer = (const void __user *)
|
||||
@@ -3346,7 +3364,6 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
|
||||
if (target_node && target_node->txn_security_ctx) {
|
||||
u32 secid;
|
||||
size_t added_size;
|
||||
|
||||
security_cred_getsecid(proc->cred, &secid);
|
||||
ret = security_secid_to_secctx(secid, &lsmctx);
|
||||
@@ -3358,9 +3375,9 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_get_secctx_failed;
|
||||
}
|
||||
added_size = ALIGN(lsmctx.len, sizeof(u64));
|
||||
extra_buffers_size += added_size;
|
||||
if (extra_buffers_size < added_size) {
|
||||
lsmctx_aligned_size = ALIGN(lsmctx.len, sizeof(u64));
|
||||
extra_buffers_size += lsmctx_aligned_size;
|
||||
if (extra_buffers_size < lsmctx_aligned_size) {
|
||||
binder_txn_error("%d:%d integer overflow of extra_buffers_size\n",
|
||||
thread->pid, proc->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
@@ -3397,7 +3414,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
|
||||
ALIGN(tr->offsets_size, sizeof(void *)) +
|
||||
ALIGN(extra_buffers_size, sizeof(void *)) -
|
||||
ALIGN(lsmctx.len, sizeof(u64));
|
||||
lsmctx_aligned_size;
|
||||
|
||||
t->security_ctx = t->buffer->user_data + buf_offset;
|
||||
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
|
||||
@@ -3452,7 +3469,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
off_end_offset = off_start_offset + tr->offsets_size;
|
||||
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
|
||||
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
|
||||
ALIGN(lsmctx.len, sizeof(u64));
|
||||
lsmctx_aligned_size;
|
||||
off_min = 0;
|
||||
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
|
||||
buffer_offset += sizeof(binder_size_t)) {
|
||||
|
||||
@@ -259,7 +259,7 @@ fn drop(&mut self) {
|
||||
|
||||
if let Some(offsets) = info.offsets.clone() {
|
||||
let view = AllocationView::new(self, offsets.start);
|
||||
for i in offsets.step_by(size_of::<usize>()) {
|
||||
for i in offsets.step_by(size_of::<u64>()) {
|
||||
if view.cleanup_object(i).is_err() {
|
||||
pr_warn!("Error cleaning up object at offset {}\n", i)
|
||||
}
|
||||
@@ -420,7 +420,8 @@ pub(crate) fn transfer_binder_object(
|
||||
}
|
||||
|
||||
fn cleanup_object(&self, index_offset: usize) -> Result {
|
||||
let offset = self.alloc.read(index_offset)?;
|
||||
let offset = self.alloc.read::<u64>(index_offset)?;
|
||||
let offset: usize = offset.try_into().map_err(|_| EINVAL)?;
|
||||
let header = self.read::<BinderObjectHeader>(offset)?;
|
||||
match header.type_ {
|
||||
BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => {
|
||||
|
||||
@@ -73,20 +73,17 @@ impl fmt::Debug for BinderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.reply {
|
||||
BR_FAILED_REPLY => match self.source.as_ref() {
|
||||
Some(source) => f
|
||||
.debug_struct("BR_FAILED_REPLY")
|
||||
.field("source", source)
|
||||
.finish(),
|
||||
Some(source) => source.fmt(f),
|
||||
None => f.pad("BR_FAILED_REPLY"),
|
||||
},
|
||||
BR_DEAD_REPLY => f.pad("BR_DEAD_REPLY"),
|
||||
BR_FROZEN_REPLY => f.pad("BR_FROZEN_REPLY"),
|
||||
BR_TRANSACTION_PENDING_FROZEN => f.pad("BR_TRANSACTION_PENDING_FROZEN"),
|
||||
BR_TRANSACTION_COMPLETE => f.pad("BR_TRANSACTION_COMPLETE"),
|
||||
_ => f
|
||||
.debug_struct("BinderError")
|
||||
.field("reply", &self.reply)
|
||||
.finish(),
|
||||
_ => match self.source.as_ref() {
|
||||
Some(source) => source.fmt(f),
|
||||
None => self.reply.fmt(f),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,10 +154,17 @@ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
impl FreezeListener {
|
||||
pub(crate) fn on_process_exit(&self, proc: &Arc<Process>) {
|
||||
/// Called when this freeze listener is cleared abnormally.
|
||||
///
|
||||
/// This occurs either because the process exited or because the process dropped its last
|
||||
/// refcount on the node ref without explicitly removing the freeze listener first.
|
||||
///
|
||||
/// The returned `KVVec` is just a value that should be dropped outside of the lock.
|
||||
pub(crate) fn on_process_cleanup(&self, proc: &Process) -> KVVec<Arc<Process>> {
|
||||
if !self.is_clearing {
|
||||
self.node.remove_freeze_listener(proc);
|
||||
return self.node.remove_freeze_listener(proc);
|
||||
}
|
||||
KVVec::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -682,12 +682,13 @@ pub(crate) fn add_freeze_listener(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
|
||||
let _unused_capacity;
|
||||
pub(crate) fn remove_freeze_listener(&self, p: &Process) -> KVVec<Arc<Process>> {
|
||||
let mut guard = self.owner.inner.lock();
|
||||
let inner = self.inner.access_mut(&mut guard);
|
||||
let len = inner.freeze_list.len();
|
||||
inner.freeze_list.retain(|proc| !Arc::ptr_eq(proc, p));
|
||||
inner
|
||||
.freeze_list
|
||||
.retain(|proc| !core::ptr::eq::<Process>(&**proc, p));
|
||||
if len == inner.freeze_list.len() {
|
||||
pr_warn!(
|
||||
"Could not remove freeze listener for {}\n",
|
||||
@@ -695,8 +696,9 @@ pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
|
||||
);
|
||||
}
|
||||
if inner.freeze_list.is_empty() {
|
||||
_unused_capacity = mem::take(&mut inner.freeze_list);
|
||||
return mem::take(&mut inner.freeze_list);
|
||||
}
|
||||
KVVec::new()
|
||||
}
|
||||
|
||||
pub(crate) fn freeze_list<'a>(&'a self, guard: &'a ProcessInner) -> &'a [Arc<Process>] {
|
||||
|
||||
@@ -900,7 +900,11 @@ pub(crate) fn insert_or_update_handle(
|
||||
pub(crate) fn get_transaction_node(&self, handle: u32) -> BinderResult<NodeRef> {
|
||||
// When handle is zero, try to get the context manager.
|
||||
if handle == 0 {
|
||||
Ok(self.ctx.get_manager_node(true)?)
|
||||
let node_ref = self.ctx.get_manager_node(true)?;
|
||||
if core::ptr::eq(self, &*node_ref.node.owner) {
|
||||
return Err(EINVAL.into());
|
||||
}
|
||||
Ok(node_ref)
|
||||
} else {
|
||||
Ok(self.get_node_from_handle(handle, true)?)
|
||||
}
|
||||
@@ -942,6 +946,8 @@ pub(crate) fn update_ref(
|
||||
|
||||
// To preserve original binder behaviour, we only fail requests where the manager tries to
|
||||
// increment references on itself.
|
||||
let _to_free_freeze_listener;
|
||||
let _to_free_freeze_listener_cleanup;
|
||||
let mut refs = self.node_refs.lock();
|
||||
if let Some(info) = refs.by_handle.get_mut(&handle) {
|
||||
if info.node_ref().update(inc, strong) {
|
||||
@@ -957,6 +963,14 @@ pub(crate) fn update_ref(
|
||||
unsafe { info.node_ref2().node.remove_node_info(info) };
|
||||
|
||||
let id = info.node_ref().node.global_id();
|
||||
|
||||
if let Some(freeze) = *info.freeze() {
|
||||
if let Some(fl) = refs.freeze_listeners.remove(&freeze) {
|
||||
_to_free_freeze_listener_cleanup = fl.on_process_cleanup(&self);
|
||||
_to_free_freeze_listener = fl;
|
||||
}
|
||||
}
|
||||
|
||||
refs.by_handle.remove(&handle);
|
||||
refs.by_node.remove(&id);
|
||||
refs.handle_is_present.release_id(handle as usize);
|
||||
@@ -1380,7 +1394,7 @@ fn deferred_release(self: Arc<Self>) {
|
||||
// Clean up freeze listeners.
|
||||
let freeze_listeners = take(&mut self.node_refs.lock().freeze_listeners);
|
||||
for listener in freeze_listeners.values() {
|
||||
listener.on_process_exit(&self);
|
||||
listener.on_process_cleanup(&self);
|
||||
}
|
||||
drop(freeze_listeners);
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ const char * const binder_command_strings[] = {
|
||||
"BC_DEAD_BINDER_DONE",
|
||||
"BC_TRANSACTION_SG",
|
||||
"BC_REPLY_SG",
|
||||
"BC_REQUEST_FREEZE_NOTIFICATION",
|
||||
"BC_CLEAR_FREEZE_NOTIFICATION",
|
||||
"BC_FREEZE_NOTIFICATION_DONE",
|
||||
};
|
||||
|
||||
const char * const binder_return_strings[] = {
|
||||
@@ -51,7 +54,9 @@ const char * const binder_return_strings[] = {
|
||||
"BR_FAILED_REPLY",
|
||||
"BR_FROZEN_REPLY",
|
||||
"BR_ONEWAY_SPAM_SUSPECT",
|
||||
"BR_TRANSACTION_PENDING_FROZEN"
|
||||
"BR_TRANSACTION_PENDING_FROZEN",
|
||||
"BR_FROZEN_BINDER",
|
||||
"BR_CLEAR_FREEZE_NOTIFICATION_DONE",
|
||||
};
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
use kernel::sync::atomic::{ordering::Relaxed, Atomic};
|
||||
use kernel::{ioctl::_IOC_NR, seq_file::SeqFile, seq_print};
|
||||
|
||||
const BC_COUNT: usize = _IOC_NR(BC_REPLY_SG) as usize + 1;
|
||||
const BR_COUNT: usize = _IOC_NR(BR_TRANSACTION_PENDING_FROZEN) as usize + 1;
|
||||
const BC_COUNT: usize = _IOC_NR(BC_FREEZE_NOTIFICATION_DONE) as usize + 1;
|
||||
const BR_COUNT: usize = _IOC_NR(BR_CLEAR_FREEZE_NOTIFICATION_DONE) as usize + 1;
|
||||
|
||||
pub(crate) static GLOBAL_STATS: BinderStats = BinderStats::new();
|
||||
|
||||
|
||||
@@ -495,9 +495,16 @@ pub(crate) fn debug_print(self: &Arc<Self>, m: &SeqFile, print_all: bool) -> Res
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn clear_extended_error(&self, debug_id: usize) {
|
||||
self.inner.lock().extended_error = ExtendedError::new(debug_id as u32, BR_OK, 0);
|
||||
}
|
||||
|
||||
pub(crate) fn get_extended_error(&self, data: UserSlice) -> Result {
|
||||
let mut writer = data.writer();
|
||||
let ee = self.inner.lock().extended_error;
|
||||
let mut inner = self.inner.lock();
|
||||
let ee = inner.extended_error;
|
||||
inner.extended_error = ExtendedError::new(0, BR_OK, 0);
|
||||
drop(inner);
|
||||
writer.write(&ee)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1109,7 +1116,10 @@ fn unwind_transaction_stack(self: &Arc<Self>) {
|
||||
inner.pop_transaction_to_reply(thread.as_ref())
|
||||
} {
|
||||
let reply = Err(BR_DEAD_REPLY);
|
||||
if !transaction.from.deliver_single_reply(reply, &transaction) {
|
||||
if !transaction
|
||||
.from
|
||||
.deliver_single_reply(reply, &transaction, None)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1121,8 +1131,9 @@ pub(crate) fn deliver_reply(
|
||||
&self,
|
||||
reply: Result<DLArc<Transaction>, u32>,
|
||||
transaction: &DArc<Transaction>,
|
||||
extended_error: Option<ExtendedError>,
|
||||
) {
|
||||
if self.deliver_single_reply(reply, transaction) {
|
||||
if self.deliver_single_reply(reply, transaction, extended_error) {
|
||||
transaction.from.unwind_transaction_stack();
|
||||
}
|
||||
}
|
||||
@@ -1136,6 +1147,7 @@ fn deliver_single_reply(
|
||||
&self,
|
||||
reply: Result<DLArc<Transaction>, u32>,
|
||||
transaction: &DArc<Transaction>,
|
||||
extended_error: Option<ExtendedError>,
|
||||
) -> bool {
|
||||
if let Ok(transaction) = &reply {
|
||||
crate::trace::trace_transaction(true, transaction, Some(&self.task));
|
||||
@@ -1152,6 +1164,12 @@ fn deliver_single_reply(
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(ee) = extended_error {
|
||||
if inner.extended_error.command == BR_OK {
|
||||
inner.extended_error = ee;
|
||||
}
|
||||
}
|
||||
|
||||
match reply {
|
||||
Ok(work) => {
|
||||
inner.push_work(work);
|
||||
@@ -1222,6 +1240,9 @@ fn read_transaction_info(
|
||||
info.buffers_size = td.buffers_size as usize;
|
||||
// SAFETY: Above `read` call initializes all bytes, so this union read is ok.
|
||||
info.target_handle = unsafe { td.transaction_data.target.handle };
|
||||
|
||||
info.debug_id = super::next_debug_id();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1230,6 +1251,8 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
|
||||
let mut info = TransactionInfo::zeroed();
|
||||
self.read_transaction_info(cmd, reader, &mut info)?;
|
||||
|
||||
self.clear_extended_error(info.debug_id);
|
||||
|
||||
let ret = if info.is_reply {
|
||||
self.reply_inner(&mut info)
|
||||
} else if info.is_oneway() {
|
||||
@@ -1239,23 +1262,21 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
|
||||
};
|
||||
|
||||
if let Err(err) = ret {
|
||||
self.push_return_work(err.reply);
|
||||
if err.reply != BR_TRANSACTION_COMPLETE {
|
||||
info.reply = err.reply;
|
||||
}
|
||||
if let Some(source) = &err.source {
|
||||
info.errno = source.to_errno();
|
||||
|
||||
self.push_return_work(err.reply);
|
||||
if let Some(source) = &err.source {
|
||||
info.errno = source.to_errno();
|
||||
info.reply = err.reply;
|
||||
|
||||
{
|
||||
let mut ee = self.inner.lock().extended_error;
|
||||
ee.command = err.reply;
|
||||
ee.param = source.to_errno();
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
inner.extended_error =
|
||||
ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
|
||||
}
|
||||
}
|
||||
|
||||
pr_warn!(
|
||||
"{}:{} transaction to {} failed: {source:?}",
|
||||
"{}:{} transaction to {} failed: {err:?}",
|
||||
info.from_pid,
|
||||
info.from_tid,
|
||||
info.to_pid
|
||||
@@ -1320,18 +1341,24 @@ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
|
||||
let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
|
||||
let reply = Transaction::new_reply(self, process, info, allow_fds)?;
|
||||
self.inner.lock().push_work(completion);
|
||||
orig.from.deliver_reply(Ok(reply), &orig);
|
||||
orig.from.deliver_reply(Ok(reply), &orig, None);
|
||||
Ok(())
|
||||
})()
|
||||
.map_err(|mut err| {
|
||||
// At this point we only return `BR_TRANSACTION_COMPLETE` to the caller, and we must let
|
||||
// the sender know that the transaction has completed (with an error in this case).
|
||||
|
||||
pr_warn!(
|
||||
"Failure {:?} during reply - delivering BR_FAILED_REPLY to sender.",
|
||||
err
|
||||
"{}:{} reply to {} failed: {err:?}",
|
||||
info.from_pid,
|
||||
info.from_tid,
|
||||
info.to_pid
|
||||
);
|
||||
let reply = Err(BR_FAILED_REPLY);
|
||||
orig.from.deliver_reply(reply, &orig);
|
||||
|
||||
let param = err.source.as_ref().map_or(0, |e| e.to_errno());
|
||||
let ee = ExtendedError::new(info.debug_id as u32, err.reply, param);
|
||||
orig.from
|
||||
.deliver_reply(Err(BR_FAILED_REPLY), &orig, Some(ee));
|
||||
err.reply = BR_TRANSACTION_COMPLETE;
|
||||
err
|
||||
});
|
||||
|
||||
@@ -42,6 +42,7 @@ pub(crate) struct TransactionInfo {
|
||||
pub(crate) reply: u32,
|
||||
pub(crate) oneway_spam_suspect: bool,
|
||||
pub(crate) is_reply: bool,
|
||||
pub(crate) debug_id: usize,
|
||||
}
|
||||
|
||||
impl TransactionInfo {
|
||||
@@ -93,7 +94,6 @@ pub(crate) fn new(
|
||||
from: &Arc<Thread>,
|
||||
info: &mut TransactionInfo,
|
||||
) -> BinderResult<DLArc<Self>> {
|
||||
let debug_id = super::next_debug_id();
|
||||
let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
|
||||
let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
|
||||
let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
|
||||
@@ -101,7 +101,7 @@ pub(crate) fn new(
|
||||
let mut alloc = match from.copy_transaction_data(
|
||||
to.clone(),
|
||||
info,
|
||||
debug_id,
|
||||
info.debug_id,
|
||||
allow_fds,
|
||||
txn_security_ctx_off.as_mut(),
|
||||
) {
|
||||
@@ -128,7 +128,7 @@ pub(crate) fn new(
|
||||
let data_address = alloc.ptr;
|
||||
|
||||
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
|
||||
debug_id,
|
||||
debug_id: info.debug_id,
|
||||
target_node: Some(target_node),
|
||||
from_parent,
|
||||
sender_euid: Kuid::current_euid(),
|
||||
@@ -152,9 +152,8 @@ pub(crate) fn new_reply(
|
||||
info: &mut TransactionInfo,
|
||||
allow_fds: bool,
|
||||
) -> BinderResult<DLArc<Self>> {
|
||||
let debug_id = super::next_debug_id();
|
||||
let mut alloc =
|
||||
match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) {
|
||||
match from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None) {
|
||||
Ok(alloc) => alloc,
|
||||
Err(err) => {
|
||||
pr_warn!("Failure in copy_transaction_data: {:?}", err);
|
||||
@@ -165,7 +164,7 @@ pub(crate) fn new_reply(
|
||||
alloc.set_info_clear_on_drop();
|
||||
}
|
||||
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
|
||||
debug_id,
|
||||
debug_id: info.debug_id,
|
||||
target_node: None,
|
||||
from_parent: None,
|
||||
sender_euid: Kuid::current_euid(),
|
||||
@@ -394,7 +393,7 @@ fn do_work(
|
||||
let send_failed_reply = ScopeGuard::new(|| {
|
||||
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
|
||||
let reply = Err(BR_FAILED_REPLY);
|
||||
self.from.deliver_reply(reply, &self);
|
||||
self.from.deliver_reply(reply, &self, None);
|
||||
}
|
||||
self.drop_outstanding_txn();
|
||||
});
|
||||
@@ -478,7 +477,7 @@ fn cancel(self: DArc<Self>) {
|
||||
// If this is not a reply or oneway transaction, then send a dead reply.
|
||||
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
|
||||
let reply = Err(BR_DEAD_REPLY);
|
||||
self.from.deliver_reply(reply, &self);
|
||||
self.from.deliver_reply(reply, &self, None);
|
||||
}
|
||||
|
||||
self.drop_outstanding_txn();
|
||||
|
||||
@@ -1338,7 +1338,7 @@ static int ata_hpa_resize(struct ata_device *dev)
|
||||
/* do we need to do it? */
|
||||
if ((dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC) ||
|
||||
!ata_id_has_lba(dev->id) || !ata_id_hpa_enabled(dev->id) ||
|
||||
(dev->quirks & ATA_QUIRK_BROKEN_HPA))
|
||||
(dev->quirks & ATA_QUIRK_BROKEN_HPA) || ata_id_is_locked(dev->id))
|
||||
return 0;
|
||||
|
||||
/* read native max address */
|
||||
@@ -3992,7 +3992,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
|
||||
|
||||
/* verify n_sectors hasn't changed */
|
||||
if (dev->class != ATA_DEV_ATA || !n_sectors ||
|
||||
dev->n_sectors == n_sectors)
|
||||
dev->n_sectors == n_sectors || ata_id_is_locked(dev->id))
|
||||
return 0;
|
||||
|
||||
/* n_sectors has changed */
|
||||
|
||||
@@ -1810,6 +1810,11 @@ static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_req
|
||||
data_size -= digest_size;
|
||||
}
|
||||
|
||||
if (data_size < 0) {
|
||||
drbd_err(peer_device, "Invalid data reply size\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* optimistically update recv_cnt. if receiving fails below,
|
||||
* we disconnect anyways, and counters will be reset. */
|
||||
peer_device->device->recv_cnt += data_size>>9;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user