Merge 0bbac3facb ("Linux 6.9-rc4") into android-mainline
Steps on the way to v6.9 Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I9bca26b829ba5a045e8e5df010e9300b43ca4398
This commit is contained in:
@@ -3146,6 +3146,10 @@ S: Triftstra=DFe 55
|
||||
S: 13353 Berlin
|
||||
S: Germany
|
||||
|
||||
N: Gustavo Pimental
|
||||
E: gustavo.pimentel@synopsys.com
|
||||
D: PCI driver for Synopsys DesignWare
|
||||
|
||||
N: Emanuel Pirker
|
||||
E: epirker@edu.uni-klu.ac.at
|
||||
D: AIC5800 IEEE 1394, RAW I/O on 1394
|
||||
|
||||
@@ -138,11 +138,10 @@ associated with the source address of the indirect branch. Specifically,
|
||||
the BHB might be shared across privilege levels even in the presence of
|
||||
Enhanced IBRS.
|
||||
|
||||
Currently the only known real-world BHB attack vector is via
|
||||
unprivileged eBPF. Therefore, it's highly recommended to not enable
|
||||
unprivileged eBPF, especially when eIBRS is used (without retpolines).
|
||||
For a full mitigation against BHB attacks, it's recommended to use
|
||||
retpolines (or eIBRS combined with retpolines).
|
||||
Previously the only known real-world BHB attack vector was via unprivileged
|
||||
eBPF. Further research has found attacks that don't require unprivileged eBPF.
|
||||
For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or
|
||||
use the BHB clearing sequence.
|
||||
|
||||
Attack scenarios
|
||||
----------------
|
||||
@@ -430,6 +429,23 @@ The possible values in this file are:
|
||||
'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB
|
||||
=========================== =======================================================
|
||||
|
||||
- Branch History Injection (BHI) protection status:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - BHI: Not affected
|
||||
- System is not affected
|
||||
* - BHI: Retpoline
|
||||
- System is protected by retpoline
|
||||
* - BHI: BHI_DIS_S
|
||||
- System is protected by BHI_DIS_S
|
||||
* - BHI: SW loop, KVM SW loop
|
||||
- System is protected by software clearing sequence
|
||||
* - BHI: Vulnerable
|
||||
- System is vulnerable to BHI
|
||||
* - BHI: Vulnerable, KVM: SW loop
|
||||
- System is vulnerable; KVM is protected by software clearing sequence
|
||||
|
||||
Full mitigation might require a microcode update from the CPU
|
||||
vendor. When the necessary microcode is not available, the kernel will
|
||||
report vulnerability.
|
||||
@@ -484,7 +500,11 @@ Spectre variant 2
|
||||
|
||||
Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at
|
||||
boot, by setting the IBRS bit, and they're automatically protected against
|
||||
Spectre v2 variant attacks.
|
||||
some Spectre v2 variant attacks. The BHB can still influence the choice of
|
||||
indirect branch predictor entry, and although branch predictor entries are
|
||||
isolated between modes when eIBRS is enabled, the BHB itself is not isolated
|
||||
between modes. Systems which support BHI_DIS_S will set it to protect against
|
||||
BHI attacks.
|
||||
|
||||
On Intel's enhanced IBRS systems, this includes cross-thread branch target
|
||||
injections on SMT systems (STIBP). In other words, Intel eIBRS enables
|
||||
@@ -638,6 +658,18 @@ kernel command line.
|
||||
spectre_v2=off. Spectre variant 1 mitigations
|
||||
cannot be disabled.
|
||||
|
||||
spectre_bhi=
|
||||
|
||||
[X86] Control mitigation of Branch History Injection
|
||||
(BHI) vulnerability. This setting affects the deployment
|
||||
of the HW BHI control and the SW BHB clearing sequence.
|
||||
|
||||
on
|
||||
(default) Enable the HW or SW mitigation as
|
||||
needed.
|
||||
off
|
||||
Disable the mitigation.
|
||||
|
||||
For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
|
||||
|
||||
Mitigation selection guide
|
||||
|
||||
@@ -3448,6 +3448,7 @@
|
||||
retbleed=off [X86]
|
||||
spec_rstack_overflow=off [X86]
|
||||
spec_store_bypass_disable=off [X86,PPC]
|
||||
spectre_bhi=off [X86]
|
||||
spectre_v2_user=off [X86]
|
||||
srbds=off [X86,INTEL]
|
||||
ssbd=force-off [ARM64]
|
||||
@@ -6082,6 +6083,15 @@
|
||||
sonypi.*= [HW] Sony Programmable I/O Control Device driver
|
||||
See Documentation/admin-guide/laptops/sonypi.rst
|
||||
|
||||
spectre_bhi= [X86] Control mitigation of Branch History Injection
|
||||
(BHI) vulnerability. This setting affects the
|
||||
deployment of the HW BHI control and the SW BHB
|
||||
clearing sequence.
|
||||
|
||||
on - (default) Enable the HW or SW mitigation
|
||||
as needed.
|
||||
off - Disable the mitigation.
|
||||
|
||||
spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2
|
||||
(indirect branch speculation) vulnerability.
|
||||
The default operation protects the kernel from
|
||||
|
||||
@@ -53,6 +53,15 @@ patternProperties:
|
||||
compatible:
|
||||
const: qcom,sm8150-dpu
|
||||
|
||||
"^displayport-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,sm8150-dp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
@@ -97,7 +97,6 @@ like this::
|
||||
|
||||
static struct virtio_driver virtio_dummy_driver = {
|
||||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.probe = virtio_dummy_probe,
|
||||
.remove = virtio_dummy_remove,
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================
|
||||
bcachefs Documentation
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
errorcodes
|
||||
@@ -69,6 +69,7 @@ Documentation for filesystem implementations.
|
||||
afs
|
||||
autofs
|
||||
autofs-mount-control
|
||||
bcachefs/index
|
||||
befs
|
||||
bfs
|
||||
btrfs
|
||||
|
||||
+24
-30
@@ -2191,7 +2191,6 @@ N: mxs
|
||||
|
||||
ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE
|
||||
M: Shawn Guo <shawnguo@kernel.org>
|
||||
M: Li Yang <leoyang.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/shawnguo/linux.git
|
||||
@@ -2708,7 +2707,7 @@ F: sound/soc/rockchip/
|
||||
N: rockchip
|
||||
|
||||
ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
R: Alim Akhtar <alim.akhtar@samsung.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: linux-samsung-soc@vger.kernel.org
|
||||
@@ -3573,6 +3572,7 @@ S: Supported
|
||||
C: irc://irc.oftc.net/bcache
|
||||
T: git https://evilpiepirate.org/git/bcachefs.git
|
||||
F: fs/bcachefs/
|
||||
F: Documentation/filesystems/bcachefs/
|
||||
|
||||
BDISP ST MEDIA DRIVER
|
||||
M: Fabien Dessenne <fabien.dessenne@foss.st.com>
|
||||
@@ -4869,7 +4869,6 @@ F: drivers/power/supply/cw2015_battery.c
|
||||
CEPH COMMON CODE (LIBCEPH)
|
||||
M: Ilya Dryomov <idryomov@gmail.com>
|
||||
M: Xiubo Li <xiubli@redhat.com>
|
||||
R: Jeff Layton <jlayton@kernel.org>
|
||||
L: ceph-devel@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://ceph.com/
|
||||
@@ -4881,7 +4880,6 @@ F: net/ceph/
|
||||
CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH)
|
||||
M: Xiubo Li <xiubli@redhat.com>
|
||||
M: Ilya Dryomov <idryomov@gmail.com>
|
||||
R: Jeff Layton <jlayton@kernel.org>
|
||||
L: ceph-devel@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://ceph.com/
|
||||
@@ -5557,7 +5555,7 @@ F: drivers/cpuidle/cpuidle-big_little.c
|
||||
CPUIDLE DRIVER - ARM EXYNOS
|
||||
M: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
M: Kukjin Kim <kgene@kernel.org>
|
||||
R: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
R: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
L: linux-samsung-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -8523,7 +8521,6 @@ S: Maintained
|
||||
F: drivers/video/fbdev/fsl-diu-fb.*
|
||||
|
||||
FREESCALE DMA DRIVER
|
||||
M: Li Yang <leoyang.li@nxp.com>
|
||||
M: Zhang Wei <zw@zh-kernel.org>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Maintained
|
||||
@@ -8688,10 +8685,9 @@ F: drivers/soc/fsl/qe/tsa.h
|
||||
F: include/dt-bindings/soc/cpm1-fsl,tsa.h
|
||||
|
||||
FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
|
||||
M: Li Yang <leoyang.li@nxp.com>
|
||||
L: netdev@vger.kernel.org
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/net/ethernet/freescale/ucc_geth*
|
||||
|
||||
FREESCALE QUICC ENGINE UCC HDLC DRIVER
|
||||
@@ -8708,10 +8704,9 @@ S: Maintained
|
||||
F: drivers/tty/serial/ucc_uart.c
|
||||
|
||||
FREESCALE SOC DRIVERS
|
||||
M: Li Yang <leoyang.li@nxp.com>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml
|
||||
F: Documentation/devicetree/bindings/soc/fsl/
|
||||
F: drivers/soc/fsl/
|
||||
@@ -8745,10 +8740,9 @@ F: Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml
|
||||
F: sound/soc/fsl/fsl_qmc_audio.c
|
||||
|
||||
FREESCALE USB PERIPHERAL DRIVERS
|
||||
M: Li Yang <leoyang.li@nxp.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/usb/gadget/udc/fsl*
|
||||
|
||||
FREESCALE USB PHY DRIVER
|
||||
@@ -9000,7 +8994,7 @@ F: drivers/i2c/muxes/i2c-mux-gpio.c
|
||||
F: include/linux/platform_data/i2c-mux-gpio.h
|
||||
|
||||
GENERIC GPIO RESET DRIVER
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
S: Maintained
|
||||
F: drivers/reset/reset-gpio.c
|
||||
|
||||
@@ -13302,7 +13296,7 @@ F: drivers/iio/adc/max11205.c
|
||||
|
||||
MAXIM MAX17040 FAMILY FUEL GAUGE DRIVERS
|
||||
R: Iskren Chernev <iskren.chernev@gmail.com>
|
||||
R: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
R: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
R: Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
R: Matheus Castello <matheus@castello.eng.br>
|
||||
L: linux-pm@vger.kernel.org
|
||||
@@ -13312,7 +13306,7 @@ F: drivers/power/supply/max17040_battery.c
|
||||
|
||||
MAXIM MAX17042 FAMILY FUEL GAUGE DRIVERS
|
||||
R: Hans de Goede <hdegoede@redhat.com>
|
||||
R: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
R: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
R: Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
R: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
|
||||
R: Purism Kernel Team <kernel@puri.sm>
|
||||
@@ -13370,7 +13364,7 @@ F: Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml
|
||||
F: drivers/power/supply/max77976_charger.c
|
||||
|
||||
MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
S: Maintained
|
||||
B: mailto:linux-samsung-soc@vger.kernel.org
|
||||
@@ -13381,7 +13375,7 @@ F: drivers/power/supply/max77693_charger.c
|
||||
|
||||
MAXIM PMIC AND MUIC DRIVERS FOR EXYNOS BASED BOARDS
|
||||
M: Chanwoo Choi <cw00.choi@samsung.com>
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
B: mailto:linux-samsung-soc@vger.kernel.org
|
||||
@@ -14165,7 +14159,7 @@ F: mm/mm_init.c
|
||||
F: tools/testing/memblock/
|
||||
|
||||
MEMORY CONTROLLER DRIVERS
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
B: mailto:krzysztof.kozlowski@linaro.org
|
||||
@@ -15546,7 +15540,7 @@ F: include/uapi/linux/nexthop.h
|
||||
F: net/ipv4/nexthop.c
|
||||
|
||||
NFC SUBSYSTEM
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/nfc/
|
||||
@@ -15923,7 +15917,7 @@ F: Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml
|
||||
F: drivers/regulator/pf8x00-regulator.c
|
||||
|
||||
NXP PTN5150A CC LOGIC AND EXTCON DRIVER
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml
|
||||
@@ -16534,7 +16528,7 @@ K: of_overlay_remove
|
||||
|
||||
OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
|
||||
M: Rob Herring <robh@kernel.org>
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk+dt@kernel.org>
|
||||
M: Conor Dooley <conor+dt@kernel.org>
|
||||
L: devicetree@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -16981,7 +16975,6 @@ F: drivers/pci/controller/dwc/pci-exynos.c
|
||||
|
||||
PCI DRIVER FOR SYNOPSYS DESIGNWARE
|
||||
M: Jingoo Han <jingoohan1@gmail.com>
|
||||
M: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
|
||||
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -17492,7 +17485,7 @@ F: Documentation/devicetree/bindings/pinctrl/renesas,*
|
||||
F: drivers/pinctrl/renesas/
|
||||
|
||||
PIN CONTROLLER - SAMSUNG
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
R: Alim Akhtar <alim.akhtar@samsung.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
@@ -19460,7 +19453,7 @@ F: Documentation/devicetree/bindings/sound/samsung*
|
||||
F: sound/soc/samsung/
|
||||
|
||||
SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-crypto@vger.kernel.org
|
||||
L: linux-samsung-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -19495,7 +19488,7 @@ S: Maintained
|
||||
F: drivers/platform/x86/samsung-laptop.c
|
||||
|
||||
SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
L: linux-samsung-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -19521,7 +19514,7 @@ F: drivers/media/platform/samsung/s3c-camif/
|
||||
F: include/media/drv-intf/s3c_camif.h
|
||||
|
||||
SAMSUNG S3FWRN5 NFC DRIVER
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
|
||||
F: drivers/nfc/s3fwrn5
|
||||
@@ -19542,7 +19535,7 @@ S: Supported
|
||||
F: drivers/media/i2c/s5k5baf.c
|
||||
|
||||
SAMSUNG S5P Security SubSystem (SSS) DRIVER
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
M: Vladimir Zapolskiy <vz@mleia.com>
|
||||
L: linux-crypto@vger.kernel.org
|
||||
L: linux-samsung-soc@vger.kernel.org
|
||||
@@ -19564,7 +19557,7 @@ F: Documentation/devicetree/bindings/media/samsung,fimc.yaml
|
||||
F: drivers/media/platform/samsung/exynos4-is/
|
||||
|
||||
SAMSUNG SOC CLOCK DRIVERS
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
M: Chanwoo Choi <cw00.choi@samsung.com>
|
||||
R: Alim Akhtar <alim.akhtar@samsung.com>
|
||||
@@ -19596,7 +19589,7 @@ F: drivers/net/ethernet/samsung/sxgbe/
|
||||
|
||||
SAMSUNG THERMAL DRIVER
|
||||
M: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
L: linux-samsung-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -22584,6 +22577,7 @@ Q: https://patchwork.kernel.org/project/linux-pm/list/
|
||||
B: https://bugzilla.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git turbostat
|
||||
F: tools/power/x86/turbostat/
|
||||
F: tools/testing/selftests/turbostat/
|
||||
|
||||
TW5864 VIDEO4LINUX DRIVER
|
||||
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
|
||||
@@ -23792,7 +23786,7 @@ S: Orphan
|
||||
F: drivers/mmc/host/vub300.c
|
||||
|
||||
W1 DALLAS'S 1-WIRE BUS
|
||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
M: Krzysztof Kozlowski <krzk@kernel.org>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/w1/
|
||||
F: Documentation/w1/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Hurr durr I'ma ninja sloth
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
+6
-6
@@ -1172,12 +1172,12 @@ config PAGE_SIZE_LESS_THAN_256KB
|
||||
|
||||
config PAGE_SHIFT
|
||||
int
|
||||
default 12 if PAGE_SIZE_4KB
|
||||
default 13 if PAGE_SIZE_8KB
|
||||
default 14 if PAGE_SIZE_16KB
|
||||
default 15 if PAGE_SIZE_32KB
|
||||
default 16 if PAGE_SIZE_64KB
|
||||
default 18 if PAGE_SIZE_256KB
|
||||
default 12 if PAGE_SIZE_4KB
|
||||
default 13 if PAGE_SIZE_8KB
|
||||
default 14 if PAGE_SIZE_16KB
|
||||
default 15 if PAGE_SIZE_32KB
|
||||
default 16 if PAGE_SIZE_64KB
|
||||
default 18 if PAGE_SIZE_256KB
|
||||
|
||||
# This allows to use a set of generic functions to determine mmap base
|
||||
# address by giving priority to top-down scheme only if the process
|
||||
|
||||
@@ -666,7 +666,7 @@
|
||||
bus-width = <4>;
|
||||
no-1-8-v;
|
||||
no-sdio;
|
||||
no-emmc;
|
||||
no-mmc;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
remote-endpoint = <&mipi_from_sensor>;
|
||||
clock-lanes = <0>;
|
||||
data-lanes = <1>;
|
||||
link-frequencies = /bits/ 64 <330000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -79,10 +79,8 @@ static struct musb_hdrc_platform_data tusb_data = {
|
||||
static struct gpiod_lookup_table tusb_gpio_table = {
|
||||
.dev_id = "musb-tusb",
|
||||
.table = {
|
||||
GPIO_LOOKUP("gpio-0-15", 0, "enable",
|
||||
GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio-48-63", 10, "int",
|
||||
GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio-0-31", 0, "enable", GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio-32-63", 26, "int", GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
@@ -140,12 +138,11 @@ static int slot1_cover_open;
|
||||
static int slot2_cover_open;
|
||||
static struct device *mmc_device;
|
||||
|
||||
static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
|
||||
static struct gpiod_lookup_table nokia800_mmc_gpio_table = {
|
||||
.dev_id = "mmci-omap.0",
|
||||
.table = {
|
||||
/* Slot switch, GPIO 96 */
|
||||
GPIO_LOOKUP("gpio-80-111", 16,
|
||||
"switch", GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
@@ -153,12 +150,12 @@ static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
|
||||
static struct gpiod_lookup_table nokia810_mmc_gpio_table = {
|
||||
.dev_id = "mmci-omap.0",
|
||||
.table = {
|
||||
/* Slot switch, GPIO 96 */
|
||||
GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH),
|
||||
/* Slot index 1, VSD power, GPIO 23 */
|
||||
GPIO_LOOKUP_IDX("gpio-16-31", 7,
|
||||
"vsd", 1, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP_IDX("gpio-0-31", 23, "vsd", 1, GPIO_ACTIVE_HIGH),
|
||||
/* Slot index 1, VIO power, GPIO 9 */
|
||||
GPIO_LOOKUP_IDX("gpio-0-15", 9,
|
||||
"vio", 1, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP_IDX("gpio-0-31", 9, "vio", 1, GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
},
|
||||
};
|
||||
@@ -415,8 +412,6 @@ static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
|
||||
|
||||
static void __init n8x0_mmc_init(void)
|
||||
{
|
||||
gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table);
|
||||
|
||||
if (board_is_n810()) {
|
||||
mmc1_data.slots[0].name = "external";
|
||||
|
||||
@@ -429,6 +424,8 @@ static void __init n8x0_mmc_init(void)
|
||||
mmc1_data.slots[1].name = "internal";
|
||||
mmc1_data.slots[1].ban_openended = 1;
|
||||
gpiod_add_lookup_table(&nokia810_mmc_gpio_table);
|
||||
} else {
|
||||
gpiod_add_lookup_table(&nokia800_mmc_gpio_table);
|
||||
}
|
||||
|
||||
mmc1_data.nr_slots = 2;
|
||||
|
||||
@@ -41,7 +41,7 @@ conn_subsys: bus@5b000000 {
|
||||
interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
|
||||
fsl,usbphy = <&usbphy1>;
|
||||
fsl,usbmisc = <&usbmisc1 0>;
|
||||
clocks = <&usb2_lpcg 0>;
|
||||
clocks = <&usb2_lpcg IMX_LPCG_CLK_6>;
|
||||
ahb-burst-config = <0x0>;
|
||||
tx-burst-size-dword = <0x10>;
|
||||
rx-burst-size-dword = <0x10>;
|
||||
@@ -58,7 +58,7 @@ conn_subsys: bus@5b000000 {
|
||||
usbphy1: usbphy@5b100000 {
|
||||
compatible = "fsl,imx7ulp-usbphy";
|
||||
reg = <0x5b100000 0x1000>;
|
||||
clocks = <&usb2_lpcg 1>;
|
||||
clocks = <&usb2_lpcg IMX_LPCG_CLK_7>;
|
||||
power-domains = <&pd IMX_SC_R_USB_0_PHY>;
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -67,8 +67,8 @@ conn_subsys: bus@5b000000 {
|
||||
interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg = <0x5b010000 0x10000>;
|
||||
clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>,
|
||||
<&sdhc0_lpcg IMX_LPCG_CLK_0>,
|
||||
<&sdhc0_lpcg IMX_LPCG_CLK_5>;
|
||||
<&sdhc0_lpcg IMX_LPCG_CLK_5>,
|
||||
<&sdhc0_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "ahb", "per";
|
||||
power-domains = <&pd IMX_SC_R_SDHC_0>;
|
||||
status = "disabled";
|
||||
@@ -78,8 +78,8 @@ conn_subsys: bus@5b000000 {
|
||||
interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg = <0x5b020000 0x10000>;
|
||||
clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>,
|
||||
<&sdhc1_lpcg IMX_LPCG_CLK_0>,
|
||||
<&sdhc1_lpcg IMX_LPCG_CLK_5>;
|
||||
<&sdhc1_lpcg IMX_LPCG_CLK_5>,
|
||||
<&sdhc1_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "ahb", "per";
|
||||
power-domains = <&pd IMX_SC_R_SDHC_1>;
|
||||
fsl,tuning-start-tap = <20>;
|
||||
@@ -91,8 +91,8 @@ conn_subsys: bus@5b000000 {
|
||||
interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg = <0x5b030000 0x10000>;
|
||||
clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>,
|
||||
<&sdhc2_lpcg IMX_LPCG_CLK_0>,
|
||||
<&sdhc2_lpcg IMX_LPCG_CLK_5>;
|
||||
<&sdhc2_lpcg IMX_LPCG_CLK_5>,
|
||||
<&sdhc2_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "ahb", "per";
|
||||
power-domains = <&pd IMX_SC_R_SDHC_2>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -28,8 +28,8 @@ dma_subsys: bus@5a000000 {
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&spi0_lpcg 0>,
|
||||
<&spi0_lpcg 1>;
|
||||
clocks = <&spi0_lpcg IMX_LPCG_CLK_0>,
|
||||
<&spi0_lpcg IMX_LPCG_CLK_4>;
|
||||
clock-names = "per", "ipg";
|
||||
assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <60000000>;
|
||||
@@ -44,8 +44,8 @@ dma_subsys: bus@5a000000 {
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&spi1_lpcg 0>,
|
||||
<&spi1_lpcg 1>;
|
||||
clocks = <&spi1_lpcg IMX_LPCG_CLK_0>,
|
||||
<&spi1_lpcg IMX_LPCG_CLK_4>;
|
||||
clock-names = "per", "ipg";
|
||||
assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <60000000>;
|
||||
@@ -60,8 +60,8 @@ dma_subsys: bus@5a000000 {
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&spi2_lpcg 0>,
|
||||
<&spi2_lpcg 1>;
|
||||
clocks = <&spi2_lpcg IMX_LPCG_CLK_0>,
|
||||
<&spi2_lpcg IMX_LPCG_CLK_4>;
|
||||
clock-names = "per", "ipg";
|
||||
assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <60000000>;
|
||||
@@ -76,8 +76,8 @@ dma_subsys: bus@5a000000 {
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&spi3_lpcg 0>,
|
||||
<&spi3_lpcg 1>;
|
||||
clocks = <&spi3_lpcg IMX_LPCG_CLK_0>,
|
||||
<&spi3_lpcg IMX_LPCG_CLK_4>;
|
||||
clock-names = "per", "ipg";
|
||||
assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <60000000>;
|
||||
@@ -145,8 +145,8 @@ dma_subsys: bus@5a000000 {
|
||||
compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
|
||||
reg = <0x5a190000 0x1000>;
|
||||
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&adma_pwm_lpcg 1>,
|
||||
<&adma_pwm_lpcg 0>;
|
||||
clocks = <&adma_pwm_lpcg IMX_LPCG_CLK_4>,
|
||||
<&adma_pwm_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "per";
|
||||
assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
@@ -355,8 +355,8 @@ dma_subsys: bus@5a000000 {
|
||||
reg = <0x5a880000 0x10000>;
|
||||
interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&adc0_lpcg 0>,
|
||||
<&adc0_lpcg 1>;
|
||||
clocks = <&adc0_lpcg IMX_LPCG_CLK_0>,
|
||||
<&adc0_lpcg IMX_LPCG_CLK_4>;
|
||||
clock-names = "per", "ipg";
|
||||
assigned-clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
@@ -370,8 +370,8 @@ dma_subsys: bus@5a000000 {
|
||||
reg = <0x5a890000 0x10000>;
|
||||
interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&adc1_lpcg 0>,
|
||||
<&adc1_lpcg 1>;
|
||||
clocks = <&adc1_lpcg IMX_LPCG_CLK_0>,
|
||||
<&adc1_lpcg IMX_LPCG_CLK_4>;
|
||||
clock-names = "per", "ipg";
|
||||
assigned-clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
@@ -384,8 +384,8 @@ dma_subsys: bus@5a000000 {
|
||||
reg = <0x5a8d0000 0x10000>;
|
||||
interrupts = <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&can0_lpcg 1>,
|
||||
<&can0_lpcg 0>;
|
||||
clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
|
||||
<&can0_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "per";
|
||||
assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <40000000>;
|
||||
@@ -405,8 +405,8 @@ dma_subsys: bus@5a000000 {
|
||||
* CAN1 shares CAN0's clock and to enable CAN0's clock it
|
||||
* has to be powered on.
|
||||
*/
|
||||
clocks = <&can0_lpcg 1>,
|
||||
<&can0_lpcg 0>;
|
||||
clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
|
||||
<&can0_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "per";
|
||||
assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <40000000>;
|
||||
@@ -426,8 +426,8 @@ dma_subsys: bus@5a000000 {
|
||||
* CAN2 shares CAN0's clock and to enable CAN0's clock it
|
||||
* has to be powered on.
|
||||
*/
|
||||
clocks = <&can0_lpcg 1>,
|
||||
<&can0_lpcg 0>;
|
||||
clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
|
||||
<&can0_lpcg IMX_LPCG_CLK_0>;
|
||||
clock-names = "ipg", "per";
|
||||
assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <40000000>;
|
||||
|
||||
@@ -25,8 +25,8 @@ lsio_subsys: bus@5d000000 {
|
||||
compatible = "fsl,imx27-pwm";
|
||||
reg = <0x5d000000 0x10000>;
|
||||
clock-names = "ipg", "per";
|
||||
clocks = <&pwm0_lpcg 4>,
|
||||
<&pwm0_lpcg 1>;
|
||||
clocks = <&pwm0_lpcg IMX_LPCG_CLK_6>,
|
||||
<&pwm0_lpcg IMX_LPCG_CLK_1>;
|
||||
assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
#pwm-cells = <3>;
|
||||
@@ -38,8 +38,8 @@ lsio_subsys: bus@5d000000 {
|
||||
compatible = "fsl,imx27-pwm";
|
||||
reg = <0x5d010000 0x10000>;
|
||||
clock-names = "ipg", "per";
|
||||
clocks = <&pwm1_lpcg 4>,
|
||||
<&pwm1_lpcg 1>;
|
||||
clocks = <&pwm1_lpcg IMX_LPCG_CLK_6>,
|
||||
<&pwm1_lpcg IMX_LPCG_CLK_1>;
|
||||
assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
#pwm-cells = <3>;
|
||||
@@ -51,8 +51,8 @@ lsio_subsys: bus@5d000000 {
|
||||
compatible = "fsl,imx27-pwm";
|
||||
reg = <0x5d020000 0x10000>;
|
||||
clock-names = "ipg", "per";
|
||||
clocks = <&pwm2_lpcg 4>,
|
||||
<&pwm2_lpcg 1>;
|
||||
clocks = <&pwm2_lpcg IMX_LPCG_CLK_6>,
|
||||
<&pwm2_lpcg IMX_LPCG_CLK_1>;
|
||||
assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
#pwm-cells = <3>;
|
||||
@@ -64,8 +64,8 @@ lsio_subsys: bus@5d000000 {
|
||||
compatible = "fsl,imx27-pwm";
|
||||
reg = <0x5d030000 0x10000>;
|
||||
clock-names = "ipg", "per";
|
||||
clocks = <&pwm3_lpcg 4>,
|
||||
<&pwm3_lpcg 1>;
|
||||
clocks = <&pwm3_lpcg IMX_LPCG_CLK_6>,
|
||||
<&pwm3_lpcg IMX_LPCG_CLK_1>;
|
||||
assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
#pwm-cells = <3>;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
pinctrl-0 = <&pinctrl_usbcon1>;
|
||||
type = "micro";
|
||||
label = "otg";
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
port {
|
||||
@@ -183,7 +184,6 @@
|
||||
};
|
||||
|
||||
&usb3_phy0 {
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
pinctrl-0 = <&pinctrl_usbcon1>;
|
||||
type = "micro";
|
||||
label = "otg";
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
port {
|
||||
@@ -202,7 +203,6 @@
|
||||
};
|
||||
|
||||
&usb3_phy0 {
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -153,15 +153,15 @@
|
||||
};
|
||||
|
||||
&flexcan2 {
|
||||
clocks = <&can1_lpcg 1>,
|
||||
<&can1_lpcg 0>;
|
||||
clocks = <&can1_lpcg IMX_LPCG_CLK_4>,
|
||||
<&can1_lpcg IMX_LPCG_CLK_0>;
|
||||
assigned-clocks = <&clk IMX_SC_R_CAN_1 IMX_SC_PM_CLK_PER>;
|
||||
fsl,clk-source = /bits/ 8 <1>;
|
||||
};
|
||||
|
||||
&flexcan3 {
|
||||
clocks = <&can2_lpcg 1>,
|
||||
<&can2_lpcg 0>;
|
||||
clocks = <&can2_lpcg IMX_LPCG_CLK_4>,
|
||||
<&can2_lpcg IMX_LPCG_CLK_0>;
|
||||
assigned-clocks = <&clk IMX_SC_R_CAN_2 IMX_SC_PM_CLK_PER>;
|
||||
fsl,clk-source = /bits/ 8 <1>;
|
||||
};
|
||||
|
||||
@@ -161,12 +161,18 @@ static inline unsigned long get_trans_granule(void)
|
||||
#define MAX_TLBI_RANGE_PAGES __TLBI_RANGE_PAGES(31, 3)
|
||||
|
||||
/*
|
||||
* Generate 'num' values from -1 to 30 with -1 rejected by the
|
||||
* __flush_tlb_range() loop below.
|
||||
* Generate 'num' values from -1 to 31 with -1 rejected by the
|
||||
* __flush_tlb_range() loop below. Its return value is only
|
||||
* significant for a maximum of MAX_TLBI_RANGE_PAGES pages. If
|
||||
* 'pages' is more than that, you must iterate over the overall
|
||||
* range.
|
||||
*/
|
||||
#define TLBI_RANGE_MASK GENMASK_ULL(4, 0)
|
||||
#define __TLBI_RANGE_NUM(pages, scale) \
|
||||
((((pages) >> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1)
|
||||
#define __TLBI_RANGE_NUM(pages, scale) \
|
||||
({ \
|
||||
int __pages = min((pages), \
|
||||
__TLBI_RANGE_PAGES(31, (scale))); \
|
||||
(__pages >> (5 * (scale) + 1)) - 1; \
|
||||
})
|
||||
|
||||
/*
|
||||
* TLB Invalidation
|
||||
@@ -379,10 +385,6 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
|
||||
* 3. If there is 1 page remaining, flush it through non-range operations. Range
|
||||
* operations can only span an even number of pages. We save this for last to
|
||||
* ensure 64KB start alignment is maintained for the LPA2 case.
|
||||
*
|
||||
* Note that certain ranges can be represented by either num = 31 and
|
||||
* scale or num = 0 and scale + 1. The loop below favours the latter
|
||||
* since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
|
||||
*/
|
||||
#define __flush_tlb_range_op(op, start, pages, stride, \
|
||||
asid, tlb_level, tlbi_user, lpa2) \
|
||||
|
||||
@@ -100,6 +100,13 @@
|
||||
#size-cells = <2>;
|
||||
dma-coherent;
|
||||
|
||||
isa@18000000 {
|
||||
compatible = "isa";
|
||||
#size-cells = <1>;
|
||||
#address-cells = <2>;
|
||||
ranges = <1 0x0 0x0 0x18000000 0x4000>;
|
||||
};
|
||||
|
||||
liointc0: interrupt-controller@1fe01400 {
|
||||
compatible = "loongson,liointc-2.0";
|
||||
reg = <0x0 0x1fe01400 0x0 0x40>,
|
||||
|
||||
@@ -61,12 +61,45 @@
|
||||
|
||||
&gmac0 {
|
||||
status = "okay";
|
||||
|
||||
phy-mode = "gmii";
|
||||
phy-handle = <&phy0>;
|
||||
mdio {
|
||||
compatible = "snps,dwmac-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
status = "okay";
|
||||
|
||||
phy-mode = "gmii";
|
||||
phy-handle = <&phy1>;
|
||||
mdio {
|
||||
compatible = "snps,dwmac-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gmac2 {
|
||||
status = "okay";
|
||||
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&phy2>;
|
||||
mdio {
|
||||
compatible = "snps,dwmac-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy2: ethernet-phy@2 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -51,6 +51,13 @@
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
isa@18400000 {
|
||||
compatible = "isa";
|
||||
#size-cells = <1>;
|
||||
#address-cells = <2>;
|
||||
ranges = <1 0x0 0x0 0x18400000 0x4000>;
|
||||
};
|
||||
|
||||
pmc: power-management@100d0000 {
|
||||
compatible = "loongson,ls2k2000-pmc", "loongson,ls2k0500-pmc", "syscon";
|
||||
reg = <0x0 0x100d0000 0x0 0x58>;
|
||||
@@ -109,6 +116,8 @@
|
||||
msi: msi-controller@1fe01140 {
|
||||
compatible = "loongson,pch-msi-1.0";
|
||||
reg = <0x0 0x1fe01140 0x0 0x8>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
msi-controller;
|
||||
loongson,msi-base-vec = <64>;
|
||||
loongson,msi-num-vecs = <192>;
|
||||
@@ -140,27 +149,34 @@
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
device_type = "pci";
|
||||
msi-parent = <&msi>;
|
||||
bus-range = <0x0 0xff>;
|
||||
ranges = <0x01000000 0x0 0x00008000 0x0 0x18400000 0x0 0x00008000>,
|
||||
ranges = <0x01000000 0x0 0x00008000 0x0 0x18408000 0x0 0x00008000>,
|
||||
<0x02000000 0x0 0x60000000 0x0 0x60000000 0x0 0x20000000>;
|
||||
|
||||
gmac0: ethernet@3,0 {
|
||||
reg = <0x1800 0x0 0x0 0x0 0x0>;
|
||||
interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq", "eth_lpi";
|
||||
interrupt-parent = <&pic>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac1: ethernet@3,1 {
|
||||
reg = <0x1900 0x0 0x0 0x0 0x0>;
|
||||
interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <14 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq", "eth_lpi";
|
||||
interrupt-parent = <&pic>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac2: ethernet@3,2 {
|
||||
reg = <0x1a00 0x0 0x0 0x0 0x0>;
|
||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<18 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq", "eth_lpi";
|
||||
interrupt-parent = <&pic>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define _ASM_ADDRSPACE_H
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
#include <asm/pgtable-bits.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
/*
|
||||
* Change "struct page" to physical address.
|
||||
*/
|
||||
#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
|
||||
|
||||
extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size);
|
||||
extern void __init early_iounmap(void __iomem *addr, unsigned long size);
|
||||
|
||||
@@ -73,6 +68,21 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t
|
||||
|
||||
#define __io_aw() mmiowb()
|
||||
|
||||
#ifdef CONFIG_KFENCE
|
||||
#define virt_to_phys(kaddr) \
|
||||
({ \
|
||||
(likely((unsigned long)kaddr < vm_map_base)) ? __pa((unsigned long)kaddr) : \
|
||||
page_to_phys(tlb_virt_to_page((unsigned long)kaddr)) + offset_in_page((unsigned long)kaddr);\
|
||||
})
|
||||
|
||||
#define phys_to_virt(paddr) \
|
||||
({ \
|
||||
extern char *__kfence_pool; \
|
||||
(unlikely(__kfence_pool == NULL)) ? __va((unsigned long)paddr) : \
|
||||
page_address(phys_to_page((unsigned long)paddr)) + offset_in_page((unsigned long)paddr);\
|
||||
})
|
||||
#endif
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
static inline bool arch_kfence_init_pool(void)
|
||||
{
|
||||
int err;
|
||||
char *kaddr, *vaddr;
|
||||
char *kfence_pool = __kfence_pool;
|
||||
struct vm_struct *area;
|
||||
|
||||
@@ -35,6 +36,14 @@ static inline bool arch_kfence_init_pool(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
kaddr = kfence_pool;
|
||||
vaddr = __kfence_pool;
|
||||
while (kaddr < kfence_pool + KFENCE_POOL_SIZE) {
|
||||
set_page_address(virt_to_page(kaddr), vaddr);
|
||||
kaddr += PAGE_SIZE;
|
||||
vaddr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,26 @@ typedef struct { unsigned long pgprot; } pgprot_t;
|
||||
struct page *dmw_virt_to_page(unsigned long kaddr);
|
||||
struct page *tlb_virt_to_page(unsigned long kaddr);
|
||||
|
||||
#define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr))
|
||||
#define pfn_to_phys(pfn) __pfn_to_phys(pfn)
|
||||
#define phys_to_pfn(paddr) __phys_to_pfn(paddr)
|
||||
|
||||
#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
|
||||
#define phys_to_page(paddr) pfn_to_page(phys_to_pfn(paddr))
|
||||
|
||||
#ifndef CONFIG_KFENCE
|
||||
|
||||
#define page_to_virt(page) __va(page_to_phys(page))
|
||||
#define virt_to_page(kaddr) phys_to_page(__pa(kaddr))
|
||||
|
||||
#else
|
||||
|
||||
#define WANT_PAGE_VIRTUAL
|
||||
|
||||
#define page_to_virt(page) \
|
||||
({ \
|
||||
extern char *__kfence_pool; \
|
||||
(__kfence_pool == NULL) ? __va(page_to_phys(page)) : page_address(page); \
|
||||
})
|
||||
|
||||
#define virt_to_page(kaddr) \
|
||||
({ \
|
||||
@@ -86,6 +105,11 @@ struct page *tlb_virt_to_page(unsigned long kaddr);
|
||||
dmw_virt_to_page((unsigned long)kaddr) : tlb_virt_to_page((unsigned long)kaddr);\
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
#define pfn_to_virt(pfn) page_to_virt(pfn_to_page(pfn))
|
||||
#define virt_to_pfn(kaddr) page_to_pfn(virt_to_page(kaddr))
|
||||
|
||||
extern int __virt_addr_valid(volatile void *kaddr);
|
||||
#define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr))
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kfence.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
@@ -111,6 +112,9 @@ int __virt_addr_valid(volatile void *kaddr)
|
||||
{
|
||||
unsigned long vaddr = (unsigned long)kaddr;
|
||||
|
||||
if (is_kfence_address((void *)kaddr))
|
||||
return 1;
|
||||
|
||||
if ((vaddr < PAGE_OFFSET) || (vaddr >= vm_map_base))
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
struct page *dmw_virt_to_page(unsigned long kaddr)
|
||||
{
|
||||
return pfn_to_page(virt_to_pfn(kaddr));
|
||||
return phys_to_page(__pa(kaddr));
|
||||
}
|
||||
EXPORT_SYMBOL(dmw_virt_to_page);
|
||||
|
||||
struct page *tlb_virt_to_page(unsigned long kaddr)
|
||||
{
|
||||
return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr)));
|
||||
return phys_to_page(pfn_to_phys(pte_pfn(*virt_to_kpte(kaddr))));
|
||||
}
|
||||
EXPORT_SYMBOL(tlb_virt_to_page);
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ extern unsigned long exception_ip(struct pt_regs *regs);
|
||||
#define exception_ip(regs) exception_ip(regs)
|
||||
#define profile_pc(regs) instruction_pointer(regs)
|
||||
|
||||
extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
|
||||
extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
|
||||
extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
|
||||
|
||||
extern void die(const char *, struct pt_regs *) __noreturn;
|
||||
|
||||
@@ -101,6 +101,7 @@ void output_thread_info_defines(void)
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||
OFFSET(TI_REGS, thread_info, regs);
|
||||
OFFSET(TI_SYSCALL, thread_info, syscall);
|
||||
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
||||
DEFINE(_THREAD_MASK, THREAD_MASK);
|
||||
DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
|
||||
|
||||
@@ -1317,16 +1317,13 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||
* Notification of system call entry/exit
|
||||
* - triggered by current->work.syscall_trace
|
||||
*/
|
||||
asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
|
||||
asmlinkage long syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
user_exit();
|
||||
|
||||
current_thread_info()->syscall = syscall;
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
|
||||
if (ptrace_report_syscall_entry(regs))
|
||||
return -1;
|
||||
syscall = current_thread_info()->syscall;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECCOMP
|
||||
@@ -1335,7 +1332,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
|
||||
struct seccomp_data sd;
|
||||
unsigned long args[6];
|
||||
|
||||
sd.nr = syscall;
|
||||
sd.nr = current_thread_info()->syscall;
|
||||
sd.arch = syscall_get_arch(current);
|
||||
syscall_get_arguments(current, regs, args);
|
||||
for (i = 0; i < 6; i++)
|
||||
@@ -1345,23 +1342,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
|
||||
ret = __secure_computing(&sd);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
syscall = current_thread_info()->syscall;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
||||
trace_sys_enter(regs, regs->regs[2]);
|
||||
|
||||
audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
|
||||
audit_syscall_entry(current_thread_info()->syscall,
|
||||
regs->regs[4], regs->regs[5],
|
||||
regs->regs[6], regs->regs[7]);
|
||||
|
||||
/*
|
||||
* Negative syscall numbers are mistaken for rejected syscalls, but
|
||||
* won't have had the return value set appropriately, so we do so now.
|
||||
*/
|
||||
if (syscall < 0)
|
||||
if (current_thread_info()->syscall < 0)
|
||||
syscall_set_return_value(current, regs, -ENOSYS, 0);
|
||||
return syscall;
|
||||
return current_thread_info()->syscall;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -77,6 +77,18 @@ loads_done:
|
||||
PTR_WD load_a7, bad_stack_a7
|
||||
.previous
|
||||
|
||||
/*
|
||||
* syscall number is in v0 unless we called syscall(__NR_###)
|
||||
* where the real syscall number is in a0
|
||||
*/
|
||||
subu t2, v0, __NR_O32_Linux
|
||||
bnez t2, 1f /* __NR_syscall at offset 0 */
|
||||
LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number
|
||||
b 2f
|
||||
1:
|
||||
LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number
|
||||
2:
|
||||
|
||||
lw t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||
and t0, t1
|
||||
@@ -114,16 +126,7 @@ syscall_trace_entry:
|
||||
SAVE_STATIC
|
||||
move a0, sp
|
||||
|
||||
/*
|
||||
* syscall number is in v0 unless we called syscall(__NR_###)
|
||||
* where the real syscall number is in a0
|
||||
*/
|
||||
move a1, v0
|
||||
subu t2, v0, __NR_O32_Linux
|
||||
bnez t2, 1f /* __NR_syscall at offset 0 */
|
||||
lw a1, PT_R4(sp)
|
||||
|
||||
1: jal syscall_trace_enter
|
||||
jal syscall_trace_enter
|
||||
|
||||
bltz v0, 1f # seccomp failed? Skip syscall
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp)
|
||||
|
||||
sd a3, PT_R26(sp) # save a3 for syscall restarting
|
||||
|
||||
LONG_S v0, TI_SYSCALL($28) # Store syscall number
|
||||
|
||||
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||
and t0, t1, t0
|
||||
@@ -72,7 +74,6 @@ syscall_common:
|
||||
n32_syscall_trace_entry:
|
||||
SAVE_STATIC
|
||||
move a0, sp
|
||||
move a1, v0
|
||||
jal syscall_trace_enter
|
||||
|
||||
bltz v0, 1f # seccomp failed? Skip syscall
|
||||
|
||||
@@ -46,6 +46,8 @@ NESTED(handle_sys64, PT_SIZE, sp)
|
||||
|
||||
sd a3, PT_R26(sp) # save a3 for syscall restarting
|
||||
|
||||
LONG_S v0, TI_SYSCALL($28) # Store syscall number
|
||||
|
||||
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||
and t0, t1, t0
|
||||
@@ -82,7 +84,6 @@ n64_syscall_exit:
|
||||
syscall_trace_entry:
|
||||
SAVE_STATIC
|
||||
move a0, sp
|
||||
move a1, v0
|
||||
jal syscall_trace_enter
|
||||
|
||||
bltz v0, 1f # seccomp failed? Skip syscall
|
||||
|
||||
@@ -79,6 +79,22 @@ loads_done:
|
||||
PTR_WD load_a7, bad_stack_a7
|
||||
.previous
|
||||
|
||||
/*
|
||||
* absolute syscall number is in v0 unless we called syscall(__NR_###)
|
||||
* where the real syscall number is in a0
|
||||
* note: NR_syscall is the first O32 syscall but the macro is
|
||||
* only defined when compiling with -mabi=32 (CONFIG_32BIT)
|
||||
* therefore __NR_O32_Linux is used (4000)
|
||||
*/
|
||||
|
||||
subu t2, v0, __NR_O32_Linux
|
||||
bnez t2, 1f /* __NR_syscall at offset 0 */
|
||||
LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number
|
||||
b 2f
|
||||
1:
|
||||
LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number
|
||||
2:
|
||||
|
||||
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||
and t0, t1, t0
|
||||
@@ -113,22 +129,7 @@ trace_a_syscall:
|
||||
sd a7, PT_R11(sp) # For indirect syscalls
|
||||
|
||||
move a0, sp
|
||||
/*
|
||||
* absolute syscall number is in v0 unless we called syscall(__NR_###)
|
||||
* where the real syscall number is in a0
|
||||
* note: NR_syscall is the first O32 syscall but the macro is
|
||||
* only defined when compiling with -mabi=32 (CONFIG_32BIT)
|
||||
* therefore __NR_O32_Linux is used (4000)
|
||||
*/
|
||||
.set push
|
||||
.set reorder
|
||||
subu t1, v0, __NR_O32_Linux
|
||||
move a1, v0
|
||||
bnez t1, 1f /* __NR_syscall at offset 0 */
|
||||
ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
|
||||
.set pop
|
||||
|
||||
1: jal syscall_trace_enter
|
||||
jal syscall_trace_enter
|
||||
|
||||
bltz v0, 1f # seccomp failed? Skip syscall
|
||||
|
||||
|
||||
@@ -2633,6 +2633,16 @@ config MITIGATION_RFDS
|
||||
stored in floating point, vector and integer registers.
|
||||
See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst>
|
||||
|
||||
config MITIGATION_SPECTRE_BHI
|
||||
bool "Mitigate Spectre-BHB (Branch History Injection)"
|
||||
depends on CPU_SUP_INTEL
|
||||
default y
|
||||
help
|
||||
Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks
|
||||
where the branch history buffer is poisoned to speculatively steer
|
||||
indirect branches.
|
||||
See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
|
||||
|
||||
endif
|
||||
|
||||
config ARCH_HAS_ADD_PAGES
|
||||
|
||||
@@ -49,7 +49,7 @@ static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr)
|
||||
|
||||
if (likely(unr < NR_syscalls)) {
|
||||
unr = array_index_nospec(unr, NR_syscalls);
|
||||
regs->ax = sys_call_table[unr](regs);
|
||||
regs->ax = x64_sys_call(regs, unr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -66,7 +66,7 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr)
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(xnr < X32_NR_syscalls)) {
|
||||
xnr = array_index_nospec(xnr, X32_NR_syscalls);
|
||||
regs->ax = x32_sys_call_table[xnr](regs);
|
||||
regs->ax = x32_sys_call(regs, xnr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -162,7 +162,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)
|
||||
|
||||
if (likely(unr < IA32_NR_syscalls)) {
|
||||
unr = array_index_nospec(unr, IA32_NR_syscalls);
|
||||
regs->ax = ia32_sys_call_table[unr](regs);
|
||||
regs->ax = ia32_sys_call(regs, unr);
|
||||
} else if (nr != -1) {
|
||||
regs->ax = __ia32_sys_ni_syscall(regs);
|
||||
}
|
||||
@@ -189,7 +189,7 @@ static __always_inline bool int80_is_external(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* int80_emulation - 32-bit legacy syscall entry
|
||||
* do_int80_emulation - 32-bit legacy syscall C entry from asm
|
||||
*
|
||||
* This entry point can be used by 32-bit and 64-bit programs to perform
|
||||
* 32-bit system calls. Instances of INT $0x80 can be found inline in
|
||||
@@ -207,7 +207,7 @@ static __always_inline bool int80_is_external(void)
|
||||
* eax: system call number
|
||||
* ebx, ecx, edx, esi, edi, ebp: arg1 - arg 6
|
||||
*/
|
||||
DEFINE_IDTENTRY_RAW(int80_emulation)
|
||||
__visible noinstr void do_int80_emulation(struct pt_regs *regs)
|
||||
{
|
||||
int nr;
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
|
||||
/* clobbers %rax, make sure it is after saving the syscall nr */
|
||||
IBRS_ENTER
|
||||
UNTRAIN_RET
|
||||
CLEAR_BRANCH_HISTORY
|
||||
|
||||
call do_syscall_64 /* returns with IRQs disabled */
|
||||
|
||||
@@ -1491,3 +1492,63 @@ SYM_CODE_START_NOALIGN(rewind_stack_and_make_dead)
|
||||
call make_task_dead
|
||||
SYM_CODE_END(rewind_stack_and_make_dead)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* This sequence executes branches in order to remove user branch information
|
||||
* from the branch history tracker in the Branch Predictor, therefore removing
|
||||
* user influence on subsequent BTB lookups.
|
||||
*
|
||||
* It should be used on parts prior to Alder Lake. Newer parts should use the
|
||||
* BHI_DIS_S hardware control instead. If a pre-Alder Lake part is being
|
||||
* virtualized on newer hardware the VMM should protect against BHI attacks by
|
||||
* setting BHI_DIS_S for the guests.
|
||||
*
|
||||
* CALLs/RETs are necessary to prevent Loop Stream Detector(LSD) from engaging
|
||||
* and not clearing the branch history. The call tree looks like:
|
||||
*
|
||||
* call 1
|
||||
* call 2
|
||||
* call 2
|
||||
* call 2
|
||||
* call 2
|
||||
* call 2
|
||||
* ret
|
||||
* ret
|
||||
* ret
|
||||
* ret
|
||||
* ret
|
||||
* ret
|
||||
*
|
||||
* This means that the stack is non-constant and ORC can't unwind it with %rsp
|
||||
* alone. Therefore we unconditionally set up the frame pointer, which allows
|
||||
* ORC to unwind properly.
|
||||
*
|
||||
* The alignment is for performance and not for safety, and may be safely
|
||||
* refactored in the future if needed.
|
||||
*/
|
||||
SYM_FUNC_START(clear_bhb_loop)
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
movl $5, %ecx
|
||||
ANNOTATE_INTRA_FUNCTION_CALL
|
||||
call 1f
|
||||
jmp 5f
|
||||
.align 64, 0xcc
|
||||
ANNOTATE_INTRA_FUNCTION_CALL
|
||||
1: call 2f
|
||||
RET
|
||||
.align 64, 0xcc
|
||||
2: movl $5, %eax
|
||||
3: jmp 4f
|
||||
nop
|
||||
4: sub $1, %eax
|
||||
jnz 3b
|
||||
sub $1, %ecx
|
||||
jnz 1b
|
||||
RET
|
||||
5: lfence
|
||||
pop %rbp
|
||||
RET
|
||||
SYM_FUNC_END(clear_bhb_loop)
|
||||
EXPORT_SYMBOL_GPL(clear_bhb_loop)
|
||||
STACK_FRAME_NON_STANDARD(clear_bhb_loop)
|
||||
|
||||
@@ -92,6 +92,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
|
||||
|
||||
IBRS_ENTER
|
||||
UNTRAIN_RET
|
||||
CLEAR_BRANCH_HISTORY
|
||||
|
||||
/*
|
||||
* SYSENTER doesn't filter flags, so we need to clear NT and AC
|
||||
@@ -206,6 +207,7 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL)
|
||||
|
||||
IBRS_ENTER
|
||||
UNTRAIN_RET
|
||||
CLEAR_BRANCH_HISTORY
|
||||
|
||||
movq %rsp, %rdi
|
||||
call do_fast_syscall_32
|
||||
@@ -276,3 +278,17 @@ SYM_INNER_LABEL(entry_SYSRETL_compat_end, SYM_L_GLOBAL)
|
||||
ANNOTATE_NOENDBR
|
||||
int3
|
||||
SYM_CODE_END(entry_SYSCALL_compat)
|
||||
|
||||
/*
|
||||
* int 0x80 is used by 32 bit mode as a system call entry. Normally idt entries
|
||||
* point to C routines, however since this is a system call interface the branch
|
||||
* history needs to be scrubbed to protect against BHI attacks, and that
|
||||
* scrubbing needs to take place in assembly code prior to entering any C
|
||||
* routines.
|
||||
*/
|
||||
SYM_CODE_START(int80_emulation)
|
||||
ANNOTATE_NOENDBR
|
||||
UNWIND_HINT_FUNC
|
||||
CLEAR_BRANCH_HISTORY
|
||||
jmp do_int80_emulation
|
||||
SYM_CODE_END(int80_emulation)
|
||||
|
||||
@@ -18,8 +18,25 @@
|
||||
#include <asm/syscalls_32.h>
|
||||
#undef __SYSCALL
|
||||
|
||||
/*
|
||||
* The sys_call_table[] is no longer used for system calls, but
|
||||
* kernel/trace/trace_syscalls.c still wants to know the system
|
||||
* call address.
|
||||
*/
|
||||
#ifdef CONFIG_X86_32
|
||||
#define __SYSCALL(nr, sym) __ia32_##sym,
|
||||
|
||||
__visible const sys_call_ptr_t ia32_sys_call_table[] = {
|
||||
const sys_call_ptr_t sys_call_table[] = {
|
||||
#include <asm/syscalls_32.h>
|
||||
};
|
||||
#undef __SYSCALL
|
||||
#endif
|
||||
|
||||
#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs);
|
||||
|
||||
long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
|
||||
{
|
||||
switch (nr) {
|
||||
#include <asm/syscalls_32.h>
|
||||
default: return __ia32_sys_ni_syscall(regs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,8 +11,23 @@
|
||||
#include <asm/syscalls_64.h>
|
||||
#undef __SYSCALL
|
||||
|
||||
/*
|
||||
* The sys_call_table[] is no longer used for system calls, but
|
||||
* kernel/trace/trace_syscalls.c still wants to know the system
|
||||
* call address.
|
||||
*/
|
||||
#define __SYSCALL(nr, sym) __x64_##sym,
|
||||
|
||||
asmlinkage const sys_call_ptr_t sys_call_table[] = {
|
||||
const sys_call_ptr_t sys_call_table[] = {
|
||||
#include <asm/syscalls_64.h>
|
||||
};
|
||||
#undef __SYSCALL
|
||||
|
||||
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
|
||||
|
||||
long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
|
||||
{
|
||||
switch (nr) {
|
||||
#include <asm/syscalls_64.h>
|
||||
default: return __x64_sys_ni_syscall(regs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,8 +11,12 @@
|
||||
#include <asm/syscalls_x32.h>
|
||||
#undef __SYSCALL
|
||||
|
||||
#define __SYSCALL(nr, sym) __x64_##sym,
|
||||
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
|
||||
|
||||
asmlinkage const sys_call_ptr_t x32_sys_call_table[] = {
|
||||
#include <asm/syscalls_x32.h>
|
||||
long x32_sys_call(const struct pt_regs *regs, unsigned int nr)
|
||||
{
|
||||
switch (nr) {
|
||||
#include <asm/syscalls_x32.h>
|
||||
default: return __x64_sys_ni_syscall(regs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1644,6 +1644,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
|
||||
while (++i < cpuc->n_events) {
|
||||
cpuc->event_list[i-1] = cpuc->event_list[i];
|
||||
cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
|
||||
cpuc->assign[i-1] = cpuc->assign[i];
|
||||
}
|
||||
cpuc->event_constraint[i-1] = NULL;
|
||||
--cpuc->n_events;
|
||||
|
||||
@@ -105,7 +105,7 @@ static bool cpu_is_self(int cpu)
|
||||
* IPI implementation on Hyper-V.
|
||||
*/
|
||||
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
||||
bool exclude_self)
|
||||
bool exclude_self)
|
||||
{
|
||||
struct hv_send_ipi_ex *ipi_arg;
|
||||
unsigned long flags;
|
||||
@@ -132,8 +132,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
||||
if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
|
||||
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
|
||||
|
||||
nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask,
|
||||
exclude_self ? cpu_is_self : NULL);
|
||||
nr_bank = cpumask_to_vpset_skip(&ipi_arg->vp_set, mask,
|
||||
exclude_self ? cpu_is_self : NULL);
|
||||
|
||||
/*
|
||||
* 'nr_bank <= 0' means some CPUs in cpumask can't be
|
||||
@@ -147,7 +147,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
||||
}
|
||||
|
||||
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
|
||||
ipi_arg, NULL);
|
||||
ipi_arg, NULL);
|
||||
|
||||
ipi_mask_ex_done:
|
||||
local_irq_restore(flags);
|
||||
@@ -155,7 +155,7 @@ ipi_mask_ex_done:
|
||||
}
|
||||
|
||||
static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
||||
bool exclude_self)
|
||||
bool exclude_self)
|
||||
{
|
||||
int cur_cpu, vcpu, this_cpu = smp_processor_id();
|
||||
struct hv_send_ipi ipi_arg;
|
||||
@@ -181,7 +181,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
|
||||
if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
|
||||
return false;
|
||||
|
||||
/*
|
||||
@@ -218,7 +218,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
||||
}
|
||||
|
||||
status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
|
||||
ipi_arg.cpu_mask);
|
||||
ipi_arg.cpu_mask);
|
||||
return hv_result_success(status);
|
||||
|
||||
do_ex_hypercall:
|
||||
@@ -241,7 +241,7 @@ static bool __send_ipi_one(int cpu, int vector)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
|
||||
if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
|
||||
return false;
|
||||
|
||||
if (vp >= 64)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/hyperv.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpuhotplug.h>
|
||||
@@ -116,12 +115,11 @@ free_buf:
|
||||
|
||||
int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
|
||||
{
|
||||
struct hv_add_logical_processor_in *input;
|
||||
struct hv_add_logical_processor_out *output;
|
||||
struct hv_input_add_logical_processor *input;
|
||||
struct hv_output_add_logical_processor *output;
|
||||
u64 status;
|
||||
unsigned long flags;
|
||||
int ret = HV_STATUS_SUCCESS;
|
||||
int pxm = node_to_pxm(node);
|
||||
|
||||
/*
|
||||
* When adding a logical processor, the hypervisor may return
|
||||
@@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
|
||||
|
||||
input->lp_index = lp_index;
|
||||
input->apic_id = apic_id;
|
||||
input->flags = 0;
|
||||
input->proximity_domain_info.domain_id = pxm;
|
||||
input->proximity_domain_info.flags.reserved = 0;
|
||||
input->proximity_domain_info.flags.proximity_info_valid = 1;
|
||||
input->proximity_domain_info.flags.proximity_preferred = 1;
|
||||
input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
|
||||
status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
|
||||
input, output);
|
||||
local_irq_restore(flags);
|
||||
@@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
|
||||
u64 status;
|
||||
unsigned long irq_flags;
|
||||
int ret = HV_STATUS_SUCCESS;
|
||||
int pxm = node_to_pxm(node);
|
||||
|
||||
/* Root VPs don't seem to need pages deposited */
|
||||
if (partition_id != hv_current_partition_id) {
|
||||
@@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
|
||||
input->vp_index = vp_index;
|
||||
input->flags = flags;
|
||||
input->subnode_type = HvSubnodeAny;
|
||||
if (node != NUMA_NO_NODE) {
|
||||
input->proximity_domain_info.domain_id = pxm;
|
||||
input->proximity_domain_info.flags.reserved = 0;
|
||||
input->proximity_domain_info.flags.proximity_info_valid = 1;
|
||||
input->proximity_domain_info.flags.proximity_preferred = 1;
|
||||
} else {
|
||||
input->proximity_domain_info.as_uint64 = 0;
|
||||
}
|
||||
input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
|
||||
status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
|
||||
local_irq_restore(irq_flags);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define ARCH_APICTIMER_STOPS_ON_C3 1
|
||||
|
||||
@@ -98,7 +99,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v)
|
||||
|
||||
static inline u32 native_apic_mem_read(u32 reg)
|
||||
{
|
||||
return *((volatile u32 *)(APIC_BASE + reg));
|
||||
return readl((void __iomem *)(APIC_BASE + reg));
|
||||
}
|
||||
|
||||
static inline void native_apic_mem_eoi(void)
|
||||
|
||||
@@ -461,11 +461,15 @@
|
||||
|
||||
/*
|
||||
* Extended auxiliary flags: Linux defined - for features scattered in various
|
||||
* CPUID levels like 0x80000022, etc.
|
||||
* CPUID levels like 0x80000022, etc and Linux defined features.
|
||||
*
|
||||
* Reuse free bits when adding new feature flags!
|
||||
*/
|
||||
#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */
|
||||
#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */
|
||||
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */
|
||||
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */
|
||||
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
|
||||
|
||||
/*
|
||||
* BUG word(s)
|
||||
@@ -515,4 +519,5 @@
|
||||
#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
|
||||
#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
|
||||
#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
|
||||
#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */
|
||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||
|
||||
@@ -61,10 +61,13 @@
|
||||
#define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
||||
#define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */
|
||||
#define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT)
|
||||
#define SPEC_CTRL_BHI_DIS_S_SHIFT 10 /* Disable Branch History Injection behavior */
|
||||
#define SPEC_CTRL_BHI_DIS_S BIT(SPEC_CTRL_BHI_DIS_S_SHIFT)
|
||||
|
||||
/* A mask for bits which the kernel toggles when controlling mitigations */
|
||||
#define SPEC_CTRL_MITIGATIONS_MASK (SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \
|
||||
| SPEC_CTRL_RRSBA_DIS_S)
|
||||
| SPEC_CTRL_RRSBA_DIS_S \
|
||||
| SPEC_CTRL_BHI_DIS_S)
|
||||
|
||||
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
||||
#define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
|
||||
@@ -163,6 +166,10 @@
|
||||
* are restricted to targets in
|
||||
* kernel.
|
||||
*/
|
||||
#define ARCH_CAP_BHI_NO BIT(20) /*
|
||||
* CPU is not affected by Branch
|
||||
* History Injection.
|
||||
*/
|
||||
#define ARCH_CAP_PBRSB_NO BIT(24) /*
|
||||
* Not susceptible to Post-Barrier
|
||||
* Return Stack Buffer Predictions.
|
||||
|
||||
@@ -326,6 +326,19 @@
|
||||
ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
.macro CLEAR_BRANCH_HISTORY
|
||||
ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
|
||||
.endm
|
||||
|
||||
.macro CLEAR_BRANCH_HISTORY_VMEXIT
|
||||
ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT
|
||||
.endm
|
||||
#else
|
||||
#define CLEAR_BRANCH_HISTORY
|
||||
#define CLEAR_BRANCH_HISTORY_VMEXIT
|
||||
#endif
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define ANNOTATE_RETPOLINE_SAFE \
|
||||
@@ -368,6 +381,10 @@ extern void srso_alias_return_thunk(void);
|
||||
extern void entry_untrain_ret(void);
|
||||
extern void entry_ibpb(void);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
extern void clear_bhb_loop(void);
|
||||
#endif
|
||||
|
||||
extern void (*x86_return_thunk)(void);
|
||||
|
||||
extern void __warn_thunk(void);
|
||||
|
||||
@@ -16,19 +16,17 @@
|
||||
#include <asm/thread_info.h> /* for TS_COMPAT */
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/* This is used purely for kernel/trace/trace_syscalls.c */
|
||||
typedef long (*sys_call_ptr_t)(const struct pt_regs *);
|
||||
extern const sys_call_ptr_t sys_call_table[];
|
||||
|
||||
#if defined(CONFIG_X86_32)
|
||||
#define ia32_sys_call_table sys_call_table
|
||||
#else
|
||||
/*
|
||||
* These may not exist, but still put the prototypes in so we
|
||||
* can use IS_ENABLED().
|
||||
*/
|
||||
extern const sys_call_ptr_t ia32_sys_call_table[];
|
||||
extern const sys_call_ptr_t x32_sys_call_table[];
|
||||
#endif
|
||||
extern long ia32_sys_call(const struct pt_regs *, unsigned int nr);
|
||||
extern long x32_sys_call(const struct pt_regs *, unsigned int nr);
|
||||
extern long x64_sys_call(const struct pt_regs *, unsigned int nr);
|
||||
|
||||
/*
|
||||
* Only the low 32 bits of orig_ax are meaningful, so we return int.
|
||||
@@ -127,6 +125,7 @@ static inline int syscall_get_arch(struct task_struct *task)
|
||||
}
|
||||
|
||||
bool do_syscall_64(struct pt_regs *regs, int nr);
|
||||
void do_int80_emulation(struct pt_regs *regs);
|
||||
|
||||
#endif /* CONFIG_X86_32 */
|
||||
|
||||
|
||||
@@ -1687,11 +1687,11 @@ static int x2apic_state;
|
||||
|
||||
static bool x2apic_hw_locked(void)
|
||||
{
|
||||
u64 ia32_cap;
|
||||
u64 x86_arch_cap_msr;
|
||||
u64 msr;
|
||||
|
||||
ia32_cap = x86_read_arch_cap_msr();
|
||||
if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) {
|
||||
x86_arch_cap_msr = x86_read_arch_cap_msr();
|
||||
if (x86_arch_cap_msr & ARCH_CAP_XAPIC_DISABLE) {
|
||||
rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr);
|
||||
return (msr & LEGACY_XAPIC_DISABLED);
|
||||
}
|
||||
|
||||
@@ -535,7 +535,6 @@ clear_sev:
|
||||
|
||||
static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 value;
|
||||
u32 dummy;
|
||||
|
||||
if (c->x86 >= 0xf)
|
||||
@@ -603,20 +602,6 @@ static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
|
||||
early_detect_mem_encrypt(c);
|
||||
|
||||
/* Re-enable TopologyExtensions if switched off by BIOS */
|
||||
if (c->x86 == 0x15 &&
|
||||
(c->x86_model >= 0x10 && c->x86_model <= 0x6f) &&
|
||||
!cpu_has(c, X86_FEATURE_TOPOEXT)) {
|
||||
|
||||
if (msr_set_bit(0xc0011005, 54) > 0) {
|
||||
rdmsrl(0xc0011005, value);
|
||||
if (value & BIT_64(54)) {
|
||||
set_cpu_cap(c, X86_FEATURE_TOPOEXT);
|
||||
pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) {
|
||||
if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB))
|
||||
setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
|
||||
|
||||
+126
-41
@@ -61,6 +61,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current);
|
||||
u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB;
|
||||
EXPORT_SYMBOL_GPL(x86_pred_cmd);
|
||||
|
||||
static u64 __ro_after_init x86_arch_cap_msr;
|
||||
|
||||
static DEFINE_MUTEX(spec_ctrl_mutex);
|
||||
|
||||
void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk;
|
||||
@@ -144,6 +146,8 @@ void __init cpu_select_mitigations(void)
|
||||
x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK;
|
||||
}
|
||||
|
||||
x86_arch_cap_msr = x86_read_arch_cap_msr();
|
||||
|
||||
/* Select the proper CPU mitigations before patching alternatives: */
|
||||
spectre_v1_select_mitigation();
|
||||
spectre_v2_select_mitigation();
|
||||
@@ -301,8 +305,6 @@ static const char * const taa_strings[] = {
|
||||
|
||||
static void __init taa_select_mitigation(void)
|
||||
{
|
||||
u64 ia32_cap;
|
||||
|
||||
if (!boot_cpu_has_bug(X86_BUG_TAA)) {
|
||||
taa_mitigation = TAA_MITIGATION_OFF;
|
||||
return;
|
||||
@@ -341,9 +343,8 @@ static void __init taa_select_mitigation(void)
|
||||
* On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode
|
||||
* update is required.
|
||||
*/
|
||||
ia32_cap = x86_read_arch_cap_msr();
|
||||
if ( (ia32_cap & ARCH_CAP_MDS_NO) &&
|
||||
!(ia32_cap & ARCH_CAP_TSX_CTRL_MSR))
|
||||
if ( (x86_arch_cap_msr & ARCH_CAP_MDS_NO) &&
|
||||
!(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR))
|
||||
taa_mitigation = TAA_MITIGATION_UCODE_NEEDED;
|
||||
|
||||
/*
|
||||
@@ -401,8 +402,6 @@ static const char * const mmio_strings[] = {
|
||||
|
||||
static void __init mmio_select_mitigation(void)
|
||||
{
|
||||
u64 ia32_cap;
|
||||
|
||||
if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
|
||||
boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
|
||||
cpu_mitigations_off()) {
|
||||
@@ -413,8 +412,6 @@ static void __init mmio_select_mitigation(void)
|
||||
if (mmio_mitigation == MMIO_MITIGATION_OFF)
|
||||
return;
|
||||
|
||||
ia32_cap = x86_read_arch_cap_msr();
|
||||
|
||||
/*
|
||||
* Enable CPU buffer clear mitigation for host and VMM, if also affected
|
||||
* by MDS or TAA. Otherwise, enable mitigation for VMM only.
|
||||
@@ -437,7 +434,7 @@ static void __init mmio_select_mitigation(void)
|
||||
* be propagated to uncore buffers, clearing the Fill buffers on idle
|
||||
* is required irrespective of SMT state.
|
||||
*/
|
||||
if (!(ia32_cap & ARCH_CAP_FBSDP_NO))
|
||||
if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO))
|
||||
static_branch_enable(&mds_idle_clear);
|
||||
|
||||
/*
|
||||
@@ -447,10 +444,10 @@ static void __init mmio_select_mitigation(void)
|
||||
* FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS
|
||||
* affected systems.
|
||||
*/
|
||||
if ((ia32_cap & ARCH_CAP_FB_CLEAR) ||
|
||||
if ((x86_arch_cap_msr & ARCH_CAP_FB_CLEAR) ||
|
||||
(boot_cpu_has(X86_FEATURE_MD_CLEAR) &&
|
||||
boot_cpu_has(X86_FEATURE_FLUSH_L1D) &&
|
||||
!(ia32_cap & ARCH_CAP_MDS_NO)))
|
||||
!(x86_arch_cap_msr & ARCH_CAP_MDS_NO)))
|
||||
mmio_mitigation = MMIO_MITIGATION_VERW;
|
||||
else
|
||||
mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED;
|
||||
@@ -508,7 +505,7 @@ static void __init rfds_select_mitigation(void)
|
||||
if (rfds_mitigation == RFDS_MITIGATION_OFF)
|
||||
return;
|
||||
|
||||
if (x86_read_arch_cap_msr() & ARCH_CAP_RFDS_CLEAR)
|
||||
if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR)
|
||||
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
|
||||
else
|
||||
rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED;
|
||||
@@ -659,8 +656,6 @@ void update_srbds_msr(void)
|
||||
|
||||
static void __init srbds_select_mitigation(void)
|
||||
{
|
||||
u64 ia32_cap;
|
||||
|
||||
if (!boot_cpu_has_bug(X86_BUG_SRBDS))
|
||||
return;
|
||||
|
||||
@@ -669,8 +664,7 @@ static void __init srbds_select_mitigation(void)
|
||||
* are only exposed to SRBDS when TSX is enabled or when CPU is affected
|
||||
* by Processor MMIO Stale Data vulnerability.
|
||||
*/
|
||||
ia32_cap = x86_read_arch_cap_msr();
|
||||
if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
|
||||
if ((x86_arch_cap_msr & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
|
||||
!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
|
||||
srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
|
||||
else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
|
||||
@@ -813,7 +807,7 @@ static void __init gds_select_mitigation(void)
|
||||
/* Will verify below that mitigation _can_ be disabled */
|
||||
|
||||
/* No microcode */
|
||||
if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) {
|
||||
if (!(x86_arch_cap_msr & ARCH_CAP_GDS_CTRL)) {
|
||||
if (gds_mitigation == GDS_MITIGATION_FORCE) {
|
||||
/*
|
||||
* This only needs to be done on the boot CPU so do it
|
||||
@@ -1544,20 +1538,25 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void)
|
||||
return SPECTRE_V2_RETPOLINE;
|
||||
}
|
||||
|
||||
static bool __ro_after_init rrsba_disabled;
|
||||
|
||||
/* Disable in-kernel use of non-RSB RET predictors */
|
||||
static void __init spec_ctrl_disable_kernel_rrsba(void)
|
||||
{
|
||||
u64 ia32_cap;
|
||||
if (rrsba_disabled)
|
||||
return;
|
||||
|
||||
if (!(x86_arch_cap_msr & ARCH_CAP_RRSBA)) {
|
||||
rrsba_disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
|
||||
return;
|
||||
|
||||
ia32_cap = x86_read_arch_cap_msr();
|
||||
|
||||
if (ia32_cap & ARCH_CAP_RRSBA) {
|
||||
x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
|
||||
update_spec_ctrl(x86_spec_ctrl_base);
|
||||
}
|
||||
x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
|
||||
update_spec_ctrl(x86_spec_ctrl_base);
|
||||
rrsba_disabled = true;
|
||||
}
|
||||
|
||||
static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
|
||||
@@ -1607,6 +1606,73 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by
|
||||
* branch history in userspace. Not needed if BHI_NO is set.
|
||||
*/
|
||||
static bool __init spec_ctrl_bhi_dis(void)
|
||||
{
|
||||
if (!boot_cpu_has(X86_FEATURE_BHI_CTRL))
|
||||
return false;
|
||||
|
||||
x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S;
|
||||
update_spec_ctrl(x86_spec_ctrl_base);
|
||||
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum bhi_mitigations {
|
||||
BHI_MITIGATION_OFF,
|
||||
BHI_MITIGATION_ON,
|
||||
};
|
||||
|
||||
static enum bhi_mitigations bhi_mitigation __ro_after_init =
|
||||
IS_ENABLED(CONFIG_MITIGATION_SPECTRE_BHI) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF;
|
||||
|
||||
static int __init spectre_bhi_parse_cmdline(char *str)
|
||||
{
|
||||
if (!str)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(str, "off"))
|
||||
bhi_mitigation = BHI_MITIGATION_OFF;
|
||||
else if (!strcmp(str, "on"))
|
||||
bhi_mitigation = BHI_MITIGATION_ON;
|
||||
else
|
||||
pr_err("Ignoring unknown spectre_bhi option (%s)", str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("spectre_bhi", spectre_bhi_parse_cmdline);
|
||||
|
||||
static void __init bhi_select_mitigation(void)
|
||||
{
|
||||
if (bhi_mitigation == BHI_MITIGATION_OFF)
|
||||
return;
|
||||
|
||||
/* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
|
||||
if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
|
||||
spec_ctrl_disable_kernel_rrsba();
|
||||
if (rrsba_disabled)
|
||||
return;
|
||||
}
|
||||
|
||||
if (spec_ctrl_bhi_dis())
|
||||
return;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_X86_64))
|
||||
return;
|
||||
|
||||
/* Mitigate KVM by default */
|
||||
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
|
||||
pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n");
|
||||
|
||||
/* Mitigate syscalls when the mitigation is forced =on */
|
||||
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
|
||||
pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
|
||||
}
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void)
|
||||
{
|
||||
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
||||
@@ -1718,6 +1784,9 @@ static void __init spectre_v2_select_mitigation(void)
|
||||
mode == SPECTRE_V2_RETPOLINE)
|
||||
spec_ctrl_disable_kernel_rrsba();
|
||||
|
||||
if (boot_cpu_has(X86_BUG_BHI))
|
||||
bhi_select_mitigation();
|
||||
|
||||
spectre_v2_enabled = mode;
|
||||
pr_info("%s\n", spectre_v2_strings[mode]);
|
||||
|
||||
@@ -1832,8 +1901,6 @@ static void update_indir_branch_cond(void)
|
||||
/* Update the static key controlling the MDS CPU buffer clear in idle */
|
||||
static void update_mds_branch_idle(void)
|
||||
{
|
||||
u64 ia32_cap = x86_read_arch_cap_msr();
|
||||
|
||||
/*
|
||||
* Enable the idle clearing if SMT is active on CPUs which are
|
||||
* affected only by MSBDS and not any other MDS variant.
|
||||
@@ -1848,7 +1915,7 @@ static void update_mds_branch_idle(void)
|
||||
if (sched_smt_active()) {
|
||||
static_branch_enable(&mds_idle_clear);
|
||||
} else if (mmio_mitigation == MMIO_MITIGATION_OFF ||
|
||||
(ia32_cap & ARCH_CAP_FBSDP_NO)) {
|
||||
(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) {
|
||||
static_branch_disable(&mds_idle_clear);
|
||||
}
|
||||
}
|
||||
@@ -2695,15 +2762,15 @@ static char *stibp_state(void)
|
||||
|
||||
switch (spectre_v2_user_stibp) {
|
||||
case SPECTRE_V2_USER_NONE:
|
||||
return ", STIBP: disabled";
|
||||
return "; STIBP: disabled";
|
||||
case SPECTRE_V2_USER_STRICT:
|
||||
return ", STIBP: forced";
|
||||
return "; STIBP: forced";
|
||||
case SPECTRE_V2_USER_STRICT_PREFERRED:
|
||||
return ", STIBP: always-on";
|
||||
return "; STIBP: always-on";
|
||||
case SPECTRE_V2_USER_PRCTL:
|
||||
case SPECTRE_V2_USER_SECCOMP:
|
||||
if (static_key_enabled(&switch_to_cond_stibp))
|
||||
return ", STIBP: conditional";
|
||||
return "; STIBP: conditional";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -2712,10 +2779,10 @@ static char *ibpb_state(void)
|
||||
{
|
||||
if (boot_cpu_has(X86_FEATURE_IBPB)) {
|
||||
if (static_key_enabled(&switch_mm_always_ibpb))
|
||||
return ", IBPB: always-on";
|
||||
return "; IBPB: always-on";
|
||||
if (static_key_enabled(&switch_mm_cond_ibpb))
|
||||
return ", IBPB: conditional";
|
||||
return ", IBPB: disabled";
|
||||
return "; IBPB: conditional";
|
||||
return "; IBPB: disabled";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -2725,14 +2792,30 @@ static char *pbrsb_eibrs_state(void)
|
||||
if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
|
||||
if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) ||
|
||||
boot_cpu_has(X86_FEATURE_RSB_VMEXIT))
|
||||
return ", PBRSB-eIBRS: SW sequence";
|
||||
return "; PBRSB-eIBRS: SW sequence";
|
||||
else
|
||||
return ", PBRSB-eIBRS: Vulnerable";
|
||||
return "; PBRSB-eIBRS: Vulnerable";
|
||||
} else {
|
||||
return ", PBRSB-eIBRS: Not affected";
|
||||
return "; PBRSB-eIBRS: Not affected";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *spectre_bhi_state(void)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_BHI))
|
||||
return "; BHI: Not affected";
|
||||
else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
|
||||
return "; BHI: BHI_DIS_S";
|
||||
else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
|
||||
return "; BHI: SW loop, KVM: SW loop";
|
||||
else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
|
||||
return "; BHI: Retpoline";
|
||||
else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
|
||||
return "; BHI: Vulnerable, KVM: SW loop";
|
||||
|
||||
return "; BHI: Vulnerable";
|
||||
}
|
||||
|
||||
static ssize_t spectre_v2_show_state(char *buf)
|
||||
{
|
||||
if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
|
||||
@@ -2745,13 +2828,15 @@ static ssize_t spectre_v2_show_state(char *buf)
|
||||
spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
|
||||
return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
|
||||
|
||||
return sysfs_emit(buf, "%s%s%s%s%s%s%s\n",
|
||||
return sysfs_emit(buf, "%s%s%s%s%s%s%s%s\n",
|
||||
spectre_v2_strings[spectre_v2_enabled],
|
||||
ibpb_state(),
|
||||
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
||||
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "",
|
||||
stibp_state(),
|
||||
boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
|
||||
boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "",
|
||||
pbrsb_eibrs_state(),
|
||||
spectre_bhi_state(),
|
||||
/* this should always be at the end */
|
||||
spectre_v2_module_string());
|
||||
}
|
||||
|
||||
|
||||
@@ -1120,6 +1120,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
||||
#define NO_SPECTRE_V2 BIT(8)
|
||||
#define NO_MMIO BIT(9)
|
||||
#define NO_EIBRS_PBRSB BIT(10)
|
||||
#define NO_BHI BIT(11)
|
||||
|
||||
#define VULNWL(vendor, family, model, whitelist) \
|
||||
X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist)
|
||||
@@ -1182,18 +1183,18 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
||||
VULNWL_INTEL(ATOM_TREMONT_D, NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
|
||||
|
||||
/* AMD Family 0xf - 0x12 */
|
||||
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
|
||||
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
|
||||
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
|
||||
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
|
||||
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
|
||||
|
||||
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
|
||||
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
|
||||
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
|
||||
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI),
|
||||
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI),
|
||||
|
||||
/* Zhaoxin Family 7 */
|
||||
VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
|
||||
VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
|
||||
VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI),
|
||||
VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1283,25 +1284,25 @@ static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long whi
|
||||
|
||||
u64 x86_read_arch_cap_msr(void)
|
||||
{
|
||||
u64 ia32_cap = 0;
|
||||
u64 x86_arch_cap_msr = 0;
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
|
||||
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
|
||||
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, x86_arch_cap_msr);
|
||||
|
||||
return ia32_cap;
|
||||
return x86_arch_cap_msr;
|
||||
}
|
||||
|
||||
static bool arch_cap_mmio_immune(u64 ia32_cap)
|
||||
static bool arch_cap_mmio_immune(u64 x86_arch_cap_msr)
|
||||
{
|
||||
return (ia32_cap & ARCH_CAP_FBSDP_NO &&
|
||||
ia32_cap & ARCH_CAP_PSDP_NO &&
|
||||
ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
|
||||
return (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO &&
|
||||
x86_arch_cap_msr & ARCH_CAP_PSDP_NO &&
|
||||
x86_arch_cap_msr & ARCH_CAP_SBDR_SSDP_NO);
|
||||
}
|
||||
|
||||
static bool __init vulnerable_to_rfds(u64 ia32_cap)
|
||||
static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr)
|
||||
{
|
||||
/* The "immunity" bit trumps everything else: */
|
||||
if (ia32_cap & ARCH_CAP_RFDS_NO)
|
||||
if (x86_arch_cap_msr & ARCH_CAP_RFDS_NO)
|
||||
return false;
|
||||
|
||||
/*
|
||||
@@ -1309,7 +1310,7 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap)
|
||||
* indicate that mitigation is needed because guest is running on a
|
||||
* vulnerable hardware or may migrate to such hardware:
|
||||
*/
|
||||
if (ia32_cap & ARCH_CAP_RFDS_CLEAR)
|
||||
if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR)
|
||||
return true;
|
||||
|
||||
/* Only consult the blacklist when there is no enumeration: */
|
||||
@@ -1318,11 +1319,11 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap)
|
||||
|
||||
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 ia32_cap = x86_read_arch_cap_msr();
|
||||
u64 x86_arch_cap_msr = x86_read_arch_cap_msr();
|
||||
|
||||
/* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
|
||||
!(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
|
||||
!(x86_arch_cap_msr & ARCH_CAP_PSCHANGE_MC_NO))
|
||||
setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
|
||||
|
||||
if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
|
||||
@@ -1334,7 +1335,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
|
||||
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
|
||||
!(ia32_cap & ARCH_CAP_SSB_NO) &&
|
||||
!(x86_arch_cap_msr & ARCH_CAP_SSB_NO) &&
|
||||
!cpu_has(c, X86_FEATURE_AMD_SSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
|
||||
|
||||
@@ -1345,17 +1346,17 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
* Don't use AutoIBRS when SNP is enabled because it degrades host
|
||||
* userspace indirect branch performance.
|
||||
*/
|
||||
if ((ia32_cap & ARCH_CAP_IBRS_ALL) ||
|
||||
if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) ||
|
||||
(cpu_has(c, X86_FEATURE_AUTOIBRS) &&
|
||||
!cpu_feature_enabled(X86_FEATURE_SEV_SNP))) {
|
||||
setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
|
||||
!(ia32_cap & ARCH_CAP_PBRSB_NO))
|
||||
!(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
|
||||
}
|
||||
|
||||
if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
|
||||
!(ia32_cap & ARCH_CAP_MDS_NO)) {
|
||||
!(x86_arch_cap_msr & ARCH_CAP_MDS_NO)) {
|
||||
setup_force_cpu_bug(X86_BUG_MDS);
|
||||
if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
|
||||
setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
|
||||
@@ -1374,9 +1375,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
* TSX_CTRL check alone is not sufficient for cases when the microcode
|
||||
* update is not present or running as guest that don't get TSX_CTRL.
|
||||
*/
|
||||
if (!(ia32_cap & ARCH_CAP_TAA_NO) &&
|
||||
if (!(x86_arch_cap_msr & ARCH_CAP_TAA_NO) &&
|
||||
(cpu_has(c, X86_FEATURE_RTM) ||
|
||||
(ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
|
||||
(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR)))
|
||||
setup_force_cpu_bug(X86_BUG_TAA);
|
||||
|
||||
/*
|
||||
@@ -1402,7 +1403,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
* Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist,
|
||||
* nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits.
|
||||
*/
|
||||
if (!arch_cap_mmio_immune(ia32_cap)) {
|
||||
if (!arch_cap_mmio_immune(x86_arch_cap_msr)) {
|
||||
if (cpu_matches(cpu_vuln_blacklist, MMIO))
|
||||
setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
|
||||
else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
|
||||
@@ -1410,7 +1411,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
|
||||
if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
|
||||
if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (x86_arch_cap_msr & ARCH_CAP_RSBA))
|
||||
setup_force_cpu_bug(X86_BUG_RETBLEED);
|
||||
}
|
||||
|
||||
@@ -1428,18 +1429,25 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
* disabling AVX2. The only way to do this in HW is to clear XCR0[2],
|
||||
* which means that AVX will be disabled.
|
||||
*/
|
||||
if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) &&
|
||||
if (cpu_matches(cpu_vuln_blacklist, GDS) && !(x86_arch_cap_msr & ARCH_CAP_GDS_NO) &&
|
||||
boot_cpu_has(X86_FEATURE_AVX))
|
||||
setup_force_cpu_bug(X86_BUG_GDS);
|
||||
|
||||
if (vulnerable_to_rfds(ia32_cap))
|
||||
if (vulnerable_to_rfds(x86_arch_cap_msr))
|
||||
setup_force_cpu_bug(X86_BUG_RFDS);
|
||||
|
||||
/* When virtualized, eIBRS could be hidden, assume vulnerable */
|
||||
if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) &&
|
||||
!cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
|
||||
(boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) ||
|
||||
boot_cpu_has(X86_FEATURE_HYPERVISOR)))
|
||||
setup_force_cpu_bug(X86_BUG_BHI);
|
||||
|
||||
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
|
||||
return;
|
||||
|
||||
/* Rogue Data Cache Load? No! */
|
||||
if (ia32_cap & ARCH_CAP_RDCL_NO)
|
||||
if (x86_arch_cap_msr & ARCH_CAP_RDCL_NO)
|
||||
return;
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
|
||||
@@ -28,6 +28,7 @@ static const struct cpuid_bit cpuid_bits[] = {
|
||||
{ X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
|
||||
{ X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 },
|
||||
{ X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 },
|
||||
{ X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 },
|
||||
{ X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
|
||||
{ X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
|
||||
{ X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
|
||||
|
||||
@@ -123,7 +123,6 @@ static void topo_set_cpuids(unsigned int cpu, u32 apic_id, u32 acpi_id)
|
||||
early_per_cpu(x86_cpu_to_apicid, cpu) = apic_id;
|
||||
early_per_cpu(x86_cpu_to_acpiid, cpu) = acpi_id;
|
||||
#endif
|
||||
set_cpu_possible(cpu, true);
|
||||
set_cpu_present(cpu, true);
|
||||
}
|
||||
|
||||
@@ -210,7 +209,11 @@ static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
|
||||
topo_info.nr_disabled_cpus++;
|
||||
}
|
||||
|
||||
/* Register present and possible CPUs in the domain maps */
|
||||
/*
|
||||
* Register present and possible CPUs in the domain
|
||||
* maps. cpu_possible_map will be updated in
|
||||
* topology_init_possible_cpus() after enumeration is done.
|
||||
*/
|
||||
for (dom = TOPO_SMT_DOMAIN; dom < TOPO_MAX_DOMAIN; dom++)
|
||||
set_bit(topo_apicid(apic_id, dom), apic_maps[dom].map);
|
||||
}
|
||||
|
||||
@@ -29,11 +29,21 @@ static bool parse_8000_0008(struct topo_scan *tscan)
|
||||
if (!sft)
|
||||
sft = get_count_order(ecx.cpu_nthreads + 1);
|
||||
|
||||
topology_set_dom(tscan, TOPO_SMT_DOMAIN, sft, ecx.cpu_nthreads + 1);
|
||||
/*
|
||||
* cpu_nthreads describes the number of threads in the package
|
||||
* sft is the number of APIC ID bits per package
|
||||
*
|
||||
* As the number of actual threads per core is not described in
|
||||
* this leaf, just set the CORE domain shift and let the later
|
||||
* parsers set SMT shift. Assume one thread per core by default
|
||||
* which is correct if there are no other CPUID leafs to parse.
|
||||
*/
|
||||
topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
|
||||
topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void store_node(struct topo_scan *tscan, unsigned int nr_nodes, u16 node_id)
|
||||
static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id)
|
||||
{
|
||||
/*
|
||||
* Starting with Fam 17h the DIE domain could probably be used to
|
||||
@@ -73,12 +83,14 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_0xb)
|
||||
tscan->c->topo.initial_apicid = leaf.ext_apic_id;
|
||||
|
||||
/*
|
||||
* If leaf 0xb is available, then SMT shift is set already. If not
|
||||
* take it from ecx.threads_per_core and use topo_update_dom() -
|
||||
* topology_set_dom() would propagate and overwrite the already
|
||||
* propagated CORE level.
|
||||
* If leaf 0xb is available, then the domain shifts are set
|
||||
* already and nothing to do here.
|
||||
*/
|
||||
if (!has_0xb) {
|
||||
/*
|
||||
* Leaf 0x80000008 set the CORE domain shift already.
|
||||
* Update the SMT domain, but do not propagate it.
|
||||
*/
|
||||
unsigned int nthreads = leaf.core_nthreads + 1;
|
||||
|
||||
topology_update_dom(tscan, TOPO_SMT_DOMAIN, get_count_order(nthreads), nthreads);
|
||||
@@ -109,13 +121,13 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_0xb)
|
||||
|
||||
static bool parse_fam10h_node_id(struct topo_scan *tscan)
|
||||
{
|
||||
struct {
|
||||
union {
|
||||
union {
|
||||
struct {
|
||||
u64 node_id : 3,
|
||||
nodes_per_pkg : 3,
|
||||
unused : 58;
|
||||
u64 msr;
|
||||
};
|
||||
u64 msr;
|
||||
} nid;
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_NODEID_MSR))
|
||||
@@ -135,6 +147,26 @@ static void legacy_set_llc(struct topo_scan *tscan)
|
||||
tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN];
|
||||
}
|
||||
|
||||
static void topoext_fixup(struct topo_scan *tscan)
|
||||
{
|
||||
struct cpuinfo_x86 *c = tscan->c;
|
||||
u64 msrval;
|
||||
|
||||
/* Try to re-enable TopologyExtensions if switched off by BIOS */
|
||||
if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD ||
|
||||
c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f)
|
||||
return;
|
||||
|
||||
if (msr_set_bit(0xc0011005, 54) <= 0)
|
||||
return;
|
||||
|
||||
rdmsrl(0xc0011005, msrval);
|
||||
if (msrval & BIT_64(54)) {
|
||||
set_cpu_cap(c, X86_FEATURE_TOPOEXT);
|
||||
pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_topology_amd(struct topo_scan *tscan)
|
||||
{
|
||||
bool has_0xb = false;
|
||||
@@ -164,6 +196,7 @@ static void parse_topology_amd(struct topo_scan *tscan)
|
||||
void cpu_parse_topology_amd(struct topo_scan *tscan)
|
||||
{
|
||||
tscan->amd_nodes_per_pkg = 1;
|
||||
topoext_fixup(tscan);
|
||||
parse_topology_amd(tscan);
|
||||
|
||||
if (tscan->amd_nodes_per_pkg > 1)
|
||||
|
||||
@@ -52,7 +52,7 @@ enum kvm_only_cpuid_leafs {
|
||||
#define X86_FEATURE_IPRED_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 1)
|
||||
#define KVM_X86_FEATURE_RRSBA_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 2)
|
||||
#define X86_FEATURE_DDPD_U KVM_X86_FEATURE(CPUID_7_2_EDX, 3)
|
||||
#define X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
|
||||
#define KVM_X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
|
||||
#define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5)
|
||||
|
||||
/* CPUID level 0x80000007 (EDX). */
|
||||
@@ -128,6 +128,7 @@ static __always_inline u32 __feature_translate(int x86_feature)
|
||||
KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC);
|
||||
KVM_X86_TRANSLATE_FEATURE(PERFMON_V2);
|
||||
KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL);
|
||||
KVM_X86_TRANSLATE_FEATURE(BHI_CTRL);
|
||||
default:
|
||||
return x86_feature;
|
||||
}
|
||||
|
||||
@@ -275,6 +275,8 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL)
|
||||
|
||||
call vmx_spec_ctrl_restore_host
|
||||
|
||||
CLEAR_BRANCH_HISTORY_VMEXIT
|
||||
|
||||
/* Put return value in AX */
|
||||
mov %_ASM_BX, %_ASM_AX
|
||||
|
||||
|
||||
+1
-1
@@ -1621,7 +1621,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr)
|
||||
ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
|
||||
ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
|
||||
ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \
|
||||
ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR)
|
||||
ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO)
|
||||
|
||||
static u64 kvm_get_arch_capabilities(void)
|
||||
{
|
||||
|
||||
+6
-3
@@ -1409,6 +1409,12 @@ static int blkcg_css_online(struct cgroup_subsys_state *css)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blkg_init_queue(struct request_queue *q)
|
||||
{
|
||||
INIT_LIST_HEAD(&q->blkg_list);
|
||||
mutex_init(&q->blkcg_mutex);
|
||||
}
|
||||
|
||||
int blkcg_init_disk(struct gendisk *disk)
|
||||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
@@ -1416,9 +1422,6 @@ int blkcg_init_disk(struct gendisk *disk)
|
||||
bool preloaded;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&q->blkg_list);
|
||||
mutex_init(&q->blkcg_mutex);
|
||||
|
||||
new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL);
|
||||
if (!new_blkg)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -189,6 +189,7 @@ struct blkcg_policy {
|
||||
extern struct blkcg blkcg_root;
|
||||
extern bool blkcg_debug_stats;
|
||||
|
||||
void blkg_init_queue(struct request_queue *q);
|
||||
int blkcg_init_disk(struct gendisk *disk);
|
||||
void blkcg_exit_disk(struct gendisk *disk);
|
||||
|
||||
@@ -482,6 +483,7 @@ struct blkcg {
|
||||
};
|
||||
|
||||
static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; }
|
||||
static inline void blkg_init_queue(struct request_queue *q) { }
|
||||
static inline int blkcg_init_disk(struct gendisk *disk) { return 0; }
|
||||
static inline void blkcg_exit_disk(struct gendisk *disk) { }
|
||||
static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
|
||||
|
||||
@@ -442,6 +442,8 @@ struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id)
|
||||
init_waitqueue_head(&q->mq_freeze_wq);
|
||||
mutex_init(&q->mq_freeze_lock);
|
||||
|
||||
blkg_init_queue(q);
|
||||
|
||||
/*
|
||||
* Init percpu_ref in atomic mode so that it's faster to shutdown.
|
||||
* See blk_register_queue() for details.
|
||||
@@ -1195,6 +1197,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule)
|
||||
if (unlikely(!rq_list_empty(plug->cached_rq)))
|
||||
blk_mq_free_plug_rqs(plug);
|
||||
|
||||
plug->cur_ktime = 0;
|
||||
current->flags &= ~PF_BLOCK_TS;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -1347,7 +1347,7 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
|
||||
{
|
||||
struct ioc *ioc = iocg->ioc;
|
||||
struct blkcg_gq *blkg = iocg_to_blkg(iocg);
|
||||
u64 tdelta, delay, new_delay;
|
||||
u64 tdelta, delay, new_delay, shift;
|
||||
s64 vover, vover_pct;
|
||||
u32 hwa;
|
||||
|
||||
@@ -1362,8 +1362,9 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
|
||||
|
||||
/* calculate the current delay in effect - 1/2 every second */
|
||||
tdelta = now->now - iocg->delay_at;
|
||||
if (iocg->delay)
|
||||
delay = iocg->delay >> div64_u64(tdelta, USEC_PER_SEC);
|
||||
shift = div64_u64(tdelta, USEC_PER_SEC);
|
||||
if (iocg->delay && shift < BITS_PER_LONG)
|
||||
delay = iocg->delay >> shift;
|
||||
else
|
||||
delay = 0;
|
||||
|
||||
|
||||
+6
-10
@@ -182,17 +182,13 @@ static int blk_validate_limits(struct queue_limits *lim)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Devices that require a virtual boundary do not support scatter/gather
|
||||
* I/O natively, but instead require a descriptor list entry for each
|
||||
* page (which might not be identical to the Linux PAGE_SIZE). Because
|
||||
* of that they are not limited by our notion of "segment size".
|
||||
* Stacking device may have both virtual boundary and max segment
|
||||
* size limit, so allow this setting now, and long-term the two
|
||||
* might need to move out of stacking limits since we have immutable
|
||||
* bvec and lower layer bio splitting is supposed to handle the two
|
||||
* correctly.
|
||||
*/
|
||||
if (lim->virt_boundary_mask) {
|
||||
if (WARN_ON_ONCE(lim->max_segment_size &&
|
||||
lim->max_segment_size != UINT_MAX))
|
||||
return -EINVAL;
|
||||
lim->max_segment_size = UINT_MAX;
|
||||
} else {
|
||||
if (!lim->virt_boundary_mask) {
|
||||
/*
|
||||
* The maximum segment size has an odd historic 64k default that
|
||||
* drivers probably should override. Just like the I/O size we
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
@@ -131,22 +131,6 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ivpu_get_core_clock_rate(struct ivpu_device *vdev, u64 *clk_rate)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ivpu_rpm_get_if_active(vdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*clk_rate = ret ? ivpu_hw_reg_pll_freq_get(vdev) : 0;
|
||||
|
||||
if (ret)
|
||||
ivpu_rpm_put(vdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
{
|
||||
struct ivpu_file_priv *file_priv = file->driver_priv;
|
||||
@@ -170,7 +154,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
|
||||
args->value = vdev->platform;
|
||||
break;
|
||||
case DRM_IVPU_PARAM_CORE_CLOCK_RATE:
|
||||
ret = ivpu_get_core_clock_rate(vdev, &args->value);
|
||||
args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio);
|
||||
break;
|
||||
case DRM_IVPU_PARAM_NUM_CONTEXTS:
|
||||
args->value = ivpu_get_context_count(vdev);
|
||||
@@ -387,12 +371,15 @@ int ivpu_shutdown(struct ivpu_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ivpu_prepare_for_reset(vdev);
|
||||
/* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */
|
||||
pci_save_state(to_pci_dev(vdev->drm.dev));
|
||||
|
||||
ret = ivpu_hw_power_down(vdev);
|
||||
if (ret)
|
||||
ivpu_warn(vdev, "Failed to power down HW: %d\n", ret);
|
||||
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -530,7 +517,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
|
||||
vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID;
|
||||
vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID;
|
||||
atomic64_set(&vdev->unique_id_counter, 0);
|
||||
xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC);
|
||||
xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
|
||||
xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1);
|
||||
xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1);
|
||||
lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key);
|
||||
@@ -560,11 +547,11 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
|
||||
/* Power up early so the rest of init code can access VPU registers */
|
||||
ret = ivpu_hw_power_up(vdev);
|
||||
if (ret)
|
||||
goto err_power_down;
|
||||
goto err_shutdown;
|
||||
|
||||
ret = ivpu_mmu_global_context_init(vdev);
|
||||
if (ret)
|
||||
goto err_power_down;
|
||||
goto err_shutdown;
|
||||
|
||||
ret = ivpu_mmu_init(vdev);
|
||||
if (ret)
|
||||
@@ -601,10 +588,8 @@ err_mmu_rctx_fini:
|
||||
ivpu_mmu_reserved_context_fini(vdev);
|
||||
err_mmu_gctx_fini:
|
||||
ivpu_mmu_global_context_fini(vdev);
|
||||
err_power_down:
|
||||
ivpu_hw_power_down(vdev);
|
||||
if (IVPU_WA(d3hot_after_power_off))
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
|
||||
err_shutdown:
|
||||
ivpu_shutdown(vdev);
|
||||
err_xa_destroy:
|
||||
xa_destroy(&vdev->db_xa);
|
||||
xa_destroy(&vdev->submitted_jobs_xa);
|
||||
@@ -628,9 +613,8 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev)
|
||||
static void ivpu_dev_fini(struct ivpu_device *vdev)
|
||||
{
|
||||
ivpu_pm_disable(vdev);
|
||||
ivpu_prepare_for_reset(vdev);
|
||||
ivpu_shutdown(vdev);
|
||||
if (IVPU_WA(d3hot_after_power_off))
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
|
||||
|
||||
ivpu_jobs_abort_all(vdev);
|
||||
ivpu_job_done_consumer_fini(vdev);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __IVPU_DRV_H__
|
||||
@@ -90,7 +90,6 @@
|
||||
struct ivpu_wa_table {
|
||||
bool punit_disabled;
|
||||
bool clear_runtime_mem;
|
||||
bool d3hot_after_power_off;
|
||||
bool interrupt_clear_with_0;
|
||||
bool disable_clock_relinquish;
|
||||
bool disable_d0i3_msg;
|
||||
|
||||
@@ -21,6 +21,7 @@ struct ivpu_hw_ops {
|
||||
u32 (*profiling_freq_get)(struct ivpu_device *vdev);
|
||||
void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable);
|
||||
u32 (*reg_pll_freq_get)(struct ivpu_device *vdev);
|
||||
u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio);
|
||||
u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev);
|
||||
u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev);
|
||||
u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev);
|
||||
@@ -130,6 +131,11 @@ static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev)
|
||||
return vdev->hw->ops->reg_pll_freq_get(vdev);
|
||||
};
|
||||
|
||||
static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
|
||||
{
|
||||
return vdev->hw->ops->ratio_to_freq(vdev, ratio);
|
||||
}
|
||||
|
||||
static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev)
|
||||
{
|
||||
return vdev->hw->ops->reg_telemetry_offset_get(vdev);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "ivpu_drv.h"
|
||||
@@ -75,7 +75,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
|
||||
{
|
||||
vdev->wa.punit_disabled = false;
|
||||
vdev->wa.clear_runtime_mem = false;
|
||||
vdev->wa.d3hot_after_power_off = true;
|
||||
|
||||
REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK);
|
||||
if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) {
|
||||
@@ -86,7 +85,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
|
||||
|
||||
IVPU_PRINT_WA(punit_disabled);
|
||||
IVPU_PRINT_WA(clear_runtime_mem);
|
||||
IVPU_PRINT_WA(d3hot_after_power_off);
|
||||
IVPU_PRINT_WA(interrupt_clear_with_0);
|
||||
}
|
||||
|
||||
@@ -805,12 +803,12 @@ static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool ena
|
||||
/* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */
|
||||
}
|
||||
|
||||
static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config)
|
||||
static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
|
||||
{
|
||||
u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
|
||||
u32 cpu_clock;
|
||||
|
||||
if ((config & 0xff) == PLL_RATIO_4_3)
|
||||
if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3)
|
||||
cpu_clock = pll_clock * 2 / 4;
|
||||
else
|
||||
cpu_clock = pll_clock * 2 / 5;
|
||||
@@ -829,7 +827,7 @@ static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev)
|
||||
if (!ivpu_is_silicon(vdev))
|
||||
return PLL_SIMULATION_FREQ;
|
||||
|
||||
return ivpu_hw_37xx_pll_to_freq(pll_curr_ratio, vdev->hw->config);
|
||||
return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio);
|
||||
}
|
||||
|
||||
static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
|
||||
@@ -1052,6 +1050,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = {
|
||||
.profiling_freq_get = ivpu_hw_37xx_profiling_freq_get,
|
||||
.profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive,
|
||||
.reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get,
|
||||
.ratio_to_freq = ivpu_hw_37xx_ratio_to_freq,
|
||||
.reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get,
|
||||
.reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get,
|
||||
.reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get,
|
||||
|
||||
@@ -980,6 +980,11 @@ static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev)
|
||||
return PLL_RATIO_TO_FREQ(pll_curr_ratio);
|
||||
}
|
||||
|
||||
static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
|
||||
{
|
||||
return PLL_RATIO_TO_FREQ(ratio);
|
||||
}
|
||||
|
||||
static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
|
||||
{
|
||||
return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET);
|
||||
@@ -1230,6 +1235,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = {
|
||||
.profiling_freq_get = ivpu_hw_40xx_profiling_freq_get,
|
||||
.profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive,
|
||||
.reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get,
|
||||
.ratio_to_freq = ivpu_hw_40xx_ratio_to_freq,
|
||||
.reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get,
|
||||
.reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get,
|
||||
.reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/genalloc.h>
|
||||
@@ -501,7 +501,11 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
|
||||
spin_lock_init(&ipc->cons_lock);
|
||||
INIT_LIST_HEAD(&ipc->cons_list);
|
||||
INIT_LIST_HEAD(&ipc->cb_msg_list);
|
||||
drmm_mutex_init(&vdev->drm, &ipc->lock);
|
||||
ret = drmm_mutex_init(&vdev->drm, &ipc->lock);
|
||||
if (ret) {
|
||||
ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret);
|
||||
goto err_free_rx;
|
||||
}
|
||||
ivpu_ipc_reset(vdev);
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ static const char *ivpu_mmu_event_to_str(u32 cmd)
|
||||
case IVPU_MMU_EVT_F_VMS_FETCH:
|
||||
return "Fetch of VMS caused external abort";
|
||||
default:
|
||||
return "Unknown CMDQ command";
|
||||
return "Unknown event";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,15 +286,15 @@ static const char *ivpu_mmu_cmdq_err_to_str(u32 err)
|
||||
{
|
||||
switch (err) {
|
||||
case IVPU_MMU_CERROR_NONE:
|
||||
return "No CMDQ Error";
|
||||
return "No error";
|
||||
case IVPU_MMU_CERROR_ILL:
|
||||
return "Illegal command";
|
||||
case IVPU_MMU_CERROR_ABT:
|
||||
return "External abort on CMDQ read";
|
||||
return "External abort on command queue read";
|
||||
case IVPU_MMU_CERROR_ATC_INV_SYNC:
|
||||
return "Sync failed to complete ATS invalidation";
|
||||
default:
|
||||
return "Unknown CMDQ Error";
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/highmem.h>
|
||||
@@ -58,14 +58,11 @@ static int ivpu_suspend(struct ivpu_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */
|
||||
pci_save_state(to_pci_dev(vdev->drm.dev));
|
||||
ivpu_prepare_for_reset(vdev);
|
||||
|
||||
ret = ivpu_shutdown(vdev);
|
||||
if (ret)
|
||||
ivpu_err(vdev, "Failed to shutdown VPU: %d\n", ret);
|
||||
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
|
||||
ivpu_err(vdev, "Failed to shutdown NPU: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -74,10 +71,10 @@ static int ivpu_resume(struct ivpu_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
|
||||
pci_restore_state(to_pci_dev(vdev->drm.dev));
|
||||
|
||||
retry:
|
||||
pci_restore_state(to_pci_dev(vdev->drm.dev));
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
|
||||
|
||||
ret = ivpu_hw_power_up(vdev);
|
||||
if (ret) {
|
||||
ivpu_err(vdev, "Failed to power up HW: %d\n", ret);
|
||||
@@ -100,6 +97,7 @@ err_mmu_disable:
|
||||
ivpu_mmu_disable(vdev);
|
||||
err_power_down:
|
||||
ivpu_hw_power_down(vdev);
|
||||
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
|
||||
|
||||
if (!ivpu_fw_is_cold_boot(vdev)) {
|
||||
ivpu_pm_prepare_cold_boot(vdev);
|
||||
|
||||
+2
-1
@@ -1843,7 +1843,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
|
||||
if (dep->honor_dep)
|
||||
adev->flags.honor_deps = 1;
|
||||
|
||||
adev->dep_unmet++;
|
||||
if (!dep->met)
|
||||
adev->dep_unmet++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,6 +666,87 @@ static int mobile_lpm_policy = -1;
|
||||
module_param(mobile_lpm_policy, int, 0644);
|
||||
MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
|
||||
|
||||
static char *ahci_mask_port_map;
|
||||
module_param_named(mask_port_map, ahci_mask_port_map, charp, 0444);
|
||||
MODULE_PARM_DESC(mask_port_map,
|
||||
"32-bits port map masks to ignore controllers ports. "
|
||||
"Valid values are: "
|
||||
"\"<mask>\" to apply the same mask to all AHCI controller "
|
||||
"devices, and \"<pci_dev>=<mask>,<pci_dev>=<mask>,...\" to "
|
||||
"specify different masks for the controllers specified, "
|
||||
"where <pci_dev> is the PCI ID of an AHCI controller in the "
|
||||
"form \"domain:bus:dev.func\"");
|
||||
|
||||
static void ahci_apply_port_map_mask(struct device *dev,
|
||||
struct ahci_host_priv *hpriv, char *mask_s)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
if (kstrtouint(mask_s, 0, &mask)) {
|
||||
dev_err(dev, "Invalid port map mask\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hpriv->mask_port_map = mask;
|
||||
}
|
||||
|
||||
static void ahci_get_port_map_mask(struct device *dev,
|
||||
struct ahci_host_priv *hpriv)
|
||||
{
|
||||
char *param, *end, *str, *mask_s;
|
||||
char *name;
|
||||
|
||||
if (!strlen(ahci_mask_port_map))
|
||||
return;
|
||||
|
||||
str = kstrdup(ahci_mask_port_map, GFP_KERNEL);
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
/* Handle single mask case */
|
||||
if (!strchr(str, '=')) {
|
||||
ahci_apply_port_map_mask(dev, hpriv, str);
|
||||
goto free;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask list case: parse the parameter to apply the mask only if
|
||||
* the device name matches.
|
||||
*/
|
||||
param = str;
|
||||
end = param + strlen(param);
|
||||
while (param && param < end && *param) {
|
||||
name = param;
|
||||
param = strchr(name, '=');
|
||||
if (!param)
|
||||
break;
|
||||
|
||||
*param = '\0';
|
||||
param++;
|
||||
if (param >= end)
|
||||
break;
|
||||
|
||||
if (strcmp(dev_name(dev), name) != 0) {
|
||||
param = strchr(param, ',');
|
||||
if (param)
|
||||
param++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mask_s = param;
|
||||
param = strchr(mask_s, ',');
|
||||
if (param) {
|
||||
*param = '\0';
|
||||
param++;
|
||||
}
|
||||
|
||||
ahci_apply_port_map_mask(dev, hpriv, mask_s);
|
||||
}
|
||||
|
||||
free:
|
||||
kfree(str);
|
||||
}
|
||||
|
||||
static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
||||
struct ahci_host_priv *hpriv)
|
||||
{
|
||||
@@ -688,6 +769,10 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
||||
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
|
||||
}
|
||||
|
||||
/* Handle port map masks passed as module parameter. */
|
||||
if (ahci_mask_port_map)
|
||||
ahci_get_port_map_mask(&pdev->dev, hpriv);
|
||||
|
||||
ahci_save_initial_config(&pdev->dev, hpriv);
|
||||
}
|
||||
|
||||
|
||||
@@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev)
|
||||
bool cdl_enabled;
|
||||
u64 val;
|
||||
|
||||
if (ata_id_major_version(dev->id) < 12)
|
||||
if (ata_id_major_version(dev->id) < 11)
|
||||
goto not_supported;
|
||||
|
||||
if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
|
||||
|
||||
@@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
* bail out.
|
||||
*/
|
||||
if (ap->pflags & ATA_PFLAG_SUSPENDED)
|
||||
goto unlock;
|
||||
goto unlock_ap;
|
||||
|
||||
if (!sdev)
|
||||
continue;
|
||||
@@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
if (do_resume) {
|
||||
ret = scsi_resume_device(sdev);
|
||||
if (ret == -EWOULDBLOCK)
|
||||
goto unlock;
|
||||
goto unlock_scan;
|
||||
dev->flags &= ~ATA_DFLAG_RESUMING;
|
||||
}
|
||||
ret = scsi_rescan_device(sdev);
|
||||
@@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
if (ret)
|
||||
goto unlock;
|
||||
goto unlock_ap;
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
unlock_ap:
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
unlock_scan:
|
||||
mutex_unlock(&ap->scsi_scan_mutex);
|
||||
|
||||
/* Reschedule with a delay if scsi_rescan_device() returned an error */
|
||||
|
||||
Vendored
+46
-26
@@ -15,6 +15,8 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cacheinfo.h>
|
||||
#include <asm/dma-noncoherent.h>
|
||||
@@ -247,13 +249,49 @@ static irqreturn_t ccache_int_handler(int irq, void *device)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int sifive_ccache_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
unsigned long quirks;
|
||||
int intr_num, rc;
|
||||
|
||||
quirks = (unsigned long)device_get_match_data(dev);
|
||||
|
||||
intr_num = platform_irq_count(pdev);
|
||||
if (!intr_num)
|
||||
return dev_err_probe(dev, -ENODEV, "No interrupts property\n");
|
||||
|
||||
for (int i = 0; i < intr_num; i++) {
|
||||
if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR))
|
||||
continue;
|
||||
|
||||
g_irq[i] = platform_get_irq(pdev, i);
|
||||
if (g_irq[i] < 0)
|
||||
return g_irq[i];
|
||||
|
||||
rc = devm_request_irq(dev, g_irq[i], ccache_int_handler, 0, "ccache_ecc", NULL);
|
||||
if (rc)
|
||||
return dev_err_probe(dev, rc, "Could not request IRQ %d\n", g_irq[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sifive_ccache_driver = {
|
||||
.probe = sifive_ccache_probe,
|
||||
.driver = {
|
||||
.name = "sifive_ccache",
|
||||
.of_match_table = sifive_ccache_ids,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sifive_ccache_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
int i, rc, intr_num;
|
||||
const struct of_device_id *match;
|
||||
unsigned long quirks;
|
||||
int rc;
|
||||
|
||||
np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match);
|
||||
if (!np)
|
||||
@@ -277,28 +315,6 @@ static int __init sifive_ccache_init(void)
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
intr_num = of_property_count_u32_elems(np, "interrupts");
|
||||
if (!intr_num) {
|
||||
pr_err("No interrupts property\n");
|
||||
rc = -ENODEV;
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
for (i = 0; i < intr_num; i++) {
|
||||
g_irq[i] = irq_of_parse_and_map(np, i);
|
||||
|
||||
if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR))
|
||||
continue;
|
||||
|
||||
rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc",
|
||||
NULL);
|
||||
if (rc) {
|
||||
pr_err("Could not request IRQ %d\n", g_irq[i]);
|
||||
goto err_free_irq;
|
||||
}
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
|
||||
if (quirks & QUIRK_NONSTANDARD_CACHE_OPS) {
|
||||
riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE;
|
||||
@@ -315,11 +331,15 @@ static int __init sifive_ccache_init(void)
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
setup_sifive_debug();
|
||||
#endif
|
||||
|
||||
rc = platform_driver_register(&sifive_ccache_driver);
|
||||
if (rc)
|
||||
goto err_unmap;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
while (--i >= 0)
|
||||
free_irq(g_irq[i], NULL);
|
||||
err_unmap:
|
||||
iounmap(ccache_base);
|
||||
err_node_put:
|
||||
|
||||
+1
-12
@@ -525,22 +525,11 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
|
||||
{
|
||||
struct acpi_device *hb = to_cxl_host_bridge(NULL, dev);
|
||||
u32 uid;
|
||||
int rc;
|
||||
|
||||
if (kstrtou32(acpi_device_uid(hb), 0, &uid))
|
||||
return -EINVAL;
|
||||
|
||||
rc = acpi_get_genport_coordinates(uid, dport->hb_coord);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Adjust back to picoseconds from nanoseconds */
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
|
||||
dport->hb_coord[i].read_latency *= 1000;
|
||||
dport->hb_coord[i].write_latency *= 1000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return acpi_get_genport_coordinates(uid, dport->coord);
|
||||
}
|
||||
|
||||
static int add_host_bridge_dport(struct device *match, void *arg)
|
||||
|
||||
+80
-74
@@ -14,12 +14,42 @@
|
||||
struct dsmas_entry {
|
||||
struct range dpa_range;
|
||||
u8 handle;
|
||||
struct access_coordinate coord;
|
||||
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
|
||||
|
||||
int entries;
|
||||
int qos_class;
|
||||
};
|
||||
|
||||
static u32 cdat_normalize(u16 entry, u64 base, u8 type)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
/*
|
||||
* Check for invalid and overflow values
|
||||
*/
|
||||
if (entry == 0xffff || !entry)
|
||||
return 0;
|
||||
else if (base > (UINT_MAX / (entry)))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* CDAT fields follow the format of HMAT fields. See table 5 Device
|
||||
* Scoped Latency and Bandwidth Information Structure in Coherent Device
|
||||
* Attribute Table (CDAT) Specification v1.01.
|
||||
*/
|
||||
value = entry * base;
|
||||
switch (type) {
|
||||
case ACPI_HMAT_ACCESS_LATENCY:
|
||||
case ACPI_HMAT_READ_LATENCY:
|
||||
case ACPI_HMAT_WRITE_LATENCY:
|
||||
value = DIV_ROUND_UP(value, 1000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
|
||||
const unsigned long end)
|
||||
{
|
||||
@@ -58,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cxl_access_coordinate_set(struct access_coordinate *coord,
|
||||
int access, unsigned int val)
|
||||
static void __cxl_access_coordinate_set(struct access_coordinate *coord,
|
||||
int access, unsigned int val)
|
||||
{
|
||||
switch (access) {
|
||||
case ACPI_HMAT_ACCESS_LATENCY:
|
||||
@@ -85,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord,
|
||||
}
|
||||
}
|
||||
|
||||
static void cxl_access_coordinate_set(struct access_coordinate *coord,
|
||||
int access, unsigned int val)
|
||||
{
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
|
||||
__cxl_access_coordinate_set(&coord[i], access, val);
|
||||
}
|
||||
|
||||
static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
|
||||
const unsigned long end)
|
||||
{
|
||||
@@ -97,7 +134,6 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
|
||||
__le16 le_val;
|
||||
u64 val;
|
||||
u16 len;
|
||||
int rc;
|
||||
|
||||
len = le16_to_cpu((__force __le16)hdr->length);
|
||||
if (len != size || (unsigned long)hdr + len > end) {
|
||||
@@ -124,12 +160,10 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
|
||||
|
||||
le_base = (__force __le64)dslbis->entry_base_unit;
|
||||
le_val = (__force __le16)dslbis->entry[0];
|
||||
rc = check_mul_overflow(le64_to_cpu(le_base),
|
||||
le16_to_cpu(le_val), &val);
|
||||
if (rc)
|
||||
pr_warn("DSLBIS value overflowed.\n");
|
||||
val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base),
|
||||
dslbis->data_type);
|
||||
|
||||
cxl_access_coordinate_set(&dent->coord, dslbis->data_type, val);
|
||||
cxl_access_coordinate_set(dent->coord, dslbis->data_type, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -163,25 +197,18 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
|
||||
static int cxl_port_perf_data_calculate(struct cxl_port *port,
|
||||
struct xarray *dsmas_xa)
|
||||
{
|
||||
struct access_coordinate ep_c;
|
||||
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
|
||||
struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
|
||||
struct dsmas_entry *dent;
|
||||
int valid_entries = 0;
|
||||
unsigned long index;
|
||||
int rc;
|
||||
|
||||
rc = cxl_endpoint_get_perf_coordinates(port, &ep_c);
|
||||
rc = cxl_endpoint_get_perf_coordinates(port, ep_c);
|
||||
if (rc) {
|
||||
dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cxl_hb_get_perf_coordinates(port, coord);
|
||||
if (rc) {
|
||||
dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port);
|
||||
|
||||
if (!cxl_root)
|
||||
@@ -193,18 +220,10 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
|
||||
xa_for_each(dsmas_xa, index, dent) {
|
||||
int qos_class;
|
||||
|
||||
cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c);
|
||||
/*
|
||||
* Keeping the host bridge coordinates separate from the dsmas
|
||||
* coordinates in order to allow calculation of access class
|
||||
* 0 and 1 for region later.
|
||||
*/
|
||||
cxl_coordinates_combine(&coord[ACCESS_COORDINATE_CPU],
|
||||
&coord[ACCESS_COORDINATE_CPU],
|
||||
&dent->coord);
|
||||
cxl_coordinates_combine(dent->coord, dent->coord, ep_c);
|
||||
dent->entries = 1;
|
||||
rc = cxl_root->ops->qos_class(cxl_root,
|
||||
&coord[ACCESS_COORDINATE_CPU],
|
||||
&dent->coord[ACCESS_COORDINATE_CPU],
|
||||
1, &qos_class);
|
||||
if (rc != 1)
|
||||
continue;
|
||||
@@ -222,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
|
||||
static void update_perf_entry(struct device *dev, struct dsmas_entry *dent,
|
||||
struct cxl_dpa_perf *dpa_perf)
|
||||
{
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
|
||||
dpa_perf->coord[i] = dent->coord[i];
|
||||
dpa_perf->dpa_range = dent->dpa_range;
|
||||
dpa_perf->coord = dent->coord;
|
||||
dpa_perf->qos_class = dent->qos_class;
|
||||
dev_dbg(dev,
|
||||
"DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
|
||||
dent->dpa_range.start, dpa_perf->qos_class,
|
||||
dent->coord.read_bandwidth, dent->coord.write_bandwidth,
|
||||
dent->coord.read_latency, dent->coord.write_latency);
|
||||
dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth,
|
||||
dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth,
|
||||
dent->coord[ACCESS_COORDINATE_CPU].read_latency,
|
||||
dent->coord[ACCESS_COORDINATE_CPU].write_latency);
|
||||
}
|
||||
|
||||
static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds,
|
||||
@@ -461,17 +483,16 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
|
||||
|
||||
le_base = (__force __le64)tbl->sslbis_header.entry_base_unit;
|
||||
le_val = (__force __le16)tbl->entries[i].latency_or_bandwidth;
|
||||
|
||||
if (check_mul_overflow(le64_to_cpu(le_base),
|
||||
le16_to_cpu(le_val), &val))
|
||||
dev_warn(dev, "SSLBIS value overflowed!\n");
|
||||
val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base),
|
||||
sslbis->data_type);
|
||||
|
||||
xa_for_each(&port->dports, index, dport) {
|
||||
if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT ||
|
||||
dsp_id == dport->port_id)
|
||||
cxl_access_coordinate_set(&dport->sw_coord,
|
||||
dsp_id == dport->port_id) {
|
||||
cxl_access_coordinate_set(dport->coord,
|
||||
sslbis->data_type,
|
||||
val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,16 +514,9 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL);
|
||||
|
||||
/**
|
||||
* cxl_coordinates_combine - Combine the two input coordinates
|
||||
*
|
||||
* @out: Output coordinate of c1 and c2 combined
|
||||
* @c1: input coordinates
|
||||
* @c2: input coordinates
|
||||
*/
|
||||
void cxl_coordinates_combine(struct access_coordinate *out,
|
||||
struct access_coordinate *c1,
|
||||
struct access_coordinate *c2)
|
||||
static void __cxl_coordinates_combine(struct access_coordinate *out,
|
||||
struct access_coordinate *c1,
|
||||
struct access_coordinate *c2)
|
||||
{
|
||||
if (c1->write_bandwidth && c2->write_bandwidth)
|
||||
out->write_bandwidth = min(c1->write_bandwidth,
|
||||
@@ -515,23 +529,34 @@ void cxl_coordinates_combine(struct access_coordinate *out,
|
||||
out->read_latency = c1->read_latency + c2->read_latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* cxl_coordinates_combine - Combine the two input coordinates
|
||||
*
|
||||
* @out: Output coordinate of c1 and c2 combined
|
||||
* @c1: input coordinates
|
||||
* @c2: input coordinates
|
||||
*/
|
||||
void cxl_coordinates_combine(struct access_coordinate *out,
|
||||
struct access_coordinate *c1,
|
||||
struct access_coordinate *c2)
|
||||
{
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
|
||||
__cxl_coordinates_combine(&out[i], &c1[i], &c2[i]);
|
||||
}
|
||||
|
||||
MODULE_IMPORT_NS(CXL);
|
||||
|
||||
void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
|
||||
struct cxl_endpoint_decoder *cxled)
|
||||
{
|
||||
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
|
||||
struct cxl_port *port = cxlmd->endpoint;
|
||||
struct cxl_dev_state *cxlds = cxlmd->cxlds;
|
||||
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
|
||||
struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
|
||||
struct access_coordinate coord;
|
||||
struct range dpa = {
|
||||
.start = cxled->dpa_res->start,
|
||||
.end = cxled->dpa_res->end,
|
||||
};
|
||||
struct cxl_dpa_perf *perf;
|
||||
int rc;
|
||||
|
||||
switch (cxlr->mode) {
|
||||
case CXL_DECODER_RAM:
|
||||
@@ -549,35 +574,16 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
|
||||
if (!range_contains(&perf->dpa_range, &dpa))
|
||||
return;
|
||||
|
||||
rc = cxl_hb_get_perf_coordinates(port, hb_coord);
|
||||
if (rc) {
|
||||
dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
|
||||
/* Pickup the host bridge coords */
|
||||
cxl_coordinates_combine(&coord, &hb_coord[i], &perf->coord);
|
||||
|
||||
/* Get total bandwidth and the worst latency for the cxl region */
|
||||
cxlr->coord[i].read_latency = max_t(unsigned int,
|
||||
cxlr->coord[i].read_latency,
|
||||
coord.read_latency);
|
||||
perf->coord[i].read_latency);
|
||||
cxlr->coord[i].write_latency = max_t(unsigned int,
|
||||
cxlr->coord[i].write_latency,
|
||||
coord.write_latency);
|
||||
cxlr->coord[i].read_bandwidth += coord.read_bandwidth;
|
||||
cxlr->coord[i].write_bandwidth += coord.write_bandwidth;
|
||||
|
||||
/*
|
||||
* Convert latency to nanosec from picosec to be consistent
|
||||
* with the resulting latency coordinates computed by the
|
||||
* HMAT_REPORTING code.
|
||||
*/
|
||||
cxlr->coord[i].read_latency =
|
||||
DIV_ROUND_UP(cxlr->coord[i].read_latency, 1000);
|
||||
cxlr->coord[i].write_latency =
|
||||
DIV_ROUND_UP(cxlr->coord[i].write_latency, 1000);
|
||||
perf->coord[i].write_latency);
|
||||
cxlr->coord[i].read_bandwidth += perf->coord[i].read_bandwidth;
|
||||
cxlr->coord[i].write_bandwidth += perf->coord[i].write_bandwidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -915,7 +915,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
|
||||
|
||||
payload->handles[i++] = gen->hdr.handle;
|
||||
dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
|
||||
le16_to_cpu(payload->handles[i]));
|
||||
le16_to_cpu(payload->handles[i - 1]));
|
||||
|
||||
if (i == max_handles) {
|
||||
payload->nr_recs = i;
|
||||
@@ -958,13 +958,14 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
|
||||
.payload_in = &log_type,
|
||||
.size_in = sizeof(log_type),
|
||||
.payload_out = payload,
|
||||
.size_out = mds->payload_size,
|
||||
.min_out = struct_size(payload, records, 0),
|
||||
};
|
||||
|
||||
do {
|
||||
int rc, i;
|
||||
|
||||
mbox_cmd.size_out = mds->payload_size;
|
||||
|
||||
rc = cxl_internal_send_cmd(mds, &mbox_cmd);
|
||||
if (rc) {
|
||||
dev_err_ratelimited(dev,
|
||||
|
||||
+70
-46
@@ -2133,36 +2133,44 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL);
|
||||
|
||||
/**
|
||||
* cxl_hb_get_perf_coordinates - Retrieve performance numbers between initiator
|
||||
* and host bridge
|
||||
*
|
||||
* @port: endpoint cxl_port
|
||||
* @coord: output access coordinates
|
||||
*
|
||||
* Return: errno on failure, 0 on success.
|
||||
*/
|
||||
int cxl_hb_get_perf_coordinates(struct cxl_port *port,
|
||||
struct access_coordinate *coord)
|
||||
static void add_latency(struct access_coordinate *c, long latency)
|
||||
{
|
||||
struct cxl_port *iter = port;
|
||||
struct cxl_dport *dport;
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
|
||||
c[i].write_latency += latency;
|
||||
c[i].read_latency += latency;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_cxl_endpoint(port))
|
||||
return -EINVAL;
|
||||
|
||||
dport = iter->parent_dport;
|
||||
while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
|
||||
iter = to_cxl_port(iter->dev.parent);
|
||||
dport = iter->parent_dport;
|
||||
static bool coordinates_valid(struct access_coordinate *c)
|
||||
{
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
|
||||
if (c[i].read_bandwidth && c[i].write_bandwidth &&
|
||||
c[i].read_latency && c[i].write_latency)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
coord[ACCESS_COORDINATE_LOCAL] =
|
||||
dport->hb_coord[ACCESS_COORDINATE_LOCAL];
|
||||
coord[ACCESS_COORDINATE_CPU] =
|
||||
dport->hb_coord[ACCESS_COORDINATE_CPU];
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void set_min_bandwidth(struct access_coordinate *c, unsigned int bw)
|
||||
{
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
|
||||
c[i].write_bandwidth = min(c[i].write_bandwidth, bw);
|
||||
c[i].read_bandwidth = min(c[i].read_bandwidth, bw);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_access_coordinates(struct access_coordinate *out,
|
||||
struct access_coordinate *in)
|
||||
{
|
||||
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
|
||||
out[i] = in[i];
|
||||
}
|
||||
|
||||
static bool parent_port_is_cxl_root(struct cxl_port *port)
|
||||
{
|
||||
return is_cxl_root(to_cxl_port(port->dev.parent));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2176,35 +2184,53 @@ int cxl_hb_get_perf_coordinates(struct cxl_port *port,
|
||||
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
|
||||
struct access_coordinate *coord)
|
||||
{
|
||||
struct access_coordinate c = {
|
||||
.read_bandwidth = UINT_MAX,
|
||||
.write_bandwidth = UINT_MAX,
|
||||
struct access_coordinate c[] = {
|
||||
{
|
||||
.read_bandwidth = UINT_MAX,
|
||||
.write_bandwidth = UINT_MAX,
|
||||
},
|
||||
{
|
||||
.read_bandwidth = UINT_MAX,
|
||||
.write_bandwidth = UINT_MAX,
|
||||
},
|
||||
};
|
||||
struct cxl_port *iter = port;
|
||||
struct cxl_dport *dport;
|
||||
struct pci_dev *pdev;
|
||||
unsigned int bw;
|
||||
bool is_cxl_root;
|
||||
|
||||
if (!is_cxl_endpoint(port))
|
||||
return -EINVAL;
|
||||
|
||||
dport = iter->parent_dport;
|
||||
|
||||
/*
|
||||
* Exit the loop when the parent port of the current port is cxl root.
|
||||
* The iterative loop starts at the endpoint and gathers the
|
||||
* latency of the CXL link from the current iter to the next downstream
|
||||
* port each iteration. If the parent is cxl root then there is
|
||||
* nothing to gather.
|
||||
* Exit the loop when the parent port of the current iter port is cxl
|
||||
* root. The iterative loop starts at the endpoint and gathers the
|
||||
* latency of the CXL link from the current device/port to the connected
|
||||
* downstream port each iteration.
|
||||
*/
|
||||
while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
|
||||
cxl_coordinates_combine(&c, &c, &dport->sw_coord);
|
||||
c.write_latency += dport->link_latency;
|
||||
c.read_latency += dport->link_latency;
|
||||
|
||||
iter = to_cxl_port(iter->dev.parent);
|
||||
do {
|
||||
dport = iter->parent_dport;
|
||||
}
|
||||
iter = to_cxl_port(iter->dev.parent);
|
||||
is_cxl_root = parent_port_is_cxl_root(iter);
|
||||
|
||||
/*
|
||||
* There's no valid access_coordinate for a root port since RPs do not
|
||||
* have CDAT and therefore needs to be skipped.
|
||||
*/
|
||||
if (!is_cxl_root) {
|
||||
if (!coordinates_valid(dport->coord))
|
||||
return -EINVAL;
|
||||
cxl_coordinates_combine(c, c, dport->coord);
|
||||
}
|
||||
add_latency(c, dport->link_latency);
|
||||
} while (!is_cxl_root);
|
||||
|
||||
dport = iter->parent_dport;
|
||||
/* Retrieve HB coords */
|
||||
if (!coordinates_valid(dport->coord))
|
||||
return -EINVAL;
|
||||
cxl_coordinates_combine(c, c, dport->coord);
|
||||
|
||||
/* Get the calculated PCI paths bandwidth */
|
||||
pdev = to_pci_dev(port->uport_dev->parent);
|
||||
@@ -2213,10 +2239,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
|
||||
return -ENXIO;
|
||||
bw /= BITS_PER_BYTE;
|
||||
|
||||
c.write_bandwidth = min(c.write_bandwidth, bw);
|
||||
c.read_bandwidth = min(c.read_bandwidth, bw);
|
||||
|
||||
*coord = c;
|
||||
set_min_bandwidth(c, bw);
|
||||
set_access_coordinates(coord, c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -271,6 +271,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL);
|
||||
static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
|
||||
struct cxl_register_map *map)
|
||||
{
|
||||
u8 reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
|
||||
int bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo);
|
||||
u64 offset = ((u64)reg_hi << 32) |
|
||||
(reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK);
|
||||
@@ -278,11 +279,11 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
|
||||
if (offset > pci_resource_len(pdev, bar)) {
|
||||
dev_warn(&pdev->dev,
|
||||
"BAR%d: %pr: too small (offset: %pa, type: %d)\n", bar,
|
||||
&pdev->resource[bar], &offset, map->reg_type);
|
||||
&pdev->resource[bar], &offset, reg_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
map->reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
|
||||
map->reg_type = reg_type;
|
||||
map->resource = pci_resource_start(pdev, bar) + offset;
|
||||
map->max_size = pci_resource_len(pdev, bar) - offset;
|
||||
return true;
|
||||
|
||||
+2
-6
@@ -663,8 +663,7 @@ struct cxl_rcrb_info {
|
||||
* @rch: Indicate whether this dport was enumerated in RCH or VH mode
|
||||
* @port: reference to cxl_port that contains this downstream port
|
||||
* @regs: Dport parsed register blocks
|
||||
* @sw_coord: access coordinates (performance) for switch from CDAT
|
||||
* @hb_coord: access coordinates (performance) from ACPI generic port (host bridge)
|
||||
* @coord: access coordinates (bandwidth and latency performance attributes)
|
||||
* @link_latency: calculated PCIe downstream latency
|
||||
*/
|
||||
struct cxl_dport {
|
||||
@@ -675,8 +674,7 @@ struct cxl_dport {
|
||||
bool rch;
|
||||
struct cxl_port *port;
|
||||
struct cxl_regs regs;
|
||||
struct access_coordinate sw_coord;
|
||||
struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
|
||||
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
|
||||
long link_latency;
|
||||
};
|
||||
|
||||
@@ -884,8 +882,6 @@ void cxl_switch_parse_cdat(struct cxl_port *port);
|
||||
|
||||
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
|
||||
struct access_coordinate *coord);
|
||||
int cxl_hb_get_perf_coordinates(struct cxl_port *port,
|
||||
struct access_coordinate *coord);
|
||||
void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
|
||||
struct cxl_endpoint_decoder *cxled);
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ enum cxl_devtype {
|
||||
*/
|
||||
struct cxl_dpa_perf {
|
||||
struct range dpa_range;
|
||||
struct access_coordinate coord;
|
||||
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
|
||||
int qos_class;
|
||||
};
|
||||
|
||||
|
||||
@@ -790,7 +790,7 @@ static void ffa_notification_info_get(void)
|
||||
|
||||
part_id = packed_id_list[ids_processed++];
|
||||
|
||||
if (!ids_count[list]) { /* Global Notification */
|
||||
if (ids_count[list] == 1) { /* Global Notification */
|
||||
__do_sched_recv_cb(part_id, 0, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -736,7 +736,7 @@ static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
|
||||
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
|
||||
POWERCAP_PAI_GET, 4, domain,
|
||||
&fc[POWERCAP_FC_PAI].get_addr, NULL,
|
||||
&fc[POWERCAP_PAI_GET].rate_limit);
|
||||
&fc[POWERCAP_FC_PAI].rate_limit);
|
||||
|
||||
*p_fc = fc;
|
||||
}
|
||||
|
||||
@@ -921,7 +921,7 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
|
||||
rd->raw = raw;
|
||||
filp->private_data = rd;
|
||||
|
||||
return 0;
|
||||
return nonseekable_open(inode, filp);
|
||||
}
|
||||
|
||||
static int scmi_dbg_raw_mode_release(struct inode *inode, struct file *filp)
|
||||
@@ -950,6 +950,7 @@ static const struct file_operations scmi_dbg_raw_mode_reset_fops = {
|
||||
.open = scmi_dbg_raw_mode_open,
|
||||
.release = scmi_dbg_raw_mode_release,
|
||||
.write = scmi_dbg_raw_mode_reset_write,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -959,6 +960,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_fops = {
|
||||
.read = scmi_dbg_raw_mode_message_read,
|
||||
.write = scmi_dbg_raw_mode_message_write,
|
||||
.poll = scmi_dbg_raw_mode_message_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -975,6 +977,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
|
||||
.read = scmi_dbg_raw_mode_message_read,
|
||||
.write = scmi_dbg_raw_mode_message_async_write,
|
||||
.poll = scmi_dbg_raw_mode_message_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -998,6 +1001,7 @@ static const struct file_operations scmi_dbg_raw_mode_notification_fops = {
|
||||
.release = scmi_dbg_raw_mode_release,
|
||||
.read = scmi_test_dbg_raw_mode_notif_read,
|
||||
.poll = scmi_test_dbg_raw_mode_notif_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -1021,6 +1025,7 @@ static const struct file_operations scmi_dbg_raw_mode_errors_fops = {
|
||||
.release = scmi_dbg_raw_mode_release,
|
||||
.read = scmi_test_dbg_raw_mode_errors_read,
|
||||
.poll = scmi_test_dbg_raw_mode_errors_poll,
|
||||
.llseek = no_llseek,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
@@ -210,6 +210,7 @@ extern int amdgpu_async_gfx_ring;
|
||||
extern int amdgpu_mcbp;
|
||||
extern int amdgpu_discovery;
|
||||
extern int amdgpu_mes;
|
||||
extern int amdgpu_mes_log_enable;
|
||||
extern int amdgpu_mes_kiq;
|
||||
extern int amdgpu_noretry;
|
||||
extern int amdgpu_force_asic_type;
|
||||
|
||||
@@ -4135,18 +4135,22 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
adev->ip_blocks[i].status.hw = true;
|
||||
}
|
||||
}
|
||||
} else if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) &&
|
||||
!amdgpu_device_has_display_hardware(adev)) {
|
||||
r = psp_gpu_reset(adev);
|
||||
} else {
|
||||
tmp = amdgpu_reset_method;
|
||||
/* It should do a default reset when loading or reloading the driver,
|
||||
* regardless of the module parameter reset_method.
|
||||
*/
|
||||
amdgpu_reset_method = AMD_RESET_METHOD_NONE;
|
||||
r = amdgpu_asic_reset(adev);
|
||||
amdgpu_reset_method = tmp;
|
||||
if (r) {
|
||||
dev_err(adev->dev, "asic reset on init failed\n");
|
||||
goto failed;
|
||||
}
|
||||
tmp = amdgpu_reset_method;
|
||||
/* It should do a default reset when loading or reloading the driver,
|
||||
* regardless of the module parameter reset_method.
|
||||
*/
|
||||
amdgpu_reset_method = AMD_RESET_METHOD_NONE;
|
||||
r = amdgpu_asic_reset(adev);
|
||||
amdgpu_reset_method = tmp;
|
||||
}
|
||||
|
||||
if (r) {
|
||||
dev_err(adev->dev, "asic reset on init failed\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1896,6 +1896,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
|
||||
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(14, 0, 0):
|
||||
case IP_VERSION(14, 0, 1):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -195,6 +195,7 @@ int amdgpu_async_gfx_ring = 1;
|
||||
int amdgpu_mcbp = -1;
|
||||
int amdgpu_discovery = -1;
|
||||
int amdgpu_mes;
|
||||
int amdgpu_mes_log_enable = 0;
|
||||
int amdgpu_mes_kiq;
|
||||
int amdgpu_noretry = -1;
|
||||
int amdgpu_force_asic_type = -1;
|
||||
@@ -667,6 +668,15 @@ MODULE_PARM_DESC(mes,
|
||||
"Enable Micro Engine Scheduler (0 = disabled (default), 1 = enabled)");
|
||||
module_param_named(mes, amdgpu_mes, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: mes_log_enable (int)
|
||||
* Enable Micro Engine Scheduler log. This is used to enable/disable MES internal log.
|
||||
* (0 = disabled (default), 1 = enabled)
|
||||
*/
|
||||
MODULE_PARM_DESC(mes_log_enable,
|
||||
"Enable Micro Engine Scheduler log (0 = disabled (default), 1 = enabled)");
|
||||
module_param_named(mes_log_enable, amdgpu_mes_log_enable, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: mes_kiq (int)
|
||||
* Enable Micro Engine Scheduler KIQ. This is a new engine pipe for kiq.
|
||||
|
||||
@@ -304,12 +304,15 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
|
||||
dma_fence_set_error(finished, -ECANCELED);
|
||||
|
||||
if (finished->error < 0) {
|
||||
DRM_INFO("Skip scheduling IBs!\n");
|
||||
dev_dbg(adev->dev, "Skip scheduling IBs in ring(%s)",
|
||||
ring->name);
|
||||
} else {
|
||||
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job,
|
||||
&fence);
|
||||
if (r)
|
||||
DRM_ERROR("Error scheduling IBs (%d)\n", r);
|
||||
dev_err(adev->dev,
|
||||
"Error scheduling IBs (%d) in ring(%s)", r,
|
||||
ring->name);
|
||||
}
|
||||
|
||||
job->job_run_counter++;
|
||||
|
||||
@@ -102,7 +102,10 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
|
||||
if (!amdgpu_mes_log_enable)
|
||||
return 0;
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, AMDGPU_MES_LOG_BUFFER_SIZE, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->mes.event_log_gpu_obj,
|
||||
&adev->mes.event_log_gpu_addr,
|
||||
@@ -1549,12 +1552,11 @@ static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused)
|
||||
uint32_t *mem = (uint32_t *)(adev->mes.event_log_cpu_addr);
|
||||
|
||||
seq_hex_dump(m, "", DUMP_PREFIX_OFFSET, 32, 4,
|
||||
mem, PAGE_SIZE, false);
|
||||
mem, AMDGPU_MES_LOG_BUFFER_SIZE, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_mes_event_log);
|
||||
|
||||
#endif
|
||||
@@ -1565,7 +1567,7 @@ void amdgpu_debugfs_mes_event_log_init(struct amdgpu_device *adev)
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
struct drm_minor *minor = adev_to_drm(adev)->primary;
|
||||
struct dentry *root = minor->debugfs_root;
|
||||
if (adev->enable_mes)
|
||||
if (adev->enable_mes && amdgpu_mes_log_enable)
|
||||
debugfs_create_file("amdgpu_mes_event_log", 0444, root,
|
||||
adev, &amdgpu_debugfs_mes_event_log_fops);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ enum amdgpu_mes_priority_level {
|
||||
|
||||
#define AMDGPU_MES_PROC_CTX_SIZE 0x1000 /* one page area */
|
||||
#define AMDGPU_MES_GANG_CTX_SIZE 0x1000 /* one page area */
|
||||
#define AMDGPU_MES_LOG_BUFFER_SIZE 0x4000 /* Maximu log buffer size for MES */
|
||||
|
||||
struct amdgpu_mes_funcs;
|
||||
|
||||
|
||||
@@ -62,6 +62,11 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev)
|
||||
adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1;
|
||||
}
|
||||
|
||||
static bool aqua_vanjaram_xcp_vcn_shared(struct amdgpu_device *adev)
|
||||
{
|
||||
return (adev->xcp_mgr->num_xcps > adev->vcn.num_vcn_inst);
|
||||
}
|
||||
|
||||
static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
|
||||
uint32_t inst_idx, struct amdgpu_ring *ring)
|
||||
{
|
||||
@@ -87,7 +92,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
|
||||
case AMDGPU_RING_TYPE_VCN_ENC:
|
||||
case AMDGPU_RING_TYPE_VCN_JPEG:
|
||||
ip_blk = AMDGPU_XCP_VCN;
|
||||
if (adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE)
|
||||
if (aqua_vanjaram_xcp_vcn_shared(adev))
|
||||
inst_mask = 1 << (inst_idx * 2);
|
||||
break;
|
||||
default:
|
||||
@@ -140,10 +145,12 @@ static int aqua_vanjaram_xcp_sched_list_update(
|
||||
|
||||
aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id);
|
||||
|
||||
/* VCN is shared by two partitions under CPX MODE */
|
||||
/* VCN may be shared by two partitions under CPX MODE in certain
|
||||
* configs.
|
||||
*/
|
||||
if ((ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC ||
|
||||
ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) &&
|
||||
adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE)
|
||||
ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) &&
|
||||
aqua_vanjaram_xcp_vcn_shared(adev))
|
||||
aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1635,7 +1635,7 @@ static void gfx_v11_0_setup_rb(struct amdgpu_device *adev)
|
||||
active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa));
|
||||
}
|
||||
|
||||
active_rb_bitmap |= global_active_rb_bitmap;
|
||||
active_rb_bitmap &= global_active_rb_bitmap;
|
||||
adev->gfx.config.backend_enable_mask = active_rb_bitmap;
|
||||
adev->gfx.config.num_rbs = hweight32(active_rb_bitmap);
|
||||
}
|
||||
@@ -5465,6 +5465,7 @@ static void gfx_v11_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
/* Make sure that we can't skip the SET_Q_MODE packets when the VM
|
||||
* changed in any way.
|
||||
*/
|
||||
ring->set_q_mode_offs = 0;
|
||||
ring->set_q_mode_ptr = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -411,8 +411,11 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
|
||||
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
|
||||
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
|
||||
mes_set_hw_res_pkt.oversubscription_timer = 50;
|
||||
mes_set_hw_res_pkt.enable_mes_event_int_logging = 1;
|
||||
mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = mes->event_log_gpu_addr;
|
||||
if (amdgpu_mes_log_enable) {
|
||||
mes_set_hw_res_pkt.enable_mes_event_int_logging = 1;
|
||||
mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr =
|
||||
mes->event_log_gpu_addr;
|
||||
}
|
||||
|
||||
return mes_v11_0_submit_pkt_and_poll_completion(mes,
|
||||
&mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt),
|
||||
|
||||
@@ -1602,19 +1602,9 @@ static int sdma_v4_4_2_set_ecc_irq_state(struct amdgpu_device *adev,
|
||||
u32 sdma_cntl;
|
||||
|
||||
sdma_cntl = RREG32_SDMA(type, regSDMA_CNTL);
|
||||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL,
|
||||
DRAM_ECC_INT_ENABLE, 0);
|
||||
WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl);
|
||||
break;
|
||||
/* sdma ecc interrupt is enabled by default
|
||||
* driver doesn't need to do anything to
|
||||
* enable the interrupt */
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, DRAM_ECC_INT_ENABLE,
|
||||
state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
|
||||
WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user