Linux 5.10-rc3
-----BEGIN PGP SIGNATURE-----
iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAl+oiOgeHHRvcnZhbGRz
QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGKBQIAJw6oad/FA7j9OO2
dMoaXb8UaBehGWgW2rdfWrFPV5v0DBnp/GkdRpLoZIjV3W4mBfnog7bIa4Eswlxo
Y8sZxo5/3JlgJQUkHvzR1TYk5z61lHkUw9Kj/cCyx6YdbjSl19AfFsnhQVVMuyp9
TXL2c7hxkHlw8eBGrymVu0Ip7Zq0x8O2g+8nQpmRcvaR6SBuSHdikDF/iWCtU1YW
wpk5eWEVaAO67keZOz6b+aCFHqjFX+1dUBBuPnslucYLR73Qi16hfaU9pebe97Gb
lX/MJ1bR9BeRp314cF0PYbm4WhKjRLudHOFJH8x3dj/BiYNrFK3SJGLiiTwsrAZ8
kytU0Xs=
=Ke/D
-----END PGP SIGNATURE-----
Merge v5.10-rc3 into drm-next
We need commit f8f6ae5d07
("mm: always have io_remap_pfn_range() set
pgprot_decrypted()") to be able to merge Jason's cleanup patch.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
commit
512bce50a4
|
@ -1,29 +1,29 @@
|
||||||
What: sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/cap
|
What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/cap
|
||||||
Date: December 3, 2009
|
Date: December 3, 2009
|
||||||
KernelVersion: 2.6.32
|
KernelVersion: 2.6.32
|
||||||
Contact: dmaengine@vger.kernel.org
|
Contact: dmaengine@vger.kernel.org
|
||||||
Description: Capabilities the DMA supports.Currently there are DMA_PQ, DMA_PQ_VAL,
|
Description: Capabilities the DMA supports.Currently there are DMA_PQ, DMA_PQ_VAL,
|
||||||
DMA_XOR,DMA_XOR_VAL,DMA_INTERRUPT.
|
DMA_XOR,DMA_XOR_VAL,DMA_INTERRUPT.
|
||||||
|
|
||||||
What: sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_active
|
What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_active
|
||||||
Date: December 3, 2009
|
Date: December 3, 2009
|
||||||
KernelVersion: 2.6.32
|
KernelVersion: 2.6.32
|
||||||
Contact: dmaengine@vger.kernel.org
|
Contact: dmaengine@vger.kernel.org
|
||||||
Description: The number of descriptors active in the ring.
|
Description: The number of descriptors active in the ring.
|
||||||
|
|
||||||
What: sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_size
|
What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/ring_size
|
||||||
Date: December 3, 2009
|
Date: December 3, 2009
|
||||||
KernelVersion: 2.6.32
|
KernelVersion: 2.6.32
|
||||||
Contact: dmaengine@vger.kernel.org
|
Contact: dmaengine@vger.kernel.org
|
||||||
Description: Descriptor ring size, total number of descriptors available.
|
Description: Descriptor ring size, total number of descriptors available.
|
||||||
|
|
||||||
What: sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/version
|
What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/version
|
||||||
Date: December 3, 2009
|
Date: December 3, 2009
|
||||||
KernelVersion: 2.6.32
|
KernelVersion: 2.6.32
|
||||||
Contact: dmaengine@vger.kernel.org
|
Contact: dmaengine@vger.kernel.org
|
||||||
Description: Version of ioatdma device.
|
Description: Version of ioatdma device.
|
||||||
|
|
||||||
What: sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/intr_coalesce
|
What: /sys/devices/pciXXXX:XX/0000:XX:XX.X/dma/dma<n>chan<n>/quickdata/intr_coalesce
|
||||||
Date: August 8, 2017
|
Date: August 8, 2017
|
||||||
KernelVersion: 4.14
|
KernelVersion: 4.14
|
||||||
Contact: dmaengine@vger.kernel.org
|
Contact: dmaengine@vger.kernel.org
|
||||||
|
|
|
@ -152,7 +152,7 @@ Description:
|
||||||
When an interface is under test, it cannot be expected
|
When an interface is under test, it cannot be expected
|
||||||
to pass packets as normal.
|
to pass packets as normal.
|
||||||
|
|
||||||
What: /sys/clas/net/<iface>/duplex
|
What: /sys/class/net/<iface>/duplex
|
||||||
Date: October 2009
|
Date: October 2009
|
||||||
KernelVersion: 2.6.33
|
KernelVersion: 2.6.33
|
||||||
Contact: netdev@vger.kernel.org
|
Contact: netdev@vger.kernel.org
|
||||||
|
|
|
@ -26,6 +26,10 @@ BUILDDIR = $(obj)/output
|
||||||
PDFLATEX = xelatex
|
PDFLATEX = xelatex
|
||||||
LATEXOPTS = -interaction=batchmode
|
LATEXOPTS = -interaction=batchmode
|
||||||
|
|
||||||
|
ifeq ($(KBUILD_VERBOSE),0)
|
||||||
|
SPHINXOPTS += "-q"
|
||||||
|
endif
|
||||||
|
|
||||||
# User-friendly check for sphinx-build
|
# User-friendly check for sphinx-build
|
||||||
HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
|
HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ for a UID/GID will prevent that UID/GID from obtaining auxiliary setid
|
||||||
privileges, such as allowing a user to set up user namespace UID/GID mappings.
|
privileges, such as allowing a user to set up user namespace UID/GID mappings.
|
||||||
|
|
||||||
Note on GID policies and setgroups()
|
Note on GID policies and setgroups()
|
||||||
==================
|
====================================
|
||||||
In v5.9 we are adding support for limiting CAP_SETGID privileges as was done
|
In v5.9 we are adding support for limiting CAP_SETGID privileges as was done
|
||||||
previously for CAP_SETUID. However, for compatibility with common sandboxing
|
previously for CAP_SETUID. However, for compatibility with common sandboxing
|
||||||
related code conventions in userspace, we currently allow arbitrary
|
related code conventions in userspace, we currently allow arbitrary
|
||||||
|
|
|
@ -478,7 +478,7 @@ order to ask the hardware to enter that state. Also, for each
|
||||||
statistics of the given idle state. That information is exposed by the kernel
|
statistics of the given idle state. That information is exposed by the kernel
|
||||||
via ``sysfs``.
|
via ``sysfs``.
|
||||||
|
|
||||||
For each CPU in the system, there is a :file:`/sys/devices/system/cpu<N>/cpuidle/`
|
For each CPU in the system, there is a :file:`/sys/devices/system/cpu/cpu<N>/cpuidle/`
|
||||||
directory in ``sysfs``, where the number ``<N>`` is assigned to the given
|
directory in ``sysfs``, where the number ``<N>`` is assigned to the given
|
||||||
CPU at the initialization time. That directory contains a set of subdirectories
|
CPU at the initialization time. That directory contains a set of subdirectories
|
||||||
called :file:`state0`, :file:`state1` and so on, up to the number of idle state
|
called :file:`state0`, :file:`state1` and so on, up to the number of idle state
|
||||||
|
@ -494,7 +494,7 @@ object corresponding to it, as follows:
|
||||||
residency.
|
residency.
|
||||||
|
|
||||||
``below``
|
``below``
|
||||||
Total number of times this idle state had been asked for, but cerainly
|
Total number of times this idle state had been asked for, but certainly
|
||||||
a deeper idle state would have been a better match for the observed idle
|
a deeper idle state would have been a better match for the observed idle
|
||||||
duration.
|
duration.
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,7 @@ Note:
|
||||||
0: 0 1 2 3 4 5 6 7
|
0: 0 1 2 3 4 5 6 7
|
||||||
RSS hash key:
|
RSS hash key:
|
||||||
84:50:f4:00:a8:15:d1:a7:e9:7f:1d:60:35:c7:47:25:42:97:74:ca:56:bb:b6:a1:d8:43:e3:c9:0c:fd:17:55:c2:3a:4d:69:ed:f1:42:89
|
84:50:f4:00:a8:15:d1:a7:e9:7f:1d:60:35:c7:47:25:42:97:74:ca:56:bb:b6:a1:d8:43:e3:c9:0c:fd:17:55:c2:3a:4d:69:ed:f1:42:89
|
||||||
|
|
||||||
netdev_tstamp_prequeue
|
netdev_tstamp_prequeue
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -148,3 +148,13 @@ SunXi family
|
||||||
* User Manual
|
* User Manual
|
||||||
|
|
||||||
http://dl.linux-sunxi.org/A64/Allwinner%20A64%20User%20Manual%20v1.0.pdf
|
http://dl.linux-sunxi.org/A64/Allwinner%20A64%20User%20Manual%20v1.0.pdf
|
||||||
|
|
||||||
|
- Allwinner H6
|
||||||
|
|
||||||
|
* Datasheet
|
||||||
|
|
||||||
|
https://linux-sunxi.org/images/5/5c/Allwinner_H6_V200_Datasheet_V1.1.pdf
|
||||||
|
|
||||||
|
* User Manual
|
||||||
|
|
||||||
|
https://linux-sunxi.org/images/4/46/Allwinner_H6_V200_User_Manual_V1.1.pdf
|
||||||
|
|
|
@ -51,7 +51,7 @@ if major >= 3:
|
||||||
support for Sphinx v3.0 and above is brand new. Be prepared for
|
support for Sphinx v3.0 and above is brand new. Be prepared for
|
||||||
possible issues in the generated output.
|
possible issues in the generated output.
|
||||||
''')
|
''')
|
||||||
if minor > 0 or patch >= 2:
|
if (major > 3) or (minor > 0 or patch >= 2):
|
||||||
# Sphinx c function parser is more pedantic with regards to type
|
# Sphinx c function parser is more pedantic with regards to type
|
||||||
# checking. Due to that, having macros at c:function cause problems.
|
# checking. Due to that, having macros at c:function cause problems.
|
||||||
# Those needed to be scaped by using c_id_attributes[] array
|
# Those needed to be scaped by using c_id_attributes[] array
|
||||||
|
|
|
@ -295,11 +295,13 @@ print the number of the test and the status of the test:
|
||||||
pass::
|
pass::
|
||||||
|
|
||||||
ok 28 - kmalloc_double_kzfree
|
ok 28 - kmalloc_double_kzfree
|
||||||
|
|
||||||
or, if kmalloc failed::
|
or, if kmalloc failed::
|
||||||
|
|
||||||
# kmalloc_large_oob_right: ASSERTION FAILED at lib/test_kasan.c:163
|
# kmalloc_large_oob_right: ASSERTION FAILED at lib/test_kasan.c:163
|
||||||
Expected ptr is not null, but is
|
Expected ptr is not null, but is
|
||||||
not ok 4 - kmalloc_large_oob_right
|
not ok 4 - kmalloc_large_oob_right
|
||||||
|
|
||||||
or, if a KASAN report was expected, but not found::
|
or, if a KASAN report was expected, but not found::
|
||||||
|
|
||||||
# kmalloc_double_kzfree: EXPECTATION FAILED at lib/test_kasan.c:629
|
# kmalloc_double_kzfree: EXPECTATION FAILED at lib/test_kasan.c:629
|
||||||
|
|
|
@ -197,7 +197,7 @@ Now add the following to ``drivers/misc/Kconfig``:
|
||||||
|
|
||||||
config MISC_EXAMPLE_TEST
|
config MISC_EXAMPLE_TEST
|
||||||
bool "Test for my example"
|
bool "Test for my example"
|
||||||
depends on MISC_EXAMPLE && KUNIT
|
depends on MISC_EXAMPLE && KUNIT=y
|
||||||
|
|
||||||
and the following to ``drivers/misc/Makefile``:
|
and the following to ``drivers/misc/Makefile``:
|
||||||
|
|
||||||
|
|
|
@ -561,6 +561,11 @@ Once the kernel is built and installed, a simple
|
||||||
|
|
||||||
...will run the tests.
|
...will run the tests.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Note that you should make sure your test depends on ``KUNIT=y`` in Kconfig
|
||||||
|
if the test does not support module build. Otherwise, it will trigger
|
||||||
|
compile errors if ``CONFIG_KUNIT`` is ``m``.
|
||||||
|
|
||||||
Writing new tests for other architectures
|
Writing new tests for other architectures
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ Clock control registers reside in different Hi6220 system controllers,
|
||||||
please refer the following document to know more about the binding rules
|
please refer the following document to know more about the binding rules
|
||||||
for these system controllers:
|
for these system controllers:
|
||||||
|
|
||||||
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
|
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.yaml
|
||||||
|
|
||||||
Required Properties:
|
Required Properties:
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,11 @@ description: |
|
||||||
| | vint | bit | | 0 |.....|63| vintx |
|
| | vint | bit | | 0 |.....|63| vintx |
|
||||||
| +--------------+ +------------+ |
|
| +--------------+ +------------+ |
|
||||||
| |
|
| |
|
||||||
|
| Unmap |
|
||||||
|
| +--------------+ |
|
||||||
|
Unmapped events ---->| | umapidx |-------------------------> Globalevents
|
||||||
|
| +--------------+ |
|
||||||
|
| |
|
||||||
+-----------------------------------------+
|
+-----------------------------------------+
|
||||||
|
|
||||||
Configuration of these Intmap registers that maps global events to vint is
|
Configuration of these Intmap registers that maps global events to vint is
|
||||||
|
@ -70,6 +75,11 @@ properties:
|
||||||
- description: |
|
- description: |
|
||||||
"limit" specifies the limit for translation
|
"limit" specifies the limit for translation
|
||||||
|
|
||||||
|
ti,unmapped-event-sources:
|
||||||
|
$ref: /schemas/types.yaml#definitions/phandle-array
|
||||||
|
description:
|
||||||
|
Array of phandles to DMA controllers where the unmapped events originate.
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/can/can-controller.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: CAN Controller Generic Binding
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Marc Kleine-Budde <mkl@pengutronix.de>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
$nodename:
|
||||||
|
pattern: "^can(@.*)?$"
|
||||||
|
|
||||||
|
additionalProperties: true
|
||||||
|
|
||||||
|
...
|
|
@ -0,0 +1,135 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/can/fsl,flexcan.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title:
|
||||||
|
Flexcan CAN controller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Marc Kleine-Budde <mkl@pengutronix.de>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: can-controller.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
oneOf:
|
||||||
|
- enum:
|
||||||
|
- fsl,imx8qm-flexcan
|
||||||
|
- fsl,imx8mp-flexcan
|
||||||
|
- fsl,imx6q-flexcan
|
||||||
|
- fsl,imx53-flexcan
|
||||||
|
- fsl,imx35-flexcan
|
||||||
|
- fsl,imx28-flexcan
|
||||||
|
- fsl,imx25-flexcan
|
||||||
|
- fsl,p1010-flexcan
|
||||||
|
- fsl,vf610-flexcan
|
||||||
|
- fsl,ls1021ar2-flexcan
|
||||||
|
- fsl,lx2160ar1-flexcan
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- fsl,imx7d-flexcan
|
||||||
|
- fsl,imx6ul-flexcan
|
||||||
|
- fsl,imx6sx-flexcan
|
||||||
|
- const: fsl,imx6q-flexcan
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- fsl,ls1028ar1-flexcan
|
||||||
|
- const: fsl,lx2160ar1-flexcan
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: ipg
|
||||||
|
- const: per
|
||||||
|
|
||||||
|
clock-frequency:
|
||||||
|
description: |
|
||||||
|
The oscillator frequency driving the flexcan device, filled in by the
|
||||||
|
boot loader. This property should only be used the used operating system
|
||||||
|
doesn't support the clocks and clock-names property.
|
||||||
|
|
||||||
|
xceiver-supply:
|
||||||
|
description: Regulator that powers the CAN transceiver.
|
||||||
|
|
||||||
|
big-endian:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description: |
|
||||||
|
This means the registers of FlexCAN controller are big endian. This is
|
||||||
|
optional property.i.e. if this property is not present in device tree
|
||||||
|
node then controller is assumed to be little endian. If this property is
|
||||||
|
present then controller is assumed to be big endian.
|
||||||
|
|
||||||
|
fsl,stop-mode:
|
||||||
|
description: |
|
||||||
|
Register bits of stop mode control.
|
||||||
|
|
||||||
|
The format should be as follows:
|
||||||
|
<gpr req_gpr req_bit>
|
||||||
|
gpr is the phandle to general purpose register node.
|
||||||
|
req_gpr is the gpr register offset of CAN stop request.
|
||||||
|
req_bit is the bit offset of CAN stop request.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
|
items:
|
||||||
|
- description: The 'gpr' is the phandle to general purpose register node.
|
||||||
|
- description: The 'req_gpr' is the gpr register offset of CAN stop request.
|
||||||
|
maximum: 0xff
|
||||||
|
- description: The 'req_bit' is the bit offset of CAN stop request.
|
||||||
|
maximum: 0x1f
|
||||||
|
|
||||||
|
fsl,clk-source:
|
||||||
|
description: |
|
||||||
|
Select the clock source to the CAN Protocol Engine (PE). It's SoC
|
||||||
|
implementation dependent. Refer to RM for detailed definition. If this
|
||||||
|
property is not set in device tree node then driver selects clock source 1
|
||||||
|
by default.
|
||||||
|
0: clock source 0 (oscillator clock)
|
||||||
|
1: clock source 1 (peripheral clock)
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
default: 1
|
||||||
|
minimum: 0
|
||||||
|
maximum: 1
|
||||||
|
|
||||||
|
wakeup-source:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
description:
|
||||||
|
Enable CAN remote wakeup.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
can@1c000 {
|
||||||
|
compatible = "fsl,p1010-flexcan";
|
||||||
|
reg = <0x1c000 0x1000>;
|
||||||
|
interrupts = <48 0x2>;
|
||||||
|
interrupt-parent = <&mpic>;
|
||||||
|
clock-frequency = <200000000>;
|
||||||
|
fsl,clk-source = <0>;
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
|
||||||
|
can@2090000 {
|
||||||
|
compatible = "fsl,imx6q-flexcan";
|
||||||
|
reg = <0x02090000 0x4000>;
|
||||||
|
interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&clks 1>, <&clks 2>;
|
||||||
|
clock-names = "ipg", "per";
|
||||||
|
fsl,stop-mode = <&gpr 0x34 28>;
|
||||||
|
};
|
|
@ -1,57 +0,0 @@
|
||||||
Flexcan CAN controller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible : Should be "fsl,<processor>-flexcan"
|
|
||||||
|
|
||||||
where <processor> is imx8qm, imx6q, imx28, imx53, imx35, imx25, p1010,
|
|
||||||
vf610, ls1021ar2, lx2160ar1, ls1028ar1.
|
|
||||||
|
|
||||||
The ls1028ar1 must be followed by lx2160ar1, e.g.
|
|
||||||
- "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan"
|
|
||||||
|
|
||||||
An implementation should also claim any of the following compatibles
|
|
||||||
that it is fully backwards compatible with:
|
|
||||||
|
|
||||||
- fsl,p1010-flexcan
|
|
||||||
|
|
||||||
- reg : Offset and length of the register set for this device
|
|
||||||
- interrupts : Interrupt tuple for this device
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
|
|
||||||
- clock-frequency : The oscillator frequency driving the flexcan device
|
|
||||||
|
|
||||||
- xceiver-supply: Regulator that powers the CAN transceiver
|
|
||||||
|
|
||||||
- big-endian: This means the registers of FlexCAN controller are big endian.
|
|
||||||
This is optional property.i.e. if this property is not present in
|
|
||||||
device tree node then controller is assumed to be little endian.
|
|
||||||
if this property is present then controller is assumed to be big
|
|
||||||
endian.
|
|
||||||
|
|
||||||
- fsl,stop-mode: register bits of stop mode control, the format is
|
|
||||||
<&gpr req_gpr req_bit>.
|
|
||||||
gpr is the phandle to general purpose register node.
|
|
||||||
req_gpr is the gpr register offset of CAN stop request.
|
|
||||||
req_bit is the bit offset of CAN stop request.
|
|
||||||
|
|
||||||
- fsl,clk-source: Select the clock source to the CAN Protocol Engine (PE).
|
|
||||||
It's SoC Implementation dependent. Refer to RM for detailed
|
|
||||||
definition. If this property is not set in device tree node
|
|
||||||
then driver selects clock source 1 by default.
|
|
||||||
0: clock source 0 (oscillator clock)
|
|
||||||
1: clock source 1 (peripheral clock)
|
|
||||||
|
|
||||||
- wakeup-source: enable CAN remote wakeup
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
can@1c000 {
|
|
||||||
compatible = "fsl,p1010-flexcan";
|
|
||||||
reg = <0x1c000 0x1000>;
|
|
||||||
interrupts = <48 0x2>;
|
|
||||||
interrupt-parent = <&mpic>;
|
|
||||||
clock-frequency = <200000000>; // filled in by bootloader
|
|
||||||
fsl,clk-source = <0>; // select clock source 0 for PE
|
|
||||||
};
|
|
|
@ -86,9 +86,6 @@ Other Functions
|
||||||
.. kernel-doc:: fs/dax.c
|
.. kernel-doc:: fs/dax.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
.. kernel-doc:: fs/direct-io.c
|
|
||||||
:export:
|
|
||||||
|
|
||||||
.. kernel-doc:: fs/libfs.c
|
.. kernel-doc:: fs/libfs.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
|
|
|
@ -83,10 +83,6 @@ AMDGPU XGMI Support
|
||||||
===================
|
===================
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
||||||
:doc: AMDGPU XGMI Support
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
AMDGPU RAS Support
|
AMDGPU RAS Support
|
||||||
==================
|
==================
|
||||||
|
@ -124,9 +120,6 @@ RAS VRAM Bad Pages sysfs Interface
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||||
:doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
|
:doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
Sample Code
|
Sample Code
|
||||||
-----------
|
-----------
|
||||||
Sample code for testing error injection can be found here:
|
Sample code for testing error injection can be found here:
|
||||||
|
|
|
@ -20,7 +20,7 @@ ADM1266 is a sequencer that features voltage readback from 17 channels via an
|
||||||
integrated 12 bit SAR ADC, accessed using a PMBus interface.
|
integrated 12 bit SAR ADC, accessed using a PMBus interface.
|
||||||
|
|
||||||
The driver is a client driver to the core PMBus driver. Please see
|
The driver is a client driver to the core PMBus driver. Please see
|
||||||
Documentation/hwmon/pmbus for details on PMBus client drivers.
|
Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
|
||||||
|
|
||||||
|
|
||||||
Sysfs entries
|
Sysfs entries
|
||||||
|
|
|
@ -132,6 +132,7 @@ Hardware Monitoring Kernel Drivers
|
||||||
mcp3021
|
mcp3021
|
||||||
menf21bmc
|
menf21bmc
|
||||||
mlxreg-fan
|
mlxreg-fan
|
||||||
|
mp2975
|
||||||
nct6683
|
nct6683
|
||||||
nct6775
|
nct6775
|
||||||
nct7802
|
nct7802
|
||||||
|
|
|
@ -20,6 +20,7 @@ This driver implements support for Monolithic Power Systems, Inc. (MPS)
|
||||||
vendor dual-loop, digital, multi-phase controller MP2975.
|
vendor dual-loop, digital, multi-phase controller MP2975.
|
||||||
|
|
||||||
This device:
|
This device:
|
||||||
|
|
||||||
- Supports up to two power rail.
|
- Supports up to two power rail.
|
||||||
- Provides 8 pulse-width modulations (PWMs), and can be configured up
|
- Provides 8 pulse-width modulations (PWMs), and can be configured up
|
||||||
to 8-phase operation for rail 1 and up to 4-phase operation for rail
|
to 8-phase operation for rail 1 and up to 4-phase operation for rail
|
||||||
|
@ -32,10 +33,12 @@ This device:
|
||||||
10-mV DAC, IMVP9 mode with 5-mV DAC.
|
10-mV DAC, IMVP9 mode with 5-mV DAC.
|
||||||
|
|
||||||
Device supports:
|
Device supports:
|
||||||
|
|
||||||
- SVID interface.
|
- SVID interface.
|
||||||
- AVSBus interface.
|
- AVSBus interface.
|
||||||
|
|
||||||
Device complaint with:
|
Device complaint with:
|
||||||
|
|
||||||
- PMBus rev 1.3 interface.
|
- PMBus rev 1.3 interface.
|
||||||
|
|
||||||
Device supports direct format for reading output current, output voltage,
|
Device supports direct format for reading output current, output voltage,
|
||||||
|
@ -45,11 +48,14 @@ Device supports VID and direct formats for reading output voltage.
|
||||||
The below VID modes are supported: VR12, VR13, IMVP9.
|
The below VID modes are supported: VR12, VR13, IMVP9.
|
||||||
|
|
||||||
The driver provides the next attributes for the current:
|
The driver provides the next attributes for the current:
|
||||||
|
|
||||||
- for current in: input, maximum alarm;
|
- for current in: input, maximum alarm;
|
||||||
- for current out input, maximum alarm and highest values;
|
- for current out input, maximum alarm and highest values;
|
||||||
- for phase current: input and label.
|
- for phase current: input and label.
|
||||||
attributes.
|
attributes.
|
||||||
|
|
||||||
The driver exports the following attributes via the 'sysfs' files, where
|
The driver exports the following attributes via the 'sysfs' files, where
|
||||||
|
|
||||||
- 'n' is number of telemetry pages (from 1 to 2);
|
- 'n' is number of telemetry pages (from 1 to 2);
|
||||||
- 'k' is number of configured phases (from 1 to 8);
|
- 'k' is number of configured phases (from 1 to 8);
|
||||||
- indexes 1, 1*n for "iin";
|
- indexes 1, 1*n for "iin";
|
||||||
|
@ -65,11 +71,14 @@ The driver exports the following attributes via the 'sysfs' files, where
|
||||||
**curr[1-{2n+k}]_label**
|
**curr[1-{2n+k}]_label**
|
||||||
|
|
||||||
The driver provides the next attributes for the voltage:
|
The driver provides the next attributes for the voltage:
|
||||||
|
|
||||||
- for voltage in: input, high critical threshold, high critical alarm, all only
|
- for voltage in: input, high critical threshold, high critical alarm, all only
|
||||||
from page 0;
|
from page 0;
|
||||||
- for voltage out: input, low and high critical thresholds, low and high
|
- for voltage out: input, low and high critical thresholds, low and high
|
||||||
critical alarms, from pages 0 and 1;
|
critical alarms, from pages 0 and 1;
|
||||||
|
|
||||||
The driver exports the following attributes via the 'sysfs' files, where
|
The driver exports the following attributes via the 'sysfs' files, where
|
||||||
|
|
||||||
- 'n' is number of telemetry pages (from 1 to 2);
|
- 'n' is number of telemetry pages (from 1 to 2);
|
||||||
- indexes 1 for "iin";
|
- indexes 1 for "iin";
|
||||||
- indexes n+1, n+2 for "vout";
|
- indexes n+1, n+2 for "vout";
|
||||||
|
@ -87,9 +96,12 @@ The driver exports the following attributes via the 'sysfs' files, where
|
||||||
**in[2-{n+1}1_lcrit_alarm**
|
**in[2-{n+1}1_lcrit_alarm**
|
||||||
|
|
||||||
The driver provides the next attributes for the power:
|
The driver provides the next attributes for the power:
|
||||||
|
|
||||||
- for power in alarm and input.
|
- for power in alarm and input.
|
||||||
- for power out: highest and input.
|
- for power out: highest and input.
|
||||||
|
|
||||||
The driver exports the following attributes via the 'sysfs' files, where
|
The driver exports the following attributes via the 'sysfs' files, where
|
||||||
|
|
||||||
- 'n' is number of telemetry pages (from 1 to 2);
|
- 'n' is number of telemetry pages (from 1 to 2);
|
||||||
- indexes 1 for "pin";
|
- indexes 1 for "pin";
|
||||||
- indexes n+1, n+2 for "pout";
|
- indexes n+1, n+2 for "pout";
|
||||||
|
|
|
@ -25,3 +25,4 @@ LEDs
|
||||||
leds-lp5562
|
leds-lp5562
|
||||||
leds-lp55xx
|
leds-lp55xx
|
||||||
leds-mlxcpld
|
leds-mlxcpld
|
||||||
|
leds-sc27xx
|
||||||
|
|
|
@ -42,6 +42,7 @@ The validator tracks lock-class usage history and divides the usage into
|
||||||
(4 usages * n STATEs + 1) categories:
|
(4 usages * n STATEs + 1) categories:
|
||||||
|
|
||||||
where the 4 usages can be:
|
where the 4 usages can be:
|
||||||
|
|
||||||
- 'ever held in STATE context'
|
- 'ever held in STATE context'
|
||||||
- 'ever held as readlock in STATE context'
|
- 'ever held as readlock in STATE context'
|
||||||
- 'ever held with STATE enabled'
|
- 'ever held with STATE enabled'
|
||||||
|
@ -49,10 +50,12 @@ where the 4 usages can be:
|
||||||
|
|
||||||
where the n STATEs are coded in kernel/locking/lockdep_states.h and as of
|
where the n STATEs are coded in kernel/locking/lockdep_states.h and as of
|
||||||
now they include:
|
now they include:
|
||||||
|
|
||||||
- hardirq
|
- hardirq
|
||||||
- softirq
|
- softirq
|
||||||
|
|
||||||
where the last 1 category is:
|
where the last 1 category is:
|
||||||
|
|
||||||
- 'ever used' [ == !unused ]
|
- 'ever used' [ == !unused ]
|
||||||
|
|
||||||
When locking rules are violated, these usage bits are presented in the
|
When locking rules are violated, these usage bits are presented in the
|
||||||
|
@ -96,9 +99,9 @@ exact case is for the lock as of the reporting time.
|
||||||
+--------------+-------------+--------------+
|
+--------------+-------------+--------------+
|
||||||
| | irq enabled | irq disabled |
|
| | irq enabled | irq disabled |
|
||||||
+--------------+-------------+--------------+
|
+--------------+-------------+--------------+
|
||||||
| ever in irq | ? | - |
|
| ever in irq | '?' | '-' |
|
||||||
+--------------+-------------+--------------+
|
+--------------+-------------+--------------+
|
||||||
| never in irq | + | . |
|
| never in irq | '+' | '.' |
|
||||||
+--------------+-------------+--------------+
|
+--------------+-------------+--------------+
|
||||||
|
|
||||||
The character '-' suggests irq is disabled because if otherwise the
|
The character '-' suggests irq is disabled because if otherwise the
|
||||||
|
@ -216,7 +219,7 @@ looks like this::
|
||||||
BD_MUTEX_PARTITION
|
BD_MUTEX_PARTITION
|
||||||
};
|
};
|
||||||
|
|
||||||
mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);
|
mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);
|
||||||
|
|
||||||
In this case the locking is done on a bdev object that is known to be a
|
In this case the locking is done on a bdev object that is known to be a
|
||||||
partition.
|
partition.
|
||||||
|
@ -334,7 +337,7 @@ Troubleshooting:
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The validator tracks a maximum of MAX_LOCKDEP_KEYS number of lock classes.
|
The validator tracks a maximum of MAX_LOCKDEP_KEYS number of lock classes.
|
||||||
Exceeding this number will trigger the following lockdep warning:
|
Exceeding this number will trigger the following lockdep warning::
|
||||||
|
|
||||||
(DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
|
(DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
|
||||||
|
|
||||||
|
@ -420,7 +423,8 @@ the critical section of another reader of the same lock instance.
|
||||||
|
|
||||||
The difference between recursive readers and non-recursive readers is because:
|
The difference between recursive readers and non-recursive readers is because:
|
||||||
recursive readers get blocked only by a write lock *holder*, while non-recursive
|
recursive readers get blocked only by a write lock *holder*, while non-recursive
|
||||||
readers could get blocked by a write lock *waiter*. Considering the follow example:
|
readers could get blocked by a write lock *waiter*. Considering the follow
|
||||||
|
example::
|
||||||
|
|
||||||
TASK A: TASK B:
|
TASK A: TASK B:
|
||||||
|
|
||||||
|
@ -448,20 +452,22 @@ There are simply four block conditions:
|
||||||
|
|
||||||
Block condition matrix, Y means the row blocks the column, and N means otherwise.
|
Block condition matrix, Y means the row blocks the column, and N means otherwise.
|
||||||
|
|
||||||
| E | r | R |
|
|
||||||
+---+---+---+---+
|
+---+---+---+---+
|
||||||
E | Y | Y | Y |
|
| | E | r | R |
|
||||||
+---+---+---+---+
|
+---+---+---+---+
|
||||||
r | Y | Y | N |
|
| E | Y | Y | Y |
|
||||||
|
+---+---+---+---+
|
||||||
|
| r | Y | Y | N |
|
||||||
|
+---+---+---+---+
|
||||||
|
| R | Y | Y | N |
|
||||||
+---+---+---+---+
|
+---+---+---+---+
|
||||||
R | Y | Y | N |
|
|
||||||
|
|
||||||
(W: writers, r: non-recursive readers, R: recursive readers)
|
(W: writers, r: non-recursive readers, R: recursive readers)
|
||||||
|
|
||||||
|
|
||||||
acquired recursively. Unlike non-recursive read locks, recursive read locks
|
acquired recursively. Unlike non-recursive read locks, recursive read locks
|
||||||
only get blocked by current write lock *holders* other than write lock
|
only get blocked by current write lock *holders* other than write lock
|
||||||
*waiters*, for example:
|
*waiters*, for example::
|
||||||
|
|
||||||
TASK A: TASK B:
|
TASK A: TASK B:
|
||||||
|
|
||||||
|
@ -491,7 +497,7 @@ Recursive locks don't block each other, while non-recursive locks do (this is
|
||||||
even true for two non-recursive read locks). A non-recursive lock can block the
|
even true for two non-recursive read locks). A non-recursive lock can block the
|
||||||
corresponding recursive lock, and vice versa.
|
corresponding recursive lock, and vice versa.
|
||||||
|
|
||||||
A deadlock case with recursive locks involved is as follow:
|
A deadlock case with recursive locks involved is as follow::
|
||||||
|
|
||||||
TASK A: TASK B:
|
TASK A: TASK B:
|
||||||
|
|
||||||
|
@ -510,7 +516,7 @@ because there are 3 types for lockers, there are, in theory, 9 types of lock
|
||||||
dependencies, but we can show that 4 types of lock dependencies are enough for
|
dependencies, but we can show that 4 types of lock dependencies are enough for
|
||||||
deadlock detection.
|
deadlock detection.
|
||||||
|
|
||||||
For each lock dependency:
|
For each lock dependency::
|
||||||
|
|
||||||
L1 -> L2
|
L1 -> L2
|
||||||
|
|
||||||
|
@ -525,20 +531,25 @@ same types).
|
||||||
With the above combination for simplification, there are 4 types of dependency edges
|
With the above combination for simplification, there are 4 types of dependency edges
|
||||||
in the lockdep graph:
|
in the lockdep graph:
|
||||||
|
|
||||||
1) -(ER)->: exclusive writer to recursive reader dependency, "X -(ER)-> Y" means
|
1) -(ER)->:
|
||||||
|
exclusive writer to recursive reader dependency, "X -(ER)-> Y" means
|
||||||
X -> Y and X is a writer and Y is a recursive reader.
|
X -> Y and X is a writer and Y is a recursive reader.
|
||||||
|
|
||||||
2) -(EN)->: exclusive writer to non-recursive locker dependency, "X -(EN)-> Y" means
|
2) -(EN)->:
|
||||||
|
exclusive writer to non-recursive locker dependency, "X -(EN)-> Y" means
|
||||||
X -> Y and X is a writer and Y is either a writer or non-recursive reader.
|
X -> Y and X is a writer and Y is either a writer or non-recursive reader.
|
||||||
|
|
||||||
3) -(SR)->: shared reader to recursive reader dependency, "X -(SR)-> Y" means
|
3) -(SR)->:
|
||||||
|
shared reader to recursive reader dependency, "X -(SR)-> Y" means
|
||||||
X -> Y and X is a reader (recursive or not) and Y is a recursive reader.
|
X -> Y and X is a reader (recursive or not) and Y is a recursive reader.
|
||||||
|
|
||||||
4) -(SN)->: shared reader to non-recursive locker dependency, "X -(SN)-> Y" means
|
4) -(SN)->:
|
||||||
|
shared reader to non-recursive locker dependency, "X -(SN)-> Y" means
|
||||||
X -> Y and X is a reader (recursive or not) and Y is either a writer or
|
X -> Y and X is a reader (recursive or not) and Y is either a writer or
|
||||||
non-recursive reader.
|
non-recursive reader.
|
||||||
|
|
||||||
Note that given two locks, they may have multiple dependencies between them, for example:
|
Note that given two locks, they may have multiple dependencies between them,
|
||||||
|
for example::
|
||||||
|
|
||||||
TASK A:
|
TASK A:
|
||||||
|
|
||||||
|
@ -592,11 +603,11 @@ circles that won't cause deadlocks.
|
||||||
|
|
||||||
Proof for sufficiency (Lemma 1):
|
Proof for sufficiency (Lemma 1):
|
||||||
|
|
||||||
Let's say we have a strong circle:
|
Let's say we have a strong circle::
|
||||||
|
|
||||||
L1 -> L2 ... -> Ln -> L1
|
L1 -> L2 ... -> Ln -> L1
|
||||||
|
|
||||||
, which means we have dependencies:
|
, which means we have dependencies::
|
||||||
|
|
||||||
L1 -> L2
|
L1 -> L2
|
||||||
L2 -> L3
|
L2 -> L3
|
||||||
|
@ -633,7 +644,7 @@ a lock held by P2, and P2 is waiting for a lock held by P3, ... and Pn is waitin
|
||||||
for a lock held by P1. Let's name the lock Px is waiting as Lx, so since P1 is waiting
|
for a lock held by P1. Let's name the lock Px is waiting as Lx, so since P1 is waiting
|
||||||
for L1 and holding Ln, so we will have Ln -> L1 in the dependency graph. Similarly,
|
for L1 and holding Ln, so we will have Ln -> L1 in the dependency graph. Similarly,
|
||||||
we have L1 -> L2, L2 -> L3, ..., Ln-1 -> Ln in the dependency graph, which means we
|
we have L1 -> L2, L2 -> L3, ..., Ln-1 -> Ln in the dependency graph, which means we
|
||||||
have a circle:
|
have a circle::
|
||||||
|
|
||||||
Ln -> L1 -> L2 -> ... -> Ln
|
Ln -> L1 -> L2 -> ... -> Ln
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ fit into other categories.
|
||||||
isl29003
|
isl29003
|
||||||
lis3lv02d
|
lis3lv02d
|
||||||
max6875
|
max6875
|
||||||
mic/index
|
|
||||||
pci-endpoint-test
|
pci-endpoint-test
|
||||||
spear-pcie-gadget
|
spear-pcie-gadget
|
||||||
uacce
|
uacce
|
||||||
|
|
|
@ -70,6 +70,7 @@ The ``ice`` driver reports the following versions
|
||||||
that both the name (as reported by ``fw.app.name``) and version are
|
that both the name (as reported by ``fw.app.name``) and version are
|
||||||
required to uniquely identify the package.
|
required to uniquely identify the package.
|
||||||
* - ``fw.app.bundle_id``
|
* - ``fw.app.bundle_id``
|
||||||
|
- running
|
||||||
- 0xc0000001
|
- 0xc0000001
|
||||||
- Unique identifier for the DDP package loaded in the device. Also
|
- Unique identifier for the DDP package loaded in the device. Also
|
||||||
referred to as the DDP Track ID. Can be used to uniquely identify
|
referred to as the DDP Track ID. Can be used to uniquely identify
|
||||||
|
|
|
@ -10,9 +10,9 @@ Overview / What Is J1939
|
||||||
SAE J1939 defines a higher layer protocol on CAN. It implements a more
|
SAE J1939 defines a higher layer protocol on CAN. It implements a more
|
||||||
sophisticated addressing scheme and extends the maximum packet size above 8
|
sophisticated addressing scheme and extends the maximum packet size above 8
|
||||||
bytes. Several derived specifications exist, which differ from the original
|
bytes. Several derived specifications exist, which differ from the original
|
||||||
J1939 on the application level, like MilCAN A, NMEA2000 and especially
|
J1939 on the application level, like MilCAN A, NMEA2000, and especially
|
||||||
ISO-11783 (ISOBUS). This last one specifies the so-called ETP (Extended
|
ISO-11783 (ISOBUS). This last one specifies the so-called ETP (Extended
|
||||||
Transport Protocol) which is has been included in this implementation. This
|
Transport Protocol), which has been included in this implementation. This
|
||||||
results in a maximum packet size of ((2 ^ 24) - 1) * 7 bytes == 111 MiB.
|
results in a maximum packet size of ((2 ^ 24) - 1) * 7 bytes == 111 MiB.
|
||||||
|
|
||||||
Specifications used
|
Specifications used
|
||||||
|
@ -32,15 +32,15 @@ sockets, we found some reasons to justify a kernel implementation for the
|
||||||
addressing and transport methods used by J1939.
|
addressing and transport methods used by J1939.
|
||||||
|
|
||||||
* **Addressing:** when a process on an ECU communicates via J1939, it should
|
* **Addressing:** when a process on an ECU communicates via J1939, it should
|
||||||
not necessarily know its source address. Although at least one process per
|
not necessarily know its source address. Although, at least one process per
|
||||||
ECU should know the source address. Other processes should be able to reuse
|
ECU should know the source address. Other processes should be able to reuse
|
||||||
that address. This way, address parameters for different processes
|
that address. This way, address parameters for different processes
|
||||||
cooperating for the same ECU, are not duplicated. This way of working is
|
cooperating for the same ECU, are not duplicated. This way of working is
|
||||||
closely related to the UNIX concept where programs do just one thing, and do
|
closely related to the UNIX concept, where programs do just one thing and do
|
||||||
it well.
|
it well.
|
||||||
|
|
||||||
* **Dynamic addressing:** Address Claiming in J1939 is time critical.
|
* **Dynamic addressing:** Address Claiming in J1939 is time critical.
|
||||||
Furthermore data transport should be handled properly during the address
|
Furthermore, data transport should be handled properly during the address
|
||||||
negotiation. Putting this functionality in the kernel eliminates it as a
|
negotiation. Putting this functionality in the kernel eliminates it as a
|
||||||
requirement for _every_ user space process that communicates via J1939. This
|
requirement for _every_ user space process that communicates via J1939. This
|
||||||
results in a consistent J1939 bus with proper addressing.
|
results in a consistent J1939 bus with proper addressing.
|
||||||
|
@ -58,7 +58,7 @@ Therefore, these parts are left to user space.
|
||||||
|
|
||||||
The J1939 sockets operate on CAN network devices (see SocketCAN). Any J1939
|
The J1939 sockets operate on CAN network devices (see SocketCAN). Any J1939
|
||||||
user space library operating on CAN raw sockets will still operate properly.
|
user space library operating on CAN raw sockets will still operate properly.
|
||||||
Since such library does not communicate with the in-kernel implementation, care
|
Since such a library does not communicate with the in-kernel implementation, care
|
||||||
must be taken that these two do not interfere. In practice, this means they
|
must be taken that these two do not interfere. In practice, this means they
|
||||||
cannot share ECU addresses. A single ECU (or virtual ECU) address is used by
|
cannot share ECU addresses. A single ECU (or virtual ECU) address is used by
|
||||||
the library exclusively, or by the in-kernel system exclusively.
|
the library exclusively, or by the in-kernel system exclusively.
|
||||||
|
@ -77,13 +77,13 @@ is composed as follows:
|
||||||
8 bits : PS (PDU Specific)
|
8 bits : PS (PDU Specific)
|
||||||
|
|
||||||
In J1939-21 distinction is made between PDU1 format (where PF < 240) and PDU2
|
In J1939-21 distinction is made between PDU1 format (where PF < 240) and PDU2
|
||||||
format (where PF >= 240). Furthermore, when using PDU2 format, the PS-field
|
format (where PF >= 240). Furthermore, when using the PDU2 format, the PS-field
|
||||||
contains a so-called Group Extension, which is part of the PGN. When using PDU2
|
contains a so-called Group Extension, which is part of the PGN. When using PDU2
|
||||||
format, the Group Extension is set in the PS-field.
|
format, the Group Extension is set in the PS-field.
|
||||||
|
|
||||||
On the other hand, when using PDU1 format, the PS-field contains a so-called
|
On the other hand, when using PDU1 format, the PS-field contains a so-called
|
||||||
Destination Address, which is _not_ part of the PGN. When communicating a PGN
|
Destination Address, which is _not_ part of the PGN. When communicating a PGN
|
||||||
from user space to kernel (or visa versa) and PDU2 format is used, the PS-field
|
from user space to kernel (or vice versa) and PDU2 format is used, the PS-field
|
||||||
of the PGN shall be set to zero. The Destination Address shall be set
|
of the PGN shall be set to zero. The Destination Address shall be set
|
||||||
elsewhere.
|
elsewhere.
|
||||||
|
|
||||||
|
@ -96,15 +96,15 @@ Addressing
|
||||||
|
|
||||||
Both static and dynamic addressing methods can be used.
|
Both static and dynamic addressing methods can be used.
|
||||||
|
|
||||||
For static addresses, no extra checks are made by the kernel, and provided
|
For static addresses, no extra checks are made by the kernel and provided
|
||||||
addresses are considered right. This responsibility is for the OEM or system
|
addresses are considered right. This responsibility is for the OEM or system
|
||||||
integrator.
|
integrator.
|
||||||
|
|
||||||
For dynamic addressing, so-called Address Claiming, extra support is foreseen
|
For dynamic addressing, so-called Address Claiming, extra support is foreseen
|
||||||
in the kernel. In J1939 any ECU is known by it's 64-bit NAME. At the moment of
|
in the kernel. In J1939 any ECU is known by its 64-bit NAME. At the moment of
|
||||||
a successful address claim, the kernel keeps track of both NAME and source
|
a successful address claim, the kernel keeps track of both NAME and source
|
||||||
address being claimed. This serves as a base for filter schemes. By default,
|
address being claimed. This serves as a base for filter schemes. By default,
|
||||||
packets with a destination that is not locally, will be rejected.
|
packets with a destination that is not locally will be rejected.
|
||||||
|
|
||||||
Mixed mode packets (from a static to a dynamic address or vice versa) are
|
Mixed mode packets (from a static to a dynamic address or vice versa) are
|
||||||
allowed. The BSD sockets define separate API calls for getting/setting the
|
allowed. The BSD sockets define separate API calls for getting/setting the
|
||||||
|
@ -131,31 +131,31 @@ API Calls
|
||||||
---------
|
---------
|
||||||
|
|
||||||
On CAN, you first need to open a socket for communicating over a CAN network.
|
On CAN, you first need to open a socket for communicating over a CAN network.
|
||||||
To use J1939, #include <linux/can/j1939.h>. From there, <linux/can.h> will be
|
To use J1939, ``#include <linux/can/j1939.h>``. From there, ``<linux/can.h>`` will be
|
||||||
included too. To open a socket, use:
|
included too. To open a socket, use:
|
||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
s = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
|
s = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
|
||||||
|
|
||||||
J1939 does use SOCK_DGRAM sockets. In the J1939 specification, connections are
|
J1939 does use ``SOCK_DGRAM`` sockets. In the J1939 specification, connections are
|
||||||
mentioned in the context of transport protocol sessions. These still deliver
|
mentioned in the context of transport protocol sessions. These still deliver
|
||||||
packets to the other end (using several CAN packets). SOCK_STREAM is not
|
packets to the other end (using several CAN packets). ``SOCK_STREAM`` is not
|
||||||
supported.
|
supported.
|
||||||
|
|
||||||
After the successful creation of the socket, you would normally use the bind(2)
|
After the successful creation of the socket, you would normally use the ``bind(2)``
|
||||||
and/or connect(2) system call to bind the socket to a CAN interface. After
|
and/or ``connect(2)`` system call to bind the socket to a CAN interface. After
|
||||||
binding and/or connecting the socket, you can read(2) and write(2) from/to the
|
binding and/or connecting the socket, you can ``read(2)`` and ``write(2)`` from/to the
|
||||||
socket or use send(2), sendto(2), sendmsg(2) and the recv*() counterpart
|
socket or use ``send(2)``, ``sendto(2)``, ``sendmsg(2)`` and the ``recv*()`` counterpart
|
||||||
operations on the socket as usual. There are also J1939 specific socket options
|
operations on the socket as usual. There are also J1939 specific socket options
|
||||||
described below.
|
described below.
|
||||||
|
|
||||||
In order to send data, a bind(2) must have been successful. bind(2) assigns a
|
In order to send data, a ``bind(2)`` must have been successful. ``bind(2)`` assigns a
|
||||||
local address to a socket.
|
local address to a socket.
|
||||||
|
|
||||||
Different from CAN is that the payload data is just the data that get send,
|
Different from CAN is that the payload data is just the data that get sends,
|
||||||
without it's header info. The header info is derived from the sockaddr supplied
|
without its header info. The header info is derived from the sockaddr supplied
|
||||||
to bind(2), connect(2), sendto(2) and recvfrom(2). A write(2) with size 4 will
|
to ``bind(2)``, ``connect(2)``, ``sendto(2)`` and ``recvfrom(2)``. A ``write(2)`` with size 4 will
|
||||||
result in a packet with 4 bytes.
|
result in a packet with 4 bytes.
|
||||||
|
|
||||||
The sockaddr structure has extensions for use with J1939 as specified below:
|
The sockaddr structure has extensions for use with J1939 as specified below:
|
||||||
|
@ -180,47 +180,47 @@ The sockaddr structure has extensions for use with J1939 as specified below:
|
||||||
} can_addr;
|
} can_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
can_family & can_ifindex serve the same purpose as for other SocketCAN sockets.
|
``can_family`` & ``can_ifindex`` serve the same purpose as for other SocketCAN sockets.
|
||||||
|
|
||||||
can_addr.j1939.pgn specifies the PGN (max 0x3ffff). Individual bits are
|
``can_addr.j1939.pgn`` specifies the PGN (max 0x3ffff). Individual bits are
|
||||||
specified above.
|
specified above.
|
||||||
|
|
||||||
can_addr.j1939.name contains the 64-bit J1939 NAME.
|
``can_addr.j1939.name`` contains the 64-bit J1939 NAME.
|
||||||
|
|
||||||
can_addr.j1939.addr contains the address.
|
``can_addr.j1939.addr`` contains the address.
|
||||||
|
|
||||||
The bind(2) system call assigns the local address, i.e. the source address when
|
The ``bind(2)`` system call assigns the local address, i.e. the source address when
|
||||||
sending packages. If a PGN during bind(2) is set, it's used as a RX filter.
|
sending packages. If a PGN during ``bind(2)`` is set, it's used as a RX filter.
|
||||||
I.e. only packets with a matching PGN are received. If an ADDR or NAME is set
|
I.e. only packets with a matching PGN are received. If an ADDR or NAME is set
|
||||||
it is used as a receive filter, too. It will match the destination NAME or ADDR
|
it is used as a receive filter, too. It will match the destination NAME or ADDR
|
||||||
of the incoming packet. The NAME filter will work only if appropriate Address
|
of the incoming packet. The NAME filter will work only if appropriate Address
|
||||||
Claiming for this name was done on the CAN bus and registered/cached by the
|
Claiming for this name was done on the CAN bus and registered/cached by the
|
||||||
kernel.
|
kernel.
|
||||||
|
|
||||||
On the other hand connect(2) assigns the remote address, i.e. the destination
|
On the other hand ``connect(2)`` assigns the remote address, i.e. the destination
|
||||||
address. The PGN from connect(2) is used as the default PGN when sending
|
address. The PGN from ``connect(2)`` is used as the default PGN when sending
|
||||||
packets. If ADDR or NAME is set it will be used as the default destination ADDR
|
packets. If ADDR or NAME is set it will be used as the default destination ADDR
|
||||||
or NAME. Further a set ADDR or NAME during connect(2) is used as a receive
|
or NAME. Further a set ADDR or NAME during ``connect(2)`` is used as a receive
|
||||||
filter. It will match the source NAME or ADDR of the incoming packet.
|
filter. It will match the source NAME or ADDR of the incoming packet.
|
||||||
|
|
||||||
Both write(2) and send(2) will send a packet with local address from bind(2) and
|
Both ``write(2)`` and ``send(2)`` will send a packet with local address from ``bind(2)`` and the
|
||||||
the remote address from connect(2). Use sendto(2) to overwrite the destination
|
remote address from ``connect(2)``. Use ``sendto(2)`` to overwrite the destination
|
||||||
address.
|
address.
|
||||||
|
|
||||||
If can_addr.j1939.name is set (!= 0) the NAME is looked up by the kernel and
|
If ``can_addr.j1939.name`` is set (!= 0) the NAME is looked up by the kernel and
|
||||||
the corresponding ADDR is used. If can_addr.j1939.name is not set (== 0),
|
the corresponding ADDR is used. If ``can_addr.j1939.name`` is not set (== 0),
|
||||||
can_addr.j1939.addr is used.
|
``can_addr.j1939.addr`` is used.
|
||||||
|
|
||||||
When creating a socket, reasonable defaults are set. Some options can be
|
When creating a socket, reasonable defaults are set. Some options can be
|
||||||
modified with setsockopt(2) & getsockopt(2).
|
modified with ``setsockopt(2)`` & ``getsockopt(2)``.
|
||||||
|
|
||||||
RX path related options:
|
RX path related options:
|
||||||
|
|
||||||
- SO_J1939_FILTER - configure array of filters
|
- ``SO_J1939_FILTER`` - configure array of filters
|
||||||
- SO_J1939_PROMISC - disable filters set by bind(2) and connect(2)
|
- ``SO_J1939_PROMISC`` - disable filters set by ``bind(2)`` and ``connect(2)``
|
||||||
|
|
||||||
By default no broadcast packets can be send or received. To enable sending or
|
By default no broadcast packets can be send or received. To enable sending or
|
||||||
receiving broadcast packets use the socket option SO_BROADCAST:
|
receiving broadcast packets use the socket option ``SO_BROADCAST``:
|
||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
|
@ -261,26 +261,26 @@ The following diagram illustrates the RX path:
|
||||||
+---------------------------+
|
+---------------------------+
|
||||||
|
|
||||||
TX path related options:
|
TX path related options:
|
||||||
SO_J1939_SEND_PRIO - change default send priority for the socket
|
``SO_J1939_SEND_PRIO`` - change default send priority for the socket
|
||||||
|
|
||||||
Message Flags during send() and Related System Calls
|
Message Flags during send() and Related System Calls
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
send(2), sendto(2) and sendmsg(2) take a 'flags' argument. Currently
|
``send(2)``, ``sendto(2)`` and ``sendmsg(2)`` take a 'flags' argument. Currently
|
||||||
supported flags are:
|
supported flags are:
|
||||||
|
|
||||||
* MSG_DONTWAIT, i.e. non-blocking operation.
|
* ``MSG_DONTWAIT``, i.e. non-blocking operation.
|
||||||
|
|
||||||
recvmsg(2)
|
recvmsg(2)
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
In most cases recvmsg(2) is needed if you want to extract more information than
|
In most cases ``recvmsg(2)`` is needed if you want to extract more information than
|
||||||
recvfrom(2) can provide. For example package priority and timestamp. The
|
``recvfrom(2)`` can provide. For example package priority and timestamp. The
|
||||||
Destination Address, name and packet priority (if applicable) are attached to
|
Destination Address, name and packet priority (if applicable) are attached to
|
||||||
the msghdr in the recvmsg(2) call. They can be extracted using cmsg(3) macros,
|
the msghdr in the ``recvmsg(2)`` call. They can be extracted using ``cmsg(3)`` macros,
|
||||||
with cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR,
|
with ``cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR``,
|
||||||
SCM_J1939_DEST_NAME or SCM_J1939_PRIO. The returned data is a uint8_t for
|
``SCM_J1939_DEST_NAME`` or ``SCM_J1939_PRIO``. The returned data is a ``uint8_t`` for
|
||||||
priority and dst_addr, and uint64_t for dst_name.
|
``priority`` and ``dst_addr``, and ``uint64_t`` for ``dst_name``.
|
||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
||||||
|
@ -305,12 +305,12 @@ Dynamic Addressing
|
||||||
|
|
||||||
Distinction has to be made between using the claimed address and doing an
|
Distinction has to be made between using the claimed address and doing an
|
||||||
address claim. To use an already claimed address, one has to fill in the
|
address claim. To use an already claimed address, one has to fill in the
|
||||||
j1939.name member and provide it to bind(2). If the name had claimed an address
|
``j1939.name`` member and provide it to ``bind(2)``. If the name had claimed an address
|
||||||
earlier, all further messages being sent will use that address. And the
|
earlier, all further messages being sent will use that address. And the
|
||||||
j1939.addr member will be ignored.
|
``j1939.addr`` member will be ignored.
|
||||||
|
|
||||||
An exception on this is PGN 0x0ee00. This is the "Address Claim/Cannot Claim
|
An exception on this is PGN 0x0ee00. This is the "Address Claim/Cannot Claim
|
||||||
Address" message and the kernel will use the j1939.addr member for that PGN if
|
Address" message and the kernel will use the ``j1939.addr`` member for that PGN if
|
||||||
necessary.
|
necessary.
|
||||||
|
|
||||||
To claim an address following code example can be used:
|
To claim an address following code example can be used:
|
||||||
|
@ -371,12 +371,12 @@ NAME can send packets.
|
||||||
|
|
||||||
If another ECU claims the address, the kernel will mark the NAME-SA expired.
|
If another ECU claims the address, the kernel will mark the NAME-SA expired.
|
||||||
No socket bound to the NAME can send packets (other than address claims). To
|
No socket bound to the NAME can send packets (other than address claims). To
|
||||||
claim another address, some socket bound to NAME, must bind(2) again, but with
|
claim another address, some socket bound to NAME, must ``bind(2)`` again, but with
|
||||||
only j1939.addr changed to the new SA, and must then send a valid address claim
|
only ``j1939.addr`` changed to the new SA, and must then send a valid address claim
|
||||||
packet. This restarts the state machine in the kernel (and any other
|
packet. This restarts the state machine in the kernel (and any other
|
||||||
participant on the bus) for this NAME.
|
participant on the bus) for this NAME.
|
||||||
|
|
||||||
can-utils also include the jacd tool, so it can be used as code example or as
|
``can-utils`` also include the ``j1939acd`` tool, so it can be used as code example or as
|
||||||
default Address Claiming daemon.
|
default Address Claiming daemon.
|
||||||
|
|
||||||
Send Examples
|
Send Examples
|
||||||
|
@ -403,8 +403,8 @@ Bind:
|
||||||
|
|
||||||
bind(sock, (struct sockaddr *)&baddr, sizeof(baddr));
|
bind(sock, (struct sockaddr *)&baddr, sizeof(baddr));
|
||||||
|
|
||||||
Now, the socket 'sock' is bound to the SA 0x20. Since no connect(2) was called,
|
Now, the socket 'sock' is bound to the SA 0x20. Since no ``connect(2)`` was called,
|
||||||
at this point we can use only sendto(2) or sendmsg(2).
|
at this point we can use only ``sendto(2)`` or ``sendmsg(2)``.
|
||||||
|
|
||||||
Send:
|
Send:
|
||||||
|
|
||||||
|
@ -414,8 +414,8 @@ Send:
|
||||||
.can_family = AF_CAN,
|
.can_family = AF_CAN,
|
||||||
.can_addr.j1939 = {
|
.can_addr.j1939 = {
|
||||||
.name = J1939_NO_NAME;
|
.name = J1939_NO_NAME;
|
||||||
.pgn = 0x30,
|
.addr = 0x30,
|
||||||
.addr = 0x12300,
|
.pgn = 0x12300,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -175,5 +175,4 @@ The following structures are internal to the kernel, their members are
|
||||||
translated to netlink attributes when dumped. Drivers must not overwrite
|
translated to netlink attributes when dumped. Drivers must not overwrite
|
||||||
the statistics they don't report with 0.
|
the statistics they don't report with 0.
|
||||||
|
|
||||||
.. kernel-doc:: include/linux/ethtool.h
|
- ethtool_pause_stats()
|
||||||
:identifiers: ethtool_pause_stats
|
|
||||||
|
|
|
@ -15,6 +15,14 @@ else:
|
||||||
import re
|
import re
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
#
|
||||||
|
# Python 2 lacks re.ASCII...
|
||||||
|
#
|
||||||
|
try:
|
||||||
|
ascii_p3 = re.ASCII
|
||||||
|
except AttributeError:
|
||||||
|
ascii_p3 = 0
|
||||||
|
|
||||||
#
|
#
|
||||||
# Regex nastiness. Of course.
|
# Regex nastiness. Of course.
|
||||||
# Try to identify "function()" that's not already marked up some
|
# Try to identify "function()" that's not already marked up some
|
||||||
|
@ -22,22 +30,22 @@ from itertools import chain
|
||||||
# :c:func: block (i.e. ":c:func:`mmap()`s" flakes out), so the last
|
# :c:func: block (i.e. ":c:func:`mmap()`s" flakes out), so the last
|
||||||
# bit tries to restrict matches to things that won't create trouble.
|
# bit tries to restrict matches to things that won't create trouble.
|
||||||
#
|
#
|
||||||
RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=re.ASCII)
|
RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=ascii_p3)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sphinx 2 uses the same :c:type role for struct, union, enum and typedef
|
# Sphinx 2 uses the same :c:type role for struct, union, enum and typedef
|
||||||
#
|
#
|
||||||
RE_generic_type = re.compile(r'\b(struct|union|enum|typedef)\s+([a-zA-Z_]\w+)',
|
RE_generic_type = re.compile(r'\b(struct|union|enum|typedef)\s+([a-zA-Z_]\w+)',
|
||||||
flags=re.ASCII)
|
flags=ascii_p3)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sphinx 3 uses a different C role for each one of struct, union, enum and
|
# Sphinx 3 uses a different C role for each one of struct, union, enum and
|
||||||
# typedef
|
# typedef
|
||||||
#
|
#
|
||||||
RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
|
RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
|
||||||
RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
|
RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
|
||||||
RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
|
RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
|
||||||
RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=re.ASCII)
|
RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Detects a reference to a documentation page of the form Documentation/... with
|
# Detects a reference to a documentation page of the form Documentation/... with
|
||||||
|
|
|
@ -22,6 +22,7 @@ place where this information is gathered.
|
||||||
spec_ctrl
|
spec_ctrl
|
||||||
accelerators/ocxl
|
accelerators/ocxl
|
||||||
ioctl/index
|
ioctl/index
|
||||||
|
iommu
|
||||||
media/index
|
media/index
|
||||||
|
|
||||||
.. only:: subproject and html
|
.. only:: subproject and html
|
||||||
|
|
19
MAINTAINERS
19
MAINTAINERS
|
@ -978,7 +978,7 @@ M: Michael Hennerich <Michael.Hennerich@analog.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://ez.analog.com/community/linux-device-drivers
|
W: http://ez.analog.com/community/linux-device-drivers
|
||||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.txt
|
F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
|
||||||
F: drivers/iio/adc/ad7768-1.c
|
F: drivers/iio/adc/ad7768-1.c
|
||||||
|
|
||||||
ANALOG DEVICES INC AD7780 DRIVER
|
ANALOG DEVICES INC AD7780 DRIVER
|
||||||
|
@ -3857,7 +3857,7 @@ M: Roger Quadros <rogerq@ti.com>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
|
||||||
F: Documentation/devicetree/bindings/usb/cdns-usb3.txt
|
F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml
|
||||||
F: drivers/usb/cdns3/
|
F: drivers/usb/cdns3/
|
||||||
|
|
||||||
CADET FM/AM RADIO RECEIVER DRIVER
|
CADET FM/AM RADIO RECEIVER DRIVER
|
||||||
|
@ -7923,7 +7923,7 @@ HISILICON LPC BUS DRIVER
|
||||||
M: john.garry@huawei.com
|
M: john.garry@huawei.com
|
||||||
S: Maintained
|
S: Maintained
|
||||||
W: http://www.hisilicon.com
|
W: http://www.hisilicon.com
|
||||||
F: Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
|
F: Documentation/devicetree/bindings/arm/hisilicon/low-pin-count.yaml
|
||||||
F: drivers/bus/hisi_lpc.c
|
F: drivers/bus/hisi_lpc.c
|
||||||
|
|
||||||
HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
|
HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
|
||||||
|
@ -11170,7 +11170,7 @@ F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt
|
||||||
F: drivers/input/touchscreen/melfas_mip4.c
|
F: drivers/input/touchscreen/melfas_mip4.c
|
||||||
|
|
||||||
MELLANOX BLUEFIELD I2C DRIVER
|
MELLANOX BLUEFIELD I2C DRIVER
|
||||||
M: Khalil Blaiech <kblaiech@mellanox.com>
|
M: Khalil Blaiech <kblaiech@nvidia.com>
|
||||||
L: linux-i2c@vger.kernel.org
|
L: linux-i2c@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/i2c/busses/i2c-mlxbf.c
|
F: drivers/i2c/busses/i2c-mlxbf.c
|
||||||
|
@ -14534,6 +14534,14 @@ F: Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
|
||||||
F: drivers/mailbox/qcom-ipcc.c
|
F: drivers/mailbox/qcom-ipcc.c
|
||||||
F: include/dt-bindings/mailbox/qcom-ipcc.h
|
F: include/dt-bindings/mailbox/qcom-ipcc.h
|
||||||
|
|
||||||
|
QUALCOMM IPQ4019 VQMMC REGULATOR DRIVER
|
||||||
|
M: Robert Marko <robert.marko@sartura.hr>
|
||||||
|
M: Luka Perkov <luka.perkov@sartura.hr>
|
||||||
|
L: linux-arm-msm@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
|
||||||
|
F: drivers/regulator/vqmmc-ipq4019-regulator.c
|
||||||
|
|
||||||
QUALCOMM RMNET DRIVER
|
QUALCOMM RMNET DRIVER
|
||||||
M: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
|
M: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
|
||||||
M: Sean Tranchetti <stranche@codeaurora.org>
|
M: Sean Tranchetti <stranche@codeaurora.org>
|
||||||
|
@ -14889,7 +14897,6 @@ RENESAS ETHERNET DRIVERS
|
||||||
R: Sergei Shtylyov <sergei.shtylyov@gmail.com>
|
R: Sergei Shtylyov <sergei.shtylyov@gmail.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
L: linux-renesas-soc@vger.kernel.org
|
L: linux-renesas-soc@vger.kernel.org
|
||||||
F: Documentation/devicetree/bindings/net/renesas,*.txt
|
|
||||||
F: Documentation/devicetree/bindings/net/renesas,*.yaml
|
F: Documentation/devicetree/bindings/net/renesas,*.yaml
|
||||||
F: drivers/net/ethernet/renesas/
|
F: drivers/net/ethernet/renesas/
|
||||||
F: include/linux/sh_eth.h
|
F: include/linux/sh_eth.h
|
||||||
|
@ -18090,7 +18097,7 @@ M: Yu Chen <chenyu56@huawei.com>
|
||||||
M: Binghui Wang <wangbinghui@hisilicon.com>
|
M: Binghui Wang <wangbinghui@hisilicon.com>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
|
F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml
|
||||||
F: drivers/phy/hisilicon/phy-hi3660-usb3.c
|
F: drivers/phy/hisilicon/phy-hi3660-usb3.c
|
||||||
|
|
||||||
USB ISP116X DRIVER
|
USB ISP116X DRIVER
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
||||||
VERSION = 5
|
VERSION = 5
|
||||||
PATCHLEVEL = 10
|
PATCHLEVEL = 10
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc2
|
EXTRAVERSION = -rc3
|
||||||
NAME = Kleptomaniac Octopus
|
NAME = Kleptomaniac Octopus
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -67,7 +67,22 @@
|
||||||
sr r5, [ARC_REG_LPB_CTRL]
|
sr r5, [ARC_REG_LPB_CTRL]
|
||||||
1:
|
1:
|
||||||
#endif /* CONFIG_ARC_LPB_DISABLE */
|
#endif /* CONFIG_ARC_LPB_DISABLE */
|
||||||
#endif
|
|
||||||
|
/* On HSDK, CCMs need to remapped super early */
|
||||||
|
#ifdef CONFIG_ARC_SOC_HSDK
|
||||||
|
mov r6, 0x60000000
|
||||||
|
lr r5, [ARC_REG_ICCM_BUILD]
|
||||||
|
breq r5, 0, 1f
|
||||||
|
sr r6, [ARC_REG_AUX_ICCM]
|
||||||
|
1:
|
||||||
|
lr r5, [ARC_REG_DCCM_BUILD]
|
||||||
|
breq r5, 0, 2f
|
||||||
|
sr r6, [ARC_REG_AUX_DCCM]
|
||||||
|
2:
|
||||||
|
#endif /* CONFIG_ARC_SOC_HSDK */
|
||||||
|
|
||||||
|
#endif /* CONFIG_ISA_ARCV2 */
|
||||||
|
|
||||||
; Config DSP_CTRL properly, so kernel may use integer multiply,
|
; Config DSP_CTRL properly, so kernel may use integer multiply,
|
||||||
; multiply-accumulate, and divide operations
|
; multiply-accumulate, and divide operations
|
||||||
DSP_EARLY_INIT
|
DSP_EARLY_INIT
|
||||||
|
|
|
@ -112,7 +112,7 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
int (*consumer_fn) (unsigned int, void *), void *arg)
|
int (*consumer_fn) (unsigned int, void *), void *arg)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||||
int ret = 0;
|
int ret = 0, cnt = 0;
|
||||||
unsigned int address;
|
unsigned int address;
|
||||||
struct unwind_frame_info frame_info;
|
struct unwind_frame_info frame_info;
|
||||||
|
|
||||||
|
@ -132,6 +132,11 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
frame_info.regs.r63 = frame_info.regs.r31;
|
frame_info.regs.r63 = frame_info.regs.r31;
|
||||||
|
|
||||||
|
if (cnt++ > 128) {
|
||||||
|
printk("unwinder looping too long, aborting !\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return address; /* return the last address it saw */
|
return address; /* return the last address it saw */
|
||||||
|
|
|
@ -17,22 +17,6 @@ int arc_hsdk_axi_dmac_coherent __section(".data") = 0;
|
||||||
|
|
||||||
#define ARC_CCM_UNUSED_ADDR 0x60000000
|
#define ARC_CCM_UNUSED_ADDR 0x60000000
|
||||||
|
|
||||||
static void __init hsdk_init_per_cpu(unsigned int cpu)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* By default ICCM is mapped to 0x7z while this area is used for
|
|
||||||
* kernel virtual mappings, so move it to currently unused area.
|
|
||||||
*/
|
|
||||||
if (cpuinfo_arc700[cpu].iccm.sz)
|
|
||||||
write_aux_reg(ARC_REG_AUX_ICCM, ARC_CCM_UNUSED_ADDR);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* By default DCCM is mapped to 0x8z while this area is used by kernel,
|
|
||||||
* so move it to currently unused area.
|
|
||||||
*/
|
|
||||||
if (cpuinfo_arc700[cpu].dccm.sz)
|
|
||||||
write_aux_reg(ARC_REG_AUX_DCCM, ARC_CCM_UNUSED_ADDR);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ARC_PERIPHERAL_BASE 0xf0000000
|
#define ARC_PERIPHERAL_BASE 0xf0000000
|
||||||
#define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000)
|
#define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000)
|
||||||
|
@ -339,5 +323,4 @@ static const char *hsdk_compat[] __initconst = {
|
||||||
MACHINE_START(SIMULATION, "hsdk")
|
MACHINE_START(SIMULATION, "hsdk")
|
||||||
.dt_compat = hsdk_compat,
|
.dt_compat = hsdk_compat,
|
||||||
.init_early = hsdk_init_early,
|
.init_early = hsdk_init_early,
|
||||||
.init_per_cpu = hsdk_init_per_cpu,
|
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
|
|
@ -354,8 +354,8 @@ static void __init free_highpages(void)
|
||||||
/* set highmem page free */
|
/* set highmem page free */
|
||||||
for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
|
for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
|
||||||
&range_start, &range_end, NULL) {
|
&range_start, &range_end, NULL) {
|
||||||
unsigned long start = PHYS_PFN(range_start);
|
unsigned long start = PFN_UP(range_start);
|
||||||
unsigned long end = PHYS_PFN(range_end);
|
unsigned long end = PFN_DOWN(range_end);
|
||||||
|
|
||||||
/* Ignore complete lowmem entries */
|
/* Ignore complete lowmem entries */
|
||||||
if (end <= max_low)
|
if (end <= max_low)
|
||||||
|
|
|
@ -1002,7 +1002,7 @@ config NUMA
|
||||||
config NODES_SHIFT
|
config NODES_SHIFT
|
||||||
int "Maximum NUMA Nodes (as a power of 2)"
|
int "Maximum NUMA Nodes (as a power of 2)"
|
||||||
range 1 10
|
range 1 10
|
||||||
default "2"
|
default "4"
|
||||||
depends on NEED_MULTIPLE_NODES
|
depends on NEED_MULTIPLE_NODES
|
||||||
help
|
help
|
||||||
Specify the maximum number of NUMA Nodes available on the target
|
Specify the maximum number of NUMA Nodes available on the target
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
* #imm16 values used for BRK instruction generation
|
* #imm16 values used for BRK instruction generation
|
||||||
* 0x004: for installing kprobes
|
* 0x004: for installing kprobes
|
||||||
* 0x005: for installing uprobes
|
* 0x005: for installing uprobes
|
||||||
|
* 0x006: for kprobe software single-step
|
||||||
* Allowed values for kgdb are 0x400 - 0x7ff
|
* Allowed values for kgdb are 0x400 - 0x7ff
|
||||||
* 0x100: for triggering a fault on purpose (reserved)
|
* 0x100: for triggering a fault on purpose (reserved)
|
||||||
* 0x400: for dynamic BRK instruction
|
* 0x400: for dynamic BRK instruction
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
#define KPROBES_BRK_IMM 0x004
|
#define KPROBES_BRK_IMM 0x004
|
||||||
#define UPROBES_BRK_IMM 0x005
|
#define UPROBES_BRK_IMM 0x005
|
||||||
|
#define KPROBES_BRK_SS_IMM 0x006
|
||||||
#define FAULT_BRK_IMM 0x100
|
#define FAULT_BRK_IMM 0x100
|
||||||
#define KGDB_DYN_DBG_BRK_IMM 0x400
|
#define KGDB_DYN_DBG_BRK_IMM 0x400
|
||||||
#define KGDB_COMPILED_DBG_BRK_IMM 0x401
|
#define KGDB_COMPILED_DBG_BRK_IMM 0x401
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
|
|
||||||
/* kprobes BRK opcodes with ESR encoding */
|
/* kprobes BRK opcodes with ESR encoding */
|
||||||
#define BRK64_OPCODE_KPROBES (AARCH64_BREAK_MON | (KPROBES_BRK_IMM << 5))
|
#define BRK64_OPCODE_KPROBES (AARCH64_BREAK_MON | (KPROBES_BRK_IMM << 5))
|
||||||
|
#define BRK64_OPCODE_KPROBES_SS (AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5))
|
||||||
/* uprobes BRK opcodes with ESR encoding */
|
/* uprobes BRK opcodes with ESR encoding */
|
||||||
#define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
|
#define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
|
|
||||||
#define __ARCH_WANT_KPROBES_INSN_SLOT
|
#define __ARCH_WANT_KPROBES_INSN_SLOT
|
||||||
#define MAX_INSN_SIZE 1
|
#define MAX_INSN_SIZE 2
|
||||||
|
|
||||||
#define flush_insn_slot(p) do { } while (0)
|
#define flush_insn_slot(p) do { } while (0)
|
||||||
#define kretprobe_blacklist_size 0
|
#define kretprobe_blacklist_size 0
|
||||||
|
|
|
@ -43,7 +43,7 @@ static void *image_load(struct kimage *image,
|
||||||
u64 flags, value;
|
u64 flags, value;
|
||||||
bool be_image, be_kernel;
|
bool be_image, be_kernel;
|
||||||
struct kexec_buf kbuf;
|
struct kexec_buf kbuf;
|
||||||
unsigned long text_offset;
|
unsigned long text_offset, kernel_segment_number;
|
||||||
struct kexec_segment *kernel_segment;
|
struct kexec_segment *kernel_segment;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -88,11 +88,37 @@ static void *image_load(struct kimage *image,
|
||||||
/* Adjust kernel segment with TEXT_OFFSET */
|
/* Adjust kernel segment with TEXT_OFFSET */
|
||||||
kbuf.memsz += text_offset;
|
kbuf.memsz += text_offset;
|
||||||
|
|
||||||
ret = kexec_add_buffer(&kbuf);
|
kernel_segment_number = image->nr_segments;
|
||||||
if (ret)
|
|
||||||
return ERR_PTR(ret);
|
|
||||||
|
|
||||||
kernel_segment = &image->segment[image->nr_segments - 1];
|
/*
|
||||||
|
* The location of the kernel segment may make it impossible to satisfy
|
||||||
|
* the other segment requirements, so we try repeatedly to find a
|
||||||
|
* location that will work.
|
||||||
|
*/
|
||||||
|
while ((ret = kexec_add_buffer(&kbuf)) == 0) {
|
||||||
|
/* Try to load additional data */
|
||||||
|
kernel_segment = &image->segment[kernel_segment_number];
|
||||||
|
ret = load_other_segments(image, kernel_segment->mem,
|
||||||
|
kernel_segment->memsz, initrd,
|
||||||
|
initrd_len, cmdline);
|
||||||
|
if (!ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We couldn't find space for the other segments; erase the
|
||||||
|
* kernel segment and try the next available hole.
|
||||||
|
*/
|
||||||
|
image->nr_segments -= 1;
|
||||||
|
kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
|
||||||
|
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
pr_err("Could not find any suitable kernel location!");
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_segment = &image->segment[kernel_segment_number];
|
||||||
kernel_segment->mem += text_offset;
|
kernel_segment->mem += text_offset;
|
||||||
kernel_segment->memsz -= text_offset;
|
kernel_segment->memsz -= text_offset;
|
||||||
image->start = kernel_segment->mem;
|
image->start = kernel_segment->mem;
|
||||||
|
@ -101,12 +127,7 @@ static void *image_load(struct kimage *image,
|
||||||
kernel_segment->mem, kbuf.bufsz,
|
kernel_segment->mem, kbuf.bufsz,
|
||||||
kernel_segment->memsz);
|
kernel_segment->memsz);
|
||||||
|
|
||||||
/* Load additional data */
|
return 0;
|
||||||
ret = load_other_segments(image,
|
|
||||||
kernel_segment->mem, kernel_segment->memsz,
|
|
||||||
initrd, initrd_len, cmdline);
|
|
||||||
|
|
||||||
return ERR_PTR(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KEXEC_IMAGE_VERIFY_SIG
|
#ifdef CONFIG_KEXEC_IMAGE_VERIFY_SIG
|
||||||
|
|
|
@ -240,6 +240,11 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tries to add the initrd and DTB to the image. If it is not possible to find
|
||||||
|
* valid locations, this function will undo changes to the image and return non
|
||||||
|
* zero.
|
||||||
|
*/
|
||||||
int load_other_segments(struct kimage *image,
|
int load_other_segments(struct kimage *image,
|
||||||
unsigned long kernel_load_addr,
|
unsigned long kernel_load_addr,
|
||||||
unsigned long kernel_size,
|
unsigned long kernel_size,
|
||||||
|
@ -248,7 +253,8 @@ int load_other_segments(struct kimage *image,
|
||||||
{
|
{
|
||||||
struct kexec_buf kbuf;
|
struct kexec_buf kbuf;
|
||||||
void *headers, *dtb = NULL;
|
void *headers, *dtb = NULL;
|
||||||
unsigned long headers_sz, initrd_load_addr = 0, dtb_len;
|
unsigned long headers_sz, initrd_load_addr = 0, dtb_len,
|
||||||
|
orig_segments = image->nr_segments;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
kbuf.image = image;
|
kbuf.image = image;
|
||||||
|
@ -334,6 +340,7 @@ int load_other_segments(struct kimage *image,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
|
image->nr_segments = orig_segments;
|
||||||
vfree(dtb);
|
vfree(dtb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,25 +36,16 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
|
||||||
static void __kprobes
|
static void __kprobes
|
||||||
post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *);
|
post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *);
|
||||||
|
|
||||||
static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opcode)
|
|
||||||
{
|
|
||||||
void *addrs[1];
|
|
||||||
u32 insns[1];
|
|
||||||
|
|
||||||
addrs[0] = addr;
|
|
||||||
insns[0] = opcode;
|
|
||||||
|
|
||||||
return aarch64_insn_patch_text(addrs, insns, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
|
static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
|
||||||
{
|
{
|
||||||
/* prepare insn slot */
|
kprobe_opcode_t *addr = p->ainsn.api.insn;
|
||||||
patch_text(p->ainsn.api.insn, p->opcode);
|
void *addrs[] = {addr, addr + 1};
|
||||||
|
u32 insns[] = {p->opcode, BRK64_OPCODE_KPROBES_SS};
|
||||||
|
|
||||||
flush_icache_range((uintptr_t) (p->ainsn.api.insn),
|
/* prepare insn slot */
|
||||||
(uintptr_t) (p->ainsn.api.insn) +
|
aarch64_insn_patch_text(addrs, insns, 2);
|
||||||
MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
|
|
||||||
|
flush_icache_range((uintptr_t)addr, (uintptr_t)(addr + MAX_INSN_SIZE));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Needs restoring of return address after stepping xol.
|
* Needs restoring of return address after stepping xol.
|
||||||
|
@ -128,13 +119,18 @@ void *alloc_insn_page(void)
|
||||||
/* arm kprobe: install breakpoint in text */
|
/* arm kprobe: install breakpoint in text */
|
||||||
void __kprobes arch_arm_kprobe(struct kprobe *p)
|
void __kprobes arch_arm_kprobe(struct kprobe *p)
|
||||||
{
|
{
|
||||||
patch_text(p->addr, BRK64_OPCODE_KPROBES);
|
void *addr = p->addr;
|
||||||
|
u32 insn = BRK64_OPCODE_KPROBES;
|
||||||
|
|
||||||
|
aarch64_insn_patch_text(&addr, &insn, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disarm kprobe: remove breakpoint from text */
|
/* disarm kprobe: remove breakpoint from text */
|
||||||
void __kprobes arch_disarm_kprobe(struct kprobe *p)
|
void __kprobes arch_disarm_kprobe(struct kprobe *p)
|
||||||
{
|
{
|
||||||
patch_text(p->addr, p->opcode);
|
void *addr = p->addr;
|
||||||
|
|
||||||
|
aarch64_insn_patch_text(&addr, &p->opcode, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __kprobes arch_remove_kprobe(struct kprobe *p)
|
void __kprobes arch_remove_kprobe(struct kprobe *p)
|
||||||
|
@ -163,20 +159,15 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interrupts need to be disabled before single-step mode is set, and not
|
* Mask all of DAIF while executing the instruction out-of-line, to keep things
|
||||||
* reenabled until after single-step mode ends.
|
* simple and avoid nesting exceptions. Interrupts do have to be disabled since
|
||||||
* Without disabling interrupt on local CPU, there is a chance of
|
* the kprobe state is per-CPU and doesn't get migrated.
|
||||||
* interrupt occurrence in the period of exception return and start of
|
|
||||||
* out-of-line single-step, that result in wrongly single stepping
|
|
||||||
* into the interrupt handler.
|
|
||||||
*/
|
*/
|
||||||
static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
|
static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
kcb->saved_irqflag = regs->pstate & DAIF_MASK;
|
kcb->saved_irqflag = regs->pstate & DAIF_MASK;
|
||||||
regs->pstate |= PSR_I_BIT;
|
regs->pstate |= DAIF_MASK;
|
||||||
/* Unmask PSTATE.D for enabling software step exceptions. */
|
|
||||||
regs->pstate &= ~PSR_D_BIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
|
static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
|
||||||
|
@ -219,10 +210,7 @@ static void __kprobes setup_singlestep(struct kprobe *p,
|
||||||
slot = (unsigned long)p->ainsn.api.insn;
|
slot = (unsigned long)p->ainsn.api.insn;
|
||||||
|
|
||||||
set_ss_context(kcb, slot); /* mark pending ss */
|
set_ss_context(kcb, slot); /* mark pending ss */
|
||||||
|
|
||||||
/* IRQs and single stepping do not mix well. */
|
|
||||||
kprobes_save_local_irqflag(kcb, regs);
|
kprobes_save_local_irqflag(kcb, regs);
|
||||||
kernel_enable_single_step(regs);
|
|
||||||
instruction_pointer_set(regs, slot);
|
instruction_pointer_set(regs, slot);
|
||||||
} else {
|
} else {
|
||||||
/* insn simulation */
|
/* insn simulation */
|
||||||
|
@ -273,12 +261,8 @@ post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
/* call post handler */
|
/* call post handler */
|
||||||
kcb->kprobe_status = KPROBE_HIT_SSDONE;
|
kcb->kprobe_status = KPROBE_HIT_SSDONE;
|
||||||
if (cur->post_handler) {
|
if (cur->post_handler)
|
||||||
/* post_handler can hit breakpoint and single step
|
|
||||||
* again, so we enable D-flag for recursive exception.
|
|
||||||
*/
|
|
||||||
cur->post_handler(cur, regs, 0);
|
cur->post_handler(cur, regs, 0);
|
||||||
}
|
|
||||||
|
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
}
|
}
|
||||||
|
@ -302,8 +286,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
|
||||||
if (!instruction_pointer(regs))
|
if (!instruction_pointer(regs))
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
kernel_disable_single_step();
|
|
||||||
|
|
||||||
if (kcb->kprobe_status == KPROBE_REENTER)
|
if (kcb->kprobe_status == KPROBE_REENTER)
|
||||||
restore_previous_kprobe(kcb);
|
restore_previous_kprobe(kcb);
|
||||||
else
|
else
|
||||||
|
@ -365,10 +347,6 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
|
||||||
* pre-handler and it returned non-zero, it will
|
* pre-handler and it returned non-zero, it will
|
||||||
* modify the execution path and no need to single
|
* modify the execution path and no need to single
|
||||||
* stepping. Let's just reset current kprobe and exit.
|
* stepping. Let's just reset current kprobe and exit.
|
||||||
*
|
|
||||||
* pre_handler can hit a breakpoint and can step thru
|
|
||||||
* before return, keep PSTATE D-flag enabled until
|
|
||||||
* pre_handler return back.
|
|
||||||
*/
|
*/
|
||||||
if (!p->pre_handler || !p->pre_handler(p, regs)) {
|
if (!p->pre_handler || !p->pre_handler(p, regs)) {
|
||||||
setup_singlestep(p, regs, kcb, 0);
|
setup_singlestep(p, regs, kcb, 0);
|
||||||
|
@ -399,7 +377,7 @@ kprobe_ss_hit(struct kprobe_ctlblk *kcb, unsigned long addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __kprobes
|
static int __kprobes
|
||||||
kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
|
kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr)
|
||||||
{
|
{
|
||||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -409,16 +387,15 @@ kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
|
||||||
|
|
||||||
if (retval == DBG_HOOK_HANDLED) {
|
if (retval == DBG_HOOK_HANDLED) {
|
||||||
kprobes_restore_local_irqflag(kcb, regs);
|
kprobes_restore_local_irqflag(kcb, regs);
|
||||||
kernel_disable_single_step();
|
|
||||||
|
|
||||||
post_kprobe_handler(kcb, regs);
|
post_kprobe_handler(kcb, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct step_hook kprobes_step_hook = {
|
static struct break_hook kprobes_break_ss_hook = {
|
||||||
.fn = kprobe_single_step_handler,
|
.imm = KPROBES_BRK_SS_IMM,
|
||||||
|
.fn = kprobe_breakpoint_ss_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __kprobes
|
static int __kprobes
|
||||||
|
@ -486,7 +463,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
|
||||||
int __init arch_init_kprobes(void)
|
int __init arch_init_kprobes(void)
|
||||||
{
|
{
|
||||||
register_kernel_break_hook(&kprobes_break_hook);
|
register_kernel_break_hook(&kprobes_break_hook);
|
||||||
register_kernel_step_hook(&kprobes_step_hook);
|
register_kernel_break_hook(&kprobes_break_ss_hook);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ static inline void restore_user_access(unsigned long flags)
|
||||||
static inline bool
|
static inline bool
|
||||||
bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
|
bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
|
||||||
{
|
{
|
||||||
return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000),
|
return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000),
|
||||||
"Bug: fault blocked by AP register !");
|
"Bug: fault blocked by AP register !");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,19 +33,18 @@
|
||||||
* respectively NA for All or X for Supervisor and no access for User.
|
* respectively NA for All or X for Supervisor and no access for User.
|
||||||
* Then we use the APG to say whether accesses are according to Page rules or
|
* Then we use the APG to say whether accesses are according to Page rules or
|
||||||
* "all Supervisor" rules (Access to all)
|
* "all Supervisor" rules (Access to all)
|
||||||
* Therefore, we define 2 APG groups. lsb is _PMD_USER
|
* _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say
|
||||||
* 0 => Kernel => 01 (all accesses performed according to page definition)
|
* "all User" rules, that will lead to NA for all.
|
||||||
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
|
* Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED
|
||||||
* 2-15 => Not Used
|
* 0 => Kernel => 11 (all accesses performed according as user iaw page definition)
|
||||||
|
* 1 => Kernel+Accessed => 01 (all accesses performed according to page definition)
|
||||||
|
* 2 => User => 11 (all accesses performed according as user iaw page definition)
|
||||||
|
* 3 => User+Accessed => 00 (all accesses performed as supervisor iaw page definition) for INIT
|
||||||
|
* => 10 (all accesses performed according to swaped page definition) for KUEP
|
||||||
|
* 4-15 => Not Used
|
||||||
*/
|
*/
|
||||||
#define MI_APG_INIT 0x40000000
|
#define MI_APG_INIT 0xdc000000
|
||||||
|
#define MI_APG_KUEP 0xde000000
|
||||||
/*
|
|
||||||
* 0 => Kernel => 01 (all accesses performed according to page definition)
|
|
||||||
* 1 => User => 10 (all accesses performed according to swaped page definition)
|
|
||||||
* 2-15 => Not Used
|
|
||||||
*/
|
|
||||||
#define MI_APG_KUEP 0x60000000
|
|
||||||
|
|
||||||
/* The effective page number register. When read, contains the information
|
/* The effective page number register. When read, contains the information
|
||||||
* about the last instruction TLB miss. When MI_RPN is written, bits in
|
* about the last instruction TLB miss. When MI_RPN is written, bits in
|
||||||
|
@ -106,25 +105,9 @@
|
||||||
#define MD_Ks 0x80000000 /* Should not be set */
|
#define MD_Ks 0x80000000 /* Should not be set */
|
||||||
#define MD_Kp 0x40000000 /* Should always be set */
|
#define MD_Kp 0x40000000 /* Should always be set */
|
||||||
|
|
||||||
/*
|
/* See explanation above at the definition of MI_APG_INIT */
|
||||||
* All pages' PP data bits are set to either 000 or 011 or 001, which means
|
#define MD_APG_INIT 0xdc000000
|
||||||
* respectively RW for Supervisor and no access for User, or RO for
|
#define MD_APG_KUAP 0xde000000
|
||||||
* Supervisor and no access for user and NA for ALL.
|
|
||||||
* Then we use the APG to say whether accesses are according to Page rules or
|
|
||||||
* "all Supervisor" rules (Access to all)
|
|
||||||
* Therefore, we define 2 APG groups. lsb is _PMD_USER
|
|
||||||
* 0 => Kernel => 01 (all accesses performed according to page definition)
|
|
||||||
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
|
|
||||||
* 2-15 => Not Used
|
|
||||||
*/
|
|
||||||
#define MD_APG_INIT 0x40000000
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 0 => No user => 01 (all accesses performed according to page definition)
|
|
||||||
* 1 => User => 10 (all accesses performed according to swaped page definition)
|
|
||||||
* 2-15 => Not Used
|
|
||||||
*/
|
|
||||||
#define MD_APG_KUAP 0x60000000
|
|
||||||
|
|
||||||
/* The effective page number register. When read, contains the information
|
/* The effective page number register. When read, contains the information
|
||||||
* about the last instruction TLB miss. When MD_RPN is written, bits in
|
* about the last instruction TLB miss. When MD_RPN is written, bits in
|
||||||
|
|
|
@ -39,9 +39,9 @@
|
||||||
* into the TLB.
|
* into the TLB.
|
||||||
*/
|
*/
|
||||||
#define _PAGE_GUARDED 0x0010 /* Copied to L1 G entry in DTLB */
|
#define _PAGE_GUARDED 0x0010 /* Copied to L1 G entry in DTLB */
|
||||||
#define _PAGE_SPECIAL 0x0020 /* SW entry */
|
#define _PAGE_ACCESSED 0x0020 /* Copied to L1 APG 1 entry in I/DTLB */
|
||||||
#define _PAGE_EXEC 0x0040 /* Copied to PP (bit 21) in ITLB */
|
#define _PAGE_EXEC 0x0040 /* Copied to PP (bit 21) in ITLB */
|
||||||
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
|
#define _PAGE_SPECIAL 0x0080 /* SW entry */
|
||||||
|
|
||||||
#define _PAGE_NA 0x0200 /* Supervisor NA, User no access */
|
#define _PAGE_NA 0x0200 /* Supervisor NA, User no access */
|
||||||
#define _PAGE_RO 0x0600 /* Supervisor RO, User no access */
|
#define _PAGE_RO 0x0600 /* Supervisor RO, User no access */
|
||||||
|
@ -59,11 +59,12 @@
|
||||||
|
|
||||||
#define _PMD_PRESENT 0x0001
|
#define _PMD_PRESENT 0x0001
|
||||||
#define _PMD_PRESENT_MASK _PMD_PRESENT
|
#define _PMD_PRESENT_MASK _PMD_PRESENT
|
||||||
#define _PMD_BAD 0x0fd0
|
#define _PMD_BAD 0x0f90
|
||||||
#define _PMD_PAGE_MASK 0x000c
|
#define _PMD_PAGE_MASK 0x000c
|
||||||
#define _PMD_PAGE_8M 0x000c
|
#define _PMD_PAGE_8M 0x000c
|
||||||
#define _PMD_PAGE_512K 0x0004
|
#define _PMD_PAGE_512K 0x0004
|
||||||
#define _PMD_USER 0x0020 /* APG 1 */
|
#define _PMD_ACCESSED 0x0020 /* APG 1 */
|
||||||
|
#define _PMD_USER 0x0040 /* APG 2 */
|
||||||
|
|
||||||
#define _PTE_NONE_MASK 0
|
#define _PTE_NONE_MASK 0
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
struct device_node;
|
struct device_node;
|
||||||
|
struct drmem_lmb;
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
|
|
||||||
|
@ -61,6 +62,9 @@ static inline int early_cpu_to_node(int cpu)
|
||||||
*/
|
*/
|
||||||
return (nid < 0) ? 0 : nid;
|
return (nid < 0) ? 0 : nid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int of_drconf_to_nid_single(struct drmem_lmb *lmb);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline int early_cpu_to_node(int cpu) { return 0; }
|
static inline int early_cpu_to_node(int cpu) { return 0; }
|
||||||
|
@ -84,10 +88,12 @@ static inline int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NUMA */
|
static inline int of_drconf_to_nid_single(struct drmem_lmb *lmb)
|
||||||
|
{
|
||||||
|
return first_online_node;
|
||||||
|
}
|
||||||
|
|
||||||
struct drmem_lmb;
|
#endif /* CONFIG_NUMA */
|
||||||
int of_drconf_to_nid_single(struct drmem_lmb *lmb);
|
|
||||||
|
|
||||||
#if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
|
#if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
|
||||||
extern int find_and_online_cpu_nid(int cpu);
|
extern int find_and_online_cpu_nid(int cpu);
|
||||||
|
|
|
@ -178,7 +178,7 @@ do { \
|
||||||
* are no aliasing issues.
|
* are no aliasing issues.
|
||||||
*/
|
*/
|
||||||
#define __put_user_asm_goto(x, addr, label, op) \
|
#define __put_user_asm_goto(x, addr, label, op) \
|
||||||
asm volatile goto( \
|
asm_volatile_goto( \
|
||||||
"1: " op "%U1%X1 %0,%1 # put_user\n" \
|
"1: " op "%U1%X1 %0,%1 # put_user\n" \
|
||||||
EX_TABLE(1b, %l2) \
|
EX_TABLE(1b, %l2) \
|
||||||
: \
|
: \
|
||||||
|
@ -191,7 +191,7 @@ do { \
|
||||||
__put_user_asm_goto(x, ptr, label, "std")
|
__put_user_asm_goto(x, ptr, label, "std")
|
||||||
#else /* __powerpc64__ */
|
#else /* __powerpc64__ */
|
||||||
#define __put_user_asm2_goto(x, addr, label) \
|
#define __put_user_asm2_goto(x, addr, label) \
|
||||||
asm volatile goto( \
|
asm_volatile_goto( \
|
||||||
"1: stw%X1 %0, %1\n" \
|
"1: stw%X1 %0, %1\n" \
|
||||||
"2: stw%X1 %L0, %L1\n" \
|
"2: stw%X1 %L0, %L1\n" \
|
||||||
EX_TABLE(1b, %l2) \
|
EX_TABLE(1b, %l2) \
|
||||||
|
|
|
@ -264,8 +264,9 @@ static int eeh_addr_cache_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct pci_io_addr_range *piar;
|
struct pci_io_addr_range *piar;
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock(&pci_io_addr_cache_root.piar_lock);
|
spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
|
||||||
for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) {
|
for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) {
|
||||||
piar = rb_entry(n, struct pci_io_addr_range, rb_node);
|
piar = rb_entry(n, struct pci_io_addr_range, rb_node);
|
||||||
|
|
||||||
|
@ -273,7 +274,7 @@ static int eeh_addr_cache_show(struct seq_file *s, void *v)
|
||||||
(piar->flags & IORESOURCE_IO) ? "i/o" : "mem",
|
(piar->flags & IORESOURCE_IO) ? "i/o" : "mem",
|
||||||
&piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
|
&piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
|
||||||
}
|
}
|
||||||
spin_unlock(&pci_io_addr_cache_root.piar_lock);
|
spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,11 +284,7 @@ _ENTRY(saved_ksp_limit)
|
||||||
|
|
||||||
rlwimi r11, r10, 22, 20, 29 /* Compute PTE address */
|
rlwimi r11, r10, 22, 20, 29 /* Compute PTE address */
|
||||||
lwz r11, 0(r11) /* Get Linux PTE */
|
lwz r11, 0(r11) /* Get Linux PTE */
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
li r9, _PAGE_PRESENT | _PAGE_ACCESSED
|
li r9, _PAGE_PRESENT | _PAGE_ACCESSED
|
||||||
#else
|
|
||||||
li r9, _PAGE_PRESENT
|
|
||||||
#endif
|
|
||||||
andc. r9, r9, r11 /* Check permission */
|
andc. r9, r9, r11 /* Check permission */
|
||||||
bne 5f
|
bne 5f
|
||||||
|
|
||||||
|
@ -369,11 +365,7 @@ _ENTRY(saved_ksp_limit)
|
||||||
|
|
||||||
rlwimi r11, r10, 22, 20, 29 /* Compute PTE address */
|
rlwimi r11, r10, 22, 20, 29 /* Compute PTE address */
|
||||||
lwz r11, 0(r11) /* Get Linux PTE */
|
lwz r11, 0(r11) /* Get Linux PTE */
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
li r9, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
|
li r9, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
|
||||||
#else
|
|
||||||
li r9, _PAGE_PRESENT | _PAGE_EXEC
|
|
||||||
#endif
|
|
||||||
andc. r9, r9, r11 /* Check permission */
|
andc. r9, r9, r11 /* Check permission */
|
||||||
bne 5f
|
bne 5f
|
||||||
|
|
||||||
|
|
|
@ -202,9 +202,7 @@ SystemCall:
|
||||||
|
|
||||||
InstructionTLBMiss:
|
InstructionTLBMiss:
|
||||||
mtspr SPRN_SPRG_SCRATCH0, r10
|
mtspr SPRN_SPRG_SCRATCH0, r10
|
||||||
#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
|
|
||||||
mtspr SPRN_SPRG_SCRATCH1, r11
|
mtspr SPRN_SPRG_SCRATCH1, r11
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we are faulting a kernel address, we have to use the
|
/* If we are faulting a kernel address, we have to use the
|
||||||
* kernel page tables.
|
* kernel page tables.
|
||||||
|
@ -224,25 +222,13 @@ InstructionTLBMiss:
|
||||||
3:
|
3:
|
||||||
mtcr r11
|
mtcr r11
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
|
|
||||||
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
|
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
|
||||||
mtspr SPRN_MD_TWC, r11
|
mtspr SPRN_MD_TWC, r11
|
||||||
#else
|
|
||||||
lwz r10, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
|
|
||||||
mtspr SPRN_MI_TWC, r10 /* Set segment attributes */
|
|
||||||
mtspr SPRN_MD_TWC, r10
|
|
||||||
#endif
|
|
||||||
mfspr r10, SPRN_MD_TWC
|
mfspr r10, SPRN_MD_TWC
|
||||||
lwz r10, 0(r10) /* Get the pte */
|
lwz r10, 0(r10) /* Get the pte */
|
||||||
#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
|
rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
|
||||||
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
|
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
|
||||||
mtspr SPRN_MI_TWC, r11
|
mtspr SPRN_MI_TWC, r11
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
rlwinm r11, r10, 32-5, _PAGE_PRESENT
|
|
||||||
and r11, r11, r10
|
|
||||||
rlwimi r10, r11, 0, _PAGE_PRESENT
|
|
||||||
#endif
|
|
||||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||||
* Software indicator bits 20 and 23 must be clear.
|
* Software indicator bits 20 and 23 must be clear.
|
||||||
* Software indicator bits 22, 24, 25, 26, and 27 must be
|
* Software indicator bits 22, 24, 25, 26, and 27 must be
|
||||||
|
@ -256,9 +242,7 @@ InstructionTLBMiss:
|
||||||
|
|
||||||
/* Restore registers */
|
/* Restore registers */
|
||||||
0: mfspr r10, SPRN_SPRG_SCRATCH0
|
0: mfspr r10, SPRN_SPRG_SCRATCH0
|
||||||
#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
|
|
||||||
mfspr r11, SPRN_SPRG_SCRATCH1
|
mfspr r11, SPRN_SPRG_SCRATCH1
|
||||||
#endif
|
|
||||||
rfi
|
rfi
|
||||||
patch_site 0b, patch__itlbmiss_exit_1
|
patch_site 0b, patch__itlbmiss_exit_1
|
||||||
|
|
||||||
|
@ -268,9 +252,7 @@ InstructionTLBMiss:
|
||||||
addi r10, r10, 1
|
addi r10, r10, 1
|
||||||
stw r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
|
stw r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
|
||||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||||
#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
|
|
||||||
mfspr r11, SPRN_SPRG_SCRATCH1
|
mfspr r11, SPRN_SPRG_SCRATCH1
|
||||||
#endif
|
|
||||||
rfi
|
rfi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -297,30 +279,16 @@ DataStoreTLBMiss:
|
||||||
mfspr r10, SPRN_MD_TWC
|
mfspr r10, SPRN_MD_TWC
|
||||||
lwz r10, 0(r10) /* Get the pte */
|
lwz r10, 0(r10) /* Get the pte */
|
||||||
|
|
||||||
/* Insert the Guarded flag into the TWC from the Linux PTE.
|
/* Insert Guarded and Accessed flags into the TWC from the Linux PTE.
|
||||||
* It is bit 27 of both the Linux PTE and the TWC (at least
|
* It is bit 27 of both the Linux PTE and the TWC (at least
|
||||||
* I got that right :-). It will be better when we can put
|
* I got that right :-). It will be better when we can put
|
||||||
* this into the Linux pgd/pmd and load it in the operation
|
* this into the Linux pgd/pmd and load it in the operation
|
||||||
* above.
|
* above.
|
||||||
*/
|
*/
|
||||||
rlwimi r11, r10, 0, _PAGE_GUARDED
|
rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
|
||||||
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
|
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
|
||||||
mtspr SPRN_MD_TWC, r11
|
mtspr SPRN_MD_TWC, r11
|
||||||
|
|
||||||
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
|
|
||||||
* We also need to know if the insn is a load/store, so:
|
|
||||||
* Clear _PAGE_PRESENT and load that which will
|
|
||||||
* trap into DTLB Error with store bit set accordinly.
|
|
||||||
*/
|
|
||||||
/* PRESENT=0x1, ACCESSED=0x20
|
|
||||||
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
|
|
||||||
* r10 = (r10 & ~PRESENT) | r11;
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
rlwinm r11, r10, 32-5, _PAGE_PRESENT
|
|
||||||
and r11, r11, r10
|
|
||||||
rlwimi r10, r11, 0, _PAGE_PRESENT
|
|
||||||
#endif
|
|
||||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||||
* Software indicator bits 24, 25, 26, and 27 must be
|
* Software indicator bits 24, 25, 26, and 27 must be
|
||||||
* set. All other Linux PTE bits control the behavior
|
* set. All other Linux PTE bits control the behavior
|
||||||
|
@ -711,7 +679,7 @@ initial_mmu:
|
||||||
li r9, 4 /* up to 4 pages of 8M */
|
li r9, 4 /* up to 4 pages of 8M */
|
||||||
mtctr r9
|
mtctr r9
|
||||||
lis r9, KERNELBASE@h /* Create vaddr for TLB */
|
lis r9, KERNELBASE@h /* Create vaddr for TLB */
|
||||||
li r10, MI_PS8MEG | MI_SVALID /* Set 8M byte page */
|
li r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
|
||||||
li r11, MI_BOOTINIT /* Create RPN for address 0 */
|
li r11, MI_BOOTINIT /* Create RPN for address 0 */
|
||||||
1:
|
1:
|
||||||
mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
|
mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
|
||||||
|
@ -775,7 +743,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||||
#ifdef CONFIG_PIN_TLB_TEXT
|
#ifdef CONFIG_PIN_TLB_TEXT
|
||||||
LOAD_REG_IMMEDIATE(r5, 28 << 8)
|
LOAD_REG_IMMEDIATE(r5, 28 << 8)
|
||||||
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
||||||
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
|
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
|
||||||
LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
|
LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
|
||||||
LOAD_REG_ADDR(r9, _sinittext)
|
LOAD_REG_ADDR(r9, _sinittext)
|
||||||
li r0, 4
|
li r0, 4
|
||||||
|
@ -797,7 +765,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||||
LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
|
LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
|
||||||
#ifdef CONFIG_PIN_TLB_DATA
|
#ifdef CONFIG_PIN_TLB_DATA
|
||||||
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
||||||
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
|
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
|
||||||
#ifdef CONFIG_PIN_TLB_IMMR
|
#ifdef CONFIG_PIN_TLB_IMMR
|
||||||
li r0, 3
|
li r0, 3
|
||||||
#else
|
#else
|
||||||
|
@ -834,7 +802,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PIN_TLB_IMMR
|
#ifdef CONFIG_PIN_TLB_IMMR
|
||||||
LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
|
LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
|
||||||
LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED)
|
LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
|
||||||
mfspr r8, SPRN_IMMR
|
mfspr r8, SPRN_IMMR
|
||||||
rlwinm r8, r8, 0, 0xfff80000
|
rlwinm r8, r8, 0, 0xfff80000
|
||||||
ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
|
ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
|
||||||
|
|
|
@ -457,11 +457,7 @@ InstructionTLBMiss:
|
||||||
cmplw 0,r1,r3
|
cmplw 0,r1,r3
|
||||||
#endif
|
#endif
|
||||||
mfspr r2, SPRN_SPRG_PGDIR
|
mfspr r2, SPRN_SPRG_PGDIR
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
|
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
|
||||||
#else
|
|
||||||
li r1,_PAGE_PRESENT | _PAGE_EXEC
|
|
||||||
#endif
|
|
||||||
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
|
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
|
||||||
bgt- 112f
|
bgt- 112f
|
||||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||||
|
@ -523,11 +519,7 @@ DataLoadTLBMiss:
|
||||||
lis r1, TASK_SIZE@h /* check if kernel address */
|
lis r1, TASK_SIZE@h /* check if kernel address */
|
||||||
cmplw 0,r1,r3
|
cmplw 0,r1,r3
|
||||||
mfspr r2, SPRN_SPRG_PGDIR
|
mfspr r2, SPRN_SPRG_PGDIR
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
li r1, _PAGE_PRESENT | _PAGE_ACCESSED
|
li r1, _PAGE_PRESENT | _PAGE_ACCESSED
|
||||||
#else
|
|
||||||
li r1, _PAGE_PRESENT
|
|
||||||
#endif
|
|
||||||
bgt- 112f
|
bgt- 112f
|
||||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||||
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
||||||
|
@ -603,11 +595,7 @@ DataStoreTLBMiss:
|
||||||
lis r1, TASK_SIZE@h /* check if kernel address */
|
lis r1, TASK_SIZE@h /* check if kernel address */
|
||||||
cmplw 0,r1,r3
|
cmplw 0,r1,r3
|
||||||
mfspr r2, SPRN_SPRG_PGDIR
|
mfspr r2, SPRN_SPRG_PGDIR
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
|
li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
|
||||||
#else
|
|
||||||
li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT
|
|
||||||
#endif
|
|
||||||
bgt- 112f
|
bgt- 112f
|
||||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||||
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
||||||
|
|
|
@ -1393,13 +1393,14 @@ static void add_cpu_to_masks(int cpu)
|
||||||
/* Activate a secondary processor. */
|
/* Activate a secondary processor. */
|
||||||
void start_secondary(void *unused)
|
void start_secondary(void *unused)
|
||||||
{
|
{
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = raw_smp_processor_id();
|
||||||
|
|
||||||
mmgrab(&init_mm);
|
mmgrab(&init_mm);
|
||||||
current->active_mm = &init_mm;
|
current->active_mm = &init_mm;
|
||||||
|
|
||||||
smp_store_cpu_info(cpu);
|
smp_store_cpu_info(cpu);
|
||||||
set_dec(tb_ticks_per_jiffy);
|
set_dec(tb_ticks_per_jiffy);
|
||||||
|
rcu_cpu_starting(cpu);
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
cpu_callin_map[cpu] = 1;
|
cpu_callin_map[cpu] = 1;
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,7 @@ do { \
|
||||||
do { \
|
do { \
|
||||||
long __kr_err; \
|
long __kr_err; \
|
||||||
\
|
\
|
||||||
__put_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \
|
__put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err); \
|
||||||
if (unlikely(__kr_err)) \
|
if (unlikely(__kr_err)) \
|
||||||
goto err_label; \
|
goto err_label; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Linaro Limited
|
* Copyright (C) 2013 Linaro Limited
|
||||||
* Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
* Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
||||||
|
|
|
@ -35,12 +35,17 @@ ENTRY(_start)
|
||||||
.word 0
|
.word 0
|
||||||
#endif
|
#endif
|
||||||
.balign 8
|
.balign 8
|
||||||
|
#ifdef CONFIG_RISCV_M_MODE
|
||||||
|
/* Image load offset (0MB) from start of RAM for M-mode */
|
||||||
|
.dword 0
|
||||||
|
#else
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
/* Image load offset(2MB) from start of RAM */
|
/* Image load offset(2MB) from start of RAM */
|
||||||
.dword 0x200000
|
.dword 0x200000
|
||||||
#else
|
#else
|
||||||
/* Image load offset(4MB) from start of RAM */
|
/* Image load offset(4MB) from start of RAM */
|
||||||
.dword 0x400000
|
.dword 0x400000
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
/* Effective size of kernel image */
|
/* Effective size of kernel image */
|
||||||
.dword _end - _start
|
.dword _end - _start
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
vdso.lds
|
vdso.lds
|
||||||
*.tmp
|
*.tmp
|
||||||
|
vdso-syms.S
|
||||||
|
|
|
@ -43,19 +43,14 @@ $(obj)/vdso.o: $(obj)/vdso.so
|
||||||
SYSCFLAGS_vdso.so.dbg = $(c_flags)
|
SYSCFLAGS_vdso.so.dbg = $(c_flags)
|
||||||
$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
|
$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
|
||||||
$(call if_changed,vdsold)
|
$(call if_changed,vdsold)
|
||||||
|
SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
|
||||||
|
-Wl,--build-id -Wl,--hash-style=both
|
||||||
|
|
||||||
# We also create a special relocatable object that should mirror the symbol
|
# We also create a special relocatable object that should mirror the symbol
|
||||||
# table and layout of the linked DSO. With ld --just-symbols we can then
|
# table and layout of the linked DSO. With ld --just-symbols we can then
|
||||||
# refer to these symbols in the kernel code rather than hand-coded addresses.
|
# refer to these symbols in the kernel code rather than hand-coded addresses.
|
||||||
|
$(obj)/vdso-syms.S: $(obj)/vdso.so FORCE
|
||||||
SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
|
$(call if_changed,so2s)
|
||||||
-Wl,--build-id=sha1 -Wl,--hash-style=both
|
|
||||||
$(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE
|
|
||||||
$(call if_changed,vdsold)
|
|
||||||
|
|
||||||
LDFLAGS_vdso-syms.o := -r --just-symbols
|
|
||||||
$(obj)/vdso-syms.o: $(obj)/vdso-dummy.o FORCE
|
|
||||||
$(call if_changed,ld)
|
|
||||||
|
|
||||||
# strip rule for the .so file
|
# strip rule for the .so file
|
||||||
$(obj)/%.so: OBJCOPYFLAGS := -S
|
$(obj)/%.so: OBJCOPYFLAGS := -S
|
||||||
|
@ -73,6 +68,11 @@ quiet_cmd_vdsold = VDSOLD $@
|
||||||
$(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
|
$(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
|
||||||
rm $@.tmp
|
rm $@.tmp
|
||||||
|
|
||||||
|
# Extracts symbol offsets from the VDSO, converting them into an assembly file
|
||||||
|
# that contains the same symbols at the same offsets.
|
||||||
|
quiet_cmd_so2s = SO2S $@
|
||||||
|
cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
|
||||||
|
|
||||||
# install commands for the unstripped file
|
# install commands for the unstripped file
|
||||||
quiet_cmd_vdso_install = INSTALL $@
|
quiet_cmd_vdso_install = INSTALL $@
|
||||||
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
|
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
# Copyright 2020 Palmer Dabbelt <palmerdabbelt@google.com>
|
||||||
|
|
||||||
|
sed 's!\([0-9a-f]*\) T \([a-z0-9_]*\)\(@@LINUX_4.15\)*!.global \2\n.set \2,0x\1!' \
|
||||||
|
| grep '^\.'
|
|
@ -86,6 +86,7 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
|
||||||
pmd_t *pmd, *pmd_k;
|
pmd_t *pmd, *pmd_k;
|
||||||
pte_t *pte_k;
|
pte_t *pte_k;
|
||||||
int index;
|
int index;
|
||||||
|
unsigned long pfn;
|
||||||
|
|
||||||
/* User mode accesses just cause a SIGSEGV */
|
/* User mode accesses just cause a SIGSEGV */
|
||||||
if (user_mode(regs))
|
if (user_mode(regs))
|
||||||
|
@ -100,7 +101,8 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
|
||||||
* of a task switch.
|
* of a task switch.
|
||||||
*/
|
*/
|
||||||
index = pgd_index(addr);
|
index = pgd_index(addr);
|
||||||
pgd = (pgd_t *)pfn_to_virt(csr_read(CSR_SATP)) + index;
|
pfn = csr_read(CSR_SATP) & SATP_PPN;
|
||||||
|
pgd = (pgd_t *)pfn_to_virt(pfn) + index;
|
||||||
pgd_k = init_mm.pgd + index;
|
pgd_k = init_mm.pgd + index;
|
||||||
|
|
||||||
if (!pgd_present(*pgd_k)) {
|
if (!pgd_present(*pgd_k)) {
|
||||||
|
|
|
@ -154,9 +154,8 @@ disable:
|
||||||
|
|
||||||
void __init setup_bootmem(void)
|
void __init setup_bootmem(void)
|
||||||
{
|
{
|
||||||
phys_addr_t mem_size = 0;
|
phys_addr_t mem_start = 0;
|
||||||
phys_addr_t total_mem = 0;
|
phys_addr_t start, end = 0;
|
||||||
phys_addr_t mem_start, start, end = 0;
|
|
||||||
phys_addr_t vmlinux_end = __pa_symbol(&_end);
|
phys_addr_t vmlinux_end = __pa_symbol(&_end);
|
||||||
phys_addr_t vmlinux_start = __pa_symbol(&_start);
|
phys_addr_t vmlinux_start = __pa_symbol(&_start);
|
||||||
u64 i;
|
u64 i;
|
||||||
|
@ -164,21 +163,18 @@ void __init setup_bootmem(void)
|
||||||
/* Find the memory region containing the kernel */
|
/* Find the memory region containing the kernel */
|
||||||
for_each_mem_range(i, &start, &end) {
|
for_each_mem_range(i, &start, &end) {
|
||||||
phys_addr_t size = end - start;
|
phys_addr_t size = end - start;
|
||||||
if (!total_mem)
|
if (!mem_start)
|
||||||
mem_start = start;
|
mem_start = start;
|
||||||
if (start <= vmlinux_start && vmlinux_end <= end)
|
if (start <= vmlinux_start && vmlinux_end <= end)
|
||||||
BUG_ON(size == 0);
|
BUG_ON(size == 0);
|
||||||
total_mem = total_mem + size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove memblock from the end of usable area to the
|
* The maximal physical memory size is -PAGE_OFFSET.
|
||||||
* end of region
|
* Make sure that any memory beyond mem_start + (-PAGE_OFFSET) is removed
|
||||||
|
* as it is unusable by kernel.
|
||||||
*/
|
*/
|
||||||
mem_size = min(total_mem, (phys_addr_t)-PAGE_OFFSET);
|
memblock_enforce_memory_limit(mem_start - PAGE_OFFSET);
|
||||||
if (mem_start + mem_size < end)
|
|
||||||
memblock_remove(mem_start + mem_size,
|
|
||||||
end - mem_start - mem_size);
|
|
||||||
|
|
||||||
/* Reserve from the start of the kernel to the end of the kernel */
|
/* Reserve from the start of the kernel to the end of the kernel */
|
||||||
memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
|
memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
|
||||||
|
@ -297,6 +293,7 @@ pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||||
#define NUM_EARLY_PMDS (1UL + MAX_EARLY_MAPPING_SIZE / PGDIR_SIZE)
|
#define NUM_EARLY_PMDS (1UL + MAX_EARLY_MAPPING_SIZE / PGDIR_SIZE)
|
||||||
#endif
|
#endif
|
||||||
pmd_t early_pmd[PTRS_PER_PMD * NUM_EARLY_PMDS] __initdata __aligned(PAGE_SIZE);
|
pmd_t early_pmd[PTRS_PER_PMD * NUM_EARLY_PMDS] __initdata __aligned(PAGE_SIZE);
|
||||||
|
pmd_t early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
|
||||||
|
|
||||||
static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
|
static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
|
||||||
{
|
{
|
||||||
|
@ -494,6 +491,18 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||||
load_pa + (va - PAGE_OFFSET),
|
load_pa + (va - PAGE_OFFSET),
|
||||||
map_size, PAGE_KERNEL_EXEC);
|
map_size, PAGE_KERNEL_EXEC);
|
||||||
|
|
||||||
|
#ifndef __PAGETABLE_PMD_FOLDED
|
||||||
|
/* Setup early PMD for DTB */
|
||||||
|
create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
|
||||||
|
(uintptr_t)early_dtb_pmd, PGDIR_SIZE, PAGE_TABLE);
|
||||||
|
/* Create two consecutive PMD mappings for FDT early scan */
|
||||||
|
pa = dtb_pa & ~(PMD_SIZE - 1);
|
||||||
|
create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA,
|
||||||
|
pa, PMD_SIZE, PAGE_KERNEL);
|
||||||
|
create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE,
|
||||||
|
pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
|
||||||
|
dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1));
|
||||||
|
#else
|
||||||
/* Create two consecutive PGD mappings for FDT early scan */
|
/* Create two consecutive PGD mappings for FDT early scan */
|
||||||
pa = dtb_pa & ~(PGDIR_SIZE - 1);
|
pa = dtb_pa & ~(PGDIR_SIZE - 1);
|
||||||
create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
|
create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
|
||||||
|
@ -501,6 +510,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||||
create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE,
|
create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE,
|
||||||
pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL);
|
pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL);
|
||||||
dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1));
|
dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1));
|
||||||
|
#endif
|
||||||
dtb_early_pa = dtb_pa;
|
dtb_early_pa = dtb_pa;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -93,9 +93,10 @@ CONFIG_CLEANCACHE=y
|
||||||
CONFIG_FRONTSWAP=y
|
CONFIG_FRONTSWAP=y
|
||||||
CONFIG_CMA_DEBUG=y
|
CONFIG_CMA_DEBUG=y
|
||||||
CONFIG_CMA_DEBUGFS=y
|
CONFIG_CMA_DEBUGFS=y
|
||||||
|
CONFIG_CMA_AREAS=7
|
||||||
CONFIG_MEM_SOFT_DIRTY=y
|
CONFIG_MEM_SOFT_DIRTY=y
|
||||||
CONFIG_ZSWAP=y
|
CONFIG_ZSWAP=y
|
||||||
CONFIG_ZSMALLOC=m
|
CONFIG_ZSMALLOC=y
|
||||||
CONFIG_ZSMALLOC_STAT=y
|
CONFIG_ZSMALLOC_STAT=y
|
||||||
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
||||||
CONFIG_IDLE_PAGE_TRACKING=y
|
CONFIG_IDLE_PAGE_TRACKING=y
|
||||||
|
@ -378,7 +379,6 @@ CONFIG_NETLINK_DIAG=m
|
||||||
CONFIG_CGROUP_NET_PRIO=y
|
CONFIG_CGROUP_NET_PRIO=y
|
||||||
CONFIG_BPF_JIT=y
|
CONFIG_BPF_JIT=y
|
||||||
CONFIG_NET_PKTGEN=m
|
CONFIG_NET_PKTGEN=m
|
||||||
# CONFIG_NET_DROP_MONITOR is not set
|
|
||||||
CONFIG_PCI=y
|
CONFIG_PCI=y
|
||||||
# CONFIG_PCIEASPM is not set
|
# CONFIG_PCIEASPM is not set
|
||||||
CONFIG_PCI_DEBUG=y
|
CONFIG_PCI_DEBUG=y
|
||||||
|
@ -386,7 +386,7 @@ CONFIG_HOTPLUG_PCI=y
|
||||||
CONFIG_HOTPLUG_PCI_S390=y
|
CONFIG_HOTPLUG_PCI_S390=y
|
||||||
CONFIG_DEVTMPFS=y
|
CONFIG_DEVTMPFS=y
|
||||||
CONFIG_CONNECTOR=y
|
CONFIG_CONNECTOR=y
|
||||||
CONFIG_ZRAM=m
|
CONFIG_ZRAM=y
|
||||||
CONFIG_BLK_DEV_LOOP=m
|
CONFIG_BLK_DEV_LOOP=m
|
||||||
CONFIG_BLK_DEV_CRYPTOLOOP=m
|
CONFIG_BLK_DEV_CRYPTOLOOP=m
|
||||||
CONFIG_BLK_DEV_DRBD=m
|
CONFIG_BLK_DEV_DRBD=m
|
||||||
|
@ -689,6 +689,7 @@ CONFIG_CRYPTO_TEST=m
|
||||||
CONFIG_CRYPTO_DH=m
|
CONFIG_CRYPTO_DH=m
|
||||||
CONFIG_CRYPTO_ECDH=m
|
CONFIG_CRYPTO_ECDH=m
|
||||||
CONFIG_CRYPTO_ECRDSA=m
|
CONFIG_CRYPTO_ECRDSA=m
|
||||||
|
CONFIG_CRYPTO_SM2=m
|
||||||
CONFIG_CRYPTO_CURVE25519=m
|
CONFIG_CRYPTO_CURVE25519=m
|
||||||
CONFIG_CRYPTO_GCM=y
|
CONFIG_CRYPTO_GCM=y
|
||||||
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
||||||
|
@ -709,7 +710,6 @@ CONFIG_CRYPTO_RMD160=m
|
||||||
CONFIG_CRYPTO_RMD256=m
|
CONFIG_CRYPTO_RMD256=m
|
||||||
CONFIG_CRYPTO_RMD320=m
|
CONFIG_CRYPTO_RMD320=m
|
||||||
CONFIG_CRYPTO_SHA3=m
|
CONFIG_CRYPTO_SHA3=m
|
||||||
CONFIG_CRYPTO_SM3=m
|
|
||||||
CONFIG_CRYPTO_TGR192=m
|
CONFIG_CRYPTO_TGR192=m
|
||||||
CONFIG_CRYPTO_WP512=m
|
CONFIG_CRYPTO_WP512=m
|
||||||
CONFIG_CRYPTO_AES_TI=m
|
CONFIG_CRYPTO_AES_TI=m
|
||||||
|
@ -753,6 +753,7 @@ CONFIG_CRYPTO_DES_S390=m
|
||||||
CONFIG_CRYPTO_AES_S390=m
|
CONFIG_CRYPTO_AES_S390=m
|
||||||
CONFIG_CRYPTO_GHASH_S390=m
|
CONFIG_CRYPTO_GHASH_S390=m
|
||||||
CONFIG_CRYPTO_CRC32_S390=y
|
CONFIG_CRYPTO_CRC32_S390=y
|
||||||
|
CONFIG_CRYPTO_DEV_VIRTIO=m
|
||||||
CONFIG_CORDIC=m
|
CONFIG_CORDIC=m
|
||||||
CONFIG_CRC32_SELFTEST=y
|
CONFIG_CRC32_SELFTEST=y
|
||||||
CONFIG_CRC4=m
|
CONFIG_CRC4=m
|
||||||
|
@ -829,6 +830,7 @@ CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
|
||||||
CONFIG_FAULT_INJECTION=y
|
CONFIG_FAULT_INJECTION=y
|
||||||
CONFIG_FAILSLAB=y
|
CONFIG_FAILSLAB=y
|
||||||
CONFIG_FAIL_PAGE_ALLOC=y
|
CONFIG_FAIL_PAGE_ALLOC=y
|
||||||
|
CONFIG_FAULT_INJECTION_USERCOPY=y
|
||||||
CONFIG_FAIL_MAKE_REQUEST=y
|
CONFIG_FAIL_MAKE_REQUEST=y
|
||||||
CONFIG_FAIL_IO_TIMEOUT=y
|
CONFIG_FAIL_IO_TIMEOUT=y
|
||||||
CONFIG_FAIL_FUTEX=y
|
CONFIG_FAIL_FUTEX=y
|
||||||
|
|
|
@ -87,9 +87,10 @@ CONFIG_KSM=y
|
||||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||||
CONFIG_CLEANCACHE=y
|
CONFIG_CLEANCACHE=y
|
||||||
CONFIG_FRONTSWAP=y
|
CONFIG_FRONTSWAP=y
|
||||||
|
CONFIG_CMA_AREAS=7
|
||||||
CONFIG_MEM_SOFT_DIRTY=y
|
CONFIG_MEM_SOFT_DIRTY=y
|
||||||
CONFIG_ZSWAP=y
|
CONFIG_ZSWAP=y
|
||||||
CONFIG_ZSMALLOC=m
|
CONFIG_ZSMALLOC=y
|
||||||
CONFIG_ZSMALLOC_STAT=y
|
CONFIG_ZSMALLOC_STAT=y
|
||||||
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
||||||
CONFIG_IDLE_PAGE_TRACKING=y
|
CONFIG_IDLE_PAGE_TRACKING=y
|
||||||
|
@ -371,7 +372,6 @@ CONFIG_NETLINK_DIAG=m
|
||||||
CONFIG_CGROUP_NET_PRIO=y
|
CONFIG_CGROUP_NET_PRIO=y
|
||||||
CONFIG_BPF_JIT=y
|
CONFIG_BPF_JIT=y
|
||||||
CONFIG_NET_PKTGEN=m
|
CONFIG_NET_PKTGEN=m
|
||||||
# CONFIG_NET_DROP_MONITOR is not set
|
|
||||||
CONFIG_PCI=y
|
CONFIG_PCI=y
|
||||||
# CONFIG_PCIEASPM is not set
|
# CONFIG_PCIEASPM is not set
|
||||||
CONFIG_HOTPLUG_PCI=y
|
CONFIG_HOTPLUG_PCI=y
|
||||||
|
@ -379,7 +379,7 @@ CONFIG_HOTPLUG_PCI_S390=y
|
||||||
CONFIG_UEVENT_HELPER=y
|
CONFIG_UEVENT_HELPER=y
|
||||||
CONFIG_DEVTMPFS=y
|
CONFIG_DEVTMPFS=y
|
||||||
CONFIG_CONNECTOR=y
|
CONFIG_CONNECTOR=y
|
||||||
CONFIG_ZRAM=m
|
CONFIG_ZRAM=y
|
||||||
CONFIG_BLK_DEV_LOOP=m
|
CONFIG_BLK_DEV_LOOP=m
|
||||||
CONFIG_BLK_DEV_CRYPTOLOOP=m
|
CONFIG_BLK_DEV_CRYPTOLOOP=m
|
||||||
CONFIG_BLK_DEV_DRBD=m
|
CONFIG_BLK_DEV_DRBD=m
|
||||||
|
@ -680,6 +680,7 @@ CONFIG_CRYPTO_TEST=m
|
||||||
CONFIG_CRYPTO_DH=m
|
CONFIG_CRYPTO_DH=m
|
||||||
CONFIG_CRYPTO_ECDH=m
|
CONFIG_CRYPTO_ECDH=m
|
||||||
CONFIG_CRYPTO_ECRDSA=m
|
CONFIG_CRYPTO_ECRDSA=m
|
||||||
|
CONFIG_CRYPTO_SM2=m
|
||||||
CONFIG_CRYPTO_CURVE25519=m
|
CONFIG_CRYPTO_CURVE25519=m
|
||||||
CONFIG_CRYPTO_GCM=y
|
CONFIG_CRYPTO_GCM=y
|
||||||
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
||||||
|
@ -701,7 +702,6 @@ CONFIG_CRYPTO_RMD160=m
|
||||||
CONFIG_CRYPTO_RMD256=m
|
CONFIG_CRYPTO_RMD256=m
|
||||||
CONFIG_CRYPTO_RMD320=m
|
CONFIG_CRYPTO_RMD320=m
|
||||||
CONFIG_CRYPTO_SHA3=m
|
CONFIG_CRYPTO_SHA3=m
|
||||||
CONFIG_CRYPTO_SM3=m
|
|
||||||
CONFIG_CRYPTO_TGR192=m
|
CONFIG_CRYPTO_TGR192=m
|
||||||
CONFIG_CRYPTO_WP512=m
|
CONFIG_CRYPTO_WP512=m
|
||||||
CONFIG_CRYPTO_AES_TI=m
|
CONFIG_CRYPTO_AES_TI=m
|
||||||
|
@ -745,6 +745,7 @@ CONFIG_CRYPTO_DES_S390=m
|
||||||
CONFIG_CRYPTO_AES_S390=m
|
CONFIG_CRYPTO_AES_S390=m
|
||||||
CONFIG_CRYPTO_GHASH_S390=m
|
CONFIG_CRYPTO_GHASH_S390=m
|
||||||
CONFIG_CRYPTO_CRC32_S390=y
|
CONFIG_CRYPTO_CRC32_S390=y
|
||||||
|
CONFIG_CRYPTO_DEV_VIRTIO=m
|
||||||
CONFIG_CORDIC=m
|
CONFIG_CORDIC=m
|
||||||
CONFIG_PRIME_NUMBERS=m
|
CONFIG_PRIME_NUMBERS=m
|
||||||
CONFIG_CRC4=m
|
CONFIG_CRC4=m
|
||||||
|
|
|
@ -17,11 +17,11 @@ CONFIG_HZ_100=y
|
||||||
# CONFIG_CHSC_SCH is not set
|
# CONFIG_CHSC_SCH is not set
|
||||||
# CONFIG_SCM_BUS is not set
|
# CONFIG_SCM_BUS is not set
|
||||||
CONFIG_CRASH_DUMP=y
|
CONFIG_CRASH_DUMP=y
|
||||||
# CONFIG_SECCOMP is not set
|
|
||||||
# CONFIG_PFAULT is not set
|
# CONFIG_PFAULT is not set
|
||||||
# CONFIG_S390_HYPFS_FS is not set
|
# CONFIG_S390_HYPFS_FS is not set
|
||||||
# CONFIG_VIRTUALIZATION is not set
|
# CONFIG_VIRTUALIZATION is not set
|
||||||
# CONFIG_S390_GUEST is not set
|
# CONFIG_S390_GUEST is not set
|
||||||
|
# CONFIG_SECCOMP is not set
|
||||||
CONFIG_PARTITION_ADVANCED=y
|
CONFIG_PARTITION_ADVANCED=y
|
||||||
CONFIG_IBM_PARTITION=y
|
CONFIG_IBM_PARTITION=y
|
||||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||||
|
|
|
@ -692,16 +692,6 @@ static inline int pud_large(pud_t pud)
|
||||||
return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
|
return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long pud_pfn(pud_t pud)
|
|
||||||
{
|
|
||||||
unsigned long origin_mask;
|
|
||||||
|
|
||||||
origin_mask = _REGION_ENTRY_ORIGIN;
|
|
||||||
if (pud_large(pud))
|
|
||||||
origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
|
|
||||||
return (pud_val(pud) & origin_mask) >> PAGE_SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define pmd_leaf pmd_large
|
#define pmd_leaf pmd_large
|
||||||
static inline int pmd_large(pmd_t pmd)
|
static inline int pmd_large(pmd_t pmd)
|
||||||
{
|
{
|
||||||
|
@ -747,16 +737,6 @@ static inline int pmd_none(pmd_t pmd)
|
||||||
return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY;
|
return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long pmd_pfn(pmd_t pmd)
|
|
||||||
{
|
|
||||||
unsigned long origin_mask;
|
|
||||||
|
|
||||||
origin_mask = _SEGMENT_ENTRY_ORIGIN;
|
|
||||||
if (pmd_large(pmd))
|
|
||||||
origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
|
|
||||||
return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define pmd_write pmd_write
|
#define pmd_write pmd_write
|
||||||
static inline int pmd_write(pmd_t pmd)
|
static inline int pmd_write(pmd_t pmd)
|
||||||
{
|
{
|
||||||
|
@ -1238,11 +1218,39 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
|
||||||
#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
|
#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
|
||||||
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
|
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
|
||||||
|
|
||||||
#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
|
|
||||||
#define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN)
|
|
||||||
#define p4d_deref(pud) (p4d_val(pud) & _REGION_ENTRY_ORIGIN)
|
#define p4d_deref(pud) (p4d_val(pud) & _REGION_ENTRY_ORIGIN)
|
||||||
#define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN)
|
#define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN)
|
||||||
|
|
||||||
|
static inline unsigned long pmd_deref(pmd_t pmd)
|
||||||
|
{
|
||||||
|
unsigned long origin_mask;
|
||||||
|
|
||||||
|
origin_mask = _SEGMENT_ENTRY_ORIGIN;
|
||||||
|
if (pmd_large(pmd))
|
||||||
|
origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
|
||||||
|
return pmd_val(pmd) & origin_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||||
|
{
|
||||||
|
return pmd_deref(pmd) >> PAGE_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long pud_deref(pud_t pud)
|
||||||
|
{
|
||||||
|
unsigned long origin_mask;
|
||||||
|
|
||||||
|
origin_mask = _REGION_ENTRY_ORIGIN;
|
||||||
|
if (pud_large(pud))
|
||||||
|
origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
|
||||||
|
return pud_val(pud) & origin_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long pud_pfn(pud_t pud)
|
||||||
|
{
|
||||||
|
return pud_deref(pud) >> PAGE_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The pgd_offset function *always* adds the index for the top-level
|
* The pgd_offset function *always* adds the index for the top-level
|
||||||
* region/segment table. This is done to get a sequence like the
|
* region/segment table. This is done to get a sequence like the
|
||||||
|
|
|
@ -61,14 +61,6 @@ int main(void)
|
||||||
BLANK();
|
BLANK();
|
||||||
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
|
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
|
||||||
BLANK();
|
BLANK();
|
||||||
/* constants used by the vdso */
|
|
||||||
DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
|
|
||||||
DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
|
|
||||||
DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
|
|
||||||
DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
|
|
||||||
DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
|
|
||||||
DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
|
|
||||||
BLANK();
|
|
||||||
/* idle data offsets */
|
/* idle data offsets */
|
||||||
OFFSET(__CLOCK_IDLE_ENTER, s390_idle_data, clock_idle_enter);
|
OFFSET(__CLOCK_IDLE_ENTER, s390_idle_data, clock_idle_enter);
|
||||||
OFFSET(__CLOCK_IDLE_EXIT, s390_idle_data, clock_idle_exit);
|
OFFSET(__CLOCK_IDLE_EXIT, s390_idle_data, clock_idle_exit);
|
||||||
|
|
|
@ -855,13 +855,14 @@ void __init smp_detect_cpus(void)
|
||||||
|
|
||||||
static void smp_init_secondary(void)
|
static void smp_init_secondary(void)
|
||||||
{
|
{
|
||||||
int cpu = smp_processor_id();
|
int cpu = raw_smp_processor_id();
|
||||||
|
|
||||||
S390_lowcore.last_update_clock = get_tod_clock();
|
S390_lowcore.last_update_clock = get_tod_clock();
|
||||||
restore_access_regs(S390_lowcore.access_regs_save_area);
|
restore_access_regs(S390_lowcore.access_regs_save_area);
|
||||||
set_cpu_flag(CIF_ASCE_PRIMARY);
|
set_cpu_flag(CIF_ASCE_PRIMARY);
|
||||||
set_cpu_flag(CIF_ASCE_SECONDARY);
|
set_cpu_flag(CIF_ASCE_SECONDARY);
|
||||||
cpu_init();
|
cpu_init();
|
||||||
|
rcu_cpu_starting(cpu);
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
init_cpu_timer();
|
init_cpu_timer();
|
||||||
vtime_init();
|
vtime_init();
|
||||||
|
|
|
@ -101,6 +101,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* the PCI function will be scanned once function 0 appears */
|
||||||
|
if (!zdev->zbus->bus)
|
||||||
|
break;
|
||||||
|
|
||||||
pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
|
pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -164,6 +164,7 @@ void initialize_identity_maps(void *rmode)
|
||||||
add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
|
add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
|
||||||
|
|
||||||
/* Load the new page-table. */
|
/* Load the new page-table. */
|
||||||
|
sev_verify_cbit(top_level_pgt);
|
||||||
write_cr3(top_level_pgt);
|
write_cr3(top_level_pgt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,9 @@ SYM_FUNC_START(get_sev_encryption_bit)
|
||||||
SYM_FUNC_END(get_sev_encryption_bit)
|
SYM_FUNC_END(get_sev_encryption_bit)
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
|
|
||||||
|
#include "../../kernel/sev_verify_cbit.S"
|
||||||
|
|
||||||
SYM_FUNC_START(set_sev_encryption_mask)
|
SYM_FUNC_START(set_sev_encryption_mask)
|
||||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||||
push %rbp
|
push %rbp
|
||||||
|
@ -81,6 +84,19 @@ SYM_FUNC_START(set_sev_encryption_mask)
|
||||||
|
|
||||||
bts %rax, sme_me_mask(%rip) /* Create the encryption mask */
|
bts %rax, sme_me_mask(%rip) /* Create the encryption mask */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
|
||||||
|
* get_sev_encryption_bit() because this function is 32-bit code and
|
||||||
|
* shared between 64-bit and 32-bit boot path.
|
||||||
|
*/
|
||||||
|
movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
|
||||||
|
rdmsr
|
||||||
|
|
||||||
|
/* Store MSR value in sev_status */
|
||||||
|
shlq $32, %rdx
|
||||||
|
orq %rdx, %rax
|
||||||
|
movq %rax, sev_status(%rip)
|
||||||
|
|
||||||
.Lno_sev_mask:
|
.Lno_sev_mask:
|
||||||
movq %rbp, %rsp /* Restore original stack pointer */
|
movq %rbp, %rsp /* Restore original stack pointer */
|
||||||
|
|
||||||
|
@ -97,4 +113,6 @@ SYM_FUNC_END(set_sev_encryption_mask)
|
||||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||||
.balign 8
|
.balign 8
|
||||||
SYM_DATA(sme_me_mask, .quad 0)
|
SYM_DATA(sme_me_mask, .quad 0)
|
||||||
|
SYM_DATA(sev_status, .quad 0)
|
||||||
|
SYM_DATA(sev_check_data, .quad 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -159,4 +159,6 @@ void boot_page_fault(void);
|
||||||
void boot_stage1_vc(void);
|
void boot_stage1_vc(void);
|
||||||
void boot_stage2_vc(void);
|
void boot_stage2_vc(void);
|
||||||
|
|
||||||
|
unsigned long sev_verify_cbit(unsigned long cr3);
|
||||||
|
|
||||||
#endif /* BOOT_COMPRESSED_MISC_H */
|
#endif /* BOOT_COMPRESSED_MISC_H */
|
||||||
|
|
|
@ -273,11 +273,15 @@ void __init hv_apic_init(void)
|
||||||
pr_info("Hyper-V: Using enlightened APIC (%s mode)",
|
pr_info("Hyper-V: Using enlightened APIC (%s mode)",
|
||||||
x2apic_enabled() ? "x2apic" : "xapic");
|
x2apic_enabled() ? "x2apic" : "xapic");
|
||||||
/*
|
/*
|
||||||
* With x2apic, architectural x2apic MSRs are equivalent to the
|
* When in x2apic mode, don't use the Hyper-V specific APIC
|
||||||
* respective synthetic MSRs, so there's no need to override
|
* accessors since the field layout in the ICR register is
|
||||||
* the apic accessors. The only exception is
|
* different in x2apic mode. Furthermore, the architectural
|
||||||
* hv_apic_eoi_write, because it benefits from lazy EOI when
|
* x2apic MSRs function just as well as the Hyper-V
|
||||||
* available, but it works for both xapic and x2apic modes.
|
* synthetic APIC MSRs, so there's no benefit in having
|
||||||
|
* separate Hyper-V accessors for x2apic mode. The only
|
||||||
|
* exception is hv_apic_eoi_write, because it benefits from
|
||||||
|
* lazy EOI when available, but the same accessor works for
|
||||||
|
* both xapic and x2apic because the field layout is the same.
|
||||||
*/
|
*/
|
||||||
apic_set_eoi_write(hv_apic_eoi_write);
|
apic_set_eoi_write(hv_apic_eoi_write);
|
||||||
if (!x2apic_enabled()) {
|
if (!x2apic_enabled()) {
|
||||||
|
|
|
@ -290,6 +290,9 @@ static void __init uv_stringify(int len, char *to, char *from)
|
||||||
{
|
{
|
||||||
/* Relies on 'to' being NULL chars so result will be NULL terminated */
|
/* Relies on 'to' being NULL chars so result will be NULL terminated */
|
||||||
strncpy(to, from, len-1);
|
strncpy(to, from, len-1);
|
||||||
|
|
||||||
|
/* Trim trailing spaces */
|
||||||
|
(void)strim(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find UV arch type entry in UVsystab */
|
/* Find UV arch type entry in UVsystab */
|
||||||
|
@ -366,7 +369,7 @@ static int __init early_get_arch_type(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init uv_set_system_type(char *_oem_id)
|
static int __init uv_set_system_type(char *_oem_id, char *_oem_table_id)
|
||||||
{
|
{
|
||||||
/* Save OEM_ID passed from ACPI MADT */
|
/* Save OEM_ID passed from ACPI MADT */
|
||||||
uv_stringify(sizeof(oem_id), oem_id, _oem_id);
|
uv_stringify(sizeof(oem_id), oem_id, _oem_id);
|
||||||
|
@ -386,13 +389,23 @@ static int __init uv_set_system_type(char *_oem_id)
|
||||||
/* (Not hubless), not a UV */
|
/* (Not hubless), not a UV */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Is UV hubless system */
|
||||||
|
uv_hubless_system = 0x01;
|
||||||
|
|
||||||
|
/* UV5 Hubless */
|
||||||
|
if (strncmp(uv_archtype, "NSGI5", 5) == 0)
|
||||||
|
uv_hubless_system |= 0x20;
|
||||||
|
|
||||||
/* UV4 Hubless: CH */
|
/* UV4 Hubless: CH */
|
||||||
if (strncmp(uv_archtype, "NSGI4", 5) == 0)
|
else if (strncmp(uv_archtype, "NSGI4", 5) == 0)
|
||||||
uv_hubless_system = 0x11;
|
uv_hubless_system |= 0x10;
|
||||||
|
|
||||||
/* UV3 Hubless: UV300/MC990X w/o hub */
|
/* UV3 Hubless: UV300/MC990X w/o hub */
|
||||||
else
|
else
|
||||||
uv_hubless_system = 0x9;
|
uv_hubless_system |= 0x8;
|
||||||
|
|
||||||
|
/* Copy APIC type */
|
||||||
|
uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id);
|
||||||
|
|
||||||
pr_info("UV: OEM IDs %s/%s, SystemType %d, HUBLESS ID %x\n",
|
pr_info("UV: OEM IDs %s/%s, SystemType %d, HUBLESS ID %x\n",
|
||||||
oem_id, oem_table_id, uv_system_type, uv_hubless_system);
|
oem_id, oem_table_id, uv_system_type, uv_hubless_system);
|
||||||
|
@ -456,7 +469,7 @@ static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id)
|
||||||
uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;
|
uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;
|
||||||
|
|
||||||
/* If not UV, return. */
|
/* If not UV, return. */
|
||||||
if (likely(uv_set_system_type(_oem_id) == 0))
|
if (uv_set_system_type(_oem_id, _oem_table_id) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Save and Decode OEM Table ID */
|
/* Save and Decode OEM Table ID */
|
||||||
|
|
|
@ -1254,6 +1254,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_spec_ib_user_controlled(void)
|
||||||
|
{
|
||||||
|
return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
|
||||||
|
spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
|
||||||
|
spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
|
||||||
|
spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP;
|
||||||
|
}
|
||||||
|
|
||||||
static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
|
static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||||
{
|
{
|
||||||
switch (ctrl) {
|
switch (ctrl) {
|
||||||
|
@ -1261,16 +1269,26 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||||
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
|
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
|
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Indirect branch speculation is always disabled in strict
|
* With strict mode for both IBPB and STIBP, the instruction
|
||||||
* mode. It can neither be enabled if it was force-disabled
|
* code paths avoid checking this task flag and instead,
|
||||||
* by a previous prctl call.
|
* unconditionally run the instruction. However, STIBP and IBPB
|
||||||
|
* are independent and either can be set to conditionally
|
||||||
|
* enabled regardless of the mode of the other.
|
||||||
|
*
|
||||||
|
* If either is set to conditional, allow the task flag to be
|
||||||
|
* updated, unless it was force-disabled by a previous prctl
|
||||||
|
* call. Currently, this is possible on an AMD CPU which has the
|
||||||
|
* feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the
|
||||||
|
* kernel is booted with 'spectre_v2_user=seccomp', then
|
||||||
|
* spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and
|
||||||
|
* spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED.
|
||||||
*/
|
*/
|
||||||
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
|
if (!is_spec_ib_user_controlled() ||
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
|
|
||||||
task_spec_ib_force_disable(task))
|
task_spec_ib_force_disable(task))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
task_clear_spec_ib_disable(task);
|
task_clear_spec_ib_disable(task);
|
||||||
task_update_spec_tif(task);
|
task_update_spec_tif(task);
|
||||||
break;
|
break;
|
||||||
|
@ -1283,10 +1301,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||||
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
|
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
|
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
|
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
if (!is_spec_ib_user_controlled())
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
task_set_spec_ib_disable(task);
|
task_set_spec_ib_disable(task);
|
||||||
if (ctrl == PR_SPEC_FORCE_DISABLE)
|
if (ctrl == PR_SPEC_FORCE_DISABLE)
|
||||||
task_set_spec_ib_force_disable(task);
|
task_set_spec_ib_force_disable(task);
|
||||||
|
@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task)
|
||||||
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
|
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
|
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
|
||||||
return PR_SPEC_ENABLE;
|
return PR_SPEC_ENABLE;
|
||||||
else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
|
else if (is_spec_ib_user_controlled()) {
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
|
|
||||||
return PR_SPEC_DISABLE;
|
|
||||||
else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
|
|
||||||
spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
|
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
|
|
||||||
spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) {
|
|
||||||
if (task_spec_ib_force_disable(task))
|
if (task_spec_ib_force_disable(task))
|
||||||
return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
|
return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
|
||||||
if (task_spec_ib_disable(task))
|
if (task_spec_ib_disable(task))
|
||||||
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
|
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
|
||||||
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
|
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
|
||||||
} else
|
} else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
|
||||||
|
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
|
||||||
|
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
|
||||||
|
return PR_SPEC_DISABLE;
|
||||||
|
else
|
||||||
return PR_SPEC_NOT_AFFECTED;
|
return PR_SPEC_NOT_AFFECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,21 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
|
||||||
|
|
||||||
/* Setup early boot stage 4-/5-level pagetables. */
|
/* Setup early boot stage 4-/5-level pagetables. */
|
||||||
addq phys_base(%rip), %rax
|
addq phys_base(%rip), %rax
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For SEV guests: Verify that the C-bit is correct. A malicious
|
||||||
|
* hypervisor could lie about the C-bit position to perform a ROP
|
||||||
|
* attack on the guest by writing to the unencrypted stack and wait for
|
||||||
|
* the next RET instruction.
|
||||||
|
* %rsi carries pointer to realmode data and is callee-clobbered. Save
|
||||||
|
* and restore it.
|
||||||
|
*/
|
||||||
|
pushq %rsi
|
||||||
|
movq %rax, %rdi
|
||||||
|
call sev_verify_cbit
|
||||||
|
popq %rsi
|
||||||
|
|
||||||
|
/* Switch to new page-table */
|
||||||
movq %rax, %cr3
|
movq %rax, %cr3
|
||||||
|
|
||||||
/* Ensure I am executing from virtual addresses */
|
/* Ensure I am executing from virtual addresses */
|
||||||
|
@ -279,6 +294,7 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
|
||||||
SYM_CODE_END(secondary_startup_64)
|
SYM_CODE_END(secondary_startup_64)
|
||||||
|
|
||||||
#include "verify_cpu.S"
|
#include "verify_cpu.S"
|
||||||
|
#include "sev_verify_cbit.S"
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -178,6 +178,32 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
|
||||||
goto fail;
|
goto fail;
|
||||||
regs->dx = val >> 32;
|
regs->dx = val >> 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a VC handler and the #VC is only raised when SEV-ES is
|
||||||
|
* active, which means SEV must be active too. Do sanity checks on the
|
||||||
|
* CPUID results to make sure the hypervisor does not trick the kernel
|
||||||
|
* into the no-sev path. This could map sensitive data unencrypted and
|
||||||
|
* make it accessible to the hypervisor.
|
||||||
|
*
|
||||||
|
* In particular, check for:
|
||||||
|
* - Hypervisor CPUID bit
|
||||||
|
* - Availability of CPUID leaf 0x8000001f
|
||||||
|
* - SEV CPUID bit.
|
||||||
|
*
|
||||||
|
* The hypervisor might still report the wrong C-bit position, but this
|
||||||
|
* can't be checked here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((fn == 1 && !(regs->cx & BIT(31))))
|
||||||
|
/* Hypervisor bit */
|
||||||
|
goto fail;
|
||||||
|
else if (fn == 0x80000000 && (regs->ax < 0x8000001f))
|
||||||
|
/* SEV leaf check */
|
||||||
|
goto fail;
|
||||||
|
else if ((fn == 0x8000001f && !(regs->ax & BIT(1))))
|
||||||
|
/* SEV bit */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/* Skip over the CPUID two-byte opcode */
|
/* Skip over the CPUID two-byte opcode */
|
||||||
regs->ip += 2;
|
regs->ip += 2;
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,7 @@ fault:
|
||||||
return ES_EXCEPTION;
|
return ES_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
|
static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
|
||||||
unsigned long vaddr, phys_addr_t *paddr)
|
unsigned long vaddr, phys_addr_t *paddr)
|
||||||
{
|
{
|
||||||
unsigned long va = (unsigned long)vaddr;
|
unsigned long va = (unsigned long)vaddr;
|
||||||
|
@ -394,15 +394,19 @@ static bool vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
|
||||||
if (user_mode(ctxt->regs))
|
if (user_mode(ctxt->regs))
|
||||||
ctxt->fi.error_code |= X86_PF_USER;
|
ctxt->fi.error_code |= X86_PF_USER;
|
||||||
|
|
||||||
return false;
|
return ES_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(pte_val(*pte) & _PAGE_ENC))
|
||||||
|
/* Emulated MMIO to/from encrypted memory not supported */
|
||||||
|
return ES_UNSUPPORTED;
|
||||||
|
|
||||||
pa = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
|
pa = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
|
||||||
pa |= va & ~page_level_mask(level);
|
pa |= va & ~page_level_mask(level);
|
||||||
|
|
||||||
*paddr = pa;
|
*paddr = pa;
|
||||||
|
|
||||||
return true;
|
return ES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Include code shared with pre-decompression boot stage */
|
/* Include code shared with pre-decompression boot stage */
|
||||||
|
@ -731,6 +735,7 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
|
||||||
{
|
{
|
||||||
u64 exit_code, exit_info_1, exit_info_2;
|
u64 exit_code, exit_info_1, exit_info_2;
|
||||||
unsigned long ghcb_pa = __pa(ghcb);
|
unsigned long ghcb_pa = __pa(ghcb);
|
||||||
|
enum es_result res;
|
||||||
phys_addr_t paddr;
|
phys_addr_t paddr;
|
||||||
void __user *ref;
|
void __user *ref;
|
||||||
|
|
||||||
|
@ -740,11 +745,12 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
|
||||||
|
|
||||||
exit_code = read ? SVM_VMGEXIT_MMIO_READ : SVM_VMGEXIT_MMIO_WRITE;
|
exit_code = read ? SVM_VMGEXIT_MMIO_READ : SVM_VMGEXIT_MMIO_WRITE;
|
||||||
|
|
||||||
if (!vc_slow_virt_to_phys(ghcb, ctxt, (unsigned long)ref, &paddr)) {
|
res = vc_slow_virt_to_phys(ghcb, ctxt, (unsigned long)ref, &paddr);
|
||||||
if (!read)
|
if (res != ES_OK) {
|
||||||
|
if (res == ES_EXCEPTION && !read)
|
||||||
ctxt->fi.error_code |= X86_PF_WRITE;
|
ctxt->fi.error_code |= X86_PF_WRITE;
|
||||||
|
|
||||||
return ES_EXCEPTION;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_info_1 = paddr;
|
exit_info_1 = paddr;
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* sev_verify_cbit.S - Code for verification of the C-bit position reported
|
||||||
|
* by the Hypervisor when running with SEV enabled.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Joerg Roedel (jroedel@suse.de)
|
||||||
|
*
|
||||||
|
* sev_verify_cbit() is called before switching to a new long-mode page-table
|
||||||
|
* at boot.
|
||||||
|
*
|
||||||
|
* Verify that the C-bit position is correct by writing a random value to
|
||||||
|
* an encrypted memory location while on the current page-table. Then it
|
||||||
|
* switches to the new page-table to verify the memory content is still the
|
||||||
|
* same. After that it switches back to the current page-table and when the
|
||||||
|
* check succeeded it returns. If the check failed the code invalidates the
|
||||||
|
* stack pointer and goes into a hlt loop. The stack-pointer is invalidated to
|
||||||
|
* make sure no interrupt or exception can get the CPU out of the hlt loop.
|
||||||
|
*
|
||||||
|
* New page-table pointer is expected in %rdi (first parameter)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
SYM_FUNC_START(sev_verify_cbit)
|
||||||
|
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||||
|
/* First check if a C-bit was detected */
|
||||||
|
movq sme_me_mask(%rip), %rsi
|
||||||
|
testq %rsi, %rsi
|
||||||
|
jz 3f
|
||||||
|
|
||||||
|
/* sme_me_mask != 0 could mean SME or SEV - Check also for SEV */
|
||||||
|
movq sev_status(%rip), %rsi
|
||||||
|
testq %rsi, %rsi
|
||||||
|
jz 3f
|
||||||
|
|
||||||
|
/* Save CR4 in %rsi */
|
||||||
|
movq %cr4, %rsi
|
||||||
|
|
||||||
|
/* Disable Global Pages */
|
||||||
|
movq %rsi, %rdx
|
||||||
|
andq $(~X86_CR4_PGE), %rdx
|
||||||
|
movq %rdx, %cr4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verified that running under SEV - now get a random value using
|
||||||
|
* RDRAND. This instruction is mandatory when running as an SEV guest.
|
||||||
|
*
|
||||||
|
* Don't bail out of the loop if RDRAND returns errors. It is better to
|
||||||
|
* prevent forward progress than to work with a non-random value here.
|
||||||
|
*/
|
||||||
|
1: rdrand %rdx
|
||||||
|
jnc 1b
|
||||||
|
|
||||||
|
/* Store value to memory and keep it in %rdx */
|
||||||
|
movq %rdx, sev_check_data(%rip)
|
||||||
|
|
||||||
|
/* Backup current %cr3 value to restore it later */
|
||||||
|
movq %cr3, %rcx
|
||||||
|
|
||||||
|
/* Switch to new %cr3 - This might unmap the stack */
|
||||||
|
movq %rdi, %cr3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare value in %rdx with memory location. If C-bit is incorrect
|
||||||
|
* this would read the encrypted data and make the check fail.
|
||||||
|
*/
|
||||||
|
cmpq %rdx, sev_check_data(%rip)
|
||||||
|
|
||||||
|
/* Restore old %cr3 */
|
||||||
|
movq %rcx, %cr3
|
||||||
|
|
||||||
|
/* Restore previous CR4 */
|
||||||
|
movq %rsi, %cr4
|
||||||
|
|
||||||
|
/* Check CMPQ result */
|
||||||
|
je 3f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The check failed, prevent any forward progress to prevent ROP
|
||||||
|
* attacks, invalidate the stack and go into a hlt loop.
|
||||||
|
*/
|
||||||
|
xorq %rsp, %rsp
|
||||||
|
subq $0x1000, %rsp
|
||||||
|
2: hlt
|
||||||
|
jmp 2b
|
||||||
|
3:
|
||||||
|
#endif
|
||||||
|
/* Return page-table pointer */
|
||||||
|
movq %rdi, %rax
|
||||||
|
ret
|
||||||
|
SYM_FUNC_END(sev_verify_cbit)
|
|
@ -16,8 +16,6 @@
|
||||||
* to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
|
* to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.weak memcpy
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* memcpy - Copy a memory block.
|
* memcpy - Copy a memory block.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +28,7 @@
|
||||||
* rax original destination
|
* rax original destination
|
||||||
*/
|
*/
|
||||||
SYM_FUNC_START_ALIAS(__memcpy)
|
SYM_FUNC_START_ALIAS(__memcpy)
|
||||||
SYM_FUNC_START_LOCAL(memcpy)
|
SYM_FUNC_START_WEAK(memcpy)
|
||||||
ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
|
ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
|
||||||
"jmp memcpy_erms", X86_FEATURE_ERMS
|
"jmp memcpy_erms", X86_FEATURE_ERMS
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
* Output:
|
* Output:
|
||||||
* rax: dest
|
* rax: dest
|
||||||
*/
|
*/
|
||||||
.weak memmove
|
SYM_FUNC_START_WEAK(memmove)
|
||||||
|
|
||||||
SYM_FUNC_START_ALIAS(memmove)
|
|
||||||
SYM_FUNC_START(__memmove)
|
SYM_FUNC_START(__memmove)
|
||||||
|
|
||||||
mov %rdi, %rax
|
mov %rdi, %rax
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
#include <asm/alternative-asm.h>
|
#include <asm/alternative-asm.h>
|
||||||
#include <asm/export.h>
|
#include <asm/export.h>
|
||||||
|
|
||||||
.weak memset
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ISO C memset - set a memory block to a byte value. This function uses fast
|
* ISO C memset - set a memory block to a byte value. This function uses fast
|
||||||
* string to get better performance than the original function. The code is
|
* string to get better performance than the original function. The code is
|
||||||
|
@ -19,7 +17,7 @@
|
||||||
*
|
*
|
||||||
* rax original destination
|
* rax original destination
|
||||||
*/
|
*/
|
||||||
SYM_FUNC_START_ALIAS(memset)
|
SYM_FUNC_START_WEAK(memset)
|
||||||
SYM_FUNC_START(__memset)
|
SYM_FUNC_START(__memset)
|
||||||
/*
|
/*
|
||||||
* Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
|
* Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
*/
|
*/
|
||||||
u64 sme_me_mask __section(".data") = 0;
|
u64 sme_me_mask __section(".data") = 0;
|
||||||
u64 sev_status __section(".data") = 0;
|
u64 sev_status __section(".data") = 0;
|
||||||
|
u64 sev_check_data __section(".data") = 0;
|
||||||
EXPORT_SYMBOL(sme_me_mask);
|
EXPORT_SYMBOL(sme_me_mask);
|
||||||
DEFINE_STATIC_KEY_FALSE(sev_enable_key);
|
DEFINE_STATIC_KEY_FALSE(sev_enable_key);
|
||||||
EXPORT_SYMBOL_GPL(sev_enable_key);
|
EXPORT_SYMBOL_GPL(sev_enable_key);
|
||||||
|
|
|
@ -89,8 +89,8 @@ static void __init free_highpages(void)
|
||||||
/* set highmem page free */
|
/* set highmem page free */
|
||||||
for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
|
for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
|
||||||
&range_start, &range_end, NULL) {
|
&range_start, &range_end, NULL) {
|
||||||
unsigned long start = PHYS_PFN(range_start);
|
unsigned long start = PFN_UP(range_start);
|
||||||
unsigned long end = PHYS_PFN(range_end);
|
unsigned long end = PFN_DOWN(range_end);
|
||||||
|
|
||||||
/* Ignore complete lowmem entries */
|
/* Ignore complete lowmem entries */
|
||||||
if (end <= max_low)
|
if (end <= max_low)
|
||||||
|
|
|
@ -773,8 +773,7 @@ static void __device_link_del(struct kref *kref)
|
||||||
dev_dbg(link->consumer, "Dropping the link to %s\n",
|
dev_dbg(link->consumer, "Dropping the link to %s\n",
|
||||||
dev_name(link->supplier));
|
dev_name(link->supplier));
|
||||||
|
|
||||||
if (link->flags & DL_FLAG_PM_RUNTIME)
|
pm_runtime_drop_link(link);
|
||||||
pm_runtime_drop_link(link->consumer);
|
|
||||||
|
|
||||||
list_del_rcu(&link->s_node);
|
list_del_rcu(&link->s_node);
|
||||||
list_del_rcu(&link->c_node);
|
list_del_rcu(&link->c_node);
|
||||||
|
@ -788,8 +787,7 @@ static void __device_link_del(struct kref *kref)
|
||||||
dev_info(link->consumer, "Dropping the link to %s\n",
|
dev_info(link->consumer, "Dropping the link to %s\n",
|
||||||
dev_name(link->supplier));
|
dev_name(link->supplier));
|
||||||
|
|
||||||
if (link->flags & DL_FLAG_PM_RUNTIME)
|
pm_runtime_drop_link(link);
|
||||||
pm_runtime_drop_link(link->consumer);
|
|
||||||
|
|
||||||
list_del(&link->s_node);
|
list_del(&link->s_node);
|
||||||
list_del(&link->c_node);
|
list_del(&link->c_node);
|
||||||
|
|
|
@ -1117,6 +1117,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
|
||||||
|
|
||||||
drv = dev->driver;
|
drv = dev->driver;
|
||||||
if (drv) {
|
if (drv) {
|
||||||
|
pm_runtime_get_sync(dev);
|
||||||
|
|
||||||
while (device_links_busy(dev)) {
|
while (device_links_busy(dev)) {
|
||||||
__device_driver_unlock(dev, parent);
|
__device_driver_unlock(dev, parent);
|
||||||
|
|
||||||
|
@ -1128,12 +1130,11 @@ static void __device_release_driver(struct device *dev, struct device *parent)
|
||||||
* have released the driver successfully while this one
|
* have released the driver successfully while this one
|
||||||
* was waiting, so check for that.
|
* was waiting, so check for that.
|
||||||
*/
|
*/
|
||||||
if (dev->driver != drv)
|
if (dev->driver != drv) {
|
||||||
|
pm_runtime_put(dev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pm_runtime_get_sync(dev);
|
|
||||||
pm_runtime_clean_up_links(dev);
|
|
||||||
|
|
||||||
driver_sysfs_remove(dev);
|
driver_sysfs_remove(dev);
|
||||||
|
|
||||||
|
|
|
@ -1642,42 +1642,6 @@ void pm_runtime_remove(struct device *dev)
|
||||||
pm_runtime_reinit(dev);
|
pm_runtime_reinit(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* pm_runtime_clean_up_links - Prepare links to consumers for driver removal.
|
|
||||||
* @dev: Device whose driver is going to be removed.
|
|
||||||
*
|
|
||||||
* Check links from this device to any consumers and if any of them have active
|
|
||||||
* runtime PM references to the device, drop the usage counter of the device
|
|
||||||
* (as many times as needed).
|
|
||||||
*
|
|
||||||
* Links with the DL_FLAG_MANAGED flag unset are ignored.
|
|
||||||
*
|
|
||||||
* Since the device is guaranteed to be runtime-active at the point this is
|
|
||||||
* called, nothing else needs to be done here.
|
|
||||||
*
|
|
||||||
* Moreover, this is called after device_links_busy() has returned 'false', so
|
|
||||||
* the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and
|
|
||||||
* therefore rpm_active can't be manipulated concurrently.
|
|
||||||
*/
|
|
||||||
void pm_runtime_clean_up_links(struct device *dev)
|
|
||||||
{
|
|
||||||
struct device_link *link;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
idx = device_links_read_lock();
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(link, &dev->links.consumers, s_node,
|
|
||||||
device_links_read_lock_held()) {
|
|
||||||
if (!(link->flags & DL_FLAG_MANAGED))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (refcount_dec_not_one(&link->rpm_active))
|
|
||||||
pm_runtime_put_noidle(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
device_links_read_unlock(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_runtime_get_suppliers - Resume and reference-count supplier devices.
|
* pm_runtime_get_suppliers - Resume and reference-count supplier devices.
|
||||||
* @dev: Consumer device.
|
* @dev: Consumer device.
|
||||||
|
@ -1729,7 +1693,7 @@ void pm_runtime_new_link(struct device *dev)
|
||||||
spin_unlock_irq(&dev->power.lock);
|
spin_unlock_irq(&dev->power.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pm_runtime_drop_link(struct device *dev)
|
static void pm_runtime_drop_link_count(struct device *dev)
|
||||||
{
|
{
|
||||||
spin_lock_irq(&dev->power.lock);
|
spin_lock_irq(&dev->power.lock);
|
||||||
WARN_ON(dev->power.links_count == 0);
|
WARN_ON(dev->power.links_count == 0);
|
||||||
|
@ -1737,6 +1701,25 @@ void pm_runtime_drop_link(struct device *dev)
|
||||||
spin_unlock_irq(&dev->power.lock);
|
spin_unlock_irq(&dev->power.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_runtime_drop_link - Prepare for device link removal.
|
||||||
|
* @link: Device link going away.
|
||||||
|
*
|
||||||
|
* Drop the link count of the consumer end of @link and decrement the supplier
|
||||||
|
* device's runtime PM usage counter as many times as needed to drop all of the
|
||||||
|
* PM runtime reference to it from the consumer.
|
||||||
|
*/
|
||||||
|
void pm_runtime_drop_link(struct device_link *link)
|
||||||
|
{
|
||||||
|
if (!(link->flags & DL_FLAG_PM_RUNTIME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pm_runtime_drop_link_count(link->consumer);
|
||||||
|
|
||||||
|
while (refcount_dec_not_one(&link->rpm_active))
|
||||||
|
pm_runtime_put(link->supplier);
|
||||||
|
}
|
||||||
|
|
||||||
static bool pm_runtime_need_not_resume(struct device *dev)
|
static bool pm_runtime_need_not_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
return atomic_read(&dev->power.usage_count) <= 1 &&
|
return atomic_read(&dev->power.usage_count) <= 1 &&
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct nullb_device {
|
||||||
unsigned int nr_zones_closed;
|
unsigned int nr_zones_closed;
|
||||||
struct blk_zone *zones;
|
struct blk_zone *zones;
|
||||||
sector_t zone_size_sects;
|
sector_t zone_size_sects;
|
||||||
spinlock_t zone_dev_lock;
|
spinlock_t zone_lock;
|
||||||
unsigned long *zone_locks;
|
unsigned long *zone_locks;
|
||||||
|
|
||||||
unsigned long size; /* device size in MB */
|
unsigned long size; /* device size in MB */
|
||||||
|
|
|
@ -46,12 +46,21 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
|
||||||
if (!dev->zones)
|
if (!dev->zones)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
spin_lock_init(&dev->zone_dev_lock);
|
/*
|
||||||
|
* With memory backing, the zone_lock spinlock needs to be temporarily
|
||||||
|
* released to avoid scheduling in atomic context. To guarantee zone
|
||||||
|
* information protection, use a bitmap to lock zones with
|
||||||
|
* wait_on_bit_lock_io(). Sleeping on the lock is OK as memory backing
|
||||||
|
* implies that the queue is marked with BLK_MQ_F_BLOCKING.
|
||||||
|
*/
|
||||||
|
spin_lock_init(&dev->zone_lock);
|
||||||
|
if (dev->memory_backed) {
|
||||||
dev->zone_locks = bitmap_zalloc(dev->nr_zones, GFP_KERNEL);
|
dev->zone_locks = bitmap_zalloc(dev->nr_zones, GFP_KERNEL);
|
||||||
if (!dev->zone_locks) {
|
if (!dev->zone_locks) {
|
||||||
kvfree(dev->zones);
|
kvfree(dev->zones);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->zone_nr_conv >= dev->nr_zones) {
|
if (dev->zone_nr_conv >= dev->nr_zones) {
|
||||||
dev->zone_nr_conv = dev->nr_zones - 1;
|
dev->zone_nr_conv = dev->nr_zones - 1;
|
||||||
|
@ -137,11 +146,16 @@ void null_free_zoned_dev(struct nullb_device *dev)
|
||||||
|
|
||||||
static inline void null_lock_zone(struct nullb_device *dev, unsigned int zno)
|
static inline void null_lock_zone(struct nullb_device *dev, unsigned int zno)
|
||||||
{
|
{
|
||||||
|
if (dev->memory_backed)
|
||||||
wait_on_bit_lock_io(dev->zone_locks, zno, TASK_UNINTERRUPTIBLE);
|
wait_on_bit_lock_io(dev->zone_locks, zno, TASK_UNINTERRUPTIBLE);
|
||||||
|
spin_lock_irq(&dev->zone_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void null_unlock_zone(struct nullb_device *dev, unsigned int zno)
|
static inline void null_unlock_zone(struct nullb_device *dev, unsigned int zno)
|
||||||
{
|
{
|
||||||
|
spin_unlock_irq(&dev->zone_lock);
|
||||||
|
|
||||||
|
if (dev->memory_backed)
|
||||||
clear_and_wake_up_bit(zno, dev->zone_locks);
|
clear_and_wake_up_bit(zno, dev->zone_locks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +336,6 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
|
||||||
return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
|
return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
|
||||||
|
|
||||||
null_lock_zone(dev, zno);
|
null_lock_zone(dev, zno);
|
||||||
spin_lock(&dev->zone_dev_lock);
|
|
||||||
|
|
||||||
switch (zone->cond) {
|
switch (zone->cond) {
|
||||||
case BLK_ZONE_COND_FULL:
|
case BLK_ZONE_COND_FULL:
|
||||||
|
@ -375,9 +388,17 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
|
||||||
if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
|
if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
|
||||||
zone->cond = BLK_ZONE_COND_IMP_OPEN;
|
zone->cond = BLK_ZONE_COND_IMP_OPEN;
|
||||||
|
|
||||||
spin_unlock(&dev->zone_dev_lock);
|
/*
|
||||||
|
* Memory backing allocation may sleep: release the zone_lock spinlock
|
||||||
|
* to avoid scheduling in atomic context. Zone operation atomicity is
|
||||||
|
* still guaranteed through the zone_locks bitmap.
|
||||||
|
*/
|
||||||
|
if (dev->memory_backed)
|
||||||
|
spin_unlock_irq(&dev->zone_lock);
|
||||||
ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
|
ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
|
||||||
spin_lock(&dev->zone_dev_lock);
|
if (dev->memory_backed)
|
||||||
|
spin_lock_irq(&dev->zone_lock);
|
||||||
|
|
||||||
if (ret != BLK_STS_OK)
|
if (ret != BLK_STS_OK)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
|
@ -392,7 +413,6 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
|
||||||
ret = BLK_STS_OK;
|
ret = BLK_STS_OK;
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock(&dev->zone_dev_lock);
|
|
||||||
null_unlock_zone(dev, zno);
|
null_unlock_zone(dev, zno);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -516,9 +536,7 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
|
||||||
null_lock_zone(dev, i);
|
null_lock_zone(dev, i);
|
||||||
zone = &dev->zones[i];
|
zone = &dev->zones[i];
|
||||||
if (zone->cond != BLK_ZONE_COND_EMPTY) {
|
if (zone->cond != BLK_ZONE_COND_EMPTY) {
|
||||||
spin_lock(&dev->zone_dev_lock);
|
|
||||||
null_reset_zone(dev, zone);
|
null_reset_zone(dev, zone);
|
||||||
spin_unlock(&dev->zone_dev_lock);
|
|
||||||
trace_nullb_zone_op(cmd, i, zone->cond);
|
trace_nullb_zone_op(cmd, i, zone->cond);
|
||||||
}
|
}
|
||||||
null_unlock_zone(dev, i);
|
null_unlock_zone(dev, i);
|
||||||
|
@ -530,7 +548,6 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
|
||||||
zone = &dev->zones[zone_no];
|
zone = &dev->zones[zone_no];
|
||||||
|
|
||||||
null_lock_zone(dev, zone_no);
|
null_lock_zone(dev, zone_no);
|
||||||
spin_lock(&dev->zone_dev_lock);
|
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case REQ_OP_ZONE_RESET:
|
case REQ_OP_ZONE_RESET:
|
||||||
|
@ -550,8 +567,6 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&dev->zone_dev_lock);
|
|
||||||
|
|
||||||
if (ret == BLK_STS_OK)
|
if (ret == BLK_STS_OK)
|
||||||
trace_nullb_zone_op(cmd, zone_no, zone->cond);
|
trace_nullb_zone_op(cmd, zone_no, zone->cond);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,11 @@ int tpm_read_log_efi(struct tpm_chip *chip)
|
||||||
log_size = log_tbl->size;
|
log_size = log_tbl->size;
|
||||||
memunmap(log_tbl);
|
memunmap(log_tbl);
|
||||||
|
|
||||||
|
if (!log_size) {
|
||||||
|
pr_warn("UEFI TPM log area empty\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
|
log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
|
||||||
MEMREMAP_WB);
|
MEMREMAP_WB);
|
||||||
if (!log_tbl) {
|
if (!log_tbl) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
#include "tpm.h"
|
#include "tpm.h"
|
||||||
#include "tpm_tis_core.h"
|
#include "tpm_tis_core.h"
|
||||||
|
|
||||||
|
@ -49,8 +50,8 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
|
||||||
return container_of(data, struct tpm_tis_tcg_phy, priv);
|
return container_of(data, struct tpm_tis_tcg_phy, priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool interrupts = true;
|
static int interrupts = -1;
|
||||||
module_param(interrupts, bool, 0444);
|
module_param(interrupts, int, 0444);
|
||||||
MODULE_PARM_DESC(interrupts, "Enable interrupts");
|
MODULE_PARM_DESC(interrupts, "Enable interrupts");
|
||||||
|
|
||||||
static bool itpm;
|
static bool itpm;
|
||||||
|
@ -63,6 +64,28 @@ module_param(force, bool, 0444);
|
||||||
MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
|
MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int tpm_tis_disable_irq(const struct dmi_system_id *d)
|
||||||
|
{
|
||||||
|
if (interrupts == -1) {
|
||||||
|
pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d->ident);
|
||||||
|
interrupts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dmi_system_id tpm_tis_dmi_table[] = {
|
||||||
|
{
|
||||||
|
.callback = tpm_tis_disable_irq,
|
||||||
|
.ident = "ThinkPad T490s",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
|
#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
|
||||||
static int has_hid(struct acpi_device *dev, const char *hid)
|
static int has_hid(struct acpi_device *dev, const char *hid)
|
||||||
{
|
{
|
||||||
|
@ -192,6 +215,8 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
|
||||||
int irq = -1;
|
int irq = -1;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
dmi_check_system(tpm_tis_dmi_table);
|
||||||
|
|
||||||
rc = check_acpi_tpm2(dev);
|
rc = check_acpi_tpm2(dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* This file add support for MD5 and SHA1/SHA224/SHA256/SHA384/SHA512.
|
* This file add support for MD5 and SHA1/SHA224/SHA256/SHA384/SHA512.
|
||||||
*
|
*
|
||||||
* You could find the datasheet in Documentation/arm/sunxi/README
|
* You could find the datasheet in Documentation/arm/sunxi.rst
|
||||||
*/
|
*/
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* This file handle the PRNG
|
* This file handle the PRNG
|
||||||
*
|
*
|
||||||
* You could find a link for the datasheet in Documentation/arm/sunxi/README
|
* You could find a link for the datasheet in Documentation/arm/sunxi.rst
|
||||||
*/
|
*/
|
||||||
#include "sun8i-ce.h"
|
#include "sun8i-ce.h"
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* This file handle the TRNG
|
* This file handle the TRNG
|
||||||
*
|
*
|
||||||
* You could find a link for the datasheet in Documentation/arm/sunxi/README
|
* You could find a link for the datasheet in Documentation/arm/sunxi.rst
|
||||||
*/
|
*/
|
||||||
#include "sun8i-ce.h"
|
#include "sun8i-ce.h"
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
|
|
@ -217,6 +217,10 @@ enum {
|
||||||
#ifndef ASICREV_IS_VANGOGH
|
#ifndef ASICREV_IS_VANGOGH
|
||||||
#define ASICREV_IS_VANGOGH(eChipRev) ((eChipRev >= VANGOGH_A0) && (eChipRev < VANGOGH_UNKNOWN))
|
#define ASICREV_IS_VANGOGH(eChipRev) ((eChipRev >= VANGOGH_A0) && (eChipRev < VANGOGH_UNKNOWN))
|
||||||
#endif
|
#endif
|
||||||
|
#define GREEN_SARDINE_A0 0xA1
|
||||||
|
#ifndef ASICREV_IS_GREEN_SARDINE
|
||||||
|
#define ASICREV_IS_GREEN_SARDINE(eChipRev) ((eChipRev >= GREEN_SARDINE_A0) && (eChipRev < 0xFF))
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASIC chip ID
|
* ASIC chip ID
|
||||||
|
|
|
@ -508,21 +508,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/*
|
|
||||||
* Already in the desired write domain? Nothing for us to do!
|
|
||||||
*
|
|
||||||
* We apply a little bit of cunning here to catch a broader set of
|
|
||||||
* no-ops. If obj->write_domain is set, we must be in the same
|
|
||||||
* obj->read_domains, and only that domain. Therefore, if that
|
|
||||||
* obj->write_domain matches the request read_domains, we are
|
|
||||||
* already in the same read/write domain and can skip the operation,
|
|
||||||
* without having to further check the requested write_domain.
|
|
||||||
*/
|
|
||||||
if (READ_ONCE(obj->write_domain) == read_domains) {
|
|
||||||
err = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to flush the object off the GPU without holding the lock.
|
* Try to flush the object off the GPU without holding the lock.
|
||||||
* We will repeat the flush holding the lock in the normal manner
|
* We will repeat the flush holding the lock in the normal manner
|
||||||
|
@ -560,6 +545,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Already in the desired write domain? Nothing for us to do!
|
||||||
|
*
|
||||||
|
* We apply a little bit of cunning here to catch a broader set of
|
||||||
|
* no-ops. If obj->write_domain is set, we must be in the same
|
||||||
|
* obj->read_domains, and only that domain. Therefore, if that
|
||||||
|
* obj->write_domain matches the request read_domains, we are
|
||||||
|
* already in the same read/write domain and can skip the operation,
|
||||||
|
* without having to further check the requested write_domain.
|
||||||
|
*/
|
||||||
|
if (READ_ONCE(obj->write_domain) == read_domains)
|
||||||
|
goto out_unpin;
|
||||||
|
|
||||||
err = i915_gem_object_lock_interruptible(obj, NULL);
|
err = i915_gem_object_lock_interruptible(obj, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unpin;
|
goto out_unpin;
|
||||||
|
|
|
@ -245,22 +245,14 @@ static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 *
|
static inline u32 *
|
||||||
__gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 flags1)
|
__gen8_emit_write_rcs(u32 *cs, u32 value, u32 offset, u32 flags0, u32 flags1)
|
||||||
{
|
{
|
||||||
/* We're using qword write, offset should be aligned to 8 bytes. */
|
|
||||||
GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
|
|
||||||
|
|
||||||
/* w/a for post sync ops following a GPGPU operation we
|
|
||||||
* need a prior CS_STALL, which is emitted by the flush
|
|
||||||
* following the batch.
|
|
||||||
*/
|
|
||||||
*cs++ = GFX_OP_PIPE_CONTROL(6) | flags0;
|
*cs++ = GFX_OP_PIPE_CONTROL(6) | flags0;
|
||||||
*cs++ = flags1 | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_GLOBAL_GTT_IVB;
|
*cs++ = flags1 | PIPE_CONTROL_QW_WRITE;
|
||||||
*cs++ = gtt_offset;
|
*cs++ = offset;
|
||||||
*cs++ = 0;
|
*cs++ = 0;
|
||||||
*cs++ = value;
|
*cs++ = value;
|
||||||
/* We're thrashing one dword of HWS. */
|
*cs++ = 0; /* We're thrashing one extra dword. */
|
||||||
*cs++ = 0;
|
|
||||||
|
|
||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
|
@ -268,13 +260,38 @@ __gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 f
|
||||||
static inline u32*
|
static inline u32*
|
||||||
gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
|
gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
|
||||||
{
|
{
|
||||||
return __gen8_emit_ggtt_write_rcs(cs, value, gtt_offset, 0, flags);
|
/* We're using qword write, offset should be aligned to 8 bytes. */
|
||||||
|
GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
|
||||||
|
|
||||||
|
return __gen8_emit_write_rcs(cs,
|
||||||
|
value,
|
||||||
|
gtt_offset,
|
||||||
|
0,
|
||||||
|
flags | PIPE_CONTROL_GLOBAL_GTT_IVB);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32*
|
static inline u32*
|
||||||
gen12_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 flags1)
|
gen12_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags0, u32 flags1)
|
||||||
{
|
{
|
||||||
return __gen8_emit_ggtt_write_rcs(cs, value, gtt_offset, flags0, flags1);
|
/* We're using qword write, offset should be aligned to 8 bytes. */
|
||||||
|
GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
|
||||||
|
|
||||||
|
return __gen8_emit_write_rcs(cs,
|
||||||
|
value,
|
||||||
|
gtt_offset,
|
||||||
|
flags0,
|
||||||
|
flags1 | PIPE_CONTROL_GLOBAL_GTT_IVB);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 *
|
||||||
|
__gen8_emit_flush_dw(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
|
||||||
|
{
|
||||||
|
*cs++ = (MI_FLUSH_DW + 1) | flags;
|
||||||
|
*cs++ = gtt_offset;
|
||||||
|
*cs++ = 0;
|
||||||
|
*cs++ = value;
|
||||||
|
|
||||||
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 *
|
static inline u32 *
|
||||||
|
@ -285,12 +302,10 @@ gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
|
||||||
/* Offset should be aligned to 8 bytes for both (QW/DW) write types */
|
/* Offset should be aligned to 8 bytes for both (QW/DW) write types */
|
||||||
GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
|
GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
|
||||||
|
|
||||||
*cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW | flags;
|
return __gen8_emit_flush_dw(cs,
|
||||||
*cs++ = gtt_offset | MI_FLUSH_DW_USE_GTT;
|
value,
|
||||||
*cs++ = 0;
|
gtt_offset | MI_FLUSH_DW_USE_GTT,
|
||||||
*cs++ = value;
|
flags | MI_FLUSH_DW_OP_STOREDW);
|
||||||
|
|
||||||
return cs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __intel_engine_reset(struct intel_engine_cs *engine,
|
static inline void __intel_engine_reset(struct intel_engine_cs *engine,
|
||||||
|
|
|
@ -3547,6 +3547,19 @@ static const struct intel_context_ops execlists_context_ops = {
|
||||||
.destroy = execlists_context_destroy,
|
.destroy = execlists_context_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u32 hwsp_offset(const struct i915_request *rq)
|
||||||
|
{
|
||||||
|
const struct intel_timeline_cacheline *cl;
|
||||||
|
|
||||||
|
/* Before the request is executed, the timeline/cachline is fixed */
|
||||||
|
|
||||||
|
cl = rcu_dereference_protected(rq->hwsp_cacheline, 1);
|
||||||
|
if (cl)
|
||||||
|
return cl->ggtt_offset;
|
||||||
|
|
||||||
|
return rcu_dereference_protected(rq->timeline, 1)->hwsp_offset;
|
||||||
|
}
|
||||||
|
|
||||||
static int gen8_emit_init_breadcrumb(struct i915_request *rq)
|
static int gen8_emit_init_breadcrumb(struct i915_request *rq)
|
||||||
{
|
{
|
||||||
u32 *cs;
|
u32 *cs;
|
||||||
|
@ -3569,7 +3582,7 @@ static int gen8_emit_init_breadcrumb(struct i915_request *rq)
|
||||||
*cs++ = MI_NOOP;
|
*cs++ = MI_NOOP;
|
||||||
|
|
||||||
*cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
|
*cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
|
||||||
*cs++ = i915_request_timeline(rq)->hwsp_offset;
|
*cs++ = hwsp_offset(rq);
|
||||||
*cs++ = 0;
|
*cs++ = 0;
|
||||||
*cs++ = rq->fence.seqno - 1;
|
*cs++ = rq->fence.seqno - 1;
|
||||||
|
|
||||||
|
@ -4886,11 +4899,9 @@ gen8_emit_fini_breadcrumb_tail(struct i915_request *request, u32 *cs)
|
||||||
return gen8_emit_wa_tail(request, cs);
|
return gen8_emit_wa_tail(request, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 *emit_xcs_breadcrumb(struct i915_request *request, u32 *cs)
|
static u32 *emit_xcs_breadcrumb(struct i915_request *rq, u32 *cs)
|
||||||
{
|
{
|
||||||
u32 addr = i915_request_active_timeline(request)->hwsp_offset;
|
return gen8_emit_ggtt_write(cs, rq->fence.seqno, hwsp_offset(rq), 0);
|
||||||
|
|
||||||
return gen8_emit_ggtt_write(cs, request->fence.seqno, addr, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 *gen8_emit_fini_breadcrumb(struct i915_request *rq, u32 *cs)
|
static u32 *gen8_emit_fini_breadcrumb(struct i915_request *rq, u32 *cs)
|
||||||
|
@ -4909,7 +4920,7 @@ static u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
|
||||||
/* XXX flush+write+CS_STALL all in one upsets gem_concurrent_blt:kbl */
|
/* XXX flush+write+CS_STALL all in one upsets gem_concurrent_blt:kbl */
|
||||||
cs = gen8_emit_ggtt_write_rcs(cs,
|
cs = gen8_emit_ggtt_write_rcs(cs,
|
||||||
request->fence.seqno,
|
request->fence.seqno,
|
||||||
i915_request_active_timeline(request)->hwsp_offset,
|
hwsp_offset(request),
|
||||||
PIPE_CONTROL_FLUSH_ENABLE |
|
PIPE_CONTROL_FLUSH_ENABLE |
|
||||||
PIPE_CONTROL_CS_STALL);
|
PIPE_CONTROL_CS_STALL);
|
||||||
|
|
||||||
|
@ -4921,7 +4932,7 @@ gen11_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
|
||||||
{
|
{
|
||||||
cs = gen8_emit_ggtt_write_rcs(cs,
|
cs = gen8_emit_ggtt_write_rcs(cs,
|
||||||
request->fence.seqno,
|
request->fence.seqno,
|
||||||
i915_request_active_timeline(request)->hwsp_offset,
|
hwsp_offset(request),
|
||||||
PIPE_CONTROL_CS_STALL |
|
PIPE_CONTROL_CS_STALL |
|
||||||
PIPE_CONTROL_TILE_CACHE_FLUSH |
|
PIPE_CONTROL_TILE_CACHE_FLUSH |
|
||||||
PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
|
PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
|
||||||
|
@ -4983,7 +4994,9 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *request, u32 *cs)
|
||||||
|
|
||||||
static u32 *gen12_emit_fini_breadcrumb(struct i915_request *rq, u32 *cs)
|
static u32 *gen12_emit_fini_breadcrumb(struct i915_request *rq, u32 *cs)
|
||||||
{
|
{
|
||||||
return gen12_emit_fini_breadcrumb_tail(rq, emit_xcs_breadcrumb(rq, cs));
|
/* XXX Stalling flush before seqno write; post-sync not */
|
||||||
|
cs = emit_xcs_breadcrumb(rq, __gen8_emit_flush_dw(cs, 0, 0, 0));
|
||||||
|
return gen12_emit_fini_breadcrumb_tail(rq, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 *
|
static u32 *
|
||||||
|
@ -4991,7 +5004,7 @@ gen12_emit_fini_breadcrumb_rcs(struct i915_request *request, u32 *cs)
|
||||||
{
|
{
|
||||||
cs = gen12_emit_ggtt_write_rcs(cs,
|
cs = gen12_emit_ggtt_write_rcs(cs,
|
||||||
request->fence.seqno,
|
request->fence.seqno,
|
||||||
i915_request_active_timeline(request)->hwsp_offset,
|
hwsp_offset(request),
|
||||||
PIPE_CONTROL0_HDC_PIPELINE_FLUSH,
|
PIPE_CONTROL0_HDC_PIPELINE_FLUSH,
|
||||||
PIPE_CONTROL_CS_STALL |
|
PIPE_CONTROL_CS_STALL |
|
||||||
PIPE_CONTROL_TILE_CACHE_FLUSH |
|
PIPE_CONTROL_TILE_CACHE_FLUSH |
|
||||||
|
|
|
@ -188,9 +188,13 @@ cacheline_alloc(struct intel_timeline_hwsp *hwsp, unsigned int cacheline)
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cacheline_acquire(struct intel_timeline_cacheline *cl)
|
static void cacheline_acquire(struct intel_timeline_cacheline *cl,
|
||||||
|
u32 ggtt_offset)
|
||||||
{
|
{
|
||||||
if (cl)
|
if (!cl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cl->ggtt_offset = ggtt_offset;
|
||||||
i915_active_acquire(&cl->active);
|
i915_active_acquire(&cl->active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +344,7 @@ int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww)
|
||||||
GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
|
GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
|
||||||
tl->fence_context, tl->hwsp_offset);
|
tl->fence_context, tl->hwsp_offset);
|
||||||
|
|
||||||
cacheline_acquire(tl->hwsp_cacheline);
|
cacheline_acquire(tl->hwsp_cacheline, tl->hwsp_offset);
|
||||||
if (atomic_fetch_inc(&tl->pin_count)) {
|
if (atomic_fetch_inc(&tl->pin_count)) {
|
||||||
cacheline_release(tl->hwsp_cacheline);
|
cacheline_release(tl->hwsp_cacheline);
|
||||||
__i915_vma_unpin(tl->hwsp_ggtt);
|
__i915_vma_unpin(tl->hwsp_ggtt);
|
||||||
|
@ -515,7 +519,7 @@ __intel_timeline_get_seqno(struct intel_timeline *tl,
|
||||||
GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
|
GT_TRACE(tl->gt, "timeline:%llx using HWSP offset:%x\n",
|
||||||
tl->fence_context, tl->hwsp_offset);
|
tl->fence_context, tl->hwsp_offset);
|
||||||
|
|
||||||
cacheline_acquire(cl);
|
cacheline_acquire(cl, tl->hwsp_offset);
|
||||||
tl->hwsp_cacheline = cl;
|
tl->hwsp_cacheline = cl;
|
||||||
|
|
||||||
*seqno = timeline_advance(tl);
|
*seqno = timeline_advance(tl);
|
||||||
|
@ -573,9 +577,7 @@ int intel_timeline_read_hwsp(struct i915_request *from,
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
*hwsp = i915_ggtt_offset(cl->hwsp->vma) +
|
*hwsp = cl->ggtt_offset;
|
||||||
ptr_unmask_bits(cl->vaddr, CACHELINE_BITS) * CACHELINE_BYTES;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
i915_active_release(&cl->active);
|
i915_active_release(&cl->active);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -94,6 +94,8 @@ struct intel_timeline_cacheline {
|
||||||
struct intel_timeline_hwsp *hwsp;
|
struct intel_timeline_hwsp *hwsp;
|
||||||
void *vaddr;
|
void *vaddr;
|
||||||
|
|
||||||
|
u32 ggtt_offset;
|
||||||
|
|
||||||
struct rcu_head rcu;
|
struct rcu_head rcu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1489,7 +1489,8 @@ static int hws_pga_write(struct intel_vgpu *vgpu, unsigned int offset,
|
||||||
const struct intel_engine_cs *engine =
|
const struct intel_engine_cs *engine =
|
||||||
intel_gvt_render_mmio_to_engine(vgpu->gvt, offset);
|
intel_gvt_render_mmio_to_engine(vgpu->gvt, offset);
|
||||||
|
|
||||||
if (!intel_gvt_ggtt_validate_range(vgpu, value, I915_GTT_PAGE_SIZE)) {
|
if (value != 0 &&
|
||||||
|
!intel_gvt_ggtt_validate_range(vgpu, value, I915_GTT_PAGE_SIZE)) {
|
||||||
gvt_vgpu_err("write invalid HWSP address, reg:0x%x, value:0x%x\n",
|
gvt_vgpu_err("write invalid HWSP address, reg:0x%x, value:0x%x\n",
|
||||||
offset, value);
|
offset, value);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1650,6 +1651,34 @@ static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FixMe:
|
||||||
|
* If guest fills non-priv batch buffer on ApolloLake/Broxton as Mesa i965 did:
|
||||||
|
* 717e7539124d (i965: Use a WC map and memcpy for the batch instead of pwrite.)
|
||||||
|
* Due to the missing flush of bb filled by VM vCPU, host GPU hangs on executing
|
||||||
|
* these MI_BATCH_BUFFER.
|
||||||
|
* Temporarily workaround this by setting SNOOP bit for PAT3 used by PPGTT
|
||||||
|
* PML4 PTE: PAT(0) PCD(1) PWT(1).
|
||||||
|
* The performance is still expected to be low, will need further improvement.
|
||||||
|
*/
|
||||||
|
static int bxt_ppat_low_write(struct intel_vgpu *vgpu, unsigned int offset,
|
||||||
|
void *p_data, unsigned int bytes)
|
||||||
|
{
|
||||||
|
u64 pat =
|
||||||
|
GEN8_PPAT(0, CHV_PPAT_SNOOP) |
|
||||||
|
GEN8_PPAT(1, 0) |
|
||||||
|
GEN8_PPAT(2, 0) |
|
||||||
|
GEN8_PPAT(3, CHV_PPAT_SNOOP) |
|
||||||
|
GEN8_PPAT(4, CHV_PPAT_SNOOP) |
|
||||||
|
GEN8_PPAT(5, CHV_PPAT_SNOOP) |
|
||||||
|
GEN8_PPAT(6, CHV_PPAT_SNOOP) |
|
||||||
|
GEN8_PPAT(7, CHV_PPAT_SNOOP);
|
||||||
|
|
||||||
|
vgpu_vreg(vgpu, offset) = lower_32_bits(pat);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int guc_status_read(struct intel_vgpu *vgpu,
|
static int guc_status_read(struct intel_vgpu *vgpu,
|
||||||
unsigned int offset, void *p_data,
|
unsigned int offset, void *p_data,
|
||||||
unsigned int bytes)
|
unsigned int bytes)
|
||||||
|
@ -2812,7 +2841,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt)
|
||||||
|
|
||||||
MMIO_DH(GEN6_PCODE_MAILBOX, D_BDW_PLUS, NULL, mailbox_write);
|
MMIO_DH(GEN6_PCODE_MAILBOX, D_BDW_PLUS, NULL, mailbox_write);
|
||||||
|
|
||||||
MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS);
|
MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS & ~D_BXT);
|
||||||
MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS);
|
MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS);
|
||||||
|
|
||||||
MMIO_D(GAMTARBMODE, D_BDW_PLUS);
|
MMIO_D(GAMTARBMODE, D_BDW_PLUS);
|
||||||
|
@ -3139,7 +3168,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
MMIO_DFH(GAMT_CHKN_BIT_REG, D_KBL | D_CFL, F_CMD_ACCESS, NULL, NULL);
|
MMIO_DFH(GAMT_CHKN_BIT_REG, D_KBL | D_CFL, F_CMD_ACCESS, NULL, NULL);
|
||||||
MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS);
|
MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS & ~D_BXT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3313,9 +3342,21 @@ static int init_bxt_mmio_info(struct intel_gvt *gvt)
|
||||||
MMIO_D(GEN8_PUSHBUS_SHIFT, D_BXT);
|
MMIO_D(GEN8_PUSHBUS_SHIFT, D_BXT);
|
||||||
MMIO_D(GEN6_GFXPAUSE, D_BXT);
|
MMIO_D(GEN6_GFXPAUSE, D_BXT);
|
||||||
MMIO_DFH(GEN8_L3SQCREG1, D_BXT, F_CMD_ACCESS, NULL, NULL);
|
MMIO_DFH(GEN8_L3SQCREG1, D_BXT, F_CMD_ACCESS, NULL, NULL);
|
||||||
|
MMIO_DFH(GEN8_L3CNTLREG, D_BXT, F_CMD_ACCESS, NULL, NULL);
|
||||||
|
MMIO_DFH(_MMIO(0x20D8), D_BXT, F_CMD_ACCESS, NULL, NULL);
|
||||||
|
MMIO_F(GEN8_RING_CS_GPR(RENDER_RING_BASE, 0), 0x40, F_CMD_ACCESS,
|
||||||
|
0, 0, D_BXT, NULL, NULL);
|
||||||
|
MMIO_F(GEN8_RING_CS_GPR(GEN6_BSD_RING_BASE, 0), 0x40, F_CMD_ACCESS,
|
||||||
|
0, 0, D_BXT, NULL, NULL);
|
||||||
|
MMIO_F(GEN8_RING_CS_GPR(BLT_RING_BASE, 0), 0x40, F_CMD_ACCESS,
|
||||||
|
0, 0, D_BXT, NULL, NULL);
|
||||||
|
MMIO_F(GEN8_RING_CS_GPR(VEBOX_RING_BASE, 0), 0x40, F_CMD_ACCESS,
|
||||||
|
0, 0, D_BXT, NULL, NULL);
|
||||||
|
|
||||||
MMIO_DFH(GEN9_CTX_PREEMPT_REG, D_BXT, F_CMD_ACCESS, NULL, NULL);
|
MMIO_DFH(GEN9_CTX_PREEMPT_REG, D_BXT, F_CMD_ACCESS, NULL, NULL);
|
||||||
|
|
||||||
|
MMIO_DH(GEN8_PRIVATE_PAT_LO, D_BXT, NULL, bxt_ppat_low_write);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue