mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
ALSA: hda: Add AW88399 HDA side codec driver for Lenovo Legion
Marco Giunta <marco_giunta@outlook.it> says:
Several Lenovo Legion laptops (Pro 7i 16IAX10H, Y9000P IAX10,
Pro 7 16AFR10H, R9000P ADR10) use AWINIC AW88399 smart amplifiers
to drive their bass woofers, connected via I2C as side codecs
to a Realtek ALC287 HDA codec.
Without a driver for these amplifiers, only the tweeters produce
sound, resulting in quiet and tinny audio.
An ASoC driver for the AW88399 already exists in-tree
(sound/soc/codecs/aw88399.c), contributed by AWINIC, but it targets
ASoC topologies and cannot drive the chip when it sits behind an
HDA controller. This series adds a proper HDA side codec driver,
following the established pattern used by the CS35L41, CS35L56,
and TAS2781 drivers.
Patch 1 extracts the device-level functions from the existing ASoC
driver into a shared library module (SND_SOC_AW88399_LIB) with a
shared header at include/sound/aw88399.h, following the CS35L41
precedent (SND_SOC_CS35L41_LIB / include/sound/cs35l41.h). This
avoids a build-time dependency on the full ASoC codec module and
ensures clean separation between the ASoC and HDA drivers.
Patches 2 through 5 prepare the shared library for use on ACPI-based
HDA systems: patch 2 extends channel assignment to work without
Device Tree properties, patch 3 adds a per-instance flag to bypass
an unreliable hardware status bit on certain boards, patch 4 adds
a firmware reload flag so that the HDA driver can signal that DSP
firmware needs to be re-uploaded after system sleep, and patch 5
adds a channel setter so that the HDA driver can configure the
amplifier without depending on ASoC-internal device headers.
NOTE ON FIRMWARE: This driver requires the firmware file
aw88399_acf.bin, which uses the same format and request path as the
existing ASoC driver. This firmware is not yet available in the
linux-firmware repository. We intend to coordinate with the AWINIC
maintainers (CC'd) to arrange its inclusion. In the meantime, users
can extract the firmware from the Windows driver and place it in
/lib/firmware/.
This work builds on the initial driver development by Yakov Till
("Lyapsus") and the bounty effort organized by Nadim Kobeissi:
https://github.com/nadimkobeissi/16iax10h-linux-sound-saga
Link: https://patch.msgid.link/DS7PR19MB77247D9AD698CF0FF37DB58BFCC62@DS7PR19MB7724.namprd19.prod.outlook.com
This commit is contained in:
commit
18a44e7045
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>
|
||||
|
|
|
|||
7
CREDITS
7
CREDITS
|
|
@ -3626,6 +3626,13 @@ S: 69 rue Dunois
|
|||
S: 75013 Paris
|
||||
S: France
|
||||
|
||||
N: Wolfram Sang
|
||||
E: wsa@kernel.org
|
||||
W: sang-engineering.com
|
||||
P: rsa4096/140DE4CC14A029B6 3991 B1EA B9E2 6751 A4F7 645D 140D E4CC 14A0 29B6
|
||||
D: I2C Maintainer 2012 - 2026
|
||||
S: Berlin, Germany
|
||||
|
||||
N: Aleksa Sarai
|
||||
E: cyphar@cyphar.com
|
||||
W: https://www.cyphar.com/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ Block ciphers
|
|||
AES
|
||||
---
|
||||
|
||||
Support for the AES block cipher.
|
||||
This API provides support for the AES block cipher.
|
||||
|
||||
.. kernel-doc:: include/crypto/aes.h
|
||||
|
||||
DES
|
||||
---
|
||||
|
||||
Support for the DES block cipher. This algorithm is obsolete and is supported
|
||||
only for backwards compatibility.
|
||||
This API provides support for the DES block cipher. This algorithm is obsolete
|
||||
and is supported only for backwards compatibility.
|
||||
|
||||
.. kernel-doc:: include/crypto/des.h
|
||||
|
|
|
|||
|
|
@ -6,81 +6,83 @@ Hash functions, MACs, and XOFs
|
|||
AES-CMAC and AES-XCBC-MAC
|
||||
-------------------------
|
||||
|
||||
Support for the AES-CMAC and AES-XCBC-MAC message authentication codes.
|
||||
This API provides support for the AES-CMAC and AES-XCBC-MAC message
|
||||
authentication codes.
|
||||
|
||||
.. kernel-doc:: include/crypto/aes-cbc-macs.h
|
||||
|
||||
BLAKE2b
|
||||
-------
|
||||
|
||||
Support for the BLAKE2b cryptographic hash function.
|
||||
This API provides support for the BLAKE2b cryptographic hash function.
|
||||
|
||||
.. kernel-doc:: include/crypto/blake2b.h
|
||||
|
||||
BLAKE2s
|
||||
-------
|
||||
|
||||
Support for the BLAKE2s cryptographic hash function.
|
||||
This API provides support for the BLAKE2s cryptographic hash function.
|
||||
|
||||
.. kernel-doc:: include/crypto/blake2s.h
|
||||
|
||||
GHASH and POLYVAL
|
||||
-----------------
|
||||
|
||||
Support for the GHASH and POLYVAL universal hash functions. These algorithms
|
||||
are used only as internal components of other algorithms.
|
||||
This API provides support for the GHASH and POLYVAL universal hash functions.
|
||||
These algorithms are used only as internal components of other algorithms.
|
||||
|
||||
.. kernel-doc:: include/crypto/gf128hash.h
|
||||
|
||||
MD5
|
||||
---
|
||||
|
||||
Support for the MD5 cryptographic hash function and HMAC-MD5. This algorithm is
|
||||
obsolete and is supported only for backwards compatibility.
|
||||
This API provides support for the MD5 cryptographic hash function and HMAC-MD5.
|
||||
This algorithm is obsolete and is supported only for backwards compatibility.
|
||||
|
||||
.. kernel-doc:: include/crypto/md5.h
|
||||
|
||||
NH
|
||||
--
|
||||
|
||||
Support for the NH universal hash function. This algorithm is used only as an
|
||||
internal component of other algorithms.
|
||||
This API provides support for the NH universal hash function. This algorithm is
|
||||
used only as an internal component of other algorithms.
|
||||
|
||||
.. kernel-doc:: include/crypto/nh.h
|
||||
|
||||
Poly1305
|
||||
--------
|
||||
|
||||
Support for the Poly1305 universal hash function. This algorithm is used only
|
||||
as an internal component of other algorithms.
|
||||
This API provides support for the Poly1305 universal hash function. This
|
||||
algorithm is used only as an internal component of other algorithms.
|
||||
|
||||
.. kernel-doc:: include/crypto/poly1305.h
|
||||
|
||||
SHA-1
|
||||
-----
|
||||
|
||||
Support for the SHA-1 cryptographic hash function and HMAC-SHA1. This algorithm
|
||||
is obsolete and is supported only for backwards compatibility.
|
||||
This API provides support for the SHA-1 cryptographic hash function and
|
||||
HMAC-SHA1. This algorithm is obsolete and is supported only for backwards
|
||||
compatibility.
|
||||
|
||||
.. kernel-doc:: include/crypto/sha1.h
|
||||
|
||||
SHA-2
|
||||
-----
|
||||
|
||||
Support for the SHA-2 family of cryptographic hash functions, including SHA-224,
|
||||
SHA-256, SHA-384, and SHA-512. This also includes their corresponding HMACs:
|
||||
HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, and HMAC-SHA512.
|
||||
This API provides support for the SHA-2 family of cryptographic hash functions,
|
||||
including SHA-224, SHA-256, SHA-384, and SHA-512. This also includes their
|
||||
corresponding HMACs: HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, and HMAC-SHA512.
|
||||
|
||||
.. kernel-doc:: include/crypto/sha2.h
|
||||
|
||||
SHA-3
|
||||
-----
|
||||
|
||||
The SHA-3 functions are documented in :ref:`sha3`.
|
||||
The SHA-3 API is documented in :ref:`sha3`.
|
||||
|
||||
SM3
|
||||
---
|
||||
|
||||
Support for the SM3 cryptographic hash function.
|
||||
This API provides support for the SM3 cryptographic hash function.
|
||||
|
||||
.. kernel-doc:: include/crypto/sm3.h
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ Digital signature algorithms
|
|||
ML-DSA
|
||||
------
|
||||
|
||||
Support for the ML-DSA digital signature algorithm.
|
||||
This API provides support for the ML-DSA digital signature algorithm.
|
||||
|
||||
.. kernel-doc:: include/crypto/mldsa.h
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@
|
|||
Crypto library
|
||||
==============
|
||||
|
||||
``lib/crypto/`` provides faster and easier access to cryptographic algorithms
|
||||
than the traditional crypto API.
|
||||
The Linux kernel's crypto library (``lib/crypto/``) provides kernel-internal
|
||||
users of cryptographic algorithms with faster and easier access to those
|
||||
algorithms than the traditional kernel crypto API.
|
||||
|
||||
Each cryptographic algorithm is supported via a set of dedicated functions.
|
||||
"Crypto agility", where needed, is left to calling code.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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``.
|
||||
|
||||
|
|
|
|||
14
MAINTAINERS
14
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*
|
||||
|
|
@ -14191,6 +14192,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>
|
||||
|
|
@ -20195,7 +20197,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
|
||||
|
|
@ -23313,7 +23315,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
|
||||
|
|
@ -23572,7 +23574,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
|
||||
|
|
@ -26526,7 +26528,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
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
|
|||
CONFIG_I2C=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_DESIGNWARE_CORE=y
|
||||
CONFIG_I2C_DESIGNWARE_PLATFORM=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_DRM=m
|
||||
CONFIG_DRM_I2C_ADV7511=m
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
|
|||
CONFIG_I2C=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_DESIGNWARE_CORE=y
|
||||
CONFIG_I2C_DESIGNWARE_PLATFORM=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_FB=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
|
|||
CONFIG_I2C=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_DESIGNWARE_CORE=y
|
||||
CONFIG_I2C_DESIGNWARE_PLATFORM=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_DRM=m
|
||||
CONFIG_DRM_I2C_ADV7511=m
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ CONFIG_SERIAL_8250_DW=y
|
|||
CONFIG_I2C=y
|
||||
# CONFIG_I2C_COMPAT is not set
|
||||
CONFIG_I2C_DESIGNWARE_CORE=y
|
||||
CONFIG_I2C_DESIGNWARE_PLATFORM=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/irqdomain.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/mach_desc.h>
|
||||
#include <asm/setup.h>
|
||||
|
|
@ -43,9 +44,10 @@ static int __init arc_get_cpu_map(const char *name, struct cpumask *cpumask)
|
|||
{
|
||||
unsigned long dt_root = of_get_flat_dt_root();
|
||||
const char *buf;
|
||||
int len;
|
||||
|
||||
buf = of_get_flat_dt_prop(dt_root, name, NULL);
|
||||
if (!buf)
|
||||
buf = of_get_flat_dt_prop(dt_root, name, &len);
|
||||
if (!buf || !memchr(buf, '\0', len))
|
||||
return -EINVAL;
|
||||
|
||||
if (cpulist_parse(buf, cpumask))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ config RISCV
|
|||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_DMA_CONTIGUOUS if MMU
|
||||
select HAVE_DYNAMIC_FTRACE if MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE)
|
||||
select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C
|
||||
select FUNCTION_ALIGNMENT_4B if DYNAMIC_FTRACE && RISCV_ISA_C
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI)
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ do { \
|
|||
flush_icache_mm(vma->vm_mm, 0); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
|
||||
/* This is accessed in assembly code. cpumask_var_t would be too complex. */
|
||||
extern DECLARE_BITMAP(new_valid_map_cpus, NR_CPUS);
|
||||
extern char _end[];
|
||||
|
|
@ -56,7 +56,8 @@ static inline void mark_new_valid_map(void)
|
|||
#define flush_cache_vmap flush_cache_vmap
|
||||
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (is_vmalloc_or_module_addr((void *)start))
|
||||
if (is_vmalloc_or_module_addr((void *)start) ||
|
||||
(start >= VMEMMAP_START && end <= VMEMMAP_END))
|
||||
mark_new_valid_map();
|
||||
}
|
||||
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)
|
||||
|
|
|
|||
|
|
@ -102,12 +102,14 @@ __io_reads_ins(reads, u32, l, __io_br(), __io_ar(addr))
|
|||
#define readsw(addr, buffer, count) __readsw(addr, buffer, count)
|
||||
#define readsl(addr, buffer, count) __readsl(addr, buffer, count)
|
||||
|
||||
#ifdef CONFIG_HAS_IOPORT
|
||||
__io_reads_ins(ins, u8, b, __io_pbr(), __io_par(addr))
|
||||
__io_reads_ins(ins, u16, w, __io_pbr(), __io_par(addr))
|
||||
__io_reads_ins(ins, u32, l, __io_pbr(), __io_par(addr))
|
||||
#define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count)
|
||||
#define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count)
|
||||
#define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count)
|
||||
#endif
|
||||
|
||||
__io_writes_outs(writes, u8, b, __io_bw(), __io_aw())
|
||||
__io_writes_outs(writes, u16, w, __io_bw(), __io_aw())
|
||||
|
|
@ -116,26 +118,32 @@ __io_writes_outs(writes, u32, l, __io_bw(), __io_aw())
|
|||
#define writesw(addr, buffer, count) __writesw(addr, buffer, count)
|
||||
#define writesl(addr, buffer, count) __writesl(addr, buffer, count)
|
||||
|
||||
#ifdef CONFIG_HAS_IOPORT
|
||||
__io_writes_outs(outs, u8, b, __io_pbw(), __io_paw())
|
||||
__io_writes_outs(outs, u16, w, __io_pbw(), __io_paw())
|
||||
__io_writes_outs(outs, u32, l, __io_pbw(), __io_paw())
|
||||
#define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count)
|
||||
#define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count)
|
||||
#define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
__io_reads_ins(reads, u64, q, __io_br(), __io_ar(addr))
|
||||
#define readsq(addr, buffer, count) __readsq(addr, buffer, count)
|
||||
|
||||
#ifdef CONFIG_HAS_IOPORT
|
||||
__io_reads_ins(ins, u64, q, __io_pbr(), __io_par(addr))
|
||||
#define insq(addr, buffer, count) __insq(PCI_IOBASE + (addr), buffer, count)
|
||||
#endif
|
||||
|
||||
__io_writes_outs(writes, u64, q, __io_bw(), __io_aw())
|
||||
#define writesq(addr, buffer, count) __writesq(addr, buffer, count)
|
||||
|
||||
#ifdef CONFIG_HAS_IOPORT
|
||||
__io_writes_outs(outs, u64, q, __io_pbr(), __io_paw())
|
||||
#define outsq(addr, buffer, count) __outsq(PCI_IOBASE + (addr), buffer, count)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ SYM_CODE_START(handle_exception)
|
|||
.Lrestore_kernel_tpsp:
|
||||
csrr tp, CSR_SCRATCH
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
|
||||
/*
|
||||
* The RISC-V kernel does not flush TLBs on all CPUS after each new
|
||||
* vmalloc mapping or kfence_unprotect(), which may result in
|
||||
|
|
|
|||
|
|
@ -450,6 +450,7 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs,
|
|||
if (cpusetsize > cpumask_size())
|
||||
cpusetsize = cpumask_size();
|
||||
|
||||
cpumask_clear(&cpus);
|
||||
ret = copy_from_user(&cpus, cpus_user, cpusetsize);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@ CPPFLAGS_$(vdso_lds) += -DHAS_VGETTIMEOFDAY
|
|||
endif
|
||||
|
||||
# Disable -pg to prevent insert call site
|
||||
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS)
|
||||
CFLAGS_REMOVE_getrandom.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS)
|
||||
CFLAGS_REMOVE_hwprobe.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS)
|
||||
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO)
|
||||
CFLAGS_REMOVE_getrandom.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO)
|
||||
CFLAGS_REMOVE_hwprobe.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO)
|
||||
|
||||
# Force dependency
|
||||
$(obj)/$(vdso_o): $(obj)/$(vdso_so)
|
||||
|
|
|
|||
|
|
@ -7,11 +7,19 @@
|
|||
#include <asm/unistd.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/*
|
||||
* WARNING: Do NOT add a CFI landing pad at the start of this function.
|
||||
* Unwinders such as libgcc identify the sigreturn trampoline by matching the
|
||||
* instruction sequence. Adding a landing pad here would break unwinding from
|
||||
* signal handlers.
|
||||
*
|
||||
* This trampoline is used only for signal return and not via an indirect
|
||||
* call/jump from userspace, so adding CFI landing pad is unnecessary.
|
||||
*/
|
||||
.text
|
||||
SYM_FUNC_START(__vdso_rt_sigreturn)
|
||||
.cfi_startproc
|
||||
.cfi_signal_frame
|
||||
vdso_lpad
|
||||
li a7, __NR_rt_sigreturn
|
||||
ecall
|
||||
.cfi_endproc
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@
|
|||
|
||||
#include "../kernel/head.h"
|
||||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
|
||||
DECLARE_BITMAP(new_valid_map_cpus, NR_CPUS);
|
||||
#endif
|
||||
|
||||
struct kernel_mapping kernel_map __ro_after_init;
|
||||
EXPORT_SYMBOL(kernel_map);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
#include <asm/cpu_mf.h>
|
||||
#include <asm/hwctrset.h>
|
||||
|
|
@ -768,6 +769,7 @@ static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
|
|||
if (!is_userspace_event(ev)) {
|
||||
if (ev >= ARRAY_SIZE(cpumf_generic_events_user))
|
||||
return -EOPNOTSUPP;
|
||||
ev = array_index_nospec(ev, ARRAY_SIZE(cpumf_generic_events_user));
|
||||
ev = cpumf_generic_events_user[ev];
|
||||
}
|
||||
} else if (!attr->exclude_kernel && attr->exclude_user) {
|
||||
|
|
@ -778,6 +780,7 @@ static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
|
|||
if (!is_userspace_event(ev)) {
|
||||
if (ev >= ARRAY_SIZE(cpumf_generic_events_basic))
|
||||
return -EOPNOTSUPP;
|
||||
ev = array_index_nospec(ev, ARRAY_SIZE(cpumf_generic_events_basic));
|
||||
ev = cpumf_generic_events_basic[ev];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __w
|
|||
if (!cpu_has_vx()) {
|
||||
if (copy)
|
||||
memcpy(dst, src, len);
|
||||
return cksm(dst, len, sum);
|
||||
return cksm(src, len, sum);
|
||||
}
|
||||
kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23);
|
||||
fpu_vlvgf(16, (__force u32)sum, 1);
|
||||
|
|
|
|||
|
|
@ -184,10 +184,15 @@ static unsigned long get_cmdline_acpi_rsdp(void)
|
|||
char val[MAX_ADDR_LEN] = { };
|
||||
int ret;
|
||||
|
||||
ret = cmdline_find_option("acpi_rsdp", val, MAX_ADDR_LEN);
|
||||
ret = cmdline_find_option("acpi_rsdp", val, sizeof(val));
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
if (ret >= sizeof(val)) {
|
||||
warn("acpi_rsdp= value too long; ignoring");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (boot_kstrtoul(val, 16, &addr))
|
||||
return 0;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ static unsigned int probe_baud(int port)
|
|||
static void parse_console_uart8250(void)
|
||||
{
|
||||
char optstr[64], *options;
|
||||
int baud = DEFAULT_BAUD;
|
||||
int baud;
|
||||
int port = 0;
|
||||
|
||||
/*
|
||||
|
|
@ -136,10 +136,13 @@ static void parse_console_uart8250(void)
|
|||
else
|
||||
return;
|
||||
|
||||
if (options && (options[0] == ','))
|
||||
baud = simple_strtoull(options + 1, &options, 0);
|
||||
else
|
||||
if (options && (options[0] == ',')) {
|
||||
baud = simple_strtoull(options + 1, NULL, 0);
|
||||
if (!baud)
|
||||
baud = DEFAULT_BAUD;
|
||||
} else {
|
||||
baud = probe_baud(port);
|
||||
}
|
||||
|
||||
if (port)
|
||||
early_serial_init(port, baud);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ obj-$(CONFIG_CPU_SUP_HYGON) += hygon.o
|
|||
obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o
|
||||
obj-$(CONFIG_CPU_SUP_CENTAUR) += centaur.o
|
||||
obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
|
||||
obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o
|
||||
obj-$(CONFIG_CPU_SUP_ZHAOXIN) += zhaoxin.o
|
||||
obj-$(CONFIG_CPU_SUP_VORTEX_32) += vortex.o
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
64
block/bio.c
64
block/bio.c
|
|
@ -555,6 +555,14 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
|
|||
bio = bio_alloc_percpu_cache(bs);
|
||||
} else {
|
||||
opf &= ~REQ_ALLOC_CACHE;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a bioset without a percpu cache, or when the percpu cache was
|
||||
* empty, try a slab allocation with optimistic GFP_ flags before
|
||||
* falling back to the mempool.
|
||||
*/
|
||||
if (!bio) {
|
||||
p = kmem_cache_alloc(bs->bio_slab, gfp);
|
||||
if (p)
|
||||
bio = p + bs->front_pad;
|
||||
|
|
@ -1191,7 +1199,7 @@ void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter)
|
|||
* for the next iteration.
|
||||
*/
|
||||
static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
|
||||
unsigned len_align_mask)
|
||||
struct bio_vec *bv, unsigned len_align_mask)
|
||||
{
|
||||
size_t nbytes = bio->bi_iter.bi_size & len_align_mask;
|
||||
|
||||
|
|
@ -1200,23 +1208,16 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
|
|||
|
||||
iov_iter_revert(iter, nbytes);
|
||||
bio->bi_iter.bi_size -= nbytes;
|
||||
do {
|
||||
struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
|
||||
|
||||
if (nbytes < bv->bv_len) {
|
||||
bv->bv_len -= nbytes;
|
||||
break;
|
||||
}
|
||||
|
||||
while (nbytes >= bv->bv_len) {
|
||||
if (bio_flagged(bio, BIO_PAGE_PINNED))
|
||||
unpin_user_page(bv->bv_page);
|
||||
|
||||
bio->bi_vcnt--;
|
||||
if (!--bio->bi_vcnt)
|
||||
return -EFAULT;
|
||||
nbytes -= bv->bv_len;
|
||||
} while (nbytes);
|
||||
|
||||
if (!bio->bi_vcnt)
|
||||
return -EFAULT;
|
||||
bv--;
|
||||
}
|
||||
bv->bv_len -= nbytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1276,7 +1277,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
|
|||
|
||||
if (is_pci_p2pdma_page(bio->bi_io_vec->bv_page))
|
||||
bio->bi_opf |= REQ_NOMERGE;
|
||||
return bio_iov_iter_align_down(bio, iter, len_align_mask);
|
||||
return bio_iov_iter_align_down(bio, iter,
|
||||
&bio->bi_io_vec[bio->bi_vcnt - 1], len_align_mask);
|
||||
}
|
||||
|
||||
static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
|
||||
|
|
@ -1285,7 +1287,8 @@ static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
|
|||
struct folio *folio;
|
||||
|
||||
while (*size > minsize) {
|
||||
folio = folio_alloc(gfp | __GFP_NORETRY, get_order(*size));
|
||||
folio = folio_alloc(gfp | __GFP_NORETRY | __GFP_NOWARN,
|
||||
get_order(*size));
|
||||
if (folio)
|
||||
return folio;
|
||||
*size = rounddown_pow_of_two(*size - 1);
|
||||
|
|
@ -1302,7 +1305,7 @@ static void bio_free_folios(struct bio *bio)
|
|||
bio_for_each_bvec_all(bv, bio, i) {
|
||||
struct folio *folio = bvec_folio(bv);
|
||||
|
||||
if (!is_zero_folio(folio))
|
||||
if (!is_zero_folio(folio) && !is_huge_zero_folio(folio))
|
||||
folio_put(folio);
|
||||
}
|
||||
}
|
||||
|
|
@ -1360,7 +1363,8 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
|
|||
|
||||
if (!bio->bi_iter.bi_size)
|
||||
return -ENOMEM;
|
||||
return bio_iov_iter_align_down(bio, iter, minsize - 1);
|
||||
return bio_iov_iter_align_down(bio, iter,
|
||||
&bio->bi_io_vec[bio->bi_vcnt - 1], minsize - 1);
|
||||
}
|
||||
|
||||
static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
|
||||
|
|
@ -1368,21 +1372,18 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
|
|||
{
|
||||
size_t len = min3(iov_iter_count(iter), maxlen, SZ_1M);
|
||||
struct folio *folio;
|
||||
ssize_t ret;
|
||||
|
||||
folio = folio_alloc_greedy(GFP_KERNEL, &len, minsize);
|
||||
if (!folio)
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
ssize_t ret;
|
||||
|
||||
ret = iov_iter_extract_bvecs(iter, bio->bi_io_vec + 1, len,
|
||||
&bio->bi_vcnt, bio->bi_max_vecs - 1, 0);
|
||||
if (ret <= 0) {
|
||||
if (!bio->bi_vcnt) {
|
||||
folio_put(folio);
|
||||
return ret;
|
||||
}
|
||||
if (!bio->bi_vcnt)
|
||||
goto out_folio_put;
|
||||
break;
|
||||
}
|
||||
len -= ret;
|
||||
|
|
@ -1398,7 +1399,20 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
|
|||
bvec_set_folio(&bio->bi_io_vec[0], folio, bio->bi_iter.bi_size, 0);
|
||||
if (iov_iter_extract_will_pin(iter))
|
||||
bio_set_flag(bio, BIO_PAGE_PINNED);
|
||||
return bio_iov_iter_align_down(bio, iter, minsize - 1);
|
||||
|
||||
/* The first vec stores the bounce buffer, so do not subtract 1 here. */
|
||||
ret = bio_iov_iter_align_down(bio, iter,
|
||||
&bio->bi_io_vec[bio->bi_vcnt], minsize - 1);
|
||||
if (ret)
|
||||
goto out_folio_put;
|
||||
|
||||
/* Update the bounc buffer bv_len to the aligned down size. */
|
||||
bio->bi_io_vec[0].bv_len = bio->bi_iter.bi_size;
|
||||
return 0;
|
||||
|
||||
out_folio_put:
|
||||
folio_put(folio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -434,15 +434,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
|
|||
blkg->pd[i]->online = true;
|
||||
}
|
||||
}
|
||||
blkg->online = true;
|
||||
}
|
||||
blkg->online = true;
|
||||
spin_unlock(&blkcg->lock);
|
||||
|
||||
if (!ret)
|
||||
return blkg;
|
||||
|
||||
/* @blkg failed fully initialized, use the usual release path */
|
||||
blkg_put(blkg);
|
||||
percpu_ref_kill(&blkg->refcnt);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
err_free_blkg:
|
||||
|
|
|
|||
|
|
@ -653,6 +653,7 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len,
|
|||
gfp_t gfp_mask)
|
||||
{
|
||||
unsigned long addr = (unsigned long) kbuf;
|
||||
bool do_copy;
|
||||
struct bio *bio;
|
||||
int ret;
|
||||
|
||||
|
|
@ -661,7 +662,8 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len,
|
|||
if (!len || !kbuf)
|
||||
return -EINVAL;
|
||||
|
||||
if (!blk_rq_aligned(rq->q, addr, len) || object_is_on_stack(kbuf))
|
||||
do_copy = !blk_rq_aligned(rq->q, addr, len) || object_is_on_stack(kbuf);
|
||||
if (do_copy)
|
||||
bio = bio_copy_kern(rq, kbuf, len, gfp_mask);
|
||||
else
|
||||
bio = bio_map_kern(rq, kbuf, len, gfp_mask);
|
||||
|
|
@ -670,8 +672,11 @@ int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len,
|
|||
return PTR_ERR(bio);
|
||||
|
||||
ret = blk_rq_append_bio(rq, bio);
|
||||
if (unlikely(ret))
|
||||
if (unlikely(ret)) {
|
||||
if (do_copy)
|
||||
bio_free_pages(bio);
|
||||
blk_mq_map_bio_put(bio);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_map_kern);
|
||||
|
|
|
|||
13
block/blk.h
13
block/blk.h
|
|
@ -717,6 +717,7 @@ static inline int req_ref_read(struct request *req)
|
|||
static inline u64 blk_time_get_ns(void)
|
||||
{
|
||||
struct blk_plug *plug = current->plug;
|
||||
u64 now;
|
||||
|
||||
if (!plug || !in_task())
|
||||
return ktime_get_ns();
|
||||
|
|
@ -725,12 +726,18 @@ static inline u64 blk_time_get_ns(void)
|
|||
* 0 could very well be a valid time, but rather than flag "this is
|
||||
* a valid timestamp" separately, just accept that we'll do an extra
|
||||
* ktime_get_ns() if we just happen to get 0 as the current time.
|
||||
*
|
||||
* cur_ktime can be zeroed by pre-emption the moment PF_BLOCK_TS is set.
|
||||
*/
|
||||
if (!plug->cur_ktime) {
|
||||
plug->cur_ktime = ktime_get_ns();
|
||||
now = READ_ONCE(plug->cur_ktime);
|
||||
if (!now) {
|
||||
now = ktime_get_ns();
|
||||
WRITE_ONCE(plug->cur_ktime, now);
|
||||
/* Ensure PF_BLOCK_TS is set after cur_ktime. */
|
||||
barrier();
|
||||
current->flags |= PF_BLOCK_TS;
|
||||
}
|
||||
return plug->cur_ktime;
|
||||
return now;
|
||||
}
|
||||
|
||||
static inline ktime_t blk_time_get(void)
|
||||
|
|
|
|||
|
|
@ -812,8 +812,13 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
|
|||
* reference during concurrent disk deletion:
|
||||
* update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del)
|
||||
* kn->active -> update_nr_hwq_lock (via this sysfs write path)
|
||||
*
|
||||
* Use the writer lock instead of the reader lock of update_nr_hwq_lock
|
||||
* to serialize the two-stage elevator switch steps in
|
||||
* elevator_change(): the core switch step under the elevator lock and
|
||||
* the elevator_change_done() step outside the elevator lock.
|
||||
*/
|
||||
if (!down_read_trylock(&set->update_nr_hwq_lock)) {
|
||||
if (!down_write_trylock(&set->update_nr_hwq_lock)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -824,7 +829,7 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
|
|||
} else {
|
||||
ret = -ENOENT;
|
||||
}
|
||||
up_read(&set->update_nr_hwq_lock);
|
||||
up_write(&set->update_nr_hwq_lock);
|
||||
|
||||
out:
|
||||
if (ctx.type)
|
||||
|
|
|
|||
|
|
@ -276,9 +276,10 @@ static int blk_error_injection_show(struct seq_file *s, void *private)
|
|||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(inj, &disk->error_injection_list, entry) {
|
||||
seq_printf(s, "%llu:%llu status=%s,chance=%u",
|
||||
inj->start, inj->end,
|
||||
blk_status_to_tag(inj->status), inj->chance);
|
||||
seq_printf(s, "%llu:%llu op=%s,status=%s,chance=%u",
|
||||
inj->start, inj->end,
|
||||
blk_op_str(inj->op),
|
||||
blk_status_to_tag(inj->status), inj->chance);
|
||||
seq_putc(s, '\n');
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
|
|
|||
|
|
@ -208,7 +208,14 @@ int aix_partition(struct parsed_partitions *state)
|
|||
if (n) {
|
||||
int foundlvs = 0;
|
||||
|
||||
for (i = 0; foundlvs < numlvs && i < state->limit; i += 1) {
|
||||
/*
|
||||
* The lvd array was read as a single sector; only the
|
||||
* struct lvd entries that fit in it are valid. Bound the
|
||||
* scan so an on-disk numlvs larger than that cannot walk
|
||||
* the read buffer out of bounds.
|
||||
*/
|
||||
for (i = 0; foundlvs < numlvs && i < state->limit &&
|
||||
i < SECTOR_SIZE / (int)sizeof(struct lvd); i++) {
|
||||
lvip[i].pps_per_lv = be16_to_cpu(p[i].num_lps);
|
||||
if (lvip[i].pps_per_lv)
|
||||
foundlvs += 1;
|
||||
|
|
|
|||
|
|
@ -358,8 +358,8 @@ config CRYPTO_AES
|
|||
tristate "AES (Advanced Encryption Standard)"
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_LIB_AES
|
||||
select CRYPTO_LIB_AES_CBC_MACS if CRYPTO_CMAC || CRYPTO_XCBC || CRYPTO_CCM
|
||||
select CRYPTO_HASH if CRYPTO_CMAC || CRYPTO_XCBC || CRYPTO_CCM
|
||||
select CRYPTO_LIB_AES_CBC_MACS if CRYPTO_CMAC != n || CRYPTO_XCBC != n || CRYPTO_CCM != n
|
||||
select CRYPTO_HASH if CRYPTO_CMAC != n || CRYPTO_XCBC != n || CRYPTO_CCM != n
|
||||
help
|
||||
AES cipher algorithms (Rijndael)(FIPS-197, ISO/IEC 18033-3)
|
||||
|
||||
|
|
|
|||
|
|
@ -577,6 +577,7 @@ void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job)
|
|||
amdxdna_arg_bos_put(job);
|
||||
amdxdna_gem_put_obj(job->cmd_bo);
|
||||
dma_fence_put(job->fence);
|
||||
mmdrop(job->mm);
|
||||
}
|
||||
|
||||
int amdxdna_cmd_submit(struct amdxdna_client *client,
|
||||
|
|
@ -590,6 +591,10 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
|
|||
int ret, idx;
|
||||
|
||||
XDNA_DBG(xdna, "Command BO hdl %d, Arg BO count %d", cmd_bo_hdl, arg_bo_cnt);
|
||||
|
||||
if (!xdna->dev_info->ops->cmd_submit)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
job = kzalloc_flex(*job, bos, arg_bo_cnt);
|
||||
if (!job)
|
||||
return -ENOMEM;
|
||||
|
|
@ -603,6 +608,16 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
|
|||
ret = -EINVAL;
|
||||
goto free_job;
|
||||
}
|
||||
} else if (!drv_cmd) {
|
||||
/*
|
||||
* Only internal driver commands (drv_cmd != NULL) may omit a
|
||||
* command BO. A user command submission with the invalid handle
|
||||
* would leave job->cmd_bo NULL and later fault when the scheduler
|
||||
* dereferences it in amdxdna_cmd_set_state().
|
||||
*/
|
||||
XDNA_DBG(xdna, "Command BO handle required for user submission");
|
||||
ret = -EINVAL;
|
||||
goto free_job;
|
||||
}
|
||||
|
||||
ret = amdxdna_arg_bos_lookup(client, job, arg_bo_hdls, arg_bo_cnt);
|
||||
|
|
@ -628,6 +643,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
|
|||
|
||||
job->hwctx = hwctx;
|
||||
job->mm = current->mm;
|
||||
mmgrab(job->mm);
|
||||
|
||||
job->fence = amdxdna_fence_create(hwctx);
|
||||
if (!job->fence) {
|
||||
|
|
@ -662,6 +678,8 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
|
|||
cmd_put:
|
||||
amdxdna_gem_put_obj(job->cmd_bo);
|
||||
free_job:
|
||||
if (job->mm)
|
||||
mmdrop(job->mm);
|
||||
kfree(job);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ static int fw_log_from_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *off
|
|||
ivpu_dbg(vdev, FW_BOOT, "Invalid header size 0x%x\n", log->header_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (log->size < log->header_size) {
|
||||
ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((char *)log + log->size > (char *)ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)) {
|
||||
ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -927,7 +927,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev)
|
|||
|
||||
static void diagnose_failure_lnl(struct ivpu_device *vdev)
|
||||
{
|
||||
u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
|
||||
u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
|
||||
|
||||
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) {
|
||||
ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/libata.h>
|
||||
|
|
@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
|
|||
struct sata_dwc_device *hsdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL);
|
||||
if (!hsdev->dma)
|
||||
|
|
@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
|
|||
hsdev->dma->id = pdev->id;
|
||||
|
||||
/* Get SATA DMA interrupt number */
|
||||
hsdev->dma->irq = irq_of_parse_and_map(np, 1);
|
||||
if (!hsdev->dma->irq) {
|
||||
dev_err(dev, "no SATA DMA irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
hsdev->dma->irq = platform_get_irq(pdev, 1);
|
||||
if (hsdev->dma->irq < 0)
|
||||
return hsdev->dma->irq;
|
||||
|
||||
/* Get physical SATA DMA register base address */
|
||||
hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1);
|
||||
|
|
@ -398,8 +394,7 @@ static void clear_serror(struct ata_port *ap)
|
|||
|
||||
static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
|
||||
{
|
||||
sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
|
||||
sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
|
||||
sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit);
|
||||
}
|
||||
|
||||
static u32 qcmd_tag_to_mask(u8 tag)
|
||||
|
|
@ -612,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
|
|||
status = ap->ops->sff_check_status(ap);
|
||||
dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
|
||||
|
||||
tag = 0;
|
||||
while (tag_mask) {
|
||||
while (!(tag_mask & 0x00000001)) {
|
||||
tag++;
|
||||
tag_mask <<= 1;
|
||||
}
|
||||
|
||||
tag_mask &= (~0x00000001);
|
||||
tag = __ffs(tag_mask);
|
||||
tag_mask &= ~(1U << tag);
|
||||
qc = ata_qc_from_tag(ap, tag);
|
||||
if (unlikely(!qc)) {
|
||||
dev_err(ap->dev, "failed to get qc");
|
||||
|
|
@ -1126,7 +1116,6 @@ static const struct ata_port_info sata_dwc_port_info[] = {
|
|||
static int sata_dwc_probe(struct platform_device *ofdev)
|
||||
{
|
||||
struct device *dev = &ofdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct sata_dwc_device *hsdev;
|
||||
u32 idr, versionr;
|
||||
char *ver = (char *)&versionr;
|
||||
|
|
@ -1169,18 +1158,13 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|||
/* Save dev for later use in dev_xxx() routines */
|
||||
hsdev->dev = dev;
|
||||
|
||||
/* Enable SATA Interrupts */
|
||||
sata_dwc_enable_interrupts(hsdev);
|
||||
|
||||
/* Get SATA interrupt number */
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq) {
|
||||
dev_err(dev, "no SATA DMA irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
irq = platform_get_irq(ofdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
#ifdef CONFIG_SATA_DWC_OLD_DMA
|
||||
if (!of_property_present(np, "dmas")) {
|
||||
if (!of_property_present(dev->of_node, "dmas")) {
|
||||
err = sata_dwc_dma_init_old(ofdev, hsdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -1204,6 +1188,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|||
if (err)
|
||||
dev_err(dev, "failed to activate host");
|
||||
|
||||
/* Enable SATA Interrupts */
|
||||
sata_dwc_enable_interrupts(hsdev);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
|
|
|
|||
|
|
@ -1113,6 +1113,7 @@ static void __loop_clr_fd(struct loop_device *lo)
|
|||
struct queue_limits lim;
|
||||
struct file *filp;
|
||||
gfp_t gfp = lo->old_gfp_mask;
|
||||
int err;
|
||||
|
||||
spin_lock_irq(&lo->lo_lock);
|
||||
filp = lo->lo_backing_file;
|
||||
|
|
@ -1146,26 +1147,21 @@ static void __loop_clr_fd(struct loop_device *lo)
|
|||
|
||||
disk_force_media_change(lo->lo_disk);
|
||||
|
||||
if (lo->lo_flags & LO_FLAGS_PARTSCAN) {
|
||||
int err;
|
||||
|
||||
/*
|
||||
* open_mutex has been held already in release path, so don't
|
||||
* acquire it if this function is called in such case.
|
||||
*
|
||||
* If the reread partition isn't from release path, lo_refcnt
|
||||
* must be at least one and it can only become zero when the
|
||||
* current holder is released.
|
||||
*/
|
||||
err = bdev_disk_changed(lo->lo_disk, false);
|
||||
if (err)
|
||||
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
|
||||
__func__, lo->lo_number, err);
|
||||
/* Device is gone, no point in returning error */
|
||||
}
|
||||
/*
|
||||
* Remove all partitions, including partitions added manually with
|
||||
* BLKPG, which may exist even if LO_FLAGS_PARTSCAN is not set.
|
||||
*
|
||||
* open_mutex has been held already in release path, so don't acquire
|
||||
* it here.
|
||||
*/
|
||||
err = bdev_disk_changed(lo->lo_disk, false);
|
||||
if (err)
|
||||
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
|
||||
__func__, lo->lo_number, err);
|
||||
/* Device is gone, no point in returning error */
|
||||
|
||||
/*
|
||||
* lo->lo_state is set to Lo_unbound here after above partscan has
|
||||
* lo->lo_state is set to Lo_unbound here after removing partitions has
|
||||
* finished. There cannot be anybody else entering __loop_clr_fd() as
|
||||
* Lo_rundown state protects us from all the other places trying to
|
||||
* change the 'lo' device.
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
|
|||
|
||||
idx = 0;
|
||||
data = tlv->data;
|
||||
while (idx < length - sizeof(struct tlv_type_nvm)) {
|
||||
while (idx + sizeof(struct tlv_type_nvm) <= length) {
|
||||
tlv_nvm = (struct tlv_type_nvm *)(data + idx);
|
||||
|
||||
tag_id = le16_to_cpu(tlv_nvm->tag_id);
|
||||
|
|
|
|||
|
|
@ -797,8 +797,9 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
|||
}
|
||||
|
||||
BT_DBG("length=%x offset=%x index %d", patch_length, patch_offset, i);
|
||||
min_size = patch_offset + patch_length;
|
||||
if (btrtl_dev->fw_len < min_size)
|
||||
if (patch_length < sizeof(epatch_info->fw_version) ||
|
||||
patch_offset > btrtl_dev->fw_len ||
|
||||
patch_length > btrtl_dev->fw_len - patch_offset)
|
||||
return -EINVAL;
|
||||
|
||||
/* Copy the firmware into a new buffer and write the version at
|
||||
|
|
|
|||
|
|
@ -1087,6 +1087,10 @@ static void qca_controller_memdump(struct work_struct *work)
|
|||
if (!(qca_memdump->ram_dump_size)) {
|
||||
bt_dev_err(hu->hdev, "Rx invalid memdump size");
|
||||
kfree(qca_memdump);
|
||||
qca->qca_memdump = NULL;
|
||||
qca->memdump_state = QCA_MEMDUMP_COLLECTED;
|
||||
clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
|
||||
clear_bit(QCA_IBS_DISABLED, &qca->flags);
|
||||
kfree_skb(skb);
|
||||
mutex_unlock(&qca->hci_memdump_lock);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2586,6 +2586,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
|
|||
|
||||
cpu = cpumask_first(policy->related_cpus);
|
||||
max_freq = arch_scale_freq_ref(cpu);
|
||||
if (!max_freq)
|
||||
max_freq = policy->cpuinfo.max_freq;
|
||||
|
||||
capped_freq = policy->max;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1058,12 +1058,14 @@ static void hybrid_clear_cpu_capacity(unsigned int cpunum)
|
|||
|
||||
static void hybrid_get_capacity_perf(struct cpudata *cpu)
|
||||
{
|
||||
u64 hwp_cap = READ_ONCE(cpu->hwp_cap_cached);
|
||||
|
||||
if (READ_ONCE(global.no_turbo)) {
|
||||
cpu->capacity_perf = cpu->pstate.max_pstate_physical;
|
||||
cpu->capacity_perf = HWP_GUARANTEED_PERF(hwp_cap);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu->capacity_perf = HWP_HIGHEST_PERF(READ_ONCE(cpu->hwp_cap_cached));
|
||||
cpu->capacity_perf = HWP_HIGHEST_PERF(hwp_cap);
|
||||
}
|
||||
|
||||
static void hybrid_set_capacity_of_cpus(void)
|
||||
|
|
|
|||
|
|
@ -224,21 +224,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
|
|||
{
|
||||
struct udmabuf *ubuf = buf->priv;
|
||||
struct device *dev = ubuf->device->this_device;
|
||||
int ret = 0;
|
||||
|
||||
if (!ubuf->sg) {
|
||||
ubuf->sg = get_sg_table(dev, buf, direction);
|
||||
if (IS_ERR(ubuf->sg)) {
|
||||
int ret;
|
||||
|
||||
ret = PTR_ERR(ubuf->sg);
|
||||
ubuf->sg = NULL;
|
||||
return ret;
|
||||
} else {
|
||||
ubuf->sg_dir = direction;
|
||||
}
|
||||
} else {
|
||||
dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
|
||||
}
|
||||
|
||||
return ret;
|
||||
dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int end_cpu_udmabuf(struct dma_buf *buf,
|
||||
|
|
|
|||
|
|
@ -567,6 +567,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin,
|
|||
if (!dpll_pin_available(ref_sync_pin))
|
||||
continue;
|
||||
ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin);
|
||||
/* Pin may have been unregistered from this dpll already */
|
||||
if (!ref_sync_pin_priv)
|
||||
continue;
|
||||
if (WARN_ON(!ops->ref_sync_get))
|
||||
return -EOPNOTSUPP;
|
||||
ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
|
|
@ -59,7 +60,9 @@
|
|||
(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
|
||||
|
||||
#define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0)
|
||||
#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK)
|
||||
#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16)
|
||||
#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x)))
|
||||
#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x)))
|
||||
|
||||
#define FFA_MAX_NOTIFICATIONS 64
|
||||
|
||||
|
|
@ -713,30 +716,39 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
|||
struct ffa_composite_mem_region *composite;
|
||||
struct ffa_mem_region_addr_range *constituents;
|
||||
struct ffa_mem_region_attributes *ep_mem_access;
|
||||
u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg);
|
||||
u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg), ep_offset;
|
||||
u32 emad_end, emad_size = ffa_emad_size_get(drv_info->version);
|
||||
|
||||
mem_region->tag = args->tag;
|
||||
mem_region->flags = args->flags;
|
||||
mem_region->sender_id = drv_info->vm_id;
|
||||
mem_region->attributes = ffa_memory_attributes_get(func_id);
|
||||
|
||||
ffa_mem_region_additional_setup(drv_info->version, mem_region);
|
||||
composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
|
||||
drv_info->version);
|
||||
if (composite_offset + sizeof(*composite) > max_fragsize)
|
||||
return -ENXIO;
|
||||
|
||||
for (idx = 0; idx < args->nattrs; idx++) {
|
||||
ep_mem_access = buffer +
|
||||
ffa_mem_desc_offset(buffer, idx, drv_info->version);
|
||||
ep_offset = ffa_mem_desc_offset(buffer, idx, drv_info->version);
|
||||
if (check_add_overflow(ep_offset, emad_size, &emad_end))
|
||||
return -ENXIO;
|
||||
|
||||
if (emad_end > max_fragsize)
|
||||
return -ENXIO;
|
||||
|
||||
ep_mem_access = buffer + ep_offset;
|
||||
memset(ep_mem_access, 0, emad_size);
|
||||
ep_mem_access->receiver = args->attrs[idx].receiver;
|
||||
ep_mem_access->attrs = args->attrs[idx].attrs;
|
||||
ep_mem_access->composite_off = composite_offset;
|
||||
ep_mem_access->flag = 0;
|
||||
ep_mem_access->reserved = 0;
|
||||
ffa_emad_impdef_value_init(drv_info->version,
|
||||
ep_mem_access->impdef_val,
|
||||
args->attrs[idx].impdef_val);
|
||||
}
|
||||
mem_region->handle = 0;
|
||||
mem_region->ep_count = args->nattrs;
|
||||
ffa_mem_region_additional_setup(drv_info->version, mem_region);
|
||||
|
||||
composite = buffer + composite_offset;
|
||||
composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
|
||||
|
|
@ -769,7 +781,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
|||
constituents = buffer;
|
||||
}
|
||||
|
||||
if ((void *)constituents - buffer > max_fragsize) {
|
||||
if ((void *)constituents + sizeof(*constituents) - buffer > max_fragsize) {
|
||||
pr_err("Memory Region Fragment > Tx Buffer size\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
@ -778,7 +790,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
|||
constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
|
||||
constituents->reserved = 0;
|
||||
constituents++;
|
||||
frag_len += sizeof(struct ffa_mem_region_addr_range);
|
||||
frag_len += sizeof(*constituents);
|
||||
} while ((args->sg = sg_next(args->sg)));
|
||||
|
||||
return ffa_transmit_fragment(func_id, addr, buf_sz, frag_len,
|
||||
|
|
@ -1139,7 +1151,7 @@ static int ffa_partition_info_get(const char *uuid_str,
|
|||
uuid_t uuid;
|
||||
struct ffa_partition_info *pbuf;
|
||||
|
||||
if (uuid_parse(uuid_str, &uuid)) {
|
||||
if (!uuid_str || uuid_parse(uuid_str, &uuid)) {
|
||||
pr_err("invalid uuid (%s)\n", uuid_str);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
@ -2101,7 +2113,7 @@ static int ffa_probe(struct platform_device *pdev)
|
|||
{
|
||||
int ret;
|
||||
u32 buf_sz;
|
||||
size_t rxtx_bufsz = SZ_4K;
|
||||
size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz;
|
||||
|
||||
if (IS_BUILTIN(CONFIG_ARM_FFA_TRANSPORT) &&
|
||||
is_protected_kvm_enabled() && !is_pkvm_initialized())
|
||||
|
|
@ -2132,15 +2144,18 @@ static int ffa_probe(struct platform_device *pdev)
|
|||
ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL);
|
||||
if (!ret) {
|
||||
if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1)
|
||||
rxtx_bufsz = SZ_64K;
|
||||
rxtx_min_bufsz = SZ_64K;
|
||||
else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2)
|
||||
rxtx_bufsz = SZ_16K;
|
||||
rxtx_min_bufsz = SZ_16K;
|
||||
else
|
||||
rxtx_bufsz = SZ_4K;
|
||||
rxtx_min_bufsz = SZ_4K;
|
||||
|
||||
rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K;
|
||||
if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz)
|
||||
rxtx_max_bufsz = rxtx_min_bufsz;
|
||||
}
|
||||
|
||||
rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
|
||||
drv_info->rxtx_bufsz = rxtx_bufsz;
|
||||
rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz);
|
||||
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
|
||||
if (!drv_info->rx_buffer) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -2156,10 +2171,17 @@ static int ffa_probe(struct platform_device *pdev)
|
|||
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
|
||||
virt_to_phys(drv_info->rx_buffer),
|
||||
rxtx_bufsz / FFA_PAGE_SIZE);
|
||||
if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) {
|
||||
rxtx_bufsz = rxtx_min_bufsz;
|
||||
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
|
||||
virt_to_phys(drv_info->rx_buffer),
|
||||
rxtx_bufsz / FFA_PAGE_SIZE);
|
||||
}
|
||||
if (ret) {
|
||||
pr_err("failed to register FFA RxTx buffers\n");
|
||||
goto free_pages;
|
||||
}
|
||||
drv_info->rxtx_bufsz = rxtx_bufsz;
|
||||
|
||||
mutex_init(&drv_info->rx_lock);
|
||||
mutex_init(&drv_info->tx_lock);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ config ARM_SCMI_POWER_CONTROL
|
|||
firmware.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called scmi_power_control. Note this may needed early in boot to catch
|
||||
early shutdown/reboot SCMI requests.
|
||||
called scmi_power_control. Note this may be needed early in boot to
|
||||
catch early shutdown/reboot SCMI requests.
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -718,7 +718,7 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
|
|||
static int scmi_clock_determine_rate(const struct scmi_protocol_handle *ph,
|
||||
u32 clk_id, unsigned long *rate)
|
||||
{
|
||||
u64 fmin, fmax, ftmp;
|
||||
u64 fmin, fmax, ftmp, step;
|
||||
struct scmi_clock_info *clk;
|
||||
struct scmi_clock_desc *clkd;
|
||||
struct clock_info *ci = ph->get_priv(ph);
|
||||
|
|
@ -749,11 +749,14 @@ static int scmi_clock_determine_rate(const struct scmi_protocol_handle *ph,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ftmp = *rate - fmin;
|
||||
ftmp += clkd->r.rates[RATE_STEP] - 1; /* to round up */
|
||||
ftmp = div64_ul(ftmp, clkd->r.rates[RATE_STEP]);
|
||||
step = clkd->r.rates[RATE_STEP];
|
||||
if (!step)
|
||||
return -EINVAL;
|
||||
|
||||
*rate = ftmp * clkd->r.rates[RATE_STEP] + fmin;
|
||||
ftmp = *rate - fmin;
|
||||
ftmp = DIV64_U64_ROUND_UP(ftmp, step);
|
||||
|
||||
*rate = ftmp * step + fmin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -600,9 +600,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id,
|
|||
return -EINVAL;
|
||||
}
|
||||
if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) {
|
||||
dev_warn(handle->dev,
|
||||
"queue full, dropping proto_id:%d evt_id:%d ts:%lld\n",
|
||||
proto_id, evt_id, ktime_to_ns(ts));
|
||||
dev_warn_ratelimited(handle->dev,
|
||||
"queue full, dropping proto_id:%d evt_id:%d ts:%lld\n",
|
||||
proto_id, evt_id, ktime_to_ns(ts));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -372,19 +372,59 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/**
|
||||
* amdgpu_acpi_vfct_match() - Check if a VFCT entry matches the device
|
||||
* @adev: AMDGPU device
|
||||
* @vhdr: VFCT image header to check
|
||||
*
|
||||
* VFCT entries contain the PCI bus number as recorded during BIOS POST.
|
||||
* On systems where the kernel renumbers PCI buses (e.g. pci=realloc or
|
||||
* resource conflicts), the runtime bus number may differ from the POST
|
||||
* value. Match by device identity (vendor + device + function) and use
|
||||
* the bus number as a preference: exact bus match is preferred, but when
|
||||
* the bus numbers disagree we accept the entry if the device identity
|
||||
* matches.
|
||||
*
|
||||
* Returns: 0 on match, -ENODEV on no match
|
||||
*/
|
||||
static int amdgpu_acpi_vfct_match(struct amdgpu_device *adev,
|
||||
VFCT_IMAGE_HEADER *vhdr)
|
||||
{
|
||||
/* Vendor and device IDs must always match */
|
||||
if (vhdr->VendorID != adev->pdev->vendor ||
|
||||
vhdr->DeviceID != adev->pdev->device)
|
||||
return -ENODEV;
|
||||
|
||||
if (vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
|
||||
vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn))
|
||||
return -ENODEV;
|
||||
|
||||
/* Exact bus number match - preferred */
|
||||
if (vhdr->PCIBus == adev->pdev->bus->number)
|
||||
return 0;
|
||||
|
||||
/* Bus mismatch but device identity matches (PCI renumbering case) */
|
||||
dev_notice(adev->dev,
|
||||
"VFCT bus number mismatch: table %u != runtime %u, matching by device identity (vendor 0x%04x device 0x%04x)\n",
|
||||
vhdr->PCIBus, adev->pdev->bus->number,
|
||||
adev->pdev->vendor, adev->pdev->device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
|
||||
{
|
||||
struct acpi_table_header *hdr;
|
||||
acpi_size tbl_size;
|
||||
UEFI_ACPI_VFCT *vfct;
|
||||
unsigned int offset;
|
||||
bool r = false;
|
||||
|
||||
if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
|
||||
return false;
|
||||
tbl_size = hdr->length;
|
||||
if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
|
||||
dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vfct = (UEFI_ACPI_VFCT *)hdr;
|
||||
|
|
@ -397,36 +437,36 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
|
|||
offset += sizeof(VFCT_IMAGE_HEADER);
|
||||
if (offset > tbl_size) {
|
||||
dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset += vhdr->ImageLength;
|
||||
if (offset > tbl_size) {
|
||||
dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vhdr->ImageLength &&
|
||||
vhdr->PCIBus == adev->pdev->bus->number &&
|
||||
vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
|
||||
vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
|
||||
vhdr->VendorID == adev->pdev->vendor &&
|
||||
vhdr->DeviceID == adev->pdev->device) {
|
||||
!amdgpu_acpi_vfct_match(adev, vhdr)) {
|
||||
adev->bios = kmemdup(&vbios->VbiosContent,
|
||||
vhdr->ImageLength,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!check_atom_bios(adev, vhdr->ImageLength)) {
|
||||
amdgpu_bios_release(adev);
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
adev->bios_size = vhdr->ImageLength;
|
||||
return true;
|
||||
r = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
|
||||
return false;
|
||||
|
||||
out:
|
||||
acpi_put_table(hdr);
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
|
||||
|
|
|
|||
|
|
@ -234,6 +234,9 @@ amdgpu_devcoredump_print_ibs(struct drm_printer *p,
|
|||
drm_printf(p, "\nIB #%d 0x%llx %d dw\n", i,
|
||||
coredump->ibs[i].gpu_addr,
|
||||
coredump->ibs[i].ib_size_dw);
|
||||
|
||||
for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
|
||||
drm_printf(p, "0xffffffff\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -355,10 +358,14 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
|
|||
drm_printf(&p, "kernel: %s\n", init_utsname()->release);
|
||||
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
|
||||
drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
|
||||
drm_printf(&p, "pasid: %u\n", coredump->pasid);
|
||||
drm_printf(&p, "vmid: %u\n", coredump->vmid);
|
||||
|
||||
if (coredump->reset_task_info.task.pid)
|
||||
drm_printf(&p, "process_name: %s PID: %d\n",
|
||||
drm_printf(&p, "process_name: %s TGID: %d thread: %s PID: %d\n",
|
||||
coredump->reset_task_info.process_name,
|
||||
coredump->reset_task_info.tgid,
|
||||
coredump->reset_task_info.task.comm,
|
||||
coredump->reset_task_info.task.pid);
|
||||
|
||||
/* SOC Information */
|
||||
|
|
@ -562,6 +569,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
amdgpu_vm_put_task_info(ti);
|
||||
}
|
||||
coredump->pasid = job->pasid;
|
||||
coredump->vmid = job->vmid;
|
||||
coredump->num_ibs = job->num_ibs;
|
||||
for (i = 0; i < job->num_ibs; ++i) {
|
||||
coredump->ibs[i].gpu_addr = job->ibs[i].gpu_addr;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ struct amdgpu_coredump_info {
|
|||
char *formatted;
|
||||
|
||||
unsigned int pasid;
|
||||
unsigned int vmid;
|
||||
int num_ibs;
|
||||
struct amdgpu_coredump_ib_info ibs[] __counted_by(num_ibs);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1323,6 +1323,15 @@ static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device
|
|||
|
||||
if (c->x86_vendor == X86_VENDOR_INTEL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs don't
|
||||
* support PCIe dynamic speed switching.
|
||||
* https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
|
||||
*/
|
||||
if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 0x17 &&
|
||||
c->x86_model == 0x08)
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3137,9 +3137,11 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
break;
|
||||
case IP_VERSION(11, 7, 0):
|
||||
case IP_VERSION(11, 7, 1):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_4;
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
|
|
|
|||
|
|
@ -276,10 +276,12 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
|
|||
goto error_free;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_pin(*bo_ptr, domain);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
|
||||
goto error_unreserve;
|
||||
if (free) {
|
||||
r = amdgpu_bo_pin(*bo_ptr, domain);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
|
||||
goto error_unreserve;
|
||||
}
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_alloc_gart(&(*bo_ptr)->tbo);
|
||||
|
|
@ -302,7 +304,8 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
|
||||
error_unpin:
|
||||
amdgpu_bo_unpin(*bo_ptr);
|
||||
if (free)
|
||||
amdgpu_bo_unpin(*bo_ptr);
|
||||
error_unreserve:
|
||||
amdgpu_bo_unreserve(*bo_ptr);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user