Linux 7.2-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQFSBAABCgA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAmpBb4seHHRvcnZhbGRz
 QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGjV8H/iFiGxRTgdNwWJsH
 5BQpc9kAmQHBMuzc2yM1HeeKVOm+zfxEmZV7kFabPEGYB1ltV52vspKI5vPUCWhP
 9VVqhIQy8ZfALEUIhQOoieJAboRgNDySldnuS8E2MFyfgKC0Tg8dkolmRFuh8Xhu
 R88kBeS1+DfpjFrnNLH98iUdtE9HabVt2VGfdrIpTYLC8VqyyuI77dXTEFkkwSCp
 NacpX5KYzD9dlDjlH6Hpqy/jqv7Y7JsEynFVUU05IQU9VojV7o1cbMQlKoe1yNeU
 dCoDCSwHhc8DUrGx1Tj6lsAS8k0R2it5FIW1eCF7cVKzZ8CbojyhluW6YPCOC0wE
 0louZxg=
 =5vas
 -----END PGP SIGNATURE-----

Merge tag 'v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into gpio/for-current

Linux 7.2-rc1
This commit is contained in:
Bartosz Golaszewski 2026-06-29 09:30:53 +02:00
commit 2ed2e359de
730 changed files with 24979 additions and 4753 deletions

View File

@ -530,7 +530,8 @@ Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
Luca Weiss <luca@lucaweiss.eu> <luca@z3ntu.xyz>
Lucas De Marchi <demarchi@kernel.org> <lucas.demarchi@intel.com>
Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
Luo Jie <quic_luoj@quicinc.com> <luoj@codeaurora.org>
Luo Jie <jie.luo@oss.qualcomm.com> <luoj@codeaurora.org>
Luo Jie <jie.luo@oss.qualcomm.com> <quic_luoj@quicinc.com>
Lance Yang <lance.yang@linux.dev> <ioworker0@gmail.com>
Lance Yang <lance.yang@linux.dev> <mingzhe.yang@ly.com>
Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>

View File

@ -24,7 +24,7 @@ properties:
const: 1
clocks:
minItems: 14
minItems: 15
items:
- description: input oscillator
- description: input sys clk
@ -40,12 +40,13 @@ properties:
- description: input gp1 pll
- description: input mpll1
- description: input mpll2
- description: input mpll3
- description: external input rmii oscillator (optional)
- description: input video pll0 (optional)
- description: external pad input for rtc (optional)
clock-names:
minItems: 14
minItems: 15
items:
- const: xtal
- const: sys
@ -61,6 +62,7 @@ properties:
- const: gp1
- const: mpll1
- const: mpll2
- const: mpll3
- const: ext_rmii
- const: vid_pll0
- const: ext_rtc
@ -97,7 +99,8 @@ examples:
<&gp0 1>,
<&gp1 1>,
<&mpll 4>,
<&mpll 6>;
<&mpll 6>,
<&mpll 8>;
clock-names = "xtal",
"sys",
"fix",
@ -111,6 +114,7 @@ examples:
"gp0",
"gp1",
"mpll1",
"mpll2";
"mpll2",
"mpll3";
};
};

View File

@ -72,7 +72,7 @@ allOf:
contains:
enum:
- amlogic,t7-gp0-pll
- amlogic,t7-gp1--pll
- amlogic,t7-gp1-pll
- amlogic,t7-hifi-pll
- amlogic,t7-pcie-pll
- amlogic,t7-mpll

View File

@ -0,0 +1,59 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/canaan,k230-clk.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Canaan Kendryte K230 Clock
maintainers:
- Xukai Wang <kingxukai@zohomail.com>
description:
The Canaan K230 clock controller generates various clocks for SoC
peripherals. See include/dt-bindings/clock/canaan,k230-clk.h for
valid clock IDs.
properties:
compatible:
const: canaan,k230-clk
reg:
items:
- description: PLL control registers
- description: Sysclk control registers
clocks:
items:
- description: Main external reference clock
- description:
External clock which used as the pulse input
for the timer to provide timing signals.
clock-names:
items:
- const: osc24m
- const: timer-pulse-in
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
additionalProperties: false
examples:
- |
clock-controller@91102000 {
compatible = "canaan,k230-clk";
reg = <0x91102000 0x40>,
<0x91100000 0x108>;
clocks = <&osc24m>, <&timerx_pulse_in>;
clock-names = "osc24m", "timer-pulse-in";
#clock-cells = <1>;
};

View File

@ -37,6 +37,9 @@ properties:
'#power-domain-cells':
const: 1
'#reset-cells':
const: 1
required:
- compatible
- reg
@ -44,16 +47,27 @@ required:
additionalProperties: false
if:
not:
properties:
compatible:
contains:
const: marvell,pxa1908-apmu
then:
properties:
'#power-domain-cells': false
allOf:
- if:
not:
properties:
compatible:
contains:
const: marvell,pxa1908-apmu
then:
properties:
'#power-domain-cells': false
- if:
not:
properties:
compatible:
contains:
enum:
- marvell,pxa1908-apbc
- marvell,pxa1908-apbcp
then:
properties:
'#reset-cells': false
examples:
# APMU block:

View File

@ -42,12 +42,6 @@ properties:
- const: cfg_ahb_clk
- const: gcc_disp_gpll0_div_clk_src
'#clock-cells':
const: 1
'#power-domain-cells':
const: 1
power-domains:
description:
A phandle and PM domain specifier for the CX power domain.
@ -58,18 +52,16 @@ properties:
A phandle to an OPP node describing the power domain's performance point.
maxItems: 1
reg:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
- '#power-domain-cells'
additionalProperties: false
allOf:
- $ref: qcom,gcc.yaml#
unevaluatedProperties: false
examples:
- |
@ -101,6 +93,7 @@ examples:
power-domains = <&rpmpd SM6125_VDDCX>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,hawi-gcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller on Hawi
maintainers:
- Vivek Aknurwar <vivek.aknurwar@oss.qualcomm.com>
description: |
Qualcomm global clock control module provides the clocks, resets and power
domains on Hawi.
See also: include/dt-bindings/clock/qcom,hawi-gcc.h
properties:
compatible:
const: qcom,hawi-gcc
clocks:
items:
- description: Board XO source
- description: Board Always On XO source
- description: Sleep clock source
- description: PCIE 0 Pipe clock source
- description: PCIE 1 Pipe clock source
- description: UFS PHY RX symbol 0 clock
- description: UFS PHY RX symbol 1 clock
- description: UFS PHY TX symbol 0 clock
- description: USB3 PHY wrapper pipe clock
required:
- compatible
- clocks
- '#power-domain-cells'
allOf:
- $ref: qcom,gcc.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@100000 {
compatible = "qcom,hawi-gcc";
reg = <0x00100000 0x1f4200>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&rpmhcc RPMH_CXO_CLK_A>,
<&sleep_clk>,
<&pcie0_phy>,
<&pcie1_phy>,
<&ufs_mem_phy 0>,
<&ufs_mem_phy 1>,
<&ufs_mem_phy 2>,
<&usb_1_qmpphy>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...

View File

@ -8,7 +8,7 @@ title: Qualcomm CMN PLL Clock Controller on IPQ SoC
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Luo Jie <quic_luoj@quicinc.com>
- Luo Jie <jie.luo@oss.qualcomm.com>
description:
The CMN (or common) PLL clock controller expects a reference
@ -25,6 +25,7 @@ properties:
compatible:
enum:
- qcom,ipq5018-cmn-pll
- qcom,ipq5332-cmn-pll
- qcom,ipq5424-cmn-pll
- qcom,ipq6018-cmn-pll
- qcom,ipq8074-cmn-pll

View File

@ -44,7 +44,7 @@ required:
- power-domains
- '#power-domain-cells'
unevaluatedProperties: false
additionalProperties: false
examples:
- |

View File

@ -25,6 +25,10 @@ properties:
- description: Sleep clock source
- description: Camera AHB clock from GCC
interconnects:
items:
- description: Interconnect path to enable the MultiMedia NoC
required:
- compatible
- clocks
@ -37,12 +41,16 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,milos-gcc.h>
#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interconnect/qcom,milos-rpmh.h>
clock-controller@adb0000 {
compatible = "qcom,milos-camcc";
reg = <0x0adb0000 0x40000>;
clocks = <&bi_tcxo_div2>,
<&sleep_clk>,
<&gcc GCC_CAMERA_AHB_CLK>;
interconnects = <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS
&mmss_noc SLAVE_MNOC_HF_MEM_NOC QCOM_ICC_TAG_ALWAYS>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;

View File

@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,milos-gxclkctl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Graphics Power Domain Controller on Milos
maintainers:
- Luca Weiss <luca.weiss@fairphone.com>
description: |
Qualcomm GX(graphics) is a clock controller which has PLLs, clocks and
Power domains (GDSC). This module provides the power domains control
of gxclkctl on Qualcomm SoCs which helps the recovery of Graphics subsystem.
See also:
include/dt-bindings/clock/qcom,kaanapali-gxclkctl.h
properties:
compatible:
enum:
- qcom,milos-gxclkctl
reg:
maxItems: 1
power-domains:
description:
Power domains required for the clock controller to operate
items:
- description: GFX power domain
- description: GPUCC(CX) power domain
'#power-domain-cells':
const: 1
required:
- compatible
- reg
- power-domains
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/power/qcom,rpmhpd.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
clock-controller@3d64000 {
compatible = "qcom,milos-gxclkctl";
reg = <0x0 0x03d64000 0x0 0x6000>;
power-domains = <&rpmhpd RPMHPD_GFX>,
<&gpucc 0>;
#power-domain-cells = <1>;
};
};
...

View File

@ -8,7 +8,7 @@ title: Qualcomm NSS Clock & Reset Controller on QCA8386/QCA8084
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Luo Jie <quic_luoj@quicinc.com>
- Luo Jie <jie.luo@oss.qualcomm.com>
description: |
Qualcomm NSS clock control module provides the clocks and resets

View File

@ -19,6 +19,7 @@ properties:
enum:
- qcom,eliza-rpmh-clk
- qcom,glymur-rpmh-clk
- qcom,hawi-rpmh-clk
- qcom,kaanapali-rpmh-clk
- qcom,milos-rpmh-clk
- qcom,nord-rpmh-clk

View File

@ -20,6 +20,7 @@ description: |
include/dt-bindings/clock/qcom,sm8450-videocc.h
include/dt-bindings/clock/qcom,sm8650-videocc.h
include/dt-bindings/clock/qcom,sm8750-videocc.h
include/dt-bindings/clock/qcom,x1p42100-videocc.h
properties:
compatible:
@ -32,6 +33,7 @@ properties:
- qcom,sm8650-videocc
- qcom,sm8750-videocc
- qcom,x1e80100-videocc
- qcom,x1p42100-videocc
clocks:
items:
@ -70,6 +72,7 @@ allOf:
- qcom,sm8450-videocc
- qcom,sm8550-videocc
- qcom,sm8750-videocc
- qcom,x1p42100-videocc
then:
required:
- required-opps

View File

@ -17,6 +17,7 @@ description: |
See also:
- include/dt-bindings/clock/qcom,eliza-tcsr.h
- include/dt-bindings/clock/qcom,glymur-tcsr.h
- include/dt-bindings/clock/qcom,hawi-tcsrcc.h
- include/dt-bindings/clock/qcom,nord-tcsrcc.h
- include/dt-bindings/clock/qcom,sm8550-tcsr.h
- include/dt-bindings/clock/qcom,sm8650-tcsr.h
@ -28,6 +29,7 @@ properties:
- enum:
- qcom,eliza-tcsr
- qcom,glymur-tcsr
- qcom,hawi-tcsrcc
- qcom,kaanapali-tcsr
- qcom,milos-tcsr
- qcom,nord-tcsrcc

View File

@ -23,6 +23,7 @@ properties:
compatible:
enum:
- qcom,x1e80100-camcc
- qcom,x1p42100-camcc
reg:
maxItems: 1

View File

@ -60,7 +60,7 @@ examples:
clock-output-names = "main", "pll0", "pll1", "pll2",
"pll2s", "pll2h", "z", "z2",
"i", "m3", "b", "m1", "m2",
"zx", "zs", "hp";
"zx", "zs", "hp", "ztr", "zt";
};
sdhi2_clk: sdhi2_clk@e615007c {

View File

@ -28,7 +28,6 @@ properties:
fan-supply:
description: Phandle to the regulator that powers the fan.
$ref: /schemas/types.yaml#/definitions/phandle
required:
- compatible

View File

@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm IPQ packet process engine (PPE)
maintainers:
- Luo Jie <quic_luoj@quicinc.com>
- Luo Jie <jie.luo@oss.qualcomm.com>
- Lei Wei <quic_leiwei@quicinc.com>
- Suruchi Agarwal <quic_suruchia@quicinc.com>
- Pavithra R <quic_pavir@quicinc.com>

View File

@ -121,8 +121,7 @@ examples:
#size-cells = <0>;
phy1: ethernet-phy@1 {
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
compatible = "ethernet-phy-id0022.1537";
reg = <1>;
interrupt-parent = <&irqc0>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;

View File

@ -0,0 +1,44 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/sprd,sc2730-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Unisoc SC2730 Power Management IC regulators
maintainers:
- Otto Pflüger <otto.pflueger@abscue.de>
patternProperties:
"^dcdc-(core|cpu|gen[0-1]|gpu|mem|memq|modem|sram)$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
"^ldo-avdd(12|18)$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
"^ldo-vdd(18-dcxo|28)$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
"^ldo-vdd(emmccore|kpled|ldo[0-2]|sd(core|io)|sim[0-2]|usb33|wcn|wifipa)$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
"^ldo-vddcam(a0|a1|d0|d1|io|mot)$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
"^ldo-vddrf(1v25|18)$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
additionalProperties: false
...

View File

@ -1,39 +0,0 @@
Epson RX6110 Real Time Clock
============================
The Epson RX6110 can be used with SPI or I2C busses. The kind of
bus depends on the SPISEL pin and can not be configured via software.
I2C mode
--------
Required properties:
- compatible: should be: "epson,rx6110"
- reg : the I2C address of the device for I2C
Example:
rtc: rtc@32 {
compatible = "epson,rx6110"
reg = <0x32>;
};
SPI mode
--------
Required properties:
- compatible: should be: "epson,rx6110"
- reg: chip select number
- spi-cs-high: RX6110 needs chipselect high
- spi-cpha: RX6110 works with SPI shifted clock phase
- spi-cpol: RX6110 works with SPI inverse clock polarity
Example:
rtc: rtc@3 {
compatible = "epson,rx6110"
reg = <3>
spi-cs-high;
spi-cpha;
spi-cpol;
};

View File

@ -0,0 +1,68 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/epson,rx6110.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Epson RX6110 Real Time Clock
description:
The Epson RX6110 can be used with SPI or I2C busses. The kind of bus depends
on the SPISEL pin and cannot be configured via software.
maintainers:
- Alexandre Belloni <alexandre.belloni@bootlin.com>
allOf:
- $ref: rtc.yaml#
- $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
const: epson,rx6110
reg:
maxItems: 1
spi-cs-high: true
spi-cpha: true
spi-cpol: true
required:
- compatible
- reg
dependencies:
spi-cs-high: [ spi-cpha, spi-cpol ]
spi-cpha: [ spi-cs-high, spi-cpol ]
spi-cpol: [ spi-cs-high, spi-cpha ]
unevaluatedProperties: false
examples:
# I2C mode
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc@32 {
compatible = "epson,rx6110";
reg = <0x32>;
};
};
# SPI mode
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
rtc@3 {
compatible = "epson,rx6110";
reg = <3>;
spi-cs-high;
spi-cpha;
spi-cpol;
};
};

View File

@ -31,6 +31,7 @@ properties:
- epson,rx8025
- isil,isl12057
- epson,rx8130
- epson,rx8901
- items:
- enum:

View File

@ -0,0 +1,50 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/st,m41t93.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST M41T93 RTC and compatible
maintainers:
- Akhilesh Patil <akhilesh@ee.iitb.ac.in>
description:
ST M41T93 is spi based Real Time Clock (RTC) with time, date,
alarm, watchdog, square wave clock output, 8 bit timer and
7 bytes of user SRAM.
properties:
compatible:
enum:
- st,m41t93
reg:
maxItems: 1
"#clock-cells":
const: 0
required:
- compatible
- reg
allOf:
- $ref: rtc.yaml
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
rtc@0 {
compatible = "st,m41t93";
reg = <0>;
#clock-cells = <0>;
spi-max-frequency = <2000000>;
};
};

View File

@ -30,6 +30,8 @@ properties:
- aspeed,ast2500-rtc
# ASPEED BMC ast2600 Real-time Clock
- aspeed,ast2600-rtc
# ASPEED BMC ast2700 Real-time Clock
- aspeed,ast2700-rtc
# Conexant Digicolor Real Time Clock Controller
- cnxt,cx92755-rtc
# I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output

View File

@ -54,6 +54,12 @@ properties:
- sophgo,sg2042-spi
- thead,th1520-spi
- const: snps,dw-apb-ssi
- description: Vendor controllers which use snps,dwc-ssi-2.00a as fallback
items:
- enum:
- starfive,jhb100-spi
- const: snps,dwc-ssi-2.00a
- const: snps,dwc-ssi-1.01a
- description: Intel Keem Bay SPI Controller
const: intel,keembay-ssi
- description: Intel Mount Evans Integrated Management Complex SPI Controller

View File

@ -25,6 +25,7 @@ properties:
oneOf:
- items:
- enum:
- qcom,hawi-spmi-pmic-arb
- qcom,kaanapali-spmi-pmic-arb
- const: qcom,glymur-spmi-pmic-arb
- enum:

View File

@ -87,9 +87,12 @@ examples:
amlogic,ao-secure = <&sec_AO>;
};
- |
#include <dt-bindings/clock/amlogic,t7-peripherals-clkc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
temperature-sensor@20000 {
compatible = "amlogic,t7-thermal";
reg = <0x0 0x20000 0x0 0x50>;
reg = <0x20000 0x50>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkc_periphs CLKID_TS>;
#thermal-sensor-cells = <0>;

View File

@ -12,7 +12,7 @@
| arm64: | ok |
| csky: | TODO |
| hexagon: | TODO |
| loongarch: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |

View File

@ -433,6 +433,8 @@ exceptions) notifiers run under the instance lock. Please extend this
documentation whenever you make explicit assumption about lock being held
from a notifier.
Drivers **must not** generate nested notifications of the ops-locked types.
NETDEV_INTERNAL symbol namespace
================================

View File

@ -6840,7 +6840,7 @@ s390 specific.
} s390_ucontrol;
s390 specific. A page fault has occurred for a user controlled virtual
machine (KVM_VM_S390_UNCONTROL) on its host page table that cannot be
machine (KVM_VM_S390_UCONTROL) on its host page table that cannot be
resolved by the kernel.
The program code and the translation exception code that were placed
in the cpu's lowcore are presented here as defined by the z Architecture

View File

@ -22323,9 +22323,9 @@ F: Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml
F: drivers/power/supply/qcom_smbx.c
QUALCOMM PPE DRIVER
M: Luo Jie <quic_luoj@quicinc.com>
M: Luo Jie <jie.luo@oss.qualcomm.com>
L: netdev@vger.kernel.org
S: Supported
S: Maintained
F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
F: drivers/net/ethernet/qualcomm/ppe/
@ -26001,9 +26001,8 @@ S: Maintained
F: drivers/net/ethernet/dlink/sundance.c
SUNPLUS ETHERNET DRIVER
M: Wells Lu <wellslutw@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
S: Orphan
W: https://sunplus.atlassian.net/wiki/spaces/doc/overview
F: Documentation/devicetree/bindings/net/sunplus,sp7021-emac.yaml
F: drivers/net/ethernet/sunplus/

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 7
PATCHLEVEL = 1
PATCHLEVEL = 2
SUBLEVEL = 0
EXTRAVERSION =
EXTRAVERSION = -rc1
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@ -559,6 +559,15 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
else
alignment_mask = 0x7;
offset = hw->address & alignment_mask;
/*
* BAS is an 8-bit field in WCR/BCR; the shift below would
* silently drop the high bits of ctrl.len when offset + len
* exceeds 8, programming hardware to watch fewer bytes than
* the user requested.
*/
if (((u32)hw->ctrl.len << offset) > ARM_BREAKPOINT_LEN_8)
return -EINVAL;
}
hw->address &= ~alignment_mask;

View File

@ -2,6 +2,7 @@
#include <linux/static_call.h>
#include <linux/memory.h>
#include <asm/text-patching.h>
#include <asm/insn.h>
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
{

View File

@ -1198,11 +1198,6 @@ static void __init map_mem(void)
__map_memblock(start, end, pgprot_tagged(PAGE_KERNEL),
flags);
}
/* Map the kernel data/bss read-only in the linear map */
__map_memblock(init_end, kernel_end, PAGE_KERNEL_RO, flags);
flush_tlb_kernel_range((unsigned long)lm_alias(__init_end),
(unsigned long)lm_alias(__bss_stop));
}
void mark_rodata_ro(void)
@ -1221,6 +1216,12 @@ void mark_rodata_ro(void)
update_mapping_prot(__pa_symbol(_text), (unsigned long)_text,
(unsigned long)_stext - (unsigned long)_text,
PAGE_KERNEL_RO);
/* Map the kernel data/bss read-only in the linear map */
update_mapping_prot(__pa_symbol(__init_end),
(unsigned long)lm_alias(__init_end),
(unsigned long)__bss_stop - (unsigned long)__init_end,
PAGE_KERNEL_RO);
}
static void __init declare_vma(struct vm_struct *vma,

View File

@ -209,6 +209,7 @@ config LOONGARCH
select SYSCTL_ARCH_UNALIGN_NO_WARN
select SYSCTL_EXCEPTION_TRACE
select SWIOTLB if 64BIT
select THREAD_INFO_IN_TASK
select TRACE_IRQFLAGS_SUPPORT
select USE_PERCPU_NUMA_NODE_ID
select USER_STACKTRACE_SUPPORT

View File

@ -405,6 +405,8 @@ uart0: serial@1ff40800 {
i2c0: i2c@1ff48000 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1ff48000 0x0 0x0800>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&eiointc>;
interrupts = <14>;
status = "disabled";
@ -413,6 +415,8 @@ i2c0: i2c@1ff48000 {
i2c@1ff48800 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1ff48800 0x0 0x0800>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&eiointc>;
interrupts = <15>;
status = "disabled";
@ -421,6 +425,8 @@ i2c@1ff48800 {
i2c@1ff49000 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1ff49000 0x0 0x0800>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&eiointc>;
interrupts = <16>;
status = "disabled";
@ -429,6 +435,8 @@ i2c@1ff49000 {
i2c@1ff49800 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1ff49800 0x0 0x0800>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&eiointc>;
interrupts = <17>;
status = "disabled";
@ -437,6 +445,8 @@ i2c@1ff49800 {
i2c@1ff4a000 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1ff4a000 0x0 0x0800>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&eiointc>;
interrupts = <18>;
status = "disabled";
@ -445,6 +455,8 @@ i2c@1ff4a000 {
i2c@1ff4a800 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1ff4a800 0x0 0x0800>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&eiointc>;
interrupts = <19>;
status = "disabled";

View File

@ -311,6 +311,8 @@ uart0: serial@1fe20000 {
i2c2: i2c@1fe21000 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1fe21000 0x0 0x8>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&liointc0>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
@ -319,6 +321,8 @@ i2c2: i2c@1fe21000 {
i2c3: i2c@1fe21800 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1fe21800 0x0 0x8>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_APB_CLK>;
interrupt-parent = <&liointc0>;
interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";

View File

@ -239,6 +239,8 @@ rtc0: rtc@100d0100 {
i2c@1fe00120 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1fe00120 0x0 0x8>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_MISC_CLK>;
interrupt-parent = <&liointc>;
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
@ -247,6 +249,8 @@ i2c@1fe00120 {
i2c@1fe00130 {
compatible = "loongson,ls2k-i2c";
reg = <0x0 0x1fe00130 0x0 0x8>;
clock-frequency = <100000>;
clocks = <&clk LOONGSON2_MISC_CLK>;
interrupt-parent = <&liointc>;
interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";

View File

@ -38,6 +38,8 @@ static inline bool acpi_has_cpu_in_madt(void)
extern struct list_head acpi_wakeup_device_list;
extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
extern void acpi_add_early_pio(void);
extern void acpi_remove_early_pio(void);
extern int __init parse_acpi_topology(void);
#endif /* !CONFIG_ACPI */

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_LOONGARCH_CURRENT_H
#define __ASM_LOONGARCH_CURRENT_H
#include <linux/compiler.h>
#ifndef __ASSEMBLER__
#include <asm/percpu.h>
struct task_struct;
DECLARE_PER_CPU(struct task_struct *, cpu_tasks);
register struct task_struct *current_thread_pointer __asm__("$tp");
static __always_inline struct task_struct *get_current(void)
{
return current_thread_pointer;
}
#define current get_current()
static __always_inline void set_current(struct task_struct *task)
{
__this_cpu_write(cpu_tasks, task);
}
#endif /* __ASSEMBLER__ */
#endif /* __ASM_LOONGARCH_CURRENT_H */

View File

@ -41,6 +41,8 @@ struct kimage_arch {
unsigned long systable_ptr;
};
struct kimage;
#ifdef CONFIG_KEXEC_FILE
extern const struct kexec_file_ops kexec_efi_ops;
extern const struct kexec_file_ops kexec_elf_ops;
@ -59,7 +61,6 @@ typedef void (*do_kexec_t)(unsigned long efi_boot,
unsigned long start_addr,
unsigned long first_ind_entry);
struct kimage;
extern const unsigned char relocate_new_kernel[];
extern const size_t relocate_new_kernel_size;
extern void kexec_reboot(void);

View File

@ -5,7 +5,6 @@
#ifndef __ASM_PERCPU_H
#define __ASM_PERCPU_H
#include <asm/cmpxchg.h>
#include <asm/loongarch.h>
/*

View File

@ -429,6 +429,8 @@ static inline pte_t pte_mkwrite_novma(pte_t pte)
static inline pte_t pte_wrprotect(pte_t pte)
{
if (pte_val(pte) & _PAGE_DIRTY)
pte_val(pte) |= _PAGE_MODIFIED;
pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
return pte;
}
@ -535,6 +537,8 @@ static inline pmd_t pmd_mkwrite_novma(pmd_t pmd)
static inline pmd_t pmd_wrprotect(pmd_t pmd)
{
if (pmd_val(pmd) & _PAGE_DIRTY)
pmd_val(pmd) |= _PAGE_MODIFIED;
pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
return pmd;
}

View File

@ -81,8 +81,9 @@ extern int __cpu_logical_map[NR_CPUS];
struct seq_file;
struct secondary_data {
unsigned long task;
unsigned long stack;
unsigned long thread_info;
unsigned long offset;
};
extern struct secondary_data cpuboot_data;

View File

@ -184,6 +184,7 @@
.cfi_rel_offset ra, PT_ERA
.endif
cfi_st tp, PT_R2, \docfi
cfi_st u0, PT_R21, \docfi
cfi_st fp, PT_R22, \docfi
/* Set thread_info if we're coming from user mode */
@ -191,10 +192,13 @@
andi t0, t0, 0x3 /* extract pplv bit */
beqz t0, 9f
LONG_LI tp, ~_THREAD_MASK
and tp, tp, sp
cfi_st u0, PT_R21, \docfi
csrrd u0, PERCPU_BASE_KS
la_abs t1, cpu_tasks
#ifdef CONFIG_SMP
LONG_ADD t1, t1, u0
#endif
LONG_L tp, t1, 0
9:
#ifdef CONFIG_KGDB
li.w t0, CSR_CRMD_WE

View File

@ -15,7 +15,6 @@ struct task_struct;
* __switch_to - switch execution of a task
* @prev: The task previously executed.
* @next: The task to begin executing.
* @next_ti: task_thread_info(next).
* @sched_ra: __schedule return address.
* @sched_cfa: __schedule call frame address.
*
@ -23,8 +22,7 @@ struct task_struct;
* the context of next. Returns prev.
*/
extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *next, struct thread_info *next_ti,
void *sched_ra, void *sched_cfa);
struct task_struct *next, void *sched_ra, void *sched_cfa);
/*
* For newly created kernel threads switch_to() will return to
@ -37,7 +35,8 @@ do { \
lose_fpu_inatomic(1, prev); \
lose_lbt_inatomic(1, prev); \
hw_breakpoint_thread_switch(next); \
(last) = __switch_to(prev, next, task_thread_info(next), \
set_current(next); \
(last) = __switch_to(prev, next, \
__builtin_return_address(0), __builtin_frame_address(0)); \
} while (0)

View File

@ -22,7 +22,6 @@
* must also be changed
*/
struct thread_info {
struct task_struct *task; /* main task structure */
unsigned long flags; /* low level flags */
unsigned long tp_value; /* thread pointer */
__u32 cpu; /* current CPU */
@ -37,20 +36,11 @@ struct thread_info {
*/
#define INIT_THREAD_INFO(tsk) \
{ \
.task = &tsk, \
.flags = _TIF_FIXADE, \
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
}
/* How to get the thread information struct from C. */
register struct thread_info *__current_thread_info __asm__("$tp");
static inline struct thread_info *current_thread_info(void)
{
return __current_thread_info;
}
register unsigned long current_stack_pointer __asm__("$sp");
#endif /* !__ASSEMBLER__ */

View File

@ -16,6 +16,7 @@
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <linux/serial_core.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/numa.h>
#include <asm/loongson.h>
@ -59,6 +60,33 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
return ioremap_cache(phys, size);
}
#define PIO_BASE (unsigned long)PCI_IOBASE
#define PIO_SIZE ALIGN(ISA_IOSIZE, PAGE_SIZE)
static bool acpi_pio;
/* Add PIO for early access */
void acpi_add_early_pio(void)
{
if (!acpi_disabled) {
acpi_pio = true;
vmap_page_range(PIO_BASE, PIO_BASE + PIO_SIZE,
LOONGSON_LIO_BASE, pgprot_device(PAGE_KERNEL));
}
}
/* Remove PIO for PCI register */
void acpi_remove_early_pio(void)
{
if (!acpi_pio)
return;
if (!acpi_disabled) {
acpi_pio = false;
vunmap_range(PIO_BASE, PIO_BASE + PIO_SIZE);
}
}
#ifdef CONFIG_SMP
static int set_processor_mask(u32 id, u32 pass)
{

View File

@ -70,7 +70,7 @@ static void __used output_task_defines(void)
{
COMMENT("LoongArch task_struct offsets.");
OFFSET(TASK_STATE, task_struct, __state);
OFFSET(TASK_THREAD_INFO, task_struct, stack);
OFFSET(TASK_STACK, task_struct, stack);
OFFSET(TASK_FLAGS, task_struct, flags);
OFFSET(TASK_MM, task_struct, mm);
OFFSET(TASK_PID, task_struct, pid);
@ -84,7 +84,6 @@ static void __used output_task_defines(void)
static void __used output_thread_info_defines(void)
{
COMMENT("LoongArch thread_info offsets.");
OFFSET(TI_TASK, thread_info, task);
OFFSET(TI_FLAGS, thread_info, flags);
OFFSET(TI_TP_VALUE, thread_info, tp_value);
OFFSET(TI_CPU, thread_info, cpu);
@ -266,8 +265,9 @@ static void __used output_signal_defines(void)
static void __used output_smpboot_defines(void)
{
COMMENT("Linux smp cpu boot offsets.");
OFFSET(CPU_BOOT_TASK, secondary_data, task);
OFFSET(CPU_BOOT_STACK, secondary_data, stack);
OFFSET(CPU_BOOT_TINFO, secondary_data, thread_info);
OFFSET(CPU_BOOT_OFFSET, secondary_data, offset);
BLANK();
}
#endif

View File

@ -67,8 +67,11 @@ SYM_CODE_START(handle_syscall)
#endif
move u0, t0
LONG_LI tp, ~_THREAD_MASK
and tp, tp, sp
la_abs t1, cpu_tasks
#ifdef CONFIG_SMP
LONG_ADD t1, t1, u0
#endif
LONG_L tp, t1, 0
move a0, sp
bl do_syscall

View File

@ -74,10 +74,11 @@ SYM_CODE_START(kernel_entry) # kernel entry point
/* GPR21 used for percpu base (runtime), initialized as 0 */
move u0, zero
la.pcrel tp, init_thread_union
/* Set the SP after an empty pt_regs. */
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
PTR_ADD sp, sp, tp
la.pcrel tp, init_task
la.pcrel t0, init_stack
PTR_LI t1, _THREAD_SIZE
PTR_ADD t0, t0, t1
PTR_ADDI sp, t0, -PT_SIZE
set_saved_sp sp, t0, t1
#ifdef CONFIG_RELOCATABLE
@ -86,8 +87,10 @@ SYM_CODE_START(kernel_entry) # kernel entry point
#ifdef CONFIG_RANDOMIZE_BASE
/* Repoint the sp into the new kernel */
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
PTR_ADD sp, sp, tp
LONG_LPTR t0, tp, TASK_STACK
PTR_LI t1, _THREAD_SIZE
PTR_ADD t0, t0, t1
PTR_ADDI sp, t0, -PT_SIZE
set_saved_sp sp, t0, t1
/* Jump to the new kernel: new_pc = current_pc + random_offset */
@ -127,8 +130,9 @@ SYM_CODE_START(smpboot_entry)
csrxchg t0, t1, LOONGARCH_CSR_IMPCTL1
#endif
la.pcrel t0, cpuboot_data
ld.d tp, t0, CPU_BOOT_TASK
ld.d sp, t0, CPU_BOOT_STACK
ld.d tp, t0, CPU_BOOT_TINFO
ld.d u0, t0, CPU_BOOT_OFFSET
bl start_secondary
ASM_BUG()

View File

@ -60,6 +60,8 @@ unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif
DEFINE_PER_CPU(struct task_struct *, cpu_tasks);
/*
* Idle related variables and functions
*/

View File

@ -313,7 +313,7 @@ unsigned long __init relocate_kernel(void)
reloc_offset += random_offset;
/* The current thread is now within the relocated kernel */
__current_thread_info = RELOCATED_KASLR(__current_thread_info);
current_thread_pointer = RELOCATED_KASLR(current_thread_pointer);
update_reloc_offset(&reloc_offset, random_offset);
}

View File

@ -502,6 +502,8 @@ static __init int arch_reserve_pio_range(void)
{
struct device_node *np;
acpi_add_early_pio();
for_each_node_by_name(np, "isa") {
struct of_range range;
struct of_range_parser parser;
@ -593,6 +595,7 @@ void __init setup_arch(char **cmdline_p)
{
cpu_probe();
unwind_init();
set_current(current);
init_environ();
efi_init();

View File

@ -400,8 +400,9 @@ void loongson_boot_secondary(int cpu, struct task_struct *idle)
pr_info("Booting CPU#%d...\n", cpu);
entry = __pa_symbol((unsigned long)&smpboot_entry);
cpuboot_data.stack = (unsigned long)__KSTK_TOS(idle);
cpuboot_data.thread_info = (unsigned long)task_thread_info(idle);
cpuboot_data.task = (unsigned long)idle;
cpuboot_data.stack = (unsigned long)task_pt_regs(idle);
cpuboot_data.offset = per_cpu_offset(cpu);
csr_mail_send(entry, cpu_logical_map(cpu), 0);
@ -663,6 +664,7 @@ asmlinkage void start_secondary(void)
set_my_cpu_offset(per_cpu_offset(cpu));
cpu_probe();
set_current(current);
constant_clockevent_init();
loongson_init_secondary();
@ -705,6 +707,7 @@ static void stop_this_cpu(void *dummy)
set_cpu_online(smp_processor_id(), false);
calculate_cpu_foreign_map();
local_irq_disable();
rcutree_report_cpu_dead();
while (true);
}

View File

@ -12,7 +12,7 @@
/*
* task_struct *__switch_to(task_struct *prev, task_struct *next,
* struct thread_info *next_ti, void *sched_ra, void *sched_cfa)
* void *sched_ra, void *sched_cfa)
*/
.align 5
SYM_FUNC_START(__switch_to)
@ -24,8 +24,8 @@ SYM_FUNC_START(__switch_to)
LONG_SPTR t1, a0, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET)
cpu_save_nonscratch a0
LONG_SPTR a3, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET)
LONG_SPTR a4, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET)
LONG_SPTR a2, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET)
LONG_SPTR a3, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET)
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
la t7, __stack_chk_guard
@ -33,11 +33,12 @@ SYM_FUNC_START(__switch_to)
LONG_SPTR t8, t7, 0
#endif
move tp, a2
move tp, a1
cpu_restore_nonscratch a1
li.w t0, _THREAD_SIZE
PTR_ADD t0, t0, tp
LONG_LPTR t0, a1, (TASK_STACK - TASK_STRUCT_OFFSET)
PTR_LI t1, _THREAD_SIZE
PTR_ADD t0, t0, t1
set_saved_sp t0, t1, t2
LONG_LPTR t1, a1, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET)
@ -45,6 +46,7 @@ SYM_FUNC_START(__switch_to)
#ifdef CONFIG_32BIT
PTR_ADDI a0, a0, -TASK_STRUCT_OFFSET
PTR_ADDI tp, tp, -TASK_STRUCT_OFFSET
#endif
jr ra
SYM_FUNC_END(__switch_to)

View File

@ -107,6 +107,12 @@ static void show_stacktrace(struct task_struct *task,
unsigned long stackdata;
unsigned long *sp = (unsigned long *)regs->regs[3];
if (!task)
task = current;
if (!try_get_task_stack(task))
return;
printk("%sStack :", loglvl);
i = 0;
while ((unsigned long) sp & (PAGE_SIZE - 1)) {
@ -129,6 +135,8 @@ static void show_stacktrace(struct task_struct *task,
}
pr_cont("\n");
show_backtrace(task, regs, loglvl, user);
put_task_stack(task);
}
void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)

View File

@ -234,5 +234,5 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
}
return __set_memory(addr, 1, set, clear);
return __set_memory(addr, nr, set, clear);
}

View File

@ -5,11 +5,18 @@
* Copyright (C) 2022 Loongson Technology Corporation Limited
*/
#include <linux/memory.h>
#include <asm/asm-offsets.h>
#include "bpf_jit.h"
#define LOONGARCH_MAX_REG_ARGS 8
#define LOONGARCH_SAVE_RA_NINSNS 1
#define LOONGARCH_LONG_JUMP_NINSNS 5
#define LOONGARCH_TCC_SLOT_NINSNS 1
#define LOONGARCH_PROLOGUE_SKIP_INSNS \
(LOONGARCH_SAVE_RA_NINSNS + LOONGARCH_LONG_JUMP_NINSNS + LOONGARCH_TCC_SLOT_NINSNS)
#define LOONGARCH_LONG_JUMP_NBYTES (LOONGARCH_LONG_JUMP_NINSNS * 4)
#define LOONGARCH_FENTRY_NINSNS 2
@ -143,8 +150,13 @@ static void build_prologue(struct jit_ctx *ctx)
stack_adjust = round_up(stack_adjust, 16);
stack_adjust += bpf_stack_adjust;
/*
* Save the original return address to a temporary register to prevent
* it from being overwritten, then reserve space for the long jump and
* fentry trampoline slot for dynamically patching by ftrace at runtime.
* These instructions are bypassed during a tail call invocation.
*/
move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA);
/* Reserve space for the move_imm + jirl instruction */
for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++)
emit_insn(ctx, nop);
@ -253,10 +265,11 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
} else {
/*
* Call the next bpf prog and skip the first instruction
* of TCC initialization.
* Tail call to the next BPF program, passing offset in number
* of instructions to jirl to bypass the initial setup slots.
*/
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7);
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO,
LOONGARCH_GPR_T3, LOONGARCH_PROLOGUE_SKIP_INSNS);
}
}
@ -312,12 +325,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
*/
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off);
emit_insn(ctx, ldd, t3, REG_TCC, 0);
emit_insn(ctx, addid, t3, t3, 1);
emit_insn(ctx, std, t3, REG_TCC, 0);
emit_insn(ctx, addid, t2, LOONGARCH_GPR_ZERO, MAX_TAIL_CALL_CNT);
if (emit_tailcall_jmp(ctx, BPF_JSGT, t3, t2, jmp_offset) < 0)
if (emit_tailcall_jmp(ctx, BPF_JSGE, t3, t2, jmp_offset) < 0)
goto toofar;
emit_insn(ctx, addid, t3, t3, 1);
/*
* prog = array->ptrs[index];
* if (!prog)
@ -330,6 +343,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
if (emit_tailcall_jmp(ctx, BPF_JEQ, t2, LOONGARCH_GPR_ZERO, jmp_offset) < 0)
goto toofar;
emit_insn(ctx, std, t3, REG_TCC, 0);
/* goto *(prog->bpf_func + 4); */
off = offsetof(struct bpf_prog, bpf_func);
emit_insn(ctx, ldd, t3, t2, off);
@ -1147,6 +1162,19 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
/* function call */
case BPF_JMP | BPF_CALL:
/* Implement helper call to bpf_get_current_task/_btf() inline */
if (insn->src_reg == 0 && (insn->imm == BPF_FUNC_get_current_task ||
insn->imm == BPF_FUNC_get_current_task_btf)) {
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_TP);
break;
}
/* Implement helper call to bpf_get_smp_processor_id() inline */
if (insn->src_reg == 0 && insn->imm == BPF_FUNC_get_smp_processor_id) {
emit_insn(ctx, ldwu, regmap[BPF_REG_0], LOONGARCH_GPR_TP, TI_CPU);
break;
}
ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass,
&func_addr, &func_addr_fixed);
if (ret < 0)
@ -2367,3 +2395,15 @@ bool bpf_jit_supports_subprog_tailcalls(void)
{
return true;
}
bool bpf_jit_inlines_helper_call(s32 imm)
{
switch (imm) {
case BPF_FUNC_get_current_task:
case BPF_FUNC_get_current_task_btf:
case BPF_FUNC_get_smp_processor_id:
return true;
default:
return false;
}
}

View File

@ -65,6 +65,8 @@ static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
struct resource_entry *entry, *tmp;
struct acpi_device *device = ci->bridge;
acpi_remove_early_pio();
status = acpi_pci_probe_root_resources(ci);
if (status > 0) {
acpi_evaluate_integer(device->handle, "PCIH", NULL, &pci_h);

View File

@ -7,9 +7,12 @@
#include <asm/vdso/vdso.h>
#include <linux/build-salt.h>
#include <linux/elfnote.h>
#include <linux/version.h>
ELFNOTE_START(Linux, 0, "a")
.long LINUX_VERSION_CODE
ELFNOTE_END
BUILD_SALT

View File

@ -980,6 +980,8 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
static inline void set_pte(pte_t *ptep, pte_t pte)
{
if (pte_present(pte))
pte = clear_pte_bit(pte, __pgprot(_PAGE_UNUSED));
WRITE_ONCE(*ptep, pte);
}
@ -1359,8 +1361,6 @@ pgprot_t pgprot_writecombine(pgprot_t prot);
static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t entry, unsigned int nr)
{
if (pte_present(entry))
entry = clear_pte_bit(entry, __pgprot(_PAGE_UNUSED));
page_table_check_ptes_set(mm, addr, ptep, entry, nr);
for (;;) {
set_pte(ptep, entry);

View File

@ -1209,7 +1209,7 @@ int dat_peek_cmma(gfn_t start, union asce asce, unsigned int *count, u8 *values)
int rc;
rc = _dat_walk_gfn_range(start, start + *count, asce, &ops, DAT_WALK_DEFAULT, &state);
*count = state.end - start;
*count = state.end >= start ? state.end - start : 0;
/* Return success if at least one value was saved, otherwise an error. */
return (rc == -EFAULT && *count > 0) ? 0 : rc;
}
@ -1253,6 +1253,9 @@ int dat_get_cmma(union asce asce, gfn_t *start, unsigned int *count, u8 *values,
};
_dat_walk_gfn_range(*start, asce_end(asce), asce, &ops, DAT_WALK_IGN_HOLES, &state);
/* If no dirty pages were found, wrap around and continue searching */
if (*start && state.start == -1)
_dat_walk_gfn_range(0, *start, asce, &ops, DAT_WALK_IGN_HOLES, &state);
if (state.start == -1) {
*count = 0;

View File

@ -332,7 +332,7 @@ static long gmap_clear_young_crste(union crste *crstep, gfn_t gfn, gfn_t end, st
new.h.i = 1;
new.s.fc1.y = 0;
new.s.fc1.prefix_notif = 0;
if (new.s.fc1.d || !new.h.p)
if ((new.s.fc1.d || !new.h.p) && !new.s.fc1.s)
folio_set_dirty(phys_to_folio(crste_origin_large(crste)));
new.s.fc1.d = 0;
new.h.p = 1;
@ -1098,23 +1098,46 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf
return 0;
}
static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
static long __set_cmma_clean_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
{
__atomic64_or(PGSTE_CMMA_D_BIT, &pgste_of(ptep)->val);
union pgste pgste;
pgste = pgste_get_lock(ptep);
pgste.cmma_d = 0;
pgste_set_unlock(ptep, pgste);
if (need_resched())
return next;
return 0;
}
void gmap_set_cmma_all_dirty(struct gmap *gmap)
static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
{
const struct dat_walk_ops ops = { .pte_entry = __set_cmma_dirty_pte, };
union pgste pgste;
pgste = pgste_get_lock(ptep);
if (!pgste.cmma_d)
atomic64_inc(walk->priv);
pgste.cmma_d = 1;
pgste_set_unlock(ptep, pgste);
if (need_resched())
return next;
return 0;
}
void _gmap_set_cmma_all(struct gmap *gmap, bool dirty)
{
const struct dat_walk_ops ops = {
.pte_entry = dirty ? __set_cmma_dirty_pte : __set_cmma_clean_pte,
};
gfn_t gfn = 0;
do {
scoped_guard(read_lock, &gmap->kvm->mmu_lock)
gfn = _dat_walk_gfn_range(gfn, asce_end(gmap->asce), gmap->asce, &ops,
DAT_WALK_IGN_HOLES, NULL);
DAT_WALK_IGN_HOLES,
&gmap->kvm->arch.cmma_dirty_pages);
cond_resched();
} while (gfn);
}
@ -1287,7 +1310,7 @@ static int gmap_protect_asce_top_level(struct kvm_s390_mmu_cache *mc, struct gma
/* Pairs with the smp_wmb() in kvm_mmu_invalidate_end(). */
smp_rmb();
rc = kvm_s390_get_guest_pages(sg->kvm, context.f, asce.rsto, asce.dt + 1, false);
rc = kvm_s390_get_guest_pages(sg->kvm, context.f, asce.rsto, asce.tl + 1, false);
if (rc > 0)
rc = -EFAULT;
if (!rc)

View File

@ -104,7 +104,7 @@ int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn
gfn_t r_gfn, int level);
int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,
kvm_pfn_t pfn, int level, bool wr);
void gmap_set_cmma_all_dirty(struct gmap *gmap);
void _gmap_set_cmma_all(struct gmap *gmap, bool dirty);
void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn);
struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *gmap,
union asce asce, int edat_level);
@ -198,6 +198,16 @@ static inline bool pte_needs_unshadow(union pte oldpte, union pte newpte, union
return !newpte.h.p || !newpte.s.pr;
}
static inline void gmap_set_cmma_all_dirty(struct gmap *gmap)
{
_gmap_set_cmma_all(gmap, true);
}
static inline void gmap_set_cmma_all_clean(struct gmap *gmap)
{
_gmap_set_cmma_all(gmap, false);
}
static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte,
union pgste pgste, gfn_t gfn, bool needs_lock)
{

View File

@ -1022,9 +1022,11 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
if (!kvm->arch.use_cmma)
break;
guard(mutex)(&kvm->lock);
VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
do {
start_gfn = dat_reset_cmma(kvm->arch.gmap->asce, start_gfn);
scoped_guard(read_lock, &kvm->mmu_lock)
start_gfn = dat_reset_cmma(kvm->arch.gmap->asce, start_gfn);
cond_resched();
} while (start_gfn);
ret = 0;
@ -1217,13 +1219,13 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
/*
* Must be called with kvm->srcu held to avoid races on memslots, and with
* kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
* kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
* and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_start_migration(struct kvm *kvm)
{
struct kvm_memory_slot *ms;
struct kvm_memslots *slots;
unsigned long ram_pages = 0;
int bkt;
/* migration mode already enabled */
@ -1240,28 +1242,54 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
kvm_for_each_memslot(ms, bkt, slots) {
if (!ms->dirty_bitmap)
return -EINVAL;
ram_pages += ms->npages;
}
/* mark all the pages as dirty */
gmap_set_cmma_all_dirty(kvm->arch.gmap);
atomic64_set(&kvm->arch.cmma_dirty_pages, ram_pages);
kvm->arch.migration_mode = 1;
/*
* Set the flag and let KVM handle ESSA manually, potentially setting
* the cmma_d bit in some PGSTEs and increasing cmma_dirty_pages.
* At this point cmma_dirty_pages is still 0, and all existing PGSTEs
* have their cmma_d bit set to 0.
* Any newly allocated page table has its entries marked as cmma-clean,
* which is fine because the CMMA values are not dirty.
*/
WRITE_ONCE(kvm->arch.migration_mode, 1);
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_START_MIGRATION);
/*
* Mark all PGSTEs as cmma-dirty, increasing cmma_dirty_pages as needed,
* but without double-counting pages that have become dirty on their own
* in the meantime.
* At this point some pages might have become dirty on their own already
* and cmma_dirty_pages might therefore be non-zero.
*/
gmap_set_cmma_all_dirty(kvm->arch.gmap);
return 0;
}
/*
* Must be called with kvm->slots_lock to avoid races with ourselves and
* kvm_s390_vm_start_migration.
* Must be called with kvm->slots_lock to avoid races with ourselves,
* kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
{
/* migration mode already disabled */
if (!kvm->arch.migration_mode)
return 0;
kvm->arch.migration_mode = 0;
/*
* Unset the flag and propagate to all vCPUs. From now on the cmma_d
* bit will not be touched on any PGSTE.
* At this point cmma_dirty_pages is possibly non-zero, and thus some
* PGSTEs might have cmma_d set.
*/
WRITE_ONCE(kvm->arch.migration_mode, 0);
if (kvm->arch.use_cmma)
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
/* Clear cmma_d on all existing PGSTEs and set cmma_dirty_pages to 0. */
gmap_set_cmma_all_clean(kvm->arch.gmap);
atomic64_set(&kvm->arch.cmma_dirty_pages, 0);
/*
* At this point the system has the expected state: migration_mode is 0,
* cmma_dirty_pages is 0, and all existing PGSTEs have their cmma_d bit
* set to 0.
*/
return 0;
}
@ -2317,8 +2345,8 @@ static int kvm_s390_get_cmma_bits(struct kvm *kvm,
static int kvm_s390_set_cmma_bits(struct kvm *kvm,
const struct kvm_s390_cmma_log *args)
{
struct kvm_s390_mmu_cache *mc;
u8 *bits = NULL;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
u8 *bits __free(kvfree) = NULL;
int r = 0;
if (!kvm->arch.use_cmma)
@ -2338,18 +2366,16 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
return -ENOMEM;
bits = vmalloc(array_size(sizeof(*bits), args->count));
if (!bits)
goto out;
return -ENOMEM;
r = copy_from_user(bits, (void __user *)args->values, args->count);
if (r) {
r = -EFAULT;
goto out;
}
if (r)
return -EFAULT;
do {
r = kvm_s390_mmu_cache_topup(mc);
if (r)
break;
return r;
scoped_guard(read_lock, &kvm->mmu_lock) {
r = dat_set_cmma_bits(mc, kvm->arch.gmap->asce, args->start_gfn,
args->count, args->mask, bits);
@ -2357,9 +2383,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
} while (r == -ENOMEM);
set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
out:
kvm_s390_free_mmu_cache(mc);
vfree(bits);
return r;
}
@ -3584,7 +3608,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
sca_add_vcpu(vcpu);
}
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0)
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
vcpu->kvm->arch.user_operexec)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
}

View File

@ -366,7 +366,9 @@ static int handle_sske(struct kvm_vcpu *vcpu)
if (rc > 1)
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
if (rc == -ENOMEM) {
kvm_s390_mmu_cache_topup(vcpu->arch.mc);
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
if (rc)
return rc;
continue;
}
if (rc < 0)
@ -1122,7 +1124,9 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
if (rc > 1)
return kvm_s390_inject_program_int(vcpu, rc);
if (rc == -ENOMEM) {
kvm_s390_mmu_cache_topup(vcpu->arch.mc);
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
if (rc)
return rc;
continue;
}
if (rc < 0)
@ -1232,7 +1236,7 @@ static int handle_essa(struct kvm_vcpu *vcpu)
: ESSA_SET_STABLE_IF_RESIDENT))
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
if (!vcpu->kvm->arch.migration_mode) {
if (!READ_ONCE(vcpu->kvm->arch.migration_mode)) {
/*
* CMMA is enabled in the KVM settings, but is disabled in
* the SIE block and in the mm_context, and we are not doing

View File

@ -181,7 +181,8 @@ void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
if (IS_ERR_OR_NULL(ptep))
return;
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
if (pte_present(*ptep))
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
pte_unmap_unlock(ptep, ptl);
}
EXPORT_SYMBOL_GPL(gmap_helper_try_set_pte_unused);

View File

@ -1434,7 +1434,6 @@ enum kvm_mmu_type {
};
struct kvm_arch {
unsigned long n_used_mmu_pages;
unsigned long n_requested_mmu_pages;
unsigned long n_max_mmu_pages;
unsigned int indirect_shadow_pages;
@ -1700,6 +1699,7 @@ struct kvm_vm_stat {
u64 mmu_recycled;
u64 mmu_cache_miss;
u64 mmu_unsync;
u64 mmu_shadow_pages;
union {
struct {
atomic64_t pages_4k;
@ -2525,16 +2525,6 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
kvm_x86_call(vcpu_unblocking)(vcpu);
}
static inline int kvm_cpu_get_apicid(int mps_cpu)
{
#ifdef CONFIG_X86_LOCAL_APIC
return default_cpu_present_to_apicid(mps_cpu);
#else
WARN_ON_ONCE(1);
return BAD_APICID;
#endif
}
int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
#define KVM_CLOCK_VALID_FLAGS \

View File

@ -26,7 +26,6 @@ u32 default_cpu_present_to_apicid(int mps_cpu)
else
return BAD_APICID;
}
EXPORT_SYMBOL_FOR_KVM(default_cpu_present_to_apicid);
/*
* Set up the logical destination ID when the APIC operates in logical

View File

@ -194,7 +194,8 @@ int kvm_pic_set_irq(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
int irq = e->irqchip.pin;
int ret, irq_level;
BUG_ON(irq < 0 || irq >= PIC_NUM_PINS);
if (WARN_ON_ONCE(irq < 0 || irq >= PIC_NUM_PINS))
return -1;
pic_lock(s);
irq_level = __kvm_irq_line_state(&s->irq_states[irq],

View File

@ -84,7 +84,7 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
static void rtc_status_pending_eoi_check_valid(struct kvm_ioapic *ioapic)
{
if (WARN_ON(ioapic->rtc_status.pending_eoi < 0))
if (WARN_ON_ONCE(ioapic->rtc_status.pending_eoi < 0))
kvm_rtc_eoi_tracking_restore_all(ioapic);
}
@ -484,7 +484,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
* ensures that it is only called if it is >= zero, namely
* if rtc_irq_check_coalesced returns false).
*/
BUG_ON(ioapic->rtc_status.pending_eoi != 0);
WARN_ON_ONCE(ioapic->rtc_status.pending_eoi);
ret = __kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
&ioapic->rtc_status);
ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
@ -504,7 +504,8 @@ int kvm_ioapic_set_irq(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
int irq = e->irqchip.pin;
int ret, irq_level;
BUG_ON(irq < 0 || irq >= IOAPIC_NUM_PINS);
if (WARN_ON_ONCE(irq < 0 || irq >= IOAPIC_NUM_PINS))
return -1;
spin_lock(&ioapic->lock);
irq_level = __kvm_irq_line_state(&ioapic->irq_states[irq],

View File

@ -767,7 +767,7 @@ static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
kvm_x86_call(hwapic_isr_update)(apic->vcpu, vec);
else {
++apic->isr_count;
BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
KVM_BUG_ON(apic->isr_count > MAX_APIC_VECTOR, apic->vcpu->kvm);
/*
* ISR (in service register) bit is set when injecting an interrupt.
* The highest vector is injected. Thus the latest bit set matches
@ -808,7 +808,7 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
kvm_x86_call(hwapic_isr_update)(apic->vcpu, apic_find_highest_isr(apic));
else {
--apic->isr_count;
BUG_ON(apic->isr_count < 0);
KVM_BUG_ON(apic->isr_count < 0, apic->vcpu->kvm);
apic->highest_isr_cache = -1;
}
}
@ -980,6 +980,8 @@ static void apic_update_ppr(struct kvm_lapic *apic)
if (__apic_update_ppr(apic, &ppr) &&
apic_has_interrupt_for_ppr(apic, ppr) != -1)
kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
else
kvm_lapic_update_cr8_intercept(apic->vcpu);
}
void kvm_apic_update_ppr(struct kvm_vcpu *vcpu)

View File

@ -1802,13 +1802,13 @@ static void kvm_mmu_check_sptes_at_free(struct kvm_mmu_page *sp)
static void kvm_account_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
kvm->arch.n_used_mmu_pages++;
kvm->stat.mmu_shadow_pages++;
kvm_account_pgtable_pages((void *)sp->spt, +1);
}
static void kvm_unaccount_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
kvm->arch.n_used_mmu_pages--;
kvm->stat.mmu_shadow_pages--;
kvm_account_pgtable_pages((void *)sp->spt, -1);
}
@ -2836,9 +2836,9 @@ static unsigned long kvm_mmu_zap_oldest_mmu_pages(struct kvm *kvm,
static inline unsigned long kvm_mmu_available_pages(struct kvm *kvm)
{
if (kvm->arch.n_max_mmu_pages > kvm->arch.n_used_mmu_pages)
if (kvm->arch.n_max_mmu_pages > kvm->stat.mmu_shadow_pages)
return kvm->arch.n_max_mmu_pages -
kvm->arch.n_used_mmu_pages;
kvm->stat.mmu_shadow_pages;
return 0;
}
@ -2874,11 +2874,11 @@ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned long goal_nr_mmu_pages)
{
write_lock(&kvm->mmu_lock);
if (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages) {
kvm_mmu_zap_oldest_mmu_pages(kvm, kvm->arch.n_used_mmu_pages -
if (kvm->stat.mmu_shadow_pages > goal_nr_mmu_pages) {
kvm_mmu_zap_oldest_mmu_pages(kvm, kvm->stat.mmu_shadow_pages -
goal_nr_mmu_pages);
goal_nr_mmu_pages = kvm->arch.n_used_mmu_pages;
goal_nr_mmu_pages = kvm->stat.mmu_shadow_pages;
}
kvm->arch.n_max_mmu_pages = goal_nr_mmu_pages;

View File

@ -303,7 +303,7 @@ TRACE_EVENT(
TP_fast_assign(
__entry->mmu_valid_gen = kvm->arch.mmu_valid_gen;
__entry->mmu_used_pages = kvm->arch.n_used_mmu_pages;
__entry->mmu_used_pages = kvm->stat.mmu_shadow_pages;
),
TP_printk("kvm-mmu-valid-gen %u used_pages %x",

View File

@ -1410,9 +1410,10 @@ static bool wrprot_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
u64 new_spte;
bool spte_set = false;
rcu_read_lock();
if (KVM_BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL, kvm))
return false;
BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL);
rcu_read_lock();
for_each_tdp_pte_min_level(iter, kvm, root, min_level, start, end) {
retry:
@ -1844,7 +1845,8 @@ static bool write_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root,
u64 new_spte;
bool spte_set = false;
BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL);
if (KVM_BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL, kvm))
return false;
rcu_read_lock();

View File

@ -460,8 +460,8 @@ void avic_ring_doorbell(struct kvm_vcpu *vcpu)
int cpu = READ_ONCE(vcpu->cpu);
if (cpu != get_cpu()) {
wrmsrq(MSR_AMD64_SVM_AVIC_DOORBELL, kvm_cpu_get_apicid(cpu));
trace_kvm_avic_doorbell(vcpu->vcpu_id, kvm_cpu_get_apicid(cpu));
wrmsrq(MSR_AMD64_SVM_AVIC_DOORBELL, cpu_physical_id(cpu));
trace_kvm_avic_doorbell(vcpu->vcpu_id, cpu_physical_id(cpu));
}
put_cpu();
}
@ -1013,7 +1013,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
enum avic_vcpu_action action)
{
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
int h_physical_id = kvm_cpu_get_apicid(cpu);
int h_physical_id = cpu_physical_id(cpu);
struct vcpu_svm *svm = to_svm(vcpu);
unsigned long flags;
u64 entry;

View File

@ -2152,7 +2152,8 @@ static gpa_t svm_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
struct vcpu_svm *svm = to_svm(vcpu);
struct kvm_mmu *mmu = vcpu->arch.mmu;
BUG_ON(!mmu_is_nested(vcpu));
if (WARN_ON_ONCE(!mmu_is_nested(vcpu)))
return gpa;
/* Non-GMET walks are always user-walks */
if (!(svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_GMET))

View File

@ -7470,7 +7470,8 @@ static gpa_t vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
{
struct kvm_mmu *mmu = vcpu->arch.mmu;
BUG_ON(!mmu_is_nested(vcpu));
if (WARN_ON_ONCE(!mmu_is_nested(vcpu)))
return gpa;
/*
* MBEC differentiates based on the effective U/S bit of

View File

@ -6873,11 +6873,10 @@ int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
void vmx_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
{
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
int tpr_threshold;
if (is_guest_mode(vcpu) &&
nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
nested_cpu_has(get_vmcs12(vcpu), CPU_BASED_TPR_SHADOW))
return;
guard(vmx_vmcs01)(vcpu);

View File

@ -244,6 +244,7 @@ const struct kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, mmu_recycled),
STATS_DESC_COUNTER(VM, mmu_cache_miss),
STATS_DESC_ICOUNTER(VM, mmu_unsync),
STATS_DESC_ICOUNTER(VM, mmu_shadow_pages),
STATS_DESC_ICOUNTER(VM, pages_4k),
STATS_DESC_ICOUNTER(VM, pages_2m),
STATS_DESC_ICOUNTER(VM, pages_1g),
@ -5317,7 +5318,6 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
r = kvm_apic_set_state(vcpu, s);
if (r)
return r;
kvm_lapic_update_cr8_intercept(vcpu);
return 0;
}
@ -12418,8 +12418,6 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
kvm_x86_call(post_set_cr3)(vcpu, sregs->cr3);
kvm_set_cr8(vcpu, sregs->cr8);
*mmu_reset_needed |= vcpu->arch.efer != sregs->efer;
kvm_x86_call(set_efer)(vcpu, sregs->efer);
@ -12448,7 +12446,7 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
kvm_lapic_update_cr8_intercept(vcpu);
kvm_set_cr8(vcpu, sregs->cr8);
/* Older userspace won't unhalt the vcpu on reset. */
if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 &&

View File

@ -550,13 +550,20 @@ static void bfq_pd_init(struct blkg_policy_data *pd)
bfqg->rq_pos_tree = RB_ROOT;
}
static void bfq_pd_free(struct blkg_policy_data *pd)
static void bfqg_release(struct rcu_head *rcu)
{
struct blkg_policy_data *pd =
container_of(rcu, struct blkg_policy_data, rcu_head);
struct bfq_group *bfqg = pd_to_bfqg(pd);
bfqg_put(bfqg);
}
static void bfq_pd_free(struct blkg_policy_data *pd)
{
call_rcu(&pd->rcu_head, bfqg_release);
}
static void bfq_pd_reset_stats(struct blkg_policy_data *pd)
{
struct bfq_group *bfqg = pd_to_bfqg(pd);
@ -936,14 +943,23 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
void bfq_end_wr_async(struct bfq_data *bfqd)
{
struct request_queue *q = bfqd->queue;
struct blkcg_gq *blkg;
list_for_each_entry(blkg, &bfqd->queue->blkg_list, q_node) {
mutex_lock(&q->blkcg_mutex);
spin_lock_irq(&q->queue_lock);
spin_lock(&bfqd->lock);
list_for_each_entry(blkg, &q->blkg_list, q_node) {
struct bfq_group *bfqg = blkg_to_bfqg(blkg);
bfq_end_wr_async_queues(bfqd, bfqg);
}
bfq_end_wr_async_queues(bfqd, bfqd->root_group);
spin_unlock(&bfqd->lock);
spin_unlock_irq(&q->queue_lock);
mutex_unlock(&q->blkcg_mutex);
}
static int bfq_io_show_weight_legacy(struct seq_file *sf, void *v)
@ -1147,16 +1163,18 @@ static u64 bfqg_prfill_stat_recursive(struct seq_file *sf,
struct cgroup_subsys_state *pos_css;
u64 sum = 0;
lockdep_assert_held(&blkg->q->queue_lock);
rcu_read_lock();
blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
struct blkg_policy_data *pd;
struct bfq_stat *stat;
if (!pos_blkg->online)
continue;
stat = (void *)blkg_to_pd(pos_blkg, &blkcg_policy_bfq) + off;
pd = blkg_to_pd(pos_blkg, &blkcg_policy_bfq);
if (!pd)
continue;
stat = (void *)pd + off;
sum += bfq_stat_read(stat) + atomic64_read(&stat->aux_cnt);
}
rcu_read_unlock();
@ -1416,7 +1434,9 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) {}
void bfq_end_wr_async(struct bfq_data *bfqd)
{
spin_lock_irq(&bfqd->lock);
bfq_end_wr_async_queues(bfqd, bfqd->root_group);
spin_unlock_irq(&bfqd->lock);
}
struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)

View File

@ -2653,9 +2653,10 @@ static void bfq_end_wr(struct bfq_data *bfqd)
}
list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list)
bfq_bfqq_end_wr(bfqq);
bfq_end_wr_async(bfqd);
spin_unlock_irq(&bfqd->lock);
bfq_end_wr_async(bfqd);
}
static sector_t bfq_io_struct_pos(void *io_struct, bool request)
@ -7203,10 +7204,7 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
return -ENOMEM;
eq->elevator_data = bfqd;
spin_lock_irq(&q->queue_lock);
q->elevator = eq;
spin_unlock_irq(&q->queue_lock);
/*
* Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
@ -7239,7 +7237,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
* If the disk supports multiple actuators, copy independent
* access ranges from the request queue structure.
*/
spin_lock_irq(&q->queue_lock);
if (ia_ranges) {
/*
* Check if the disk ia_ranges size exceeds the current bfq
@ -7265,7 +7262,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
bfqd->sector[0] = 0;
bfqd->nr_sectors[0] = get_capacity(q->disk);
}
spin_unlock_irq(&q->queue_lock);
INIT_LIST_HEAD(&bfqd->dispatch);

View File

@ -94,7 +94,7 @@ void bio_integrity_prep(struct bio *bio, unsigned int action)
bio_integrity_init(bio, &bid->bip, &bid->bvec, 1);
bid->bio = bio;
bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY;
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
bio_integrity_alloc_buf(bio, GFP_NOIO, action & BI_ACT_ZERO);
if (action & BI_ACT_CHECK)
bio_integrity_setup_default(bio);

View File

@ -23,10 +23,10 @@ unsigned int fs_bio_integrity_alloc(struct bio *bio)
if (!action)
return 0;
iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOIO);
iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOFS);
bio_integrity_init(bio, &iib->bip, &iib->bvec, 1);
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
bio_integrity_alloc_buf(bio, GFP_NOFS, action & BI_ACT_ZERO);
if (action & BI_ACT_CHECK)
bio_integrity_setup_default(bio);
return action;

View File

@ -38,6 +38,7 @@ unsigned int __bio_integrity_action(struct bio *bio)
}
return BI_ACT_BUFFER | BI_ACT_CHECK;
case REQ_OP_WRITE:
case REQ_OP_ZONE_APPEND:
/*
* Flush masquerading as write?
*/
@ -64,20 +65,18 @@ unsigned int __bio_integrity_action(struct bio *bio)
}
EXPORT_SYMBOL_GPL(__bio_integrity_action);
void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer)
void bio_integrity_alloc_buf(struct bio *bio, gfp_t gfp, bool zero_buffer)
{
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct bio_integrity_payload *bip = bio_integrity(bio);
unsigned int len = bio_integrity_bytes(bi, bio_sectors(bio));
gfp_t gfp = GFP_NOIO | (zero_buffer ? __GFP_ZERO : 0);
void *buf;
buf = kmalloc(len, (gfp & ~__GFP_DIRECT_RECLAIM) |
__GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN);
buf = kmalloc(len, gfp | __GFP_NOWARN | (zero_buffer ? __GFP_ZERO : 0));
if (unlikely(!buf)) {
struct page *page;
page = mempool_alloc(&integrity_buf_pool, GFP_NOFS);
page = mempool_alloc(&integrity_buf_pool, gfp);
if (zero_buffer)
memset(page_address(page), 0, len);
bvec_set_page(&bip->bip_vec[0], page, len, 0);

View File

@ -1321,6 +1321,7 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
do {
size_t this_len = min(total_len, SZ_1M);
size_t copied;
struct folio *folio;
if (this_len > minsize * 2)
@ -1334,12 +1335,26 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
break;
bio_add_folio_nofail(bio, folio, this_len, 0);
if (copy_from_iter(folio_address(folio), this_len, iter) !=
this_len) {
if (iter->nofault)
copied = copy_folio_from_iter_atomic(folio, 0, this_len,
iter);
else
copied = copy_folio_from_iter(folio, 0, this_len, iter);
if (copied < this_len) {
/*
* Need to revert the iov iter for all bytes we have
* copied.
*
* However the bio size differs from the real copied
* bytes as @this_len is queued but only advanced
* less than that.
* Need to compensate that for the revert.
*/
iov_iter_revert(iter, bio->bi_iter.bi_size - this_len +
copied);
bio_free_folios(bio);
return -EFAULT;
}
total_len -= this_len;
} while (total_len && bio->bi_vcnt < bio->bi_max_vecs);

View File

@ -101,24 +101,27 @@ void blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol,
struct cgroup_subsys_state *pos_css;
unsigned int i;
lockdep_assert_held(&blkg->q->queue_lock);
WARN_ON_ONCE(!rcu_read_lock_held());
memset(sum, 0, sizeof(*sum));
rcu_read_lock();
blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
struct blkg_rwstat *rwstat;
if (!pos_blkg->online)
continue;
if (pol)
rwstat = (void *)blkg_to_pd(pos_blkg, pol) + off;
else
if (pol) {
struct blkg_policy_data *pd = blkg_to_pd(pos_blkg, pol);
if (!pd)
continue;
rwstat = (void *)pd + off;
} else {
rwstat = (void *)pos_blkg + off;
}
for (i = 0; i < BLKG_RWSTAT_NR; i++)
sum->cnt[i] += blkg_rwstat_read_counter(rwstat, i);
}
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(blkg_rwstat_recursive_sum);

View File

@ -136,6 +136,11 @@ static void blkg_free_workfn(struct work_struct *work)
spin_unlock_irq(&q->queue_lock);
mutex_unlock(&q->blkcg_mutex);
/*
* Release blkcg css ref only after blkg is removed from q->blkg_list,
* so concurrent iterators won't see a blkg with a freed blkcg.
*/
css_put(&blkg->blkcg->css);
blk_put_queue(q);
free_percpu(blkg->iostat_cpu);
percpu_ref_exit(&blkg->refcnt);
@ -164,23 +169,11 @@ static void blkg_free(struct blkcg_gq *blkg)
static void __blkg_release(struct rcu_head *rcu)
{
struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head);
struct blkcg *blkcg = blkg->blkcg;
int cpu;
#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
WARN_ON(!bio_list_empty(&blkg->async_bios));
#endif
/*
* Flush all the non-empty percpu lockless lists before releasing
* us, given these stat belongs to us.
*
* blkg_stat_lock is for serializing blkg stat update
*/
for_each_possible_cpu(cpu)
__blkcg_rstat_flush(blkcg, cpu);
/* release the blkcg and parent blkg refs this blkg has been holding */
css_put(&blkg->blkcg->css);
blkg_free(blkg);
}
@ -195,6 +188,17 @@ static void __blkg_release(struct rcu_head *rcu)
static void blkg_release(struct percpu_ref *ref)
{
struct blkcg_gq *blkg = container_of(ref, struct blkcg_gq, refcnt);
struct blkcg *blkcg = blkg->blkcg;
int cpu;
/*
* Flush all the non-empty percpu lockless lists before releasing
* us, given these stat belongs to us.
*
* blkg_stat_lock is for serializing blkg stat update
*/
for_each_possible_cpu(cpu)
__blkcg_rstat_flush(blkcg, cpu);
call_rcu(&blkg->rcu_head, __blkg_release);
}
@ -313,6 +317,9 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
goto out_exit_refcnt;
if (!blk_get_queue(disk->queue))
goto out_free_iostat;
/* blkg holds a reference to blkcg */
if (!css_tryget_online(&blkcg->css))
goto out_put_queue;
blkg->q = disk->queue;
INIT_LIST_HEAD(&blkg->q_node);
@ -353,6 +360,8 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
while (--i >= 0)
if (blkg->pd[i])
blkcg_policy[i]->pd_free_fn(blkg->pd[i]);
css_put(&blkcg->css);
out_put_queue:
blk_put_queue(disk->queue);
out_free_iostat:
free_percpu(blkg->iostat_cpu);
@ -381,18 +390,12 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
goto err_free_blkg;
}
/* blkg holds a reference to blkcg */
if (!css_tryget_online(&blkcg->css)) {
ret = -ENODEV;
goto err_free_blkg;
}
/* allocate */
if (!new_blkg) {
new_blkg = blkg_alloc(blkcg, disk, GFP_NOWAIT);
if (unlikely(!new_blkg)) {
ret = -ENOMEM;
goto err_put_css;
goto err_free_blkg;
}
}
blkg = new_blkg;
@ -402,7 +405,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
blkg->parent = blkg_lookup(blkcg_parent(blkcg), disk->queue);
if (WARN_ON_ONCE(!blkg->parent)) {
ret = -ENODEV;
goto err_put_css;
goto err_free_blkg;
}
blkg_get(blkg->parent);
}
@ -442,8 +445,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
blkg_put(blkg);
return ERR_PTR(ret);
err_put_css:
css_put(&blkcg->css);
err_free_blkg:
if (new_blkg)
blkg_free(new_blkg);
@ -468,22 +469,17 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
{
struct request_queue *q = disk->queue;
struct blkcg_gq *blkg;
unsigned long flags;
WARN_ON_ONCE(!rcu_read_lock_held());
blkg = blkg_lookup(blkcg, q);
if (blkg)
return blkg;
spin_lock_irqsave(&q->queue_lock, flags);
rcu_read_lock();
blkg = blkg_lookup(blkcg, q);
if (blkg) {
if (blkcg != &blkcg_root &&
blkg != rcu_dereference(blkcg->blkg_hint))
rcu_assign_pointer(blkcg->blkg_hint, blkg);
goto found;
rcu_read_unlock();
return blkg;
}
rcu_read_unlock();
/*
* Create blkgs walking down from blkcg_root to @blkcg, so that all
@ -515,8 +511,6 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
break;
}
found:
spin_unlock_irqrestore(&q->queue_lock, flags);
return blkg;
}
@ -698,9 +692,9 @@ const char *blkg_dev_name(struct blkcg_gq *blkg)
*
* This function invokes @prfill on each blkg of @blkcg if pd for the
* policy specified by @pol exists. @prfill is invoked with @sf, the
* policy data and @data and the matching queue lock held. If @show_total
* is %true, the sum of the return values from @prfill is printed with
* "Total" label at the end.
* policy data and @data under RCU read lock. If @show_total is %true, the
* sum of the return values from @prfill is printed with "Total" label at the
* end.
*
* This is to be used to construct print functions for
* cftype->read_seq_string method.
@ -716,10 +710,14 @@ void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg,
rcu_read_lock();
hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
spin_lock_irq(&blkg->q->queue_lock);
if (blkcg_policy_enabled(blkg->q, pol))
total += prfill(sf, blkg->pd[pol->plid], data);
spin_unlock_irq(&blkg->q->queue_lock);
struct blkg_policy_data *pd;
if (!blkcg_policy_enabled(blkg->q, pol))
continue;
pd = blkg_to_pd(blkg, pol);
if (pd)
total += prfill(sf, pd, data);
}
rcu_read_unlock();
@ -1190,13 +1188,10 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
else
css_rstat_flush(&blkcg->css);
rcu_read_lock();
hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
spin_lock_irq(&blkg->q->queue_lock);
guard(spinlock_irq)(&blkcg->lock);
hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node)
blkcg_print_one_stat(blkg, sf);
spin_unlock_irq(&blkg->q->queue_lock);
}
rcu_read_unlock();
return 0;
}
@ -1244,6 +1239,21 @@ struct list_head *blkcg_get_cgwb_list(struct cgroup_subsys_state *css)
* This finally frees the blkcg.
*/
static struct blkcg_gq *blkcg_get_first_blkg(struct blkcg *blkcg)
{
struct blkcg_gq *blkg = NULL;
spin_lock_irq(&blkcg->lock);
if (!hlist_empty(&blkcg->blkg_list)) {
blkg = hlist_entry(blkcg->blkg_list.first, struct blkcg_gq,
blkcg_node);
blkg_get(blkg);
}
spin_unlock_irq(&blkcg->lock);
return blkg;
}
/**
* blkcg_destroy_blkgs - responsible for shooting down blkgs
* @blkcg: blkcg of interest
@ -1257,32 +1267,24 @@ struct list_head *blkcg_get_cgwb_list(struct cgroup_subsys_state *css)
*/
static void blkcg_destroy_blkgs(struct blkcg *blkcg)
{
struct blkcg_gq *blkg;
might_sleep();
spin_lock_irq(&blkcg->lock);
while (!hlist_empty(&blkcg->blkg_list)) {
struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first,
struct blkcg_gq, blkcg_node);
while ((blkg = blkcg_get_first_blkg(blkcg))) {
struct request_queue *q = blkg->q;
if (need_resched() || !spin_trylock(&q->queue_lock)) {
/*
* Given that the system can accumulate a huge number
* of blkgs in pathological cases, check to see if we
* need to rescheduling to avoid softlockup.
*/
spin_unlock_irq(&blkcg->lock);
cond_resched();
spin_lock_irq(&blkcg->lock);
continue;
}
spin_lock_irq(&q->queue_lock);
spin_lock(&blkcg->lock);
blkg_destroy(blkg);
spin_unlock(&q->queue_lock);
}
spin_unlock_irq(&blkcg->lock);
spin_unlock(&blkcg->lock);
spin_unlock_irq(&q->queue_lock);
blkg_put(blkg);
cond_resched();
}
}
/**
@ -1606,7 +1608,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
pd->blkg = blkg;
pd->plid = pol->plid;
blkg->pd[pol->plid] = pd;
WRITE_ONCE(blkg->pd[pol->plid], pd);
if (pol->pd_init_fn)
pol->pd_init_fn(pd);
@ -1645,7 +1647,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
pol->pd_offline_fn(pd);
pd->online = false;
pol->pd_free_fn(pd);
blkg->pd[pol->plid] = NULL;
WRITE_ONCE(blkg->pd[pol->plid], NULL);
}
spin_unlock(&blkcg->lock);
}
@ -2044,6 +2046,18 @@ void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta)
atomic64_add(delta, &blkg->delay_nsec);
}
static inline struct blkcg_gq *blkg_lookup_tryget(struct blkcg_gq *blkg)
{
retry:
if (blkg_tryget(blkg))
return blkg;
blkg = blkg->parent;
if (blkg)
goto retry;
return NULL;
}
/**
* blkg_tryget_closest - try and get a blkg ref on the closet blkg
* @bio: target bio
@ -2056,20 +2070,30 @@ void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta)
static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,
struct cgroup_subsys_state *css)
{
struct blkcg_gq *blkg, *ret_blkg = NULL;
struct request_queue *q = bio->bi_bdev->bd_queue;
struct blkcg *blkcg = css_to_blkcg(css);
struct blkcg_gq *blkg;
rcu_read_lock();
blkg = blkg_lookup_create(css_to_blkcg(css), bio->bi_bdev->bd_disk);
while (blkg) {
if (blkg_tryget(blkg)) {
ret_blkg = blkg;
break;
}
blkg = blkg->parent;
}
blkg = blkg_lookup(blkcg, q);
if (likely(blkg))
blkg = blkg_lookup_tryget(blkg);
rcu_read_unlock();
return ret_blkg;
if (blkg)
return blkg;
/*
* Fast path failed, we're probably issuing IO in this cgroup the first
* time, hold lock to create new blkg.
*/
spin_lock_irq(&q->queue_lock);
blkg = blkg_lookup_create(blkcg, bio->bi_bdev->bd_disk);
if (blkg)
blkg = blkg_lookup_tryget(blkg);
spin_unlock_irq(&q->queue_lock);
return blkg;
}
/**
@ -2117,16 +2141,20 @@ void bio_associate_blkg(struct bio *bio)
if (blk_op_is_passthrough(bio->bi_opf))
return;
rcu_read_lock();
if (bio->bi_blkg)
if (bio->bi_blkg) {
css = bio_blkcg_css(bio);
else
bio_associate_blkg_from_css(bio, css);
} else {
rcu_read_lock();
css = blkcg_css();
if (!css_tryget_online(css))
css = NULL;
rcu_read_unlock();
bio_associate_blkg_from_css(bio, css);
rcu_read_unlock();
bio_associate_blkg_from_css(bio, css);
if (css)
css_put(css);
}
}
EXPORT_SYMBOL_GPL(bio_associate_blkg);

View File

@ -140,6 +140,8 @@ struct blkg_policy_data {
struct blkcg_gq *blkg;
int plid;
bool online;
struct rcu_head rcu_head;
};
/*
@ -282,9 +284,9 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
* Return pointer to private data associated with the @blkg-@pol pair.
*/
static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg,
struct blkcg_policy *pol)
const struct blkcg_policy *pol)
{
return blkg ? blkg->pd[pol->plid] : NULL;
return blkg ? READ_ONCE(blkg->pd[pol->plid]) : NULL;
}
static inline struct blkcg_policy_data *blkcg_to_cpd(struct blkcg *blkcg,
@ -491,7 +493,7 @@ static inline void blkcg_deactivate_policy(struct gendisk *disk,
const struct blkcg_policy *pol) { }
static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg,
struct blkcg_policy *pol) { return NULL; }
const struct blkcg_policy *pol) { return NULL; }
static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd) { return NULL; }
static inline void blkg_get(struct blkcg_gq *blkg) { }
static inline void blkg_put(struct blkcg_gq *blkg) { }

View File

@ -669,11 +669,6 @@ static inline blk_status_t blk_check_zone_append(struct request_queue *q,
static void __submit_bio(struct bio *bio)
{
/* If plug is not used, add new plug here to cache nsecs time. */
struct blk_plug plug;
blk_start_plug(&plug);
if (!bdev_test_flag(bio->bi_bdev, BD_HAS_SUBMIT_BIO)) {
blk_mq_submit_bio(bio);
} else if (likely(bio_queue_enter(bio) == 0)) {
@ -686,8 +681,6 @@ static void __submit_bio(struct bio *bio)
disk->fops->submit_bio(bio);
blk_queue_exit(disk->queue);
}
blk_finish_plug(&plug);
}
/*

View File

@ -3050,6 +3050,16 @@ static void ioc_pd_init(struct blkg_policy_data *pd)
spin_unlock_irqrestore(&ioc->lock, flags);
}
static void iocg_release(struct rcu_head *rcu)
{
struct blkg_policy_data *pd =
container_of(rcu, struct blkg_policy_data, rcu_head);
struct ioc_gq *iocg = pd_to_iocg(pd);
free_percpu(iocg->pcpu_stat);
kfree(iocg);
}
static void ioc_pd_free(struct blkg_policy_data *pd)
{
struct ioc_gq *iocg = pd_to_iocg(pd);
@ -3074,8 +3084,8 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
hrtimer_cancel(&iocg->waitq_timer);
}
free_percpu(iocg->pcpu_stat);
kfree(iocg);
call_rcu(&pd->rcu_head, iocg_release);
}
static void ioc_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
@ -3211,7 +3221,7 @@ static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
if (!dname)
return 0;
spin_lock(&ioc->lock);
spin_lock_irq(&ioc->lock);
seq_printf(sf, "%s enable=%d ctrl=%s rpct=%u.%02u rlat=%u wpct=%u.%02u wlat=%u min=%u.%02u max=%u.%02u\n",
dname, ioc->enabled, ioc->user_qos_params ? "user" : "auto",
ioc->params.qos[QOS_RPPM] / 10000,
@ -3224,7 +3234,7 @@ static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
ioc->params.qos[QOS_MIN] % 10000 / 100,
ioc->params.qos[QOS_MAX] / 10000,
ioc->params.qos[QOS_MAX] % 10000 / 100);
spin_unlock(&ioc->lock);
spin_unlock_irq(&ioc->lock);
return 0;
}
@ -3420,14 +3430,14 @@ static u64 ioc_cost_model_prfill(struct seq_file *sf,
if (!dname)
return 0;
spin_lock(&ioc->lock);
spin_lock_irq(&ioc->lock);
seq_printf(sf, "%s ctrl=%s model=linear "
"rbps=%llu rseqiops=%llu rrandiops=%llu "
"wbps=%llu wseqiops=%llu wrandiops=%llu\n",
dname, ioc->user_cost_model ? "user" : "auto",
u[I_LCOEF_RBPS], u[I_LCOEF_RSEQIOPS], u[I_LCOEF_RRANDIOPS],
u[I_LCOEF_WBPS], u[I_LCOEF_WSEQIOPS], u[I_LCOEF_WRANDIOPS]);
spin_unlock(&ioc->lock);
spin_unlock_irq(&ioc->lock);
return 0;
}

View File

@ -1031,13 +1031,21 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd)
iolatency_clear_scaling(blkg);
}
static void iolatency_pd_free(struct blkg_policy_data *pd)
static void iolat_release(struct rcu_head *rcu)
{
struct blkg_policy_data *pd =
container_of(rcu, struct blkg_policy_data, rcu_head);
struct iolatency_grp *iolat = pd_to_lat(pd);
free_percpu(iolat->stats);
kfree(iolat);
}
static void iolatency_pd_free(struct blkg_policy_data *pd)
{
call_rcu(&pd->rcu_head, iolat_release);
}
static struct cftype iolatency_files[] = {
{
.name = "latency",

View File

@ -353,14 +353,23 @@ static void throtl_pd_online(struct blkg_policy_data *pd)
tg_update_has_rules(tg);
}
static void tg_release(struct rcu_head *rcu)
{
struct blkg_policy_data *pd =
container_of(rcu, struct blkg_policy_data, rcu_head);
struct throtl_grp *tg = pd_to_tg(pd);
blkg_rwstat_exit(&tg->stat_bytes);
blkg_rwstat_exit(&tg->stat_ios);
kfree(tg);
}
static void throtl_pd_free(struct blkg_policy_data *pd)
{
struct throtl_grp *tg = pd_to_tg(pd);
timer_delete_sync(&tg->service_queue.pending_timer);
blkg_rwstat_exit(&tg->stat_bytes);
blkg_rwstat_exit(&tg->stat_ios);
kfree(tg);
call_rcu(&pd->rcu_head, tg_release);
}
static struct throtl_grp *

View File

@ -120,13 +120,13 @@ static void error_inject_removeall(struct gendisk *disk)
struct blk_error_inject *inj;
mutex_lock(&disk->error_injection_lock);
clear_bit(GD_ERROR_INJECT, &disk->state);
if (test_and_clear_bit(GD_ERROR_INJECT, &disk->state))
static_branch_dec(&blk_error_injection_enabled);
while ((inj = list_first_entry_or_null(&disk->error_injection_list,
struct blk_error_inject, entry))) {
list_del_rcu(&inj->entry);
kfree_rcu_mightsleep(inj);
}
static_branch_dec(&blk_error_injection_enabled);
mutex_unlock(&disk->error_injection_lock);
}

View File

@ -951,7 +951,7 @@ int blkdev_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
u32 cmd_op = cmd->cmd_op;
/* Read what we need from the SQE on the first issue */
if (!(issue_flags & IORING_URING_CMD_REISSUE)) {
if (!(cmd->flags & IORING_URING_CMD_REISSUE)) {
const struct io_uring_sqe *sqe = cmd->sqe;
if (unlikely(sqe->ioprio || sqe->__pad1 || sqe->len ||

View File

@ -1300,7 +1300,7 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
args->handle, args->offset, args->size);
if (args->direction == SYNC_DIRECT_FROM_DEVICE)
ret = amdxdna_hwctx_sync_debug_bo(abo->client, args->handle);
ret = amdxdna_hwctx_sync_debug_bo(client, args->handle);
put_obj:
drm_gem_object_put(gobj);

Some files were not shown because too many files have changed in this diff Show More