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