mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.3-rc7). Conflicts: include/net/strparser.h0984ebc631("strparser: make sure __strp_recv isn't running before tearing down the parser")02fd0a2111("net: strparser: removed the aborted bit and aborts counter") https://lore.kernel.org/asYfmLsfy-SCxXjr@sirena.co.uk Adjacent changes: Documentation/networking/strparser.rst5f193cdabf("docs: networking: strparser: remove general mode")0984ebc631("strparser: make sure __strp_recv isn't running before tearing down the parser") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d8674294ae
5
.mailmap
5
.mailmap
|
|
@ -102,6 +102,7 @@ Andy Chiu <andybnac@gmail.com> <andy.chiu@sifive.com>
|
|||
Andy Chiu <andybnac@gmail.com> <taochiu@synology.com>
|
||||
Andy Shevchenko <andy@kernel.org> <andy@smile.org.ua>
|
||||
Andy Shevchenko <andy@kernel.org> <ext-andriy.shevchenko@nokia.com>
|
||||
Andy Yan <andyshrk@163.com> <andy.yan@rock-chips.com>
|
||||
Anilkumar Kolli <quic_akolli@quicinc.com> <akolli@codeaurora.org>
|
||||
Anirudh Ghayal <quic_aghayal@quicinc.com> <aghayal@codeaurora.org>
|
||||
Antoine Tenart <atenart@kernel.org> <antoine.tenart@bootlin.com>
|
||||
|
|
@ -463,7 +464,8 @@ Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
|
|||
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
|
||||
John Crispin <john@phrozen.org> <blogic@openwrt.org>
|
||||
John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
|
||||
John Garry <john.g.garry@oracle.com> <john.garry@huawei.com>
|
||||
John Garry <john.garry@linux.dev> <john.garry@huawei.com>
|
||||
John Garry <john.garry@linux.dev> <john.g.garry@oracle.com>
|
||||
John Keeping <john@keeping.me.uk> <john@metanate.com>
|
||||
John Moon <john@jmoon.dev> <quic_johmoo@quicinc.com>
|
||||
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
||||
|
|
@ -488,6 +490,7 @@ Juha Yrjola <juha.yrjola@nokia.com>
|
|||
Juha Yrjola <juha.yrjola@solidboot.com>
|
||||
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
|
||||
Justin Iurman <justin.iurman@gmail.com> <justin.iurman@uliege.be>
|
||||
Imre Kaloz <kaloz@kernel.org> <kaloz@openwrt.org>
|
||||
Ira Weiny <iweiny@kernel.org> <ira.weiny@intel.com>
|
||||
Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com>
|
||||
Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org>
|
||||
|
|
|
|||
|
|
@ -172,7 +172,8 @@ When mounting an ext4 filesystem, the following option are accepted:
|
|||
data=journal
|
||||
All data are committed into the journal prior to being written into the
|
||||
main file system. Enabling this mode will disable delayed allocation
|
||||
and O_DIRECT support.
|
||||
and O_DIRECT support. This feature is deprecated and support
|
||||
will be removed in January 2028.
|
||||
|
||||
data=ordered (*)
|
||||
All data are forced directly out to the main file system prior to its
|
||||
|
|
@ -418,7 +419,8 @@ There are 3 different data modes:
|
|||
consistent state. This mode is the slowest except when data needs to be read
|
||||
from and written to disk at the same time where it outperforms all others
|
||||
modes. Enabling this mode will disable delayed allocation and O_DIRECT
|
||||
support.
|
||||
support. The data=journal feature is deprecated and support will be
|
||||
removed in January 2028.
|
||||
|
||||
/proc entries
|
||||
=============
|
||||
|
|
|
|||
|
|
@ -174,6 +174,8 @@ stable kernels.
|
|||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-A725 | #3821522 | ARM64_ERRATUM_3821522 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-X1 | #1502854 | N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 |
|
||||
|
|
|
|||
|
|
@ -12,19 +12,19 @@ maintainers:
|
|||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,saradc
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- const: rockchip,rk3528-saradc
|
||||
- enum:
|
||||
- rockchip,saradc
|
||||
- rockchip,rk3066-tsadc
|
||||
- rockchip,rk3399-saradc
|
||||
- rockchip,rk3528-saradc
|
||||
- rockchip,rk3562-saradc
|
||||
- rockchip,rk3588-saradc
|
||||
- rockchip,rv1106-saradc
|
||||
- items:
|
||||
- const: rockchip,rk3506-saradc
|
||||
- const: rockchip,rk3528-saradc
|
||||
- const: rockchip,rk3562-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3576-saradc
|
||||
- rockchip,rv1106-saradc
|
||||
- const: rockchip,rk3576-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- enum:
|
||||
|
|
|
|||
|
|
@ -451,6 +451,32 @@ one.
|
|||
The inode should be marked ``NETFS_ICTX_SINGLE_NO_UPLOAD`` if this API is to be
|
||||
used. The writeback function requires the buffer to be of ITER_FOLIOQ type.
|
||||
|
||||
Clearing Stale Post-EOF Pagecache
|
||||
---------------------------------
|
||||
|
||||
When a file is extended, data left in the pagecache past the old EOF by a write
|
||||
through an mmap must not be exposed as file content. Netfslib clears this on
|
||||
its own write paths, and exports a helper so a filesystem can do the same from
|
||||
a resize path (truncate, setattr, fallocate and the like) that holds the
|
||||
inode's ``i_rwsem`` exclusively across the whole resize::
|
||||
|
||||
void netfs_clear_stale_post_isize(struct inode *inode, uoff_t from,
|
||||
uoff_t to);
|
||||
|
||||
This zeroes any such data within the ``[from, to)`` hole to be made, where
|
||||
@from is the old EOF and @to is the new one, and the caller must have already
|
||||
updated ``i_size`` to @to before calling it. Only the folio straddling @from
|
||||
can hold data written past the EOF through an mmap, as pages wholly beyond the
|
||||
EOF can't be faulted in, so the zeroing is limited to that folio. The folio is
|
||||
zeroed rather than dropped so that a concurrent extending write can't lose
|
||||
data.
|
||||
|
||||
This overlaps with ``pagecache_isize_extended()`` but can't reuse it: that
|
||||
helper is keyed on a sub-page block size and is a no-op when the block size is
|
||||
``>= PAGE_SIZE`` (as on network filesystems), and it doesn't wait for
|
||||
writeback. As both address the same problem, a change to one should probably
|
||||
be reflected in the other to keep them in sync.
|
||||
|
||||
High-Level VM API
|
||||
==================
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ Functions
|
|||
|
||||
strp_done is called to release any resources held by the stream
|
||||
parser instance. This must be called after the stream processor
|
||||
has been stopped.
|
||||
has been stopped. The socket lock must not be held.
|
||||
|
||||
::
|
||||
|
||||
|
|
|
|||
11
MAINTAINERS
11
MAINTAINERS
|
|
@ -3012,7 +3012,7 @@ F: arch/arm/boot/dts/ti/omap/omap3-igep*
|
|||
|
||||
ARM/INTEL IXP4XX ARM ARCHITECTURE
|
||||
M: Linus Walleij <linusw@kernel.org>
|
||||
M: Imre Kaloz <kaloz@openwrt.org>
|
||||
M: Imre Kaloz <kaloz@kernel.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
|
||||
|
|
@ -9863,7 +9863,7 @@ L: linux-ext4@vger.kernel.org
|
|||
S: Maintained
|
||||
W: http://ext4.wiki.kernel.org
|
||||
Q: http://patchwork.ozlabs.org/project/linux-ext4/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev
|
||||
F: Documentation/filesystems/ext4/
|
||||
F: fs/ext4/
|
||||
F: include/trace/events/ext4.h
|
||||
|
|
@ -24503,6 +24503,11 @@ R: Marc Murphy <marc.murphy@sancloud.com>
|
|||
S: Supported
|
||||
F: arch/arm/boot/dts/ti/omap/am335x-sancloud*
|
||||
|
||||
SB1250-DUART BROADCOM SOC SERIAL DRIVER
|
||||
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
|
||||
S: Maintained
|
||||
F: drivers/tty/serial/sb1250-duart.c
|
||||
|
||||
SBOM
|
||||
M: Luis Augenstein <luis.augenstein@tngtech.com>
|
||||
M: Maximilian Huber <maximilian.huber@tngtech.com>
|
||||
|
|
@ -25213,7 +25218,7 @@ R: David Rientjes <rientjes@google.com>
|
|||
R: Roman Gushchin <roman.gushchin@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/slab.git
|
||||
F: Documentation/admin-guide/mm/slab.rst
|
||||
F: Documentation/mm/slab.rst
|
||||
F: include/linux/mempool.h
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 3
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -1040,9 +1040,17 @@ config ARM64_ERRATUM_1902691
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
|
||||
bool
|
||||
# Targeting errata affecting AMEVCNTR01, the AMU constant counter.
|
||||
# On affected CPUs the counter may not increment at the expected rate,
|
||||
# making it unreliable. As a result, AMU users should treat it as
|
||||
# unavailable rather than relying on misleading counter values.
|
||||
|
||||
config ARM64_ERRATUM_2457168
|
||||
bool "Cortex-A510: 2457168: workaround for AMEVCNTR01 incrementing incorrectly"
|
||||
depends on ARM64_AMU_EXTN
|
||||
select ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
|
||||
default y
|
||||
help
|
||||
This option adds the workaround for ARM Cortex-A510 erratum 2457168.
|
||||
|
|
@ -1073,6 +1081,28 @@ config ARM64_ERRATUM_2645198
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_ERRATUM_3821522
|
||||
bool "Cortex-A725: 3821522: workaround for possible CNT_CYCLES increment error due to WFE/WFI"
|
||||
depends on ARM64_AMU_EXTN
|
||||
select ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
|
||||
default y
|
||||
help
|
||||
This option adds the workaround for ARM Cortex-A725 erratum 3821522.
|
||||
|
||||
On affected A725 cores, the CNT_CYCLES event may incur a significant
|
||||
increment error when entering and subsequently exiting WFx.
|
||||
As a result, the CNT_CYCLES may diverge from the system counter
|
||||
frequency at which it is expected to increment.
|
||||
This renders the AMU counter AMEVCNTR01, that implements CNT_CYCLES,
|
||||
being unreliable and unsuitable for use.
|
||||
|
||||
Since there is no hardware workaround, reads of the affected CNT_CYCLES
|
||||
counter return 0 in the relevant paths. This causes users of the counter
|
||||
to treat it as unavailable and is functionally equivalent to firmware
|
||||
disabling the affected counter.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
|
||||
bool
|
||||
|
||||
|
|
|
|||
|
|
@ -1602,7 +1602,7 @@ esdhc0_clksync_pins: iic5-sdhc-clk-pins {
|
|||
};
|
||||
|
||||
dspi2_miso_mosi_pins: iic5-spi3-pins {
|
||||
pinctrl-single,bits = <0x3 (0x2 << 9) (0x7 << 9)>;
|
||||
pinctrl-single,bits = <0x0 (0x3 << 9) (0x7 << 9)>;
|
||||
};
|
||||
|
||||
i2c5_pins: iic6-i2c-pins {
|
||||
|
|
@ -1622,7 +1622,7 @@ fspi_data74_pins: xspi1-data74-pins {
|
|||
};
|
||||
|
||||
gpio1_31_28_pins: xspi1-data74-gpio-pins {
|
||||
pinctrl-single,bits = <0x0 0x1 (0x7 << 15)>;
|
||||
pinctrl-single,bits = <0x0 (0x1 << 15) (0x7 << 15)>;
|
||||
};
|
||||
|
||||
fspi_data30_pins: xspi1-data30-pins {
|
||||
|
|
@ -1630,7 +1630,7 @@ fspi_data30_pins: xspi1-data30-pins {
|
|||
};
|
||||
|
||||
gpio1_27_24_pins: xspi1-data30-gpio-pins {
|
||||
pinctrl-single,bits = <0x0 0x1 (0x7 << 18)>;
|
||||
pinctrl-single,bits = <0x0 (0x1 << 18) (0x7 << 18)>;
|
||||
};
|
||||
|
||||
fspi_dqs_sck_cs10_pins: xspi1-base-pins {
|
||||
|
|
@ -1638,7 +1638,7 @@ fspi_dqs_sck_cs10_pins: xspi1-base-pins {
|
|||
};
|
||||
|
||||
gpio1_23_20_pins: xspi1-base-gpio-pins {
|
||||
pinctrl-single,bits = <0x0 0x1 (0x7 << 21)>;
|
||||
pinctrl-single,bits = <0x0 (0x1 << 21) (0x7 << 21)>;
|
||||
};
|
||||
|
||||
esdhc0_cmd_data30_clk_vsel_pins: sdhc1-base-sdhc-vsel-pins {
|
||||
|
|
@ -1687,12 +1687,19 @@ i2c6_i2c7_pins: iic8-iic7-i2c-pins {
|
|||
};
|
||||
|
||||
/* RCWSR14 */
|
||||
/*
|
||||
* IIC1_PMUX is a single bit at RCWSR14[10], but bit-per-mux
|
||||
* uses the mask for the field to clear before applying the
|
||||
* value.
|
||||
* So bits 11 and 12, which are reserved, are written as 0
|
||||
* on every mux switch, it is harmless.
|
||||
*/
|
||||
i2c0_pins: iic1-i2c-pins {
|
||||
pinctrl-single,bits = <0x8 0x0 (0x1 << 10)>;
|
||||
pinctrl-single,bits = <0x8 0x0 (0x7 << 10)>;
|
||||
};
|
||||
|
||||
gpio0_3_2_pins: iic1-gpio-pins {
|
||||
pinctrl-single,bits = <0x8 (0x1 << 10) (0x1 << 10)>;
|
||||
pinctrl-single,bits = <0x8 (0x1 << 10) (0x7 << 10)>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -511,6 +511,7 @@ &usdhc2 {
|
|||
pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
|
||||
cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
|
||||
vmmc-supply = <®_usdhc2_vmmc>;
|
||||
vqmmc-supply = <&ldo5>;
|
||||
bus-width = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -863,11 +863,11 @@ spkr_01_sd_n_active: spkr-01-sd-n-active-state {
|
|||
};
|
||||
|
||||
&lpass_vamacro {
|
||||
pinctrl-0 = <&dmic01_default>, <&dmic23_default>;
|
||||
pinctrl-0 = <&dmic01_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
vdd-micb-supply = <&vreg_l1b_1p8>;
|
||||
qcom,dmic-sample-rate = <4800000>;
|
||||
qcom,dmic-sample-rate = <2400000>;
|
||||
};
|
||||
|
||||
&mdss {
|
||||
|
|
|
|||
|
|
@ -384,6 +384,20 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
|
||||
static const struct midr_range workaround_amu_constcnt_list[] = {
|
||||
#ifdef CONFIG_ARM64_ERRATUM_2457168
|
||||
/* Cortex-A510 r0p0-r1p1 */
|
||||
MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1),
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_3821522
|
||||
/* Cortex-A725 r0p0 - r0p2 */
|
||||
MIDR_RANGE(MIDR_CORTEX_A725, 0, 0, 0, 2),
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
#endif /* CONFIG_ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT */
|
||||
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_23154
|
||||
static const struct midr_range cavium_erratum_23154_cpus[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_THUNDERX),
|
||||
|
|
@ -919,14 +933,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
|||
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2)
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_2457168
|
||||
#ifdef CONFIG_ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT
|
||||
{
|
||||
.desc = "ARM erratum 2457168",
|
||||
.capability = ARM64_WORKAROUND_2457168,
|
||||
.desc = "Broken AMU AMEVCNTR01 (const counter)",
|
||||
.capability = ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT,
|
||||
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
|
||||
|
||||
/* Cortex-A510 r0p0-r1p1 */
|
||||
CAP_MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1)
|
||||
CAP_MIDR_RANGE_LIST(workaround_amu_constcnt_list)
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_2038923
|
||||
|
|
|
|||
|
|
@ -2089,7 +2089,7 @@ static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)
|
|||
cpumask_set_cpu(smp_processor_id(), &amu_cpus);
|
||||
|
||||
/* 0 reference values signal broken/disabled counters */
|
||||
if (!this_cpu_has_cap(ARM64_WORKAROUND_2457168))
|
||||
if (!this_cpu_has_cap(ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT))
|
||||
update_freq_counters_refs();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -433,6 +433,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
|
|||
unsigned int vl, vq;
|
||||
struct user_fpsimd_state fpsimd;
|
||||
u16 user_vl, flags;
|
||||
bool fpsimd_only;
|
||||
bool sm;
|
||||
|
||||
if (user->sve_size < sizeof(*user->sve))
|
||||
|
|
@ -443,19 +444,33 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
fpsimd_only = (user->sve_size == sizeof(*user->sve));
|
||||
sm = flags & SVE_SIG_FLAG_SM;
|
||||
|
||||
if (sm) {
|
||||
if (!system_supports_sme())
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Streaming SVE state is always preserved with an SVE payload.
|
||||
* Only accept streaming state which has an SVE payload.
|
||||
*/
|
||||
if (fpsimd_only)
|
||||
return -EINVAL;
|
||||
|
||||
vl = task_get_sme_vl(current);
|
||||
} else {
|
||||
/*
|
||||
* A SME only system use SVE for streaming mode so can
|
||||
* have a SVE formatted context with a zero VL and no
|
||||
* payload data.
|
||||
* Non-streaming SVE state may be preserved without an SVE
|
||||
* payload, in which case all state is saved in the FPSIMD
|
||||
* context.
|
||||
*
|
||||
* On SME-only systems, non-streaming (FPSIMD-only) state is
|
||||
* always preserved without an SVE payload, and with VL==0. On
|
||||
* such systems, only accept non-streaming state without an SVE
|
||||
* payload.
|
||||
*/
|
||||
if (!system_supports_sve() && !system_supports_sme())
|
||||
if (!system_supports_sve() && !fpsimd_only)
|
||||
return -EINVAL;
|
||||
|
||||
vl = task_get_sve_vl(current);
|
||||
|
|
@ -464,16 +479,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
|
|||
if (user_vl != vl)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Non-streaming SVE state may be preserved without an SVE payload, in
|
||||
* which case the SVE context only has a header with VL==0, and all
|
||||
* state can be restored from the FPSIMD context.
|
||||
*
|
||||
* Streaming SVE state is always preserved with an SVE payload. For
|
||||
* consistency and robustness, reject restoring streaming SVE state
|
||||
* without an SVE payload.
|
||||
*/
|
||||
if (!sm && user->sve_size == sizeof(*user->sve))
|
||||
if (fpsimd_only)
|
||||
return restore_fpsimd_context(user);
|
||||
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
|
|
|||
|
|
@ -186,7 +186,6 @@ int arch_freq_get_on_cpu(int cpu)
|
|||
struct amu_cntr_sample *amu_sample;
|
||||
unsigned int start_cpu = cpu;
|
||||
unsigned long last_update;
|
||||
unsigned int freq = 0;
|
||||
u64 scale;
|
||||
|
||||
if (!amu_fie_cpu_supported(cpu) || !arch_scale_freq_ref(cpu))
|
||||
|
|
@ -245,9 +244,8 @@ int arch_freq_get_on_cpu(int cpu)
|
|||
* (see amu_scale_freq_tick for details)
|
||||
*/
|
||||
scale = arch_scale_freq_capacity(cpu);
|
||||
freq = scale * arch_scale_freq_ref(cpu);
|
||||
freq >>= SCHED_CAPACITY_SHIFT;
|
||||
return freq;
|
||||
|
||||
return (scale * arch_scale_freq_ref(cpu)) >> SCHED_CAPACITY_SHIFT;
|
||||
}
|
||||
|
||||
static void amu_fie_setup(const struct cpumask *cpus)
|
||||
|
|
@ -397,12 +395,13 @@ static void cpu_read_corecnt(void *val)
|
|||
static void cpu_read_constcnt(void *val)
|
||||
{
|
||||
/*
|
||||
* Return 0 if the current CPU is affected by erratum 2457168. A value
|
||||
* of 0 is also returned if the current CPU does not support AMUs or if
|
||||
* the counter is disabled. A return value of 0 at counter read is
|
||||
* properly handled as an error case by the users of the counter.
|
||||
* Return 0 if the current CPU is affected by a HW erratum.
|
||||
* A value of 0 is also returned if the current CPU does not
|
||||
* support AMUs or if the counter is disabled. A return
|
||||
* value of 0 at counter read is properly handled as an error
|
||||
* case by the users of the counter.
|
||||
*/
|
||||
*(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_2457168) ?
|
||||
*(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT) ?
|
||||
0UL : read_constcnt();
|
||||
}
|
||||
|
||||
|
|
@ -463,8 +462,9 @@ static void amu_read_core_const_ctrs(void *val)
|
|||
|
||||
/*
|
||||
* cpu_read_constcnt() incurs slight latency due to the
|
||||
* ARM64_WORKAROUND_2457168 check. Read it first to minimize
|
||||
* the sampling skew between the const and core counters.
|
||||
* ARM64_WORKAROUND_BROKEN_AMU_CONSTCNT check.
|
||||
* Read it first to minimize the sampling skew between the const
|
||||
* and core counters.
|
||||
*/
|
||||
cpu_read_constcnt(&ctrs->constcnt);
|
||||
cpu_read_corecnt(&ctrs->corecnt);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
|
|||
$(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
|
||||
-Wmissing-prototypes -Wmissing-declarations
|
||||
|
||||
CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
|
||||
CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables $(CONFIG_CC_OPT_INLINE_MEMSET)
|
||||
|
||||
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_REMOVE_VDSO)
|
||||
CFLAGS_REMOVE_vgetrandom.o = $(CC_FLAGS_REMOVE_VDSO)
|
||||
|
|
|
|||
|
|
@ -2386,9 +2386,6 @@ int __init populate_nv_trap_config(void)
|
|||
print_nv_trap_error(fgt, "FGT bit is reserved", ret);
|
||||
}
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_HAS_FGT))
|
||||
continue;
|
||||
|
||||
prev = xa_store(&sr_forward_xa, enc,
|
||||
xa_mk_value(tc.val), GFP_KERNEL);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,15 @@
|
|||
#include <nvhe/gfp.h>
|
||||
#include <nvhe/spinlock.h>
|
||||
|
||||
/*
|
||||
* HCR_EL2 bits EL2 takes from the host on each entry, per VM type. The rest
|
||||
* are EL2's own and nothing the host sets there reaches the guest.
|
||||
*/
|
||||
#define PKVM_HCR_EL2_HOST_PVM (HCR_EL2_TWI | HCR_EL2_TWE | HCR_EL2_VSE)
|
||||
#define PKVM_HCR_EL2_HOST_NPVM (PKVM_HCR_EL2_HOST_PVM | HCR_EL2_VI | HCR_EL2_VF | \
|
||||
HCR_EL2_TVM | HCR_EL2_TID2 | HCR_EL2_TID4 | \
|
||||
HCR_EL2_TID5 | HCR_EL2_TTLBOS)
|
||||
|
||||
/*
|
||||
* Holds the relevant data for maintaining the vcpu state completely at hyp.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ static void sync_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
|
|||
static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
{
|
||||
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
|
||||
u64 host_hcr_mask = PKVM_HCR_EL2_HOST_PVM;
|
||||
|
||||
fpsimd_sve_flush();
|
||||
flush_debug_state(hyp_vcpu);
|
||||
|
|
@ -228,6 +229,7 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
|
|||
if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu)) {
|
||||
if (vcpu_get_flag(host_vcpu, PKVM_HOST_STATE_DIRTY))
|
||||
flush_hyp_vcpu_state(hyp_vcpu);
|
||||
host_hcr_mask = PKVM_HCR_EL2_HOST_NPVM;
|
||||
} else {
|
||||
hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
|
||||
}
|
||||
|
|
@ -241,9 +243,8 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
|
|||
* trap-control bit, so it must flow to the hyp vCPU alongside TWI/TWE
|
||||
* for the vSError to be delivered. sync_hyp_vcpu() reflects it back.
|
||||
*/
|
||||
hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE | HCR_VSE);
|
||||
hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
|
||||
(HCR_TWI | HCR_TWE | HCR_VSE);
|
||||
hyp_vcpu->vcpu.arch.hcr_el2 &= ~host_hcr_mask;
|
||||
hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) & host_hcr_mask;
|
||||
|
||||
hyp_vcpu->vcpu.arch.iflags = host_vcpu->arch.iflags;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ unsigned int kvm_host_sve_max_vl;
|
|||
*/
|
||||
static DEFINE_PER_CPU(struct pkvm_hyp_vcpu *, loaded_hyp_vcpu);
|
||||
|
||||
/* The PKVM_HCR_EL2_HOST_{PVM,NPVM} bits of this value come from the host on each entry. */
|
||||
static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
|
||||
|
|
@ -47,18 +48,17 @@ static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
|
|||
if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
|
||||
vcpu->arch.hcr_el2 |= HCR_FWB;
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_EVT) &&
|
||||
!cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE) &&
|
||||
kvm_read_vm_id_reg(vcpu->kvm, SYS_CTR_EL0) == read_cpuid(CTR_EL0))
|
||||
vcpu->arch.hcr_el2 |= HCR_TID4;
|
||||
else
|
||||
vcpu->arch.hcr_el2 |= HCR_TID2;
|
||||
/*
|
||||
* Without AArch32 EL1, leave RW set and let the entry fail with an
|
||||
* illegal exception return: the *32_EL2 registers EL2 would otherwise
|
||||
* switch are UNDEFINED there.
|
||||
*/
|
||||
if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT) &&
|
||||
cpus_have_final_cap(ARM64_HAS_32BIT_EL1))
|
||||
vcpu->arch.hcr_el2 &= ~HCR_EL2_RW;
|
||||
|
||||
if (vcpu_has_ptrauth(vcpu))
|
||||
vcpu->arch.hcr_el2 |= (HCR_API | HCR_APK);
|
||||
|
||||
if (kvm_has_mte(vcpu->kvm))
|
||||
vcpu->arch.hcr_el2 |= HCR_ATA;
|
||||
}
|
||||
|
||||
static void pvm_init_traps_hcr(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -76,6 +76,13 @@ static void pvm_init_traps_hcr(struct kvm_vcpu *vcpu)
|
|||
*/
|
||||
val |= HCR_TACR | HCR_TIDCP | HCR_TID3 | HCR_TID1;
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_EVT) &&
|
||||
!cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE) &&
|
||||
kvm_read_vm_id_reg(kvm, SYS_CTR_EL0) == read_cpuid(CTR_EL0))
|
||||
val |= HCR_EL2_TID4;
|
||||
else
|
||||
val |= HCR_EL2_TID2;
|
||||
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP)) {
|
||||
val |= HCR_TERR | HCR_TEA;
|
||||
val &= ~(HCR_FIEN);
|
||||
|
|
|
|||
|
|
@ -1468,32 +1468,11 @@ transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
|||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
|
||||
static int get_vma_page_shift(struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long pa;
|
||||
|
||||
if (is_vm_hugetlb_page(vma) && !(vma->vm_flags & VM_PFNMAP))
|
||||
if (is_vm_hugetlb_page(vma))
|
||||
return huge_page_shift(hstate_vma(vma));
|
||||
|
||||
if (!(vma->vm_flags & VM_PFNMAP))
|
||||
return PAGE_SHIFT;
|
||||
|
||||
VM_BUG_ON(is_vm_hugetlb_page(vma));
|
||||
|
||||
pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
|
||||
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
if ((hva & (PUD_SIZE - 1)) == (pa & (PUD_SIZE - 1)) &&
|
||||
ALIGN_DOWN(hva, PUD_SIZE) >= vma->vm_start &&
|
||||
ALIGN(hva, PUD_SIZE) <= vma->vm_end)
|
||||
return PUD_SHIFT;
|
||||
#endif
|
||||
|
||||
if ((hva & (PMD_SIZE - 1)) == (pa & (PMD_SIZE - 1)) &&
|
||||
ALIGN_DOWN(hva, PMD_SIZE) >= vma->vm_start &&
|
||||
ALIGN(hva, PMD_SIZE) <= vma->vm_end)
|
||||
return PMD_SHIFT;
|
||||
|
||||
return PAGE_SHIFT;
|
||||
}
|
||||
|
||||
|
|
@ -1794,7 +1773,7 @@ static short kvm_s2_resolve_vma_size(const struct kvm_s2_fault_desc *s2fd,
|
|||
vma_shift = PAGE_SHIFT;
|
||||
} else {
|
||||
s2vi->max_map_size = PUD_SIZE;
|
||||
vma_shift = get_vma_page_shift(vma, s2fd->hva);
|
||||
vma_shift = get_vma_page_shift(vma);
|
||||
}
|
||||
|
||||
switch (vma_shift) {
|
||||
|
|
@ -1952,16 +1931,6 @@ static int kvm_s2_fault_pin_pfn(const struct kvm_s2_fault_desc *s2fd,
|
|||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If the page was identified as device early by looking at
|
||||
* the VMA flags, vma_pagesize is already representing the
|
||||
* largest quantity we can map. If instead it was mapped
|
||||
* via __kvm_faultin_pfn(), vma_pagesize is set to PAGE_SIZE
|
||||
* and must not be upgraded.
|
||||
*
|
||||
* In both cases, we don't let transparent_hugepage_adjust()
|
||||
* change things at the last minute.
|
||||
*/
|
||||
s2vi->map_non_cacheable = true;
|
||||
}
|
||||
|
||||
|
|
@ -2051,10 +2020,10 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault_desc *s2fd,
|
|||
|
||||
/*
|
||||
* If we are not forced to use page mapping, check if we are
|
||||
* backed by a THP and thus use block mapping if possible.
|
||||
* backed by a huge stage-1 mapping and thus use block mapping if
|
||||
* possible.
|
||||
*/
|
||||
if (mapping_size == PAGE_SIZE &&
|
||||
!(s2vi->max_map_size == PAGE_SIZE || s2vi->map_non_cacheable)) {
|
||||
if (mapping_size == PAGE_SIZE && s2vi->max_map_size != PAGE_SIZE) {
|
||||
if (perm_fault_granule > PAGE_SIZE) {
|
||||
mapping_size = perm_fault_granule;
|
||||
} else {
|
||||
|
|
@ -2135,10 +2104,6 @@ static int user_mem_abort(const struct kvm_s2_fault_desc *s2fd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Let's check if we will get back a huge page backed by hugetlbfs, or
|
||||
* get block mapping for device MMIO region.
|
||||
*/
|
||||
ret = kvm_s2_fault_pin_pfn(s2fd, &s2vi);
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,9 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
|
|||
/*
|
||||
* - Acquiring the vCPU mutex for every *online* vCPU to prevent
|
||||
* concurrent vCPU ioctls for vCPUs already visible to userspace.
|
||||
* This also ensures KVM isn't in the middle of creating a vCPU,
|
||||
* i.e. that there are no vCPUs that have been created but aren't
|
||||
* yet fully online.
|
||||
*/
|
||||
ret = -EBUSY;
|
||||
if (kvm_trylock_all_vcpus(kvm))
|
||||
|
|
@ -105,18 +108,11 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
|
|||
/*
|
||||
* - Taking the config_lock which protects VGIC data structures such
|
||||
* as the per-vCPU arrays of private IRQs (SGIs, PPIs).
|
||||
*/
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
|
||||
/*
|
||||
* - Bailing on the entire thing if a vCPU is in the middle of creation,
|
||||
* dropped the kvm->lock, but hasn't reached kvm_arch_vcpu_create().
|
||||
*
|
||||
* The whole combination of this guarantees that no vCPU can get into
|
||||
* KVM with a VGIC configuration inconsistent with the VM's VGIC.
|
||||
*/
|
||||
if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus))
|
||||
goto out_unlock;
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
|
||||
if (irqchip_in_kernel(kvm)) {
|
||||
ret = -EEXIST;
|
||||
|
|
|
|||
|
|
@ -319,12 +319,16 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
|
||||
static int update_affinity(struct vgic_irq *irq,
|
||||
struct kvm_vcpu *from_vcpu, struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct its_vlpi_map map;
|
||||
int ret;
|
||||
|
||||
guard(raw_spinlock_irqsave)(&irq->irq_lock);
|
||||
if (from_vcpu && irq->target_vcpu != from_vcpu)
|
||||
return 0;
|
||||
|
||||
irq->target_vcpu = vcpu;
|
||||
|
||||
if (!irq->hw)
|
||||
|
|
@ -362,7 +366,7 @@ static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
|
|||
return;
|
||||
|
||||
vcpu = collection_to_vcpu(kvm, ite->collection);
|
||||
update_affinity(ite->irq, vcpu);
|
||||
update_affinity(ite->irq, NULL, vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -856,7 +860,7 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
|
|||
|
||||
vgic_its_invalidate_cache(its);
|
||||
|
||||
return update_affinity(ite->irq, vcpu);
|
||||
return update_affinity(ite->irq, NULL, vcpu);
|
||||
}
|
||||
|
||||
static bool __is_visible_gfn_locked(struct vgic_its *its, gpa_t gpa)
|
||||
|
|
@ -1383,7 +1387,7 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
|
|||
if (!irq)
|
||||
continue;
|
||||
|
||||
update_affinity(irq, vcpu2);
|
||||
update_affinity(irq, vcpu1, vcpu2);
|
||||
|
||||
vgic_put_irq(kvm, irq);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,10 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
for (int lr = 0; lr < vgic_cpu->vgic_v2.used_lrs; lr++)
|
||||
vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]);
|
||||
|
||||
cpuif->used_lrs = 0;
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
/* See the GICv3 equivalent for the EOIcount handling rationale */
|
||||
list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||
u32 lr;
|
||||
|
|
@ -144,8 +148,6 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
vgic_v2_fold_lr(vcpu, lr);
|
||||
eoicount--;
|
||||
}
|
||||
|
||||
cpuif->used_lrs = 0;
|
||||
}
|
||||
|
||||
void vgic_v2_deactivate(struct kvm_vcpu *vcpu, u32 val)
|
||||
|
|
|
|||
|
|
@ -155,6 +155,10 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
for (int lr = 0; lr < cpuif->used_lrs; lr++)
|
||||
vgic_v3_fold_lr(vcpu, cpuif->vgic_lr[lr]);
|
||||
|
||||
cpuif->used_lrs = 0;
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
/*
|
||||
* EOIMode=0: use EOIcount to emulate deactivation. We are
|
||||
* guaranteed to deactivate in reverse order of the activation, so
|
||||
|
|
@ -188,8 +192,6 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
vgic_v3_fold_lr(vcpu, lr);
|
||||
eoicount--;
|
||||
}
|
||||
|
||||
cpuif->used_lrs = 0;
|
||||
}
|
||||
|
||||
void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
|
||||
|
|
|
|||
|
|
@ -853,6 +853,17 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
|
|||
goto retry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix the last_lr_irq refcount which was obtained while
|
||||
* populating the LRs. This can also result in the LPI being
|
||||
* deleted.
|
||||
*/
|
||||
irq = *host_data_ptr(last_lr_irq);
|
||||
if (irq) {
|
||||
deleted_lpis |= vgic_put_irq_norelease(vcpu->kvm, irq);
|
||||
*host_data_ptr(last_lr_irq) = NULL;
|
||||
}
|
||||
|
||||
raw_spin_unlock(&vgic_cpu->ap_list_lock);
|
||||
|
||||
if (unlikely(deleted_lpis))
|
||||
|
|
@ -866,9 +877,6 @@ static void vgic_fold_state(struct kvm_vcpu *vcpu)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!*host_data_ptr(last_lr_irq))
|
||||
return;
|
||||
|
||||
if (kvm_vgic_global_state.type == VGIC_V2)
|
||||
vgic_v2_fold_lr_state(vcpu);
|
||||
else
|
||||
|
|
@ -1021,11 +1029,14 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
|||
scoped_guard(raw_spinlock, &irq->irq_lock) {
|
||||
if (likely(vgic_target_oracle(irq) == vcpu)) {
|
||||
vgic_populate_lr(vcpu, irq, count++);
|
||||
*host_data_ptr(last_lr_irq) = irq;
|
||||
if (count == kvm_vgic_global_state.nr_lr) {
|
||||
vgic_get_irq_ref(irq);
|
||||
*host_data_ptr(last_lr_irq) = irq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == kvm_vgic_global_state.nr_lr)
|
||||
if (*host_data_ptr(last_lr_irq))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2295,7 +2295,7 @@ pte_t modify_prot_start_ptes(struct vm_area_struct *vma, unsigned long addr,
|
|||
* in cases where cpu is affected with errata #2645198.
|
||||
*/
|
||||
if (pte_accessible(vma->vm_mm, pte) && pte_user_exec(pte))
|
||||
__flush_tlb_range(vma, addr, nr * PAGE_SIZE,
|
||||
__flush_tlb_range(vma, addr, addr + nr * PAGE_SIZE,
|
||||
PAGE_SIZE, 3, TLBF_NOWALKCACHE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2418,10 +2418,11 @@ bool bpf_jit_supports_subprog_tailcalls(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_node *node,
|
||||
int bargs_off, int retval_off, int run_ctx_off,
|
||||
bool save_ret)
|
||||
static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_node *node, int bargs_off,
|
||||
int retval_off, int run_ctx_off, bool save_ret)
|
||||
{
|
||||
void *skip;
|
||||
__le32 *branch;
|
||||
u64 enter_prog;
|
||||
u64 exit_prog;
|
||||
|
|
@ -2431,6 +2432,10 @@ static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_node *node,
|
|||
enter_prog = (u64)bpf_trampoline_enter(p);
|
||||
exit_prog = (u64)bpf_trampoline_exit(p);
|
||||
|
||||
/* nop, patched to skip this prog when it is detached */
|
||||
skip = ctx->ro_image + ctx->idx;
|
||||
emit(A64_NOP, ctx);
|
||||
|
||||
if (node->cookie == 0) {
|
||||
/* if cookie is zero, one instruction is enough to store it */
|
||||
emit(A64_STR64I(A64_ZR, A64_SP, run_ctx_off + cookie_off), ctx);
|
||||
|
|
@ -2483,11 +2488,13 @@ static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_node *node,
|
|||
emit(A64_ADD_I(1, A64_R(2), A64_SP, run_ctx_off), ctx);
|
||||
|
||||
emit_call(exit_prog, ctx);
|
||||
|
||||
bpf_tramp_image_add_skip(im, p, skip, ctx->ro_image + ctx->idx);
|
||||
}
|
||||
|
||||
static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_nodes *tn,
|
||||
int bargs_off, int retval_off, int run_ctx_off,
|
||||
__le32 **branches)
|
||||
static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_nodes *tn, int bargs_off,
|
||||
int retval_off, int run_ctx_off, __le32 **branches)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -2496,7 +2503,7 @@ static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_nodes *tn,
|
|||
*/
|
||||
emit(A64_STR64I(A64_ZR, A64_SP, retval_off), ctx);
|
||||
for (i = 0; i < tn->nr_nodes; i++) {
|
||||
invoke_bpf_prog(ctx, tn->nodes[i], bargs_off, retval_off,
|
||||
invoke_bpf_prog(ctx, im, tn->nodes[i], bargs_off, retval_off,
|
||||
run_ctx_off, true);
|
||||
/* if (*(u64 *)(sp + retval_off) != 0)
|
||||
* goto do_fexit;
|
||||
|
|
@ -2882,7 +2889,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|||
store_func_meta(ctx, meta, func_meta_off);
|
||||
cookie_bargs_off--;
|
||||
}
|
||||
invoke_bpf_prog(ctx, fentry->nodes[i], bargs_off,
|
||||
invoke_bpf_prog(ctx, im, fentry->nodes[i], bargs_off,
|
||||
retval_off, run_ctx_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET);
|
||||
}
|
||||
|
|
@ -2893,7 +2900,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|||
if (!branches)
|
||||
return -ENOMEM;
|
||||
|
||||
invoke_bpf_mod_ret(ctx, fmod_ret, bargs_off, retval_off,
|
||||
invoke_bpf_mod_ret(ctx, im, fmod_ret, bargs_off, retval_off,
|
||||
run_ctx_off, branches);
|
||||
}
|
||||
|
||||
|
|
@ -2906,9 +2913,6 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|||
emit(A64_RET(A64_R(10)), ctx);
|
||||
/* store return value */
|
||||
emit(A64_STR64I(A64_R(0), A64_SP, retval_off), ctx);
|
||||
/* reserve a nop for bpf_tramp_image_put */
|
||||
im->ip_after_call = ctx->ro_image + ctx->idx;
|
||||
emit(A64_NOP, ctx);
|
||||
}
|
||||
|
||||
/* update the branches saved in invoke_bpf_mod_ret with cbnz */
|
||||
|
|
@ -2930,12 +2934,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|||
store_func_meta(ctx, meta, func_meta_off);
|
||||
cookie_bargs_off--;
|
||||
}
|
||||
invoke_bpf_prog(ctx, fexit->nodes[i], bargs_off, retval_off,
|
||||
invoke_bpf_prog(ctx, im, fexit->nodes[i], bargs_off, retval_off,
|
||||
run_ctx_off, false);
|
||||
}
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = ctx->ro_image + ctx->idx;
|
||||
/* for the first pass, assume the worst case */
|
||||
if (!ctx->image)
|
||||
ctx->idx += 4;
|
||||
|
|
@ -2994,7 +2997,7 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
|||
.image = NULL,
|
||||
.idx = 0,
|
||||
};
|
||||
struct bpf_tramp_image im;
|
||||
struct bpf_tramp_image im = {};
|
||||
struct arg_aux aaux;
|
||||
int ret;
|
||||
|
||||
|
|
@ -3281,6 +3284,10 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
|||
* longer reachable, since bpf_tramp_image_put() function already
|
||||
* uses percpu_ref and task-based rcu to do the sync, no need to call
|
||||
* the sync version here, see bpf_tramp_image_put() for details.
|
||||
*
|
||||
* 3. when a detached prog is patched out of a trampoline, a CPU that
|
||||
* still executes the old nop calls the prog before it went through
|
||||
* a quiescent state, and the prog is freed after grace periods.
|
||||
*/
|
||||
ret = aarch64_insn_patch_text_nosync(ip, new_insn);
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ WORKAROUND_1902691
|
|||
WORKAROUND_2038923
|
||||
WORKAROUND_2064142
|
||||
WORKAROUND_2077057
|
||||
WORKAROUND_2457168
|
||||
WORKAROUND_2645198
|
||||
WORKAROUND_2658417
|
||||
WORKAROUND_4193714
|
||||
|
|
@ -132,3 +131,4 @@ WORKAROUND_REPEAT_TLBI_SYNC
|
|||
WORKAROUND_SPECULATIVE_AT
|
||||
WORKAROUND_SPECULATIVE_SSBS
|
||||
WORKAROUND_SPECULATIVE_UNPRIV_LOAD
|
||||
WORKAROUND_BROKEN_AMU_CONSTCNT
|
||||
|
|
|
|||
|
|
@ -1578,6 +1578,24 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len)
|
|||
return ret ? ERR_PTR(-EINVAL) : dst;
|
||||
}
|
||||
|
||||
int arch_bpf_trampoline_skip(void *nop, void *target)
|
||||
{
|
||||
u32 old_insn = INSN_NOP;
|
||||
u32 new_insn = larch_insn_gen_b((unsigned long)nop, (unsigned long)target);
|
||||
int ret;
|
||||
|
||||
if (memcmp(nop, &old_insn, LOONGARCH_INSN_SIZE))
|
||||
return -EFAULT;
|
||||
|
||||
cpus_read_lock();
|
||||
mutex_lock(&text_mutex);
|
||||
ret = larch_insn_text_copy(nop, &new_insn, LOONGARCH_INSN_SIZE);
|
||||
mutex_unlock(&text_mutex);
|
||||
cpus_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||
enum bpf_text_poke_type new_t, void *old_addr,
|
||||
void *new_addr)
|
||||
|
|
@ -1696,13 +1714,18 @@ static void restore_stk_args(struct jit_ctx *ctx, int nr_stk_args, int args_off,
|
|||
}
|
||||
}
|
||||
|
||||
static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_node *n,
|
||||
int args_off, int retval_off, int run_ctx_off, bool save_ret)
|
||||
static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_node *n, int args_off, int retval_off,
|
||||
int run_ctx_off, bool save_ret)
|
||||
{
|
||||
int ret;
|
||||
u32 *branch;
|
||||
struct bpf_prog *p = n->link->prog;
|
||||
int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
|
||||
void *skip = ctx->ro_image + ctx->idx;
|
||||
|
||||
/* nop, patched to a b over this prog when it is detached */
|
||||
emit_insn(ctx, nop);
|
||||
|
||||
if (n->cookie)
|
||||
emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1,
|
||||
|
|
@ -1755,13 +1778,17 @@ static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_node *n,
|
|||
/* arg3: &run_ctx */
|
||||
emit_insn(ctx, addid, LOONGARCH_GPR_A2, LOONGARCH_GPR_FP, -run_ctx_off);
|
||||
ret = emit_call(ctx, (const u64)bpf_trampoline_exit(p));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
bpf_tramp_image_add_skip(im, p, skip, ctx->ro_image + ctx->idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invoke_bpf(struct jit_ctx *ctx, struct bpf_tramp_nodes *tn,
|
||||
int args_off, int retval_off, int run_ctx_off,
|
||||
int func_meta_off, bool save_ret, u64 func_meta, int cookie_off)
|
||||
static int invoke_bpf(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_nodes *tn, int args_off, int retval_off,
|
||||
int run_ctx_off, int func_meta_off, bool save_ret,
|
||||
u64 func_meta, int cookie_off)
|
||||
{
|
||||
int i, cur_cookie = (cookie_off - args_off) / 8;
|
||||
|
||||
|
|
@ -1774,7 +1801,8 @@ static int invoke_bpf(struct jit_ctx *ctx, struct bpf_tramp_nodes *tn,
|
|||
emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, meta);
|
||||
cur_cookie--;
|
||||
}
|
||||
err = invoke_bpf_prog(ctx, tn->nodes[i], args_off, retval_off, run_ctx_off, save_ret);
|
||||
err = invoke_bpf_prog(ctx, im, tn->nodes[i], args_off, retval_off,
|
||||
run_ctx_off, save_ret);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
|
@ -2017,7 +2045,7 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
|
|||
}
|
||||
|
||||
if (fentry->nr_nodes) {
|
||||
ret = invoke_bpf(ctx, fentry, args_off, retval_off, run_ctx_off, func_meta_off,
|
||||
ret = invoke_bpf(ctx, im, fentry, args_off, retval_off, run_ctx_off, func_meta_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -2029,7 +2057,7 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
|
|||
|
||||
emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off);
|
||||
for (i = 0; i < fmod_ret->nr_nodes; i++) {
|
||||
ret = invoke_bpf_prog(ctx, fmod_ret->nodes[i],
|
||||
ret = invoke_bpf_prog(ctx, im, fmod_ret->nodes[i],
|
||||
args_off, retval_off, run_ctx_off, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -2051,10 +2079,6 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
|
|||
goto out;
|
||||
emit_insn(ctx, std, LOONGARCH_GPR_A0, LOONGARCH_GPR_FP, -retval_off);
|
||||
emit_insn(ctx, std, regmap[BPF_REG_0], LOONGARCH_GPR_FP, -(retval_off - 8));
|
||||
im->ip_after_call = ctx->ro_image + ctx->idx;
|
||||
/* Reserve space for the move_imm + jirl instruction */
|
||||
for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++)
|
||||
emit_insn(ctx, nop);
|
||||
}
|
||||
|
||||
for (i = 0; ctx->image && i < fmod_ret->nr_nodes; i++) {
|
||||
|
|
@ -2068,14 +2092,13 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
|
|||
emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, func_meta);
|
||||
|
||||
if (fexit->nr_nodes) {
|
||||
ret = invoke_bpf(ctx, fexit, args_off, retval_off, run_ctx_off,
|
||||
ret = invoke_bpf(ctx, im, fexit, args_off, retval_off, run_ctx_off,
|
||||
func_meta_off, false, func_meta, cookie_off);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = ctx->ro_image + ctx->idx;
|
||||
move_addr(ctx, LOONGARCH_GPR_A0, (const u64)im);
|
||||
ret = emit_call(ctx, (const u64)__bpf_tramp_exit);
|
||||
if (ret)
|
||||
|
|
@ -2177,11 +2200,8 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
|||
struct bpf_tramp_nodes *tnodes, void *func_addr)
|
||||
{
|
||||
int ret;
|
||||
struct jit_ctx ctx;
|
||||
struct bpf_tramp_image im;
|
||||
|
||||
ctx.image = NULL;
|
||||
ctx.idx = 0;
|
||||
struct jit_ctx ctx = {};
|
||||
struct bpf_tramp_image im = {};
|
||||
|
||||
ret = __arch_prepare_bpf_trampoline(&ctx, &im, m, tnodes, func_addr, flags);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ ccflags-vdso := \
|
|||
$(filter -m64,$(KBUILD_CFLAGS)) \
|
||||
$(filter -march=%,$(KBUILD_CFLAGS)) \
|
||||
$(filter -m%-float,$(KBUILD_CFLAGS)) \
|
||||
$(CONFIG_CC_OPT_INLINE_MEMSET) \
|
||||
$(CLANG_FLAGS) \
|
||||
-D__VDSO__
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ ccflags-y := -fno-common -fno-builtin -DBUILD_VDSO
|
|||
ccflags-y += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
ccflags-y += $(call cc-option, -fno-stack-protector)
|
||||
ccflags-y += -DDISABLE_BRANCH_PROFILING
|
||||
ccflags-y += $(CONFIG_CC_OPT_INLINE_MEMSET)
|
||||
ccflags-y += -ffreestanding -fasynchronous-unwind-tables
|
||||
ccflags-remove-y := $(CC_FLAGS_FTRACE)
|
||||
ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)
|
||||
|
|
|
|||
|
|
@ -3058,7 +3058,6 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
|
|||
|
||||
init_waitqueue_head(&vcpu->arch.cpu_run);
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
vcore = NULL;
|
||||
err = -EINVAL;
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
|
||||
|
|
@ -3091,7 +3090,6 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
|
|||
mutex_unlock(&kvm->arch.mmu_setup_lock);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
if (!vcore)
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -602,14 +602,18 @@ int arch_protect_bpf_trampoline(void *image, unsigned int size)
|
|||
}
|
||||
|
||||
static int invoke_bpf_prog(u32 *image, u32 *ro_image, struct codegen_context *ctx,
|
||||
struct bpf_tramp_node *n, int regs_off, int retval_off,
|
||||
int run_ctx_off, bool save_ret)
|
||||
struct bpf_tramp_image *im, struct bpf_tramp_node *n,
|
||||
int regs_off, int retval_off, int run_ctx_off, bool save_ret)
|
||||
{
|
||||
struct bpf_prog *p = n->link->prog;
|
||||
ppc_inst_t branch_insn;
|
||||
u32 jmp_idx;
|
||||
u32 jmp_idx, skip_idx;
|
||||
int ret = 0;
|
||||
|
||||
/* nop, patched to skip this prog when it is detached */
|
||||
skip_idx = ctx->idx;
|
||||
EMIT(PPC_RAW_NOP());
|
||||
|
||||
/* Save cookie */
|
||||
if (IS_ENABLED(CONFIG_PPC64)) {
|
||||
PPC_LI64(_R3, n->cookie);
|
||||
|
|
@ -679,13 +683,17 @@ static int invoke_bpf_prog(u32 *image, u32 *ro_image, struct codegen_context *ct
|
|||
EMIT(PPC_RAW_ADDI(_R5, _R1, run_ctx_off));
|
||||
ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
|
||||
(unsigned long)bpf_trampoline_exit(p));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
if (ro_image) /* image is NULL for dummy pass */
|
||||
bpf_tramp_image_add_skip(im, p, &ro_image[skip_idx], &ro_image[ctx->idx]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invoke_bpf_mod_ret(u32 *image, u32 *ro_image, struct codegen_context *ctx,
|
||||
struct bpf_tramp_nodes *tn, int regs_off, int retval_off,
|
||||
int run_ctx_off, u32 *branches)
|
||||
struct bpf_tramp_image *im, struct bpf_tramp_nodes *tn,
|
||||
int regs_off, int retval_off, int run_ctx_off, u32 *branches)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -696,8 +704,8 @@ static int invoke_bpf_mod_ret(u32 *image, u32 *ro_image, struct codegen_context
|
|||
EMIT(PPC_RAW_LI(_R3, 0));
|
||||
EMIT(PPC_RAW_STL(_R3, _R1, retval_off));
|
||||
for (i = 0; i < tn->nr_nodes; i++) {
|
||||
if (invoke_bpf_prog(image, ro_image, ctx, tn->nodes[i], regs_off, retval_off,
|
||||
run_ctx_off, true))
|
||||
if (invoke_bpf_prog(image, ro_image, ctx, im, tn->nodes[i], regs_off,
|
||||
retval_off, run_ctx_off, true))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
|
@ -1043,8 +1051,8 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
cookie_ctx_off--;
|
||||
}
|
||||
|
||||
if (invoke_bpf_prog(image, ro_image, ctx, fentry->nodes[i], regs_off, retval_off,
|
||||
run_ctx_off, flags & BPF_TRAMP_F_RET_FENTRY_RET))
|
||||
if (invoke_bpf_prog(image, ro_image, ctx, im, fentry->nodes[i], regs_off,
|
||||
retval_off, run_ctx_off, flags & BPF_TRAMP_F_RET_FENTRY_RET))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1053,7 +1061,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
if (!branches)
|
||||
return -ENOMEM;
|
||||
|
||||
if (invoke_bpf_mod_ret(image, ro_image, ctx, fmod_ret, regs_off, retval_off,
|
||||
if (invoke_bpf_mod_ret(image, ro_image, ctx, im, fmod_ret, regs_off, retval_off,
|
||||
run_ctx_off, branches)) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
|
|
@ -1090,11 +1098,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
/* Restore updated tail_call_cnt */
|
||||
if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
|
||||
bpf_trampoline_restore_tail_call_cnt(image, ctx, bpf_frame_size, r4_off);
|
||||
|
||||
/* Reserve space to patch branch instruction to skip fexit progs */
|
||||
if (ro_image) /* image is NULL for dummy pass */
|
||||
im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
|
||||
EMIT(PPC_RAW_NOP());
|
||||
}
|
||||
|
||||
/* Update branches saved in invoke_bpf_mod_ret with address of do_fexit */
|
||||
|
|
@ -1123,16 +1126,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
cookie_ctx_off--;
|
||||
}
|
||||
|
||||
if (invoke_bpf_prog(image, ro_image, ctx, fexit->nodes[i], regs_off, retval_off,
|
||||
run_ctx_off, false)) {
|
||||
if (invoke_bpf_prog(image, ro_image, ctx, im, fexit->nodes[i], regs_off,
|
||||
retval_off, run_ctx_off, false)) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
if (ro_image) /* image is NULL for dummy pass */
|
||||
im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
|
||||
PPC_LI_ADDR(_R3, im);
|
||||
ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
|
||||
(unsigned long)__bpf_tramp_exit);
|
||||
|
|
@ -1192,7 +1193,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
||||
struct bpf_tramp_nodes *tnodes, void *func_addr)
|
||||
{
|
||||
struct bpf_tramp_image im;
|
||||
struct bpf_tramp_image im = {};
|
||||
int ret;
|
||||
|
||||
ret = __arch_prepare_bpf_trampoline(&im, NULL, NULL, NULL, m, flags, tnodes, func_addr);
|
||||
|
|
@ -1320,7 +1321,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
|||
|
||||
/*
|
||||
* If we are not poking at bpf prog entry, then we are simply patching in/out
|
||||
* an unconditional branch instruction at im->ip_after_call
|
||||
* an unconditional branch instruction in a trampoline image
|
||||
*/
|
||||
if (offset) {
|
||||
if (old_t == BPF_MOD_CALL || new_t == BPF_MOD_CALL) {
|
||||
|
|
|
|||
|
|
@ -1275,6 +1275,8 @@ static int trace_imc_prepare_sample(struct trace_imc_data *mem,
|
|||
struct perf_event_header *header,
|
||||
struct perf_event *event)
|
||||
{
|
||||
u16 misc = 0;
|
||||
|
||||
/* Sanity checks for a valid record */
|
||||
if (be64_to_cpu(READ_ONCE(mem->tb1)) > *prev_tb)
|
||||
*prev_tb = be64_to_cpu(READ_ONCE(mem->tb1));
|
||||
|
|
@ -1289,23 +1291,19 @@ static int trace_imc_prepare_sample(struct trace_imc_data *mem,
|
|||
data->ip = be64_to_cpu(READ_ONCE(mem->ip));
|
||||
data->period = event->hw.last_period;
|
||||
|
||||
header->type = PERF_RECORD_SAMPLE;
|
||||
header->size = sizeof(*header) + event->header_size;
|
||||
header->misc = 0;
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_31)) {
|
||||
switch (IMC_TRACE_RECORD_VAL_HVPR(be64_to_cpu(READ_ONCE(mem->val)))) {
|
||||
case 0:/* when MSR HV and PR not set in the trace-record */
|
||||
header->misc |= PERF_RECORD_MISC_GUEST_KERNEL;
|
||||
misc |= PERF_RECORD_MISC_GUEST_KERNEL;
|
||||
break;
|
||||
case 1: /* MSR HV is 0 and PR is 1 */
|
||||
header->misc |= PERF_RECORD_MISC_GUEST_USER;
|
||||
misc |= PERF_RECORD_MISC_GUEST_USER;
|
||||
break;
|
||||
case 2: /* MSR HV is 1 and PR is 0 */
|
||||
header->misc |= PERF_RECORD_MISC_KERNEL;
|
||||
misc |= PERF_RECORD_MISC_KERNEL;
|
||||
break;
|
||||
case 3: /* MSR HV is 1 and PR is 1 */
|
||||
header->misc |= PERF_RECORD_MISC_USER;
|
||||
misc |= PERF_RECORD_MISC_USER;
|
||||
break;
|
||||
default:
|
||||
pr_info("IMC: Unable to set the flag based on MSR bits\n");
|
||||
|
|
@ -1313,11 +1311,14 @@ static int trace_imc_prepare_sample(struct trace_imc_data *mem,
|
|||
}
|
||||
} else {
|
||||
if (is_kernel_addr(data->ip))
|
||||
header->misc |= PERF_RECORD_MISC_KERNEL;
|
||||
misc |= PERF_RECORD_MISC_KERNEL;
|
||||
else
|
||||
header->misc |= PERF_RECORD_MISC_USER;
|
||||
misc |= PERF_RECORD_MISC_USER;
|
||||
}
|
||||
perf_event_header__init_id(header, data, event);
|
||||
perf_event_header__init(header, data,
|
||||
PERF_RECORD_SAMPLE, misc,
|
||||
sizeof(*header) + event->header_size,
|
||||
event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ endif
|
|||
ccflags-y := -fno-stack-protector
|
||||
ccflags-y += -DDISABLE_BRANCH_PROFILING
|
||||
ccflags-y += -fno-builtin
|
||||
ccflags-y += $(CONFIG_CC_OPT_INLINE_MEMSET)
|
||||
ccflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH)
|
||||
ccflags-y += $(CFI_FULL)
|
||||
asflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH)
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ static int aia_init(struct kvm *kvm)
|
|||
return -EBUSY;
|
||||
|
||||
/* We might be in the middle of creating a VCPU? */
|
||||
if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus))
|
||||
if (kvm_is_vcpu_creation_in_progress(kvm))
|
||||
return -EBUSY;
|
||||
|
||||
/* Number of sources should be less than or equals number of IDs */
|
||||
|
|
|
|||
|
|
@ -822,6 +822,24 @@ static int gen_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
|
|||
return emit_jump_and_link(is_call ? RV_REG_T0 : RV_REG_ZERO, rvoff, false, &ctx);
|
||||
}
|
||||
|
||||
int arch_bpf_trampoline_skip(void *nop, void *target)
|
||||
{
|
||||
u32 old_insn = rv_nop();
|
||||
u32 new_insn = rv_jal(RV_REG_ZERO, (target - nop) >> 1);
|
||||
int ret;
|
||||
|
||||
if (memcmp(nop, &old_insn, sizeof(old_insn)))
|
||||
return -EFAULT;
|
||||
|
||||
cpus_read_lock();
|
||||
mutex_lock(&text_mutex);
|
||||
ret = patch_text(nop, &new_insn, sizeof(new_insn));
|
||||
mutex_unlock(&text_mutex);
|
||||
cpus_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||
enum bpf_text_poke_type new_t, void *old_addr,
|
||||
void *new_addr)
|
||||
|
|
@ -904,12 +922,17 @@ static void emit_store_stack_imm64(u8 reg, int stack_off, u64 imm64,
|
|||
emit_sd(RV_REG_FP, stack_off, reg, ctx);
|
||||
}
|
||||
|
||||
static int invoke_bpf_prog(struct bpf_tramp_node *node, int args_off, int retval_off,
|
||||
int run_ctx_off, bool save_ret, struct rv_jit_context *ctx)
|
||||
static int invoke_bpf_prog(struct bpf_tramp_image *im, struct bpf_tramp_node *node,
|
||||
int args_off, int retval_off, int run_ctx_off, bool save_ret,
|
||||
struct rv_jit_context *ctx)
|
||||
{
|
||||
int ret, branch_off;
|
||||
struct bpf_prog *p = node->link->prog;
|
||||
int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
|
||||
void *skip = ctx->ro_insns + ctx->ninsns;
|
||||
|
||||
/* nop, patched to a jal over this prog when it is detached */
|
||||
emit(rv_nop(), ctx);
|
||||
|
||||
if (node->cookie)
|
||||
emit_store_stack_imm64(RV_REG_T1, -run_ctx_off + cookie_off, node->cookie, ctx);
|
||||
|
|
@ -962,13 +985,17 @@ static int invoke_bpf_prog(struct bpf_tramp_node *node, int args_off, int retval
|
|||
/* arg3: &run_ctx */
|
||||
emit_addi(RV_REG_A2, RV_REG_FP, -run_ctx_off, ctx);
|
||||
ret = emit_call((const u64)bpf_trampoline_exit(p), true, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
bpf_tramp_image_add_skip(im, p, skip, ctx->ro_insns + ctx->ninsns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invoke_bpf(struct bpf_tramp_nodes *tn, int args_off, int retval_off,
|
||||
int run_ctx_off, int func_meta_off, bool save_ret, u64 func_meta,
|
||||
int cookie_off, struct rv_jit_context *ctx)
|
||||
static int invoke_bpf(struct bpf_tramp_image *im, struct bpf_tramp_nodes *tn,
|
||||
int args_off, int retval_off, int run_ctx_off, int func_meta_off,
|
||||
bool save_ret, u64 func_meta, int cookie_off,
|
||||
struct rv_jit_context *ctx)
|
||||
{
|
||||
int i, cur_cookie = (cookie_off - args_off) / 8;
|
||||
|
||||
|
|
@ -981,8 +1008,8 @@ static int invoke_bpf(struct bpf_tramp_nodes *tn, int args_off, int retval_off,
|
|||
emit_store_stack_imm64(RV_REG_T1, -func_meta_off, meta, ctx);
|
||||
cur_cookie--;
|
||||
}
|
||||
err = invoke_bpf_prog(tn->nodes[i], args_off, retval_off, run_ctx_off,
|
||||
save_ret, ctx);
|
||||
err = invoke_bpf_prog(im, tn->nodes[i], args_off, retval_off,
|
||||
run_ctx_off, save_ret, ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1170,7 +1197,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
}
|
||||
|
||||
if (fentry->nr_nodes) {
|
||||
ret = invoke_bpf(fentry, args_off, retval_off, run_ctx_off, func_meta_off,
|
||||
ret = invoke_bpf(im, fentry, args_off, retval_off, run_ctx_off, func_meta_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1184,7 +1211,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
/* cleanup to avoid garbage return value confusion */
|
||||
emit_sd(RV_REG_FP, -retval_off, RV_REG_ZERO, ctx);
|
||||
for (i = 0; i < fmod_ret->nr_nodes; i++) {
|
||||
ret = invoke_bpf_prog(fmod_ret->nodes[i], args_off, retval_off,
|
||||
ret = invoke_bpf_prog(im, fmod_ret->nodes[i], args_off, retval_off,
|
||||
run_ctx_off, true, ctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -1211,10 +1238,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
emit_sd(RV_REG_FP, -tcc_off, RV_REG_TCC, ctx);
|
||||
emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
|
||||
emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
|
||||
im->ip_after_call = ctx->ro_insns + ctx->ninsns;
|
||||
/* 2 nops reserved for auipc+jalr pair */
|
||||
emit(rv_nop(), ctx);
|
||||
emit(rv_nop(), ctx);
|
||||
}
|
||||
|
||||
/* update branches saved in invoke_bpf_mod_ret with bnez */
|
||||
|
|
@ -1230,14 +1253,13 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx);
|
||||
|
||||
if (fexit->nr_nodes) {
|
||||
ret = invoke_bpf(fexit, args_off, retval_off, run_ctx_off, func_meta_off,
|
||||
ret = invoke_bpf(im, fexit, args_off, retval_off, run_ctx_off, func_meta_off,
|
||||
false, func_meta, cookie_off, ctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = ctx->ro_insns + ctx->ninsns;
|
||||
emit_imm(RV_REG_A0, ctx->insns ? (const s64)im : RV_MAX_COUNT_IMM, ctx);
|
||||
ret = emit_call((const u64)__bpf_tramp_exit, true, ctx);
|
||||
if (ret)
|
||||
|
|
@ -1299,7 +1321,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
||||
struct bpf_tramp_nodes *tnodes, void *func_addr)
|
||||
{
|
||||
struct bpf_tramp_image im;
|
||||
struct bpf_tramp_image im = {};
|
||||
struct rv_jit_context ctx;
|
||||
int ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ KBUILD_CFLAGS_VDSO := $(filter-out -munaligned-symbols,$(KBUILD_CFLAGS_VDSO))
|
|||
KBUILD_CFLAGS_VDSO := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_VDSO))
|
||||
KBUILD_CFLAGS_VDSO += -fPIC -fno-common -fno-builtin -fasynchronous-unwind-tables
|
||||
KBUILD_CFLAGS_VDSO += -fno-stack-protector $(DISABLE_KSTACK_ERASE)
|
||||
KBUILD_CFLAGS_VDSO += $(CONFIG_CC_OPT_INLINE_MEMSET)
|
||||
ldflags-y := -shared -soname=linux-vdso.so.1 \
|
||||
--hash-style=both --build-id=sha1 \
|
||||
$(call ld-option, --eh-frame-hdr) -T
|
||||
|
|
|
|||
|
|
@ -3579,12 +3579,11 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
|||
|
||||
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
mutex_lock(&vcpu->kvm->lock);
|
||||
preempt_disable();
|
||||
vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
|
||||
vcpu->arch.sie_block->epdx = vcpu->kvm->arch.epdx;
|
||||
preempt_enable();
|
||||
mutex_unlock(&vcpu->kvm->lock);
|
||||
|
||||
if (!kvm_is_ucontrol(vcpu->kvm)) {
|
||||
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
|
||||
sca_add_vcpu(vcpu);
|
||||
|
|
@ -3757,13 +3756,11 @@ static int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
|
|||
|
||||
kvm_s390_vcpu_pci_setup(vcpu);
|
||||
|
||||
mutex_lock(&vcpu->kvm->lock);
|
||||
if (kvm_s390_pv_is_protected(vcpu->kvm)) {
|
||||
rc = kvm_s390_pv_create_cpu(vcpu, &uvrc, &uvrrc);
|
||||
if (rc)
|
||||
kvm_s390_vcpu_unsetup_cmma(vcpu);
|
||||
}
|
||||
mutex_unlock(&vcpu->kvm->lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2566,6 +2566,8 @@ struct bpf_tramp_jit {
|
|||
int r14_off; /* Offset of saved %r14, has to be at the
|
||||
* bottom */
|
||||
int do_fexit; /* do_fexit: label */
|
||||
int skip[BPF_MAX_TRAMP_LINKS]; /* skip: labels after each prog */
|
||||
int nr_progs;
|
||||
};
|
||||
|
||||
static void load_imm64(struct bpf_jit *jit, int dst_reg, u64 val)
|
||||
|
|
@ -2584,6 +2586,7 @@ static void emit_store_stack_imm64(struct bpf_jit *jit, int tmp_reg, int stack_o
|
|||
}
|
||||
|
||||
static int invoke_bpf_prog(struct bpf_tramp_jit *tjit,
|
||||
struct bpf_tramp_image *im,
|
||||
const struct btf_func_model *m,
|
||||
struct bpf_tramp_node *node, bool save_ret)
|
||||
{
|
||||
|
|
@ -2591,8 +2594,20 @@ static int invoke_bpf_prog(struct bpf_tramp_jit *tjit,
|
|||
int cookie_off = tjit->run_ctx_off +
|
||||
offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
|
||||
struct bpf_prog *p = node->link->prog;
|
||||
void *skip = jit->prg_buf + jit->prg;
|
||||
int idx = tjit->nr_progs++;
|
||||
int patch;
|
||||
|
||||
if (idx >= ARRAY_SIZE(tjit->skip))
|
||||
return -E2BIG;
|
||||
|
||||
/*
|
||||
* nop, patched to skip this prog when it is detached
|
||||
*/
|
||||
|
||||
/* brcl 0,skip */
|
||||
EMIT6_PCREL_RILC(0xc0040000, 0, tjit->skip[idx]);
|
||||
|
||||
/*
|
||||
* run_ctx.cookie = node->cookie;
|
||||
*/
|
||||
|
|
@ -2652,10 +2667,15 @@ static int invoke_bpf_prog(struct bpf_tramp_jit *tjit,
|
|||
/* brasl %r14,__bpf_prog_exit */
|
||||
EMIT6_PCREL_RILB_PTR(0xc0050000, REG_14, bpf_trampoline_exit(p));
|
||||
|
||||
/* skip: */
|
||||
tjit->skip[idx] = jit->prg;
|
||||
bpf_tramp_image_add_skip(im, p, skip, jit->prg_buf + jit->prg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invoke_bpf(struct bpf_tramp_jit *tjit,
|
||||
struct bpf_tramp_image *im,
|
||||
const struct btf_func_model *m,
|
||||
struct bpf_tramp_nodes *tn, bool save_ret,
|
||||
u64 func_meta, int cookie_off)
|
||||
|
|
@ -2670,7 +2690,7 @@ static int invoke_bpf(struct bpf_tramp_jit *tjit,
|
|||
emit_store_stack_imm64(jit, REG_0, tjit->func_meta_off, meta);
|
||||
cur_cookie--;
|
||||
}
|
||||
if (invoke_bpf_prog(tjit, m, tn->nodes[i], save_ret))
|
||||
if (invoke_bpf_prog(tjit, im, m, tn->nodes[i], save_ret))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2712,6 +2732,11 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
u64 func_meta;
|
||||
int i, j;
|
||||
|
||||
/* The skip labels are taken from the previous pass. */
|
||||
tjit->nr_progs = 0;
|
||||
if (im)
|
||||
im->nr_skips = 0;
|
||||
|
||||
/* Support as many stack arguments as "mvc" instruction can handle. */
|
||||
nr_reg_args = min_t(int, m->nr_args, MAX_NR_REG_ARGS);
|
||||
nr_stack_args = m->nr_args - nr_reg_args;
|
||||
|
|
@ -2875,7 +2900,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
emit_store_stack_imm64(jit, REG_0, tjit->retval_off, 0);
|
||||
}
|
||||
|
||||
if (invoke_bpf(tjit, m, fentry, flags & BPF_TRAMP_F_RET_FENTRY_RET,
|
||||
if (invoke_bpf(tjit, im, m, fentry, flags & BPF_TRAMP_F_RET_FENTRY_RET,
|
||||
func_meta, cookie_off))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -2889,7 +2914,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
0xf000 | tjit->retval_off);
|
||||
|
||||
for (i = 0; i < fmod_ret->nr_nodes; i++) {
|
||||
if (invoke_bpf_prog(tjit, m, fmod_ret->nodes[i], true))
|
||||
if (invoke_bpf_prog(tjit, im, m, fmod_ret->nodes[i], true))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
|
@ -2943,15 +2968,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
/* mvc tccnt_off(%r15),tail_call_cnt(4,%r15) */
|
||||
_EMIT6(0xd203f000 | tjit->tccnt_off,
|
||||
0xf000 | offsetof(struct prog_frame, tail_call_cnt));
|
||||
|
||||
im->ip_after_call = jit->prg_buf + jit->prg;
|
||||
|
||||
/*
|
||||
* The following nop will be patched by bpf_tramp_image_put().
|
||||
*/
|
||||
|
||||
/* brcl 0,im->ip_epilogue */
|
||||
EMIT6_PCREL_RILC(0xc0040000, 0, (u64)im->ip_epilogue);
|
||||
}
|
||||
|
||||
/* Set the "is_return" flag for fsession. */
|
||||
|
|
@ -2962,12 +2978,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
|
||||
/* do_fexit: */
|
||||
tjit->do_fexit = jit->prg;
|
||||
if (invoke_bpf(tjit, m, fexit, false, func_meta, cookie_off))
|
||||
if (invoke_bpf(tjit, im, m, fexit, false, func_meta, cookie_off))
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = jit->prg_buf + jit->prg;
|
||||
|
||||
/*
|
||||
* __bpf_tramp_exit(im);
|
||||
*/
|
||||
|
|
@ -3016,7 +3030,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
|||
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
||||
struct bpf_tramp_nodes *tnodes, void *orig_call)
|
||||
{
|
||||
struct bpf_tramp_image im;
|
||||
struct bpf_tramp_image im = {};
|
||||
struct bpf_tramp_jit tjit;
|
||||
int ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ static int raw_verify_header(
|
|||
if ((vheader->flags & VIRTIO_NET_HDR_F_DATA_VALID) > 0)
|
||||
return 1;
|
||||
|
||||
skb_set_network_header(skb, ETH_HLEN);
|
||||
virtio_net_hdr_to_skb(skb, vheader, virtio_legacy_is_little_endian());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1293,6 +1293,7 @@ static void gcm_process_assoc(const struct aes_gcm_key *key, u8 ghash_acc[16],
|
|||
unsigned int len;
|
||||
const u8 *src = walk.addr;
|
||||
|
||||
assoclen -= orig_len_this_step;
|
||||
if (unlikely(pos)) {
|
||||
len = min(len_this_step, 16 - pos);
|
||||
memcpy(&buf[pos], src, len);
|
||||
|
|
@ -1320,7 +1321,6 @@ static void gcm_process_assoc(const struct aes_gcm_key *key, u8 ghash_acc[16],
|
|||
kernel_fpu_end();
|
||||
kernel_fpu_begin();
|
||||
}
|
||||
assoclen -= orig_len_this_step;
|
||||
}
|
||||
if (unlikely(pos))
|
||||
aes_gcm_aad_update(key, ghash_acc, buf, pos, flags);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ vobjs-$(CONFIG_X86_SGX) += vsgx.o
|
|||
vobjs-$(CONFIG_FUTEX_ROBUST_UNLOCK) += vfutex.o
|
||||
|
||||
# Compilation flags
|
||||
flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small
|
||||
flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small $(CONFIG_CC_OPT_INLINE_MEMSET)
|
||||
|
||||
# The location of this include matters!
|
||||
include $(src)/../common/Makefile.include
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#ifndef _ASM_X86_PTRACE_ABI_H
|
||||
#define _ASM_X86_PTRACE_ABI_H
|
||||
|
||||
#if defined(__ASSEMBLER__) || defined(__FRAME_OFFSETS)
|
||||
#ifdef __i386__
|
||||
|
||||
#define EBX 0
|
||||
|
|
@ -25,7 +26,6 @@
|
|||
|
||||
#else /* __i386__ */
|
||||
|
||||
#if defined(__ASSEMBLER__) || defined(__FRAME_OFFSETS)
|
||||
/*
|
||||
* C ABI says these regs are callee-preserved. They aren't saved on kernel entry
|
||||
* unless syscall needs a complete, fully filled "struct pt_regs".
|
||||
|
|
@ -57,12 +57,12 @@
|
|||
#define EFLAGS 144
|
||||
#define RSP 152
|
||||
#define SS 160
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/* top of stack page */
|
||||
#define FRAME_SIZE 168
|
||||
|
||||
#endif /* !__i386__ */
|
||||
#endif /* defined(__ASSEMBLER__) || defined(__FRAME_OFFSETS) */
|
||||
|
||||
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
|
||||
#define PTRACE_GETREGS 12
|
||||
|
|
|
|||
|
|
@ -50,9 +50,16 @@ static unsigned long get_align_mask(struct file *filp)
|
|||
* value before calling vm_unmapped_area() or ORed directly to the
|
||||
* address.
|
||||
*/
|
||||
static unsigned long get_align_bits(void)
|
||||
static unsigned long get_align_bits(struct file *filp)
|
||||
{
|
||||
return va_align.bits & get_align_mask(NULL);
|
||||
/*
|
||||
* va_align.bits is smaller than the huge page size and will
|
||||
* lead to misaligned huge pages. Ignore it for huge mappings.
|
||||
*/
|
||||
if (is_file_hugepages(filp))
|
||||
return 0;
|
||||
|
||||
return va_align.bits & get_align_mask(filp);
|
||||
}
|
||||
|
||||
static int __init control_va_addr_alignment(char *str)
|
||||
|
|
@ -157,7 +164,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len,
|
|||
}
|
||||
if (filp) {
|
||||
info.align_mask = get_align_mask(filp);
|
||||
info.align_offset += get_align_bits();
|
||||
info.align_offset += get_align_bits(filp);
|
||||
}
|
||||
|
||||
return vm_unmapped_area(&info);
|
||||
|
|
@ -222,7 +229,7 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0,
|
|||
|
||||
if (filp) {
|
||||
info.align_mask = get_align_mask(filp);
|
||||
info.align_offset += get_align_bits();
|
||||
info.align_offset += get_align_bits(filp);
|
||||
}
|
||||
addr = vm_unmapped_area(&info);
|
||||
if (!(addr & ~PAGE_MASK))
|
||||
|
|
|
|||
|
|
@ -2512,6 +2512,12 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato
|
|||
|
||||
iterator->addr = addr;
|
||||
iterator->shadow_addr = root;
|
||||
|
||||
if (WARN_ON_ONCE(!VALID_PAGE(root)) || kvm_mmu_is_dummy_root(root)) {
|
||||
iterator->level = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
iterator->level = vcpu->arch.mmu->root_role.level;
|
||||
|
||||
if (iterator->level >= PT64_ROOT_4LEVEL &&
|
||||
|
|
|
|||
|
|
@ -488,6 +488,20 @@ static void snp_guest_req_cleanup(struct kvm *kvm)
|
|||
sev->guest_resp_buf = NULL;
|
||||
}
|
||||
|
||||
static int sev_alloc_have_run_cpus(struct kvm_sev_info *sev)
|
||||
{
|
||||
if (!zalloc_cpumask_var(&sev->have_run_cpus, GFP_KERNEL_ACCOUNT))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sev_free_have_run_cpus(struct kvm_sev_info *sev)
|
||||
{
|
||||
free_cpumask_var(sev->have_run_cpus);
|
||||
memset(&sev->have_run_cpus, 0, sizeof(sev->have_run_cpus));
|
||||
}
|
||||
|
||||
static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
|
||||
struct kvm_sev_init *data,
|
||||
unsigned long vm_type)
|
||||
|
|
@ -545,10 +559,9 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
|
|||
if (ret)
|
||||
goto e_free_asid;
|
||||
|
||||
if (!zalloc_cpumask_var(&sev->have_run_cpus, GFP_KERNEL_ACCOUNT)) {
|
||||
ret = -ENOMEM;
|
||||
ret = sev_alloc_have_run_cpus(sev);
|
||||
if (ret)
|
||||
goto e_free_asid;
|
||||
}
|
||||
|
||||
/* This needs to happen after SEV/SNP firmware initialization. */
|
||||
if (snp_active) {
|
||||
|
|
@ -566,7 +579,7 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
|
|||
return 0;
|
||||
|
||||
e_free:
|
||||
free_cpumask_var(sev->have_run_cpus);
|
||||
sev_free_have_run_cpus(sev);
|
||||
e_free_asid:
|
||||
argp->error = init_args.error;
|
||||
sev_asid_free(sev);
|
||||
|
|
@ -1125,9 +1138,6 @@ static int sev_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
|||
if (!sev_es_guest(kvm))
|
||||
return -ENOTTY;
|
||||
|
||||
if (kvm_is_vcpu_creation_in_progress(kvm))
|
||||
return -EBUSY;
|
||||
|
||||
ret = kvm_lock_all_vcpus(kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -2035,6 +2045,13 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
|
|||
struct kvm_sev_info *mirror;
|
||||
unsigned long i;
|
||||
|
||||
/*
|
||||
* Do cache maintenance on the source VM *before* clearing "SEV active",
|
||||
* as memory reclaim flows won't trigger cache maintenance on the VM
|
||||
* once it's no longer an SEV VM.
|
||||
*/
|
||||
sev_writeback_caches(src_kvm);
|
||||
|
||||
dst->active = true;
|
||||
dst->asid = src->asid;
|
||||
dst->handle = src->handle;
|
||||
|
|
@ -2048,12 +2065,6 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
|
|||
src->pages_locked = 0;
|
||||
src->es_active = false;
|
||||
|
||||
/*
|
||||
* Do cache maintenance on the source VM as it is no longer an SEV VM,
|
||||
* i.e. memory reclaim flows won't trigger cache maintenance on the VM.
|
||||
*/
|
||||
sev_writeback_caches(src_kvm);
|
||||
|
||||
list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list);
|
||||
|
||||
mutex_lock(&sev_mirror_lock);
|
||||
|
|
@ -2121,10 +2132,6 @@ static int sev_check_source_vcpus(struct kvm *dst, struct kvm *src)
|
|||
struct kvm_vcpu *src_vcpu;
|
||||
unsigned long i;
|
||||
|
||||
if (kvm_is_vcpu_creation_in_progress(src) ||
|
||||
kvm_is_vcpu_creation_in_progress(dst))
|
||||
return -EBUSY;
|
||||
|
||||
if (!sev_es_guest(src))
|
||||
return 0;
|
||||
|
||||
|
|
@ -2198,10 +2205,9 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
|||
* does not, i.e. KVM could skip flushes if memory is reclaimed from
|
||||
* the old VM but not the new VM.
|
||||
*/
|
||||
if (!zalloc_cpumask_var(&dst_sev->have_run_cpus, GFP_KERNEL_ACCOUNT)) {
|
||||
ret = -ENOMEM;
|
||||
ret = sev_alloc_have_run_cpus(dst_sev);
|
||||
if (ret)
|
||||
goto out_source_vcpu;
|
||||
}
|
||||
|
||||
sev_migrate_from(kvm, source_kvm);
|
||||
kvm_vm_dead(source_kvm);
|
||||
|
|
@ -2520,9 +2526,6 @@ static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
|||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
if (kvm_is_vcpu_creation_in_progress(kvm))
|
||||
return -EBUSY;
|
||||
|
||||
ret = kvm_lock_all_vcpus(kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -2898,10 +2901,9 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
|||
}
|
||||
|
||||
mirror_sev = to_kvm_sev_info(kvm);
|
||||
if (!zalloc_cpumask_var(&mirror_sev->have_run_cpus, GFP_KERNEL_ACCOUNT)) {
|
||||
ret = -ENOMEM;
|
||||
ret = sev_alloc_have_run_cpus(mirror_sev);
|
||||
if (ret)
|
||||
goto e_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* The mirror kvm holds an enc_context_owner ref so its asid can't
|
||||
|
|
@ -2994,7 +2996,7 @@ void sev_vm_destroy(struct kvm *kvm)
|
|||
* Free the mask even if the VM is not *currently* an SEV VM, as it may
|
||||
* have been an SEV VM prior to intra-host migration.
|
||||
*/
|
||||
free_cpumask_var(sev->have_run_cpus);
|
||||
sev_free_have_run_cpus(sev);
|
||||
|
||||
if (!sev_guest(kvm))
|
||||
return;
|
||||
|
|
@ -3630,7 +3632,6 @@ int pre_sev_run(struct vcpu_svm *svm, int cpu)
|
|||
|
||||
sd->sev_vmcbs[asid] = svm->vmcb;
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
|
||||
vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -673,16 +673,7 @@ static void clr_dr_intercepts(struct vcpu_svm *svm)
|
|||
|
||||
static bool msr_write_intercepted(struct vcpu_svm *svm, u32 msr)
|
||||
{
|
||||
/*
|
||||
* For non-nested case:
|
||||
* If the L01 MSR bitmap does not intercept the MSR, then we need to
|
||||
* save it.
|
||||
*
|
||||
* For nested case:
|
||||
* If the L02 MSR bitmap does not intercept the MSR, then we need to
|
||||
* save it.
|
||||
*/
|
||||
void *msrpm = is_guest_mode(&svm->vcpu) ? svm->nested.msrpm : svm->msrpm;
|
||||
void *msrpm = __va(__sme_clr(svm->vmcb->control.msrpm_base_pa));
|
||||
|
||||
return svm_test_msr_bitmap_write(msrpm, msr);
|
||||
}
|
||||
|
|
@ -1902,8 +1893,7 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
|
|||
if (sd->next_asid > sd->max_asid) {
|
||||
++sd->asid_generation;
|
||||
sd->next_asid = sd->min_asid;
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
|
||||
vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
|
||||
sd->flush_all_asids = true;
|
||||
}
|
||||
|
||||
svm->current_vmcb->asid_generation = sd->asid_generation;
|
||||
|
|
@ -4528,6 +4518,9 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
svm->vmcb->control.asid = svm->asid;
|
||||
vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
|
||||
}
|
||||
if (this_cpu_ptr(&svm_data)->flush_all_asids)
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
|
||||
|
||||
svm->vmcb->save.cr2 = vcpu->arch.cr2;
|
||||
|
||||
if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS) &&
|
||||
|
|
@ -4618,16 +4611,23 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
vcpu->arch.nested_run_pending = 0;
|
||||
}
|
||||
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
|
||||
if (!svm_is_vmrun_failure(svm->vmcb->control.exit_code)) {
|
||||
this_cpu_ptr(&svm_data)->flush_all_asids = false;
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
|
||||
|
||||
/*
|
||||
* Unconditionally mask off the CLEAR_RAP bit, the AND is just as cheap
|
||||
* as the TEST+Jcc to avoid it.
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_ERAPS))
|
||||
svm->vmcb->control.erap_ctl &= ~ERAP_CONTROL_CLEAR_RAP;
|
||||
/*
|
||||
* Unconditionally mask off the CLEAR_RAP bit, the AND is just
|
||||
* as cheap as the TEST+Jcc to avoid it.
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_ERAPS))
|
||||
svm->vmcb->control.erap_ctl &= ~ERAP_CONTROL_CLEAR_RAP;
|
||||
|
||||
vmcb_mark_all_clean(svm->vmcb);
|
||||
vmcb_mark_all_clean(svm->vmcb);
|
||||
|
||||
if (!msr_write_intercepted(svm, MSR_AMD64_PERF_CNTR_GLOBAL_CTL))
|
||||
rdmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_CTL,
|
||||
vcpu_to_pmu(vcpu)->global_ctrl);
|
||||
}
|
||||
|
||||
/* if exit due to PF check for async PF */
|
||||
if (svm->vmcb->control.exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR)
|
||||
|
|
@ -4636,9 +4636,6 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
|
||||
kvm_clear_available_registers(vcpu, SVM_REGS_LAZY_LOAD_SET);
|
||||
|
||||
if (!msr_write_intercepted(svm, MSR_AMD64_PERF_CNTR_GLOBAL_CTL))
|
||||
rdmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, vcpu_to_pmu(vcpu)->global_ctrl);
|
||||
|
||||
trace_kvm_exit(vcpu, KVM_ISA_SVM);
|
||||
|
||||
svm_complete_interrupts(vcpu);
|
||||
|
|
|
|||
|
|
@ -376,6 +376,7 @@ struct svm_cpu_data {
|
|||
u32 next_asid;
|
||||
u32 min_asid;
|
||||
|
||||
bool flush_all_asids;
|
||||
bool bp_spec_reduce_set;
|
||||
|
||||
struct vmcb *save_area;
|
||||
|
|
|
|||
|
|
@ -1754,6 +1754,9 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
|
|||
static void copy_enlightened_to_vmcs12(struct vcpu_vmx *vmx, u32 hv_clean_fields)
|
||||
{
|
||||
#ifdef CONFIG_KVM_HYPERV
|
||||
const u64 runtime_controls = HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1 |
|
||||
HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2 |
|
||||
HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_PROC;
|
||||
struct vmcs12 *vmcs12 = vmx->nested.cached_vmcs12;
|
||||
struct hv_enlightened_vmcs *evmcs = nested_vmx_evmcs(vmx);
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(&vmx->vcpu);
|
||||
|
|
@ -1762,6 +1765,9 @@ static void copy_enlightened_to_vmcs12(struct vcpu_vmx *vmx, u32 hv_clean_fields
|
|||
vmcs12->tpr_threshold = evmcs->tpr_threshold;
|
||||
vmcs12->guest_rip = evmcs->guest_rip;
|
||||
|
||||
if ((hv_clean_fields & runtime_controls) != runtime_controls)
|
||||
vmx->nested.force_msr_bitmap_recalc = true;
|
||||
|
||||
if (unlikely(!(hv_clean_fields &
|
||||
HV_VMX_ENLIGHTENED_CLEAN_FIELD_ENLIGHTENMENTSCONTROL))) {
|
||||
hv_vcpu->nested.pa_page_gpa = evmcs->partition_assist_page;
|
||||
|
|
|
|||
|
|
@ -2728,11 +2728,6 @@ static tdx_vm_state_guard_t tdx_acquire_vm_state_locks(struct kvm *kvm)
|
|||
|
||||
mutex_lock(&kvm->lock);
|
||||
|
||||
if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus)) {
|
||||
r = -EBUSY;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
r = kvm_lock_all_vcpus(kvm);
|
||||
if (r)
|
||||
goto out_err;
|
||||
|
|
|
|||
|
|
@ -705,47 +705,37 @@ int pmd_clear_huge(pmd_t *pmd)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/**
|
||||
* pud_free_pmd_page - Clear PUD entry and free PMD page
|
||||
* @pud: Pointer to a PUD
|
||||
* @addr: Virtual address associated with PUD
|
||||
*
|
||||
* Context: The PUD range has been unmapped and TLB purged.
|
||||
* Return: 1 if clearing the entry succeeded. 0 otherwise.
|
||||
*
|
||||
* NOTE: Callers must allow a single page allocation.
|
||||
/*
|
||||
* Given a PUD poitner, detach and free the pointed-to
|
||||
* PMD page and any PTE page children. The entire range
|
||||
* under the PUD must not have any valid translations
|
||||
* and the TLB must have already been flushed.
|
||||
*/
|
||||
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
pmd_t *pmd, *pmd_sv;
|
||||
struct ptdesc *pt;
|
||||
pmd_t *pmd;
|
||||
int i;
|
||||
|
||||
pmd = pud_pgtable(*pud);
|
||||
pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL);
|
||||
if (!pmd_sv)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
pmd_sv[i] = pmd[i];
|
||||
if (!pmd_none(pmd[i]))
|
||||
pmd_clear(&pmd[i]);
|
||||
}
|
||||
|
||||
/* Detach the PMD page: */
|
||||
pud_clear(pud);
|
||||
|
||||
/* INVLPG to clear all paging-structure caches */
|
||||
/*
|
||||
* PMD and all its descendents are unreachable
|
||||
* via normal page walks. Make them unreachable
|
||||
* in cached mid-level walks too:
|
||||
*/
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
if (!pmd_none(pmd_sv[i])) {
|
||||
pt = page_ptdesc(pmd_page(pmd_sv[i]));
|
||||
if (!pmd_none(pmd[i])) {
|
||||
pt = page_ptdesc(pmd_page(pmd[i]));
|
||||
pagetable_dtor_free(pt);
|
||||
}
|
||||
}
|
||||
|
||||
free_page((unsigned long)pmd_sv);
|
||||
|
||||
pmd_free(&init_mm, pmd);
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -3217,16 +3217,21 @@ static void restore_regs(const struct btf_func_model *m, u8 **prog,
|
|||
}
|
||||
|
||||
static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
|
||||
struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_node *node, int stack_size,
|
||||
int run_ctx_off, bool save_ret,
|
||||
void *image, void *rw_image)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
u8 *jmp_insn;
|
||||
u8 *jmp_insn, *skip;
|
||||
int ctx_cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
|
||||
struct bpf_prog *p = node->link->prog;
|
||||
u64 cookie = node->cookie;
|
||||
|
||||
/* nop, patched to skip this prog when it is detached */
|
||||
skip = image + (prog - (u8 *)rw_image);
|
||||
emit_nops(&prog, X86_PATCH_SIZE);
|
||||
|
||||
/* mov rdi, cookie */
|
||||
emit_mov_imm64(&prog, BPF_REG_1, (long) cookie >> 32, (u32) (long) cookie);
|
||||
|
||||
|
|
@ -3301,6 +3306,8 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
|
|||
if (emit_rsb_call(&prog, bpf_trampoline_exit(p), image + (prog - (u8 *)rw_image)))
|
||||
return -EINVAL;
|
||||
|
||||
bpf_tramp_image_add_skip(im, p, skip, image + (prog - (u8 *)rw_image));
|
||||
|
||||
*pprog = prog;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3332,6 +3339,7 @@ static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
|
|||
}
|
||||
|
||||
static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
|
||||
struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_nodes *tl, int stack_size,
|
||||
int run_ctx_off, int func_meta_off, bool save_ret,
|
||||
void *image, void *rw_image, u64 func_meta,
|
||||
|
|
@ -3346,7 +3354,7 @@ static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
|
|||
func_meta | (cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT));
|
||||
cur_cookie--;
|
||||
}
|
||||
if (invoke_bpf_prog(m, &prog, tl->nodes[i], stack_size,
|
||||
if (invoke_bpf_prog(m, &prog, im, tl->nodes[i], stack_size,
|
||||
run_ctx_off, save_ret, image, rw_image))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -3355,6 +3363,7 @@ static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
|
|||
}
|
||||
|
||||
static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
|
||||
struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_nodes *tl, int stack_size,
|
||||
int run_ctx_off, u8 **branches,
|
||||
void *image, void *rw_image)
|
||||
|
|
@ -3368,7 +3377,7 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
|
|||
emit_mov_imm32(&prog, false, BPF_REG_0, 0);
|
||||
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8);
|
||||
for (i = 0; i < tl->nr_nodes; i++) {
|
||||
if (invoke_bpf_prog(m, &prog, tl->nodes[i], stack_size, run_ctx_off, true,
|
||||
if (invoke_bpf_prog(m, &prog, im, tl->nodes[i], stack_size, run_ctx_off, true,
|
||||
image, rw_image))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -3640,7 +3649,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
}
|
||||
|
||||
if (fentry->nr_nodes) {
|
||||
if (invoke_bpf(m, &prog, fentry, regs_off, run_ctx_off, func_meta_off,
|
||||
if (invoke_bpf(m, &prog, im, fentry, regs_off, run_ctx_off, func_meta_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET, image, rw_image,
|
||||
func_meta, cookie_off))
|
||||
return -EINVAL;
|
||||
|
|
@ -3652,7 +3661,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
if (!branches)
|
||||
return -ENOMEM;
|
||||
|
||||
if (invoke_bpf_mod_ret(m, &prog, fmod_ret, regs_off,
|
||||
if (invoke_bpf_mod_ret(m, &prog, im, fmod_ret, regs_off,
|
||||
run_ctx_off, branches, image, rw_image)) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
|
|
@ -3682,8 +3691,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
}
|
||||
/* remember return value in a stack for bpf prog to access */
|
||||
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8);
|
||||
im->ip_after_call = image + (prog - (u8 *)rw_image);
|
||||
emit_nops(&prog, X86_PATCH_SIZE);
|
||||
}
|
||||
|
||||
if (fmod_ret->nr_nodes) {
|
||||
|
|
@ -3708,7 +3715,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
|
||||
|
||||
if (fexit->nr_nodes) {
|
||||
if (invoke_bpf(m, &prog, fexit, regs_off, run_ctx_off, func_meta_off,
|
||||
if (invoke_bpf(m, &prog, im, fexit, regs_off, run_ctx_off, func_meta_off,
|
||||
false, image, rw_image, func_meta, cookie_off)) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
|
|
@ -3723,7 +3730,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
|||
* restored to R0.
|
||||
*/
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = image + (prog - (u8 *)rw_image);
|
||||
/* arg1: mov rdi, im */
|
||||
emit_mov_imm64(&prog, BPF_REG_1, (long) im >> 32, (u32) (long) im);
|
||||
if (emit_rsb_call(&prog, __bpf_tramp_exit, image + (prog - (u8 *)rw_image))) {
|
||||
|
|
@ -3811,7 +3817,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
|
|||
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
||||
struct bpf_tramp_nodes *tnodes, void *func_addr)
|
||||
{
|
||||
struct bpf_tramp_image im;
|
||||
struct bpf_tramp_image im = {};
|
||||
void *image;
|
||||
int ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ enum {
|
|||
};
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#ifndef CONFIG_X86_32
|
||||
#define __FRAME_OFFSETS /* Needed to get the R* macros */
|
||||
#endif
|
||||
#define __FRAME_OFFSETS /* Needed to get the register macros */
|
||||
#include <asm/ptrace-generic.h>
|
||||
|
||||
#define user_mode(r) UPT_IS_USER(&(r)->regs)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/regset.h>
|
||||
#define __FRAME_OFFSETS
|
||||
#include <asm/ptrace-abi.h>
|
||||
#include <registers.h>
|
||||
#include <skas.h>
|
||||
|
|
|
|||
|
|
@ -2091,6 +2091,7 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,
|
|||
struct request_queue *q = bio->bi_bdev->bd_queue;
|
||||
struct blkcg *blkcg = css_to_blkcg(css);
|
||||
struct blkcg_gq *blkg;
|
||||
unsigned long flags;
|
||||
|
||||
rcu_read_lock();
|
||||
blkg = blkg_lookup(blkcg, q);
|
||||
|
|
@ -2105,11 +2106,11 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,
|
|||
* 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);
|
||||
spin_lock_irqsave(&q->queue_lock, flags);
|
||||
blkg = blkg_lookup_create(blkcg, bio->bi_bdev->bd_disk);
|
||||
if (blkg)
|
||||
blkg = blkg_lookup_tryget(blkg);
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
spin_unlock_irqrestore(&q->queue_lock, flags);
|
||||
|
||||
return blkg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -447,16 +447,6 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
|
|||
WRITE_ONCE(rq->deadline, 0);
|
||||
req_ref_set(rq, 1);
|
||||
|
||||
if (rq->rq_flags & RQF_USE_SCHED) {
|
||||
struct elevator_queue *e = data->q->elevator;
|
||||
|
||||
INIT_HLIST_NODE(&rq->hash);
|
||||
RB_CLEAR_NODE(&rq->rb_node);
|
||||
|
||||
if (e->type->ops.prepare_request)
|
||||
e->type->ops.prepare_request(rq);
|
||||
}
|
||||
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
|
@ -498,6 +488,12 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)
|
|||
return rq_list_pop(data->cached_rqs);
|
||||
}
|
||||
|
||||
static bool blk_op_bypass_sched(blk_opf_t opf)
|
||||
{
|
||||
return (opf & REQ_OP_MASK) == REQ_OP_FLUSH ||
|
||||
blk_op_is_passthrough(opf);
|
||||
}
|
||||
|
||||
static void blk_mq_limit_depth(struct blk_mq_alloc_data *data)
|
||||
{
|
||||
struct elevator_mq_ops *ops;
|
||||
|
|
@ -518,12 +514,10 @@ static void blk_mq_limit_depth(struct blk_mq_alloc_data *data)
|
|||
* Flush/passthrough requests are special and go directly to the
|
||||
* dispatch list, they are not subject to the async_depth limit.
|
||||
*/
|
||||
if ((data->cmd_flags & REQ_OP_MASK) == REQ_OP_FLUSH ||
|
||||
blk_op_is_passthrough(data->cmd_flags))
|
||||
if (blk_op_bypass_sched(data->cmd_flags))
|
||||
return;
|
||||
|
||||
WARN_ON_ONCE(data->flags & BLK_MQ_REQ_RESERVED);
|
||||
data->rq_flags |= RQF_USE_SCHED;
|
||||
|
||||
/*
|
||||
* By default, sync requests have no limit, and async requests are
|
||||
|
|
@ -534,6 +528,29 @@ static void blk_mq_limit_depth(struct blk_mq_alloc_data *data)
|
|||
ops->limit_depth(data->cmd_flags, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish initializing a request once it has been claimed for an operation.
|
||||
* Cached requests are allocated before that operation is known.
|
||||
*/
|
||||
static void blk_mq_rq_late_init(struct request *rq, u64 alloc_time_ns)
|
||||
{
|
||||
struct elevator_queue *e;
|
||||
|
||||
blk_mq_rq_time_init(rq, alloc_time_ns);
|
||||
|
||||
if (!(rq->rq_flags & RQF_SCHED_TAGS) || (rq->rq_flags & RQF_RESV) ||
|
||||
blk_op_bypass_sched(rq->cmd_flags))
|
||||
return;
|
||||
|
||||
rq->rq_flags |= RQF_USE_SCHED;
|
||||
INIT_HLIST_NODE(&rq->hash);
|
||||
RB_CLEAR_NODE(&rq->rb_node);
|
||||
|
||||
e = rq->q->elevator;
|
||||
if (e->type->ops.prepare_request)
|
||||
e->type->ops.prepare_request(rq);
|
||||
}
|
||||
|
||||
static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
|
||||
{
|
||||
struct request_queue *q = data->q;
|
||||
|
|
@ -562,7 +579,7 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
|
|||
if (data->nr_tags > 1) {
|
||||
rq = __blk_mq_alloc_requests_batch(data);
|
||||
if (rq) {
|
||||
blk_mq_rq_time_init(rq, alloc_time_ns);
|
||||
blk_mq_rq_late_init(rq, alloc_time_ns);
|
||||
return rq;
|
||||
}
|
||||
data->nr_tags = 1;
|
||||
|
|
@ -590,7 +607,7 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
|
|||
if (!(data->rq_flags & RQF_SCHED_TAGS))
|
||||
blk_mq_inc_active_requests(data->hctx);
|
||||
rq = blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag);
|
||||
blk_mq_rq_time_init(rq, alloc_time_ns);
|
||||
blk_mq_rq_late_init(rq, alloc_time_ns);
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
|
@ -637,8 +654,6 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
|
|||
if (plug->nr_ios == 1)
|
||||
return NULL;
|
||||
rq = blk_mq_rq_cache_fill(q, plug, opf, flags);
|
||||
if (!rq)
|
||||
return NULL;
|
||||
} else {
|
||||
rq = rq_list_peek(&plug->cached_rqs);
|
||||
if (!rq || rq->q != q)
|
||||
|
|
@ -646,15 +661,13 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
|
|||
|
||||
if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
|
||||
return NULL;
|
||||
if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
|
||||
return NULL;
|
||||
|
||||
rq_list_pop(&plug->cached_rqs);
|
||||
blk_mq_rq_time_init(rq, blk_time_get_ns());
|
||||
rq->cmd_flags = opf;
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
blk_mq_rq_late_init(rq, blk_time_get_ns());
|
||||
}
|
||||
|
||||
rq->cmd_flags = opf;
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
|
@ -766,7 +779,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
|
|||
if (!(data.rq_flags & RQF_SCHED_TAGS))
|
||||
blk_mq_inc_active_requests(data.hctx);
|
||||
rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag);
|
||||
blk_mq_rq_time_init(rq, alloc_time_ns);
|
||||
blk_mq_rq_late_init(rq, alloc_time_ns);
|
||||
rq->__data_len = 0;
|
||||
rq->phys_gap_bit = 0;
|
||||
rq->__sector = (sector_t) -1;
|
||||
|
|
@ -3060,8 +3073,6 @@ static struct request *blk_mq_get_cached_request(struct blk_plug *plug,
|
|||
if (type != rq->mq_hctx->type &&
|
||||
(type != HCTX_TYPE_READ || rq->mq_hctx->type != HCTX_TYPE_DEFAULT))
|
||||
return NULL;
|
||||
if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
|
||||
return NULL;
|
||||
rq_list_pop(&plug->cached_rqs);
|
||||
return rq;
|
||||
}
|
||||
|
|
@ -3163,9 +3174,9 @@ void blk_mq_submit_bio(struct bio *bio)
|
|||
new_request:
|
||||
if (rq) {
|
||||
rq_qos_throttle(rq->q, bio);
|
||||
blk_mq_rq_time_init(rq, blk_time_get_ns());
|
||||
rq->cmd_flags = bio->bi_opf;
|
||||
INIT_LIST_HEAD(&rq->queuelist);
|
||||
blk_mq_rq_late_init(rq, blk_time_get_ns());
|
||||
} else {
|
||||
rq = blk_mq_get_new_requests(q, plug, bio);
|
||||
if (unlikely(!rq)) {
|
||||
|
|
|
|||
|
|
@ -402,6 +402,11 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|||
if (blkdev_dio_invalid(bdev, iocb, iter))
|
||||
return -EINVAL;
|
||||
|
||||
/* HIPRI needs private as bio; HAS_METADATA keeps it as uio_meta */
|
||||
if ((iocb->ki_flags & IOCB_HIPRI) &&
|
||||
(iocb->ki_flags & IOCB_HAS_METADATA))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (iov_iter_rw(iter) == WRITE) {
|
||||
u16 max_write_streams = bdev_max_write_streams(bdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -685,7 +685,7 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
|
|||
blk_mq_free_requests(&free);
|
||||
}
|
||||
|
||||
/* Callback from inside blk_mq_rq_ctx_init(). */
|
||||
/* Callback from inside blk_mq_rq_late_init(). */
|
||||
static void dd_prepare_request(struct request *rq)
|
||||
{
|
||||
rq->elv.priv[0] = NULL;
|
||||
|
|
|
|||
51
crypto/aes.c
51
crypto/aes.c
|
|
@ -637,7 +637,18 @@ static struct skcipher_alg skcipher_algs[] = {
|
|||
.decrypt = crypto_aes_cbc_decrypt,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_CTS)
|
||||
/*
|
||||
* Don't register library-based "cts(cbc(aes))" on architectures where
|
||||
* it might block a "better" implementation from being instantiated via
|
||||
* the "cts" template. These exclusions are temporary and will go away
|
||||
* as the arch-optimized AES code is migrated into the library.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_CTS) && \
|
||||
!(IS_ENABLED(CONFIG_ARM) || \
|
||||
IS_ENABLED(CONFIG_ARM64) || \
|
||||
IS_ENABLED(CONFIG_PPC) || \
|
||||
IS_ENABLED(CONFIG_S390) || \
|
||||
IS_ENABLED(CONFIG_SPARC))
|
||||
{
|
||||
.base.cra_name = "cts(cbc(aes))",
|
||||
.base.cra_driver_name = "cts-cbc-aes-lib",
|
||||
|
|
@ -687,7 +698,13 @@ static struct skcipher_alg skcipher_algs[] = {
|
|||
.decrypt = crypto_aes_xctr_crypt,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_XTS)
|
||||
/*
|
||||
* Don't register library-based "xts(aes)" on architectures where it
|
||||
* might block a "better" implementation from being instantiated via the
|
||||
* "xts" template. This exclusion is temporary and will go away when
|
||||
* the library AES-XTS is optimized for SPARC.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_XTS) && !IS_ENABLED(CONFIG_SPARC)
|
||||
{
|
||||
.base.cra_name = "xts(aes)",
|
||||
.base.cra_driver_name = "xts-aes-lib",
|
||||
|
|
@ -980,7 +997,20 @@ static __maybe_unused int crypto_aes_ccm_decrypt(struct aead_request *req)
|
|||
}
|
||||
|
||||
static struct aead_alg aead_algs[] = {
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_GCM)
|
||||
/*
|
||||
* Don't register library-based "gcm(aes)" and "rfc4106(gcm(aes))" on
|
||||
* architectures where they might block a "better" implementation from
|
||||
* being instantiated via the "gcm" and "rfc4106" templates. These
|
||||
* exclusions are temporary and will go away as the arch-optimized AES
|
||||
* code is migrated into the library.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_GCM) && \
|
||||
!(IS_ENABLED(CONFIG_ARM) || \
|
||||
IS_ENABLED(CONFIG_ARM64) || \
|
||||
IS_ENABLED(CONFIG_PPC) || \
|
||||
IS_ENABLED(CONFIG_RISCV) || \
|
||||
IS_ENABLED(CONFIG_S390) || \
|
||||
IS_ENABLED(CONFIG_SPARC))
|
||||
{
|
||||
.base.cra_name = "gcm(aes)",
|
||||
.base.cra_driver_name = "gcm-aes-lib",
|
||||
|
|
@ -1012,7 +1042,20 @@ static struct aead_alg aead_algs[] = {
|
|||
.chunksize = AES_BLOCK_SIZE,
|
||||
},
|
||||
#endif /* CONFIG_CRYPTO_GCM */
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_CCM)
|
||||
/*
|
||||
* Don't register library-based "ccm(aes)" on architectures where it
|
||||
* might block a "better" implementation from being instantiated via the
|
||||
* "ccm" template. These exclusions are temporary and will go away as
|
||||
* the arch-optimized AES code is migrated into the library.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_CCM) && \
|
||||
!(IS_ENABLED(CONFIG_ARM) || \
|
||||
IS_ENABLED(CONFIG_ARM64) || \
|
||||
IS_ENABLED(CONFIG_PPC) || \
|
||||
IS_ENABLED(CONFIG_RISCV) || \
|
||||
IS_ENABLED(CONFIG_S390) || \
|
||||
IS_ENABLED(CONFIG_SPARC) || \
|
||||
IS_ENABLED(CONFIG_X86))
|
||||
{
|
||||
.base.cra_name = "ccm(aes)",
|
||||
.base.cra_driver_name = "ccm-aes-lib",
|
||||
|
|
|
|||
|
|
@ -62,14 +62,50 @@ static void braille_write(u16 *buf)
|
|||
{
|
||||
static u16 lastwrite[WIDTH];
|
||||
unsigned char data[1 + 1 + 2*WIDTH + 2 + 1], csum = 0, *c;
|
||||
struct nbcon_write_context wctxt = { };
|
||||
unsigned long flags;
|
||||
u16 out;
|
||||
int i;
|
||||
|
||||
if (!braille_co)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Braille console is not registered in console_list. Instead, it
|
||||
* is integrated with VT and shows what appears on the graphical
|
||||
* console under console_lock(). From this POV it is a legacy
|
||||
* console. But it calls serial console driver which might be
|
||||
* converted to the NBCON API. It is similar to
|
||||
* nbcon_legacy_emit_next_record() except that we should try
|
||||
* harder to get the lock. Otherwise, the Braille device won't show
|
||||
* everything what is displayed on the terminal.
|
||||
*
|
||||
* In short, simulate the original locking using NBCON API.
|
||||
*/
|
||||
if (braille_co->flags & CON_NBCON) {
|
||||
if (panic_on_this_cpu()) {
|
||||
/*
|
||||
* This should be good enough in practice. Most/all
|
||||
* serial console drivers have the atomic callback.
|
||||
*/
|
||||
if (!braille_co->write_atomic)
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
/* NBCON API strictly requires the ownership. */
|
||||
if (!nbcon_braille_try_acquire(braille_co, &wctxt)) {
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
braille_co->device_lock(braille_co, &flags);
|
||||
while (!nbcon_braille_try_acquire(braille_co, &wctxt))
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
if (!memcmp(lastwrite, buf, WIDTH * sizeof(*buf)))
|
||||
return;
|
||||
goto unlock_nbcon;
|
||||
memcpy(lastwrite, buf, WIDTH * sizeof(*buf));
|
||||
|
||||
#define SOH 1
|
||||
|
|
@ -102,7 +138,24 @@ static void braille_write(u16 *buf)
|
|||
*c++ = csum;
|
||||
*c++ = ETX;
|
||||
|
||||
braille_co->write(braille_co, data, c - data);
|
||||
if (braille_co->flags & CON_NBCON) {
|
||||
nbcon_write_context_set_buf(&wctxt, (char *)data, c - data);
|
||||
if (panic_on_this_cpu())
|
||||
braille_co->write_atomic(braille_co, &wctxt);
|
||||
else
|
||||
braille_co->write_thread(braille_co, &wctxt);
|
||||
} else {
|
||||
braille_co->write(braille_co, data, c - data);
|
||||
}
|
||||
|
||||
unlock_nbcon:
|
||||
if (braille_co->flags & CON_NBCON) {
|
||||
nbcon_braille_release(&wctxt);
|
||||
if (panic_on_this_cpu())
|
||||
local_irq_restore(flags);
|
||||
else
|
||||
braille_co->device_unlock(braille_co, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* Follow the VC cursor*/
|
||||
|
|
|
|||
|
|
@ -2930,8 +2930,9 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
|||
t_outdated->buffer = NULL;
|
||||
buffer->transaction = NULL;
|
||||
trace_binder_transaction_update_buffer_release(buffer);
|
||||
binder_release_entire_buffer(proc, NULL, buffer, false);
|
||||
binder_release_entire_buffer(proc, NULL, buffer, true);
|
||||
binder_alloc_free_buf(&proc->alloc, buffer);
|
||||
binder_free_txn_fixups(t_outdated);
|
||||
kfree(t_outdated);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@
|
|||
/// about to drop the weak reference, then the strong increment could be processed after the
|
||||
/// other thread has already exited, which would be too late.
|
||||
///
|
||||
/// Note that trying to create a `ListArc` to the node can succeed even if `has_normal_push` is
|
||||
/// Note that trying to create a `ListArc` to the node can succeed even if `has_pushed_node` is
|
||||
/// set. This is because another thread might just have popped the node from a todo list, but not
|
||||
/// yet called `do_work`. However, if `has_normal_push` is false, then creating a `ListArc` should
|
||||
/// yet called `do_work`. However, if `has_pushed_node` is false, then creating a `ListArc` should
|
||||
/// always succeed.
|
||||
///
|
||||
/// Like the other fields in `NodeInner`, the delivery state is protected by the process lock.
|
||||
|
|
@ -738,7 +738,21 @@ fn do_work(
|
|||
self.do_work_locked(writer, owner_inner)
|
||||
}
|
||||
|
||||
fn cancel(self: DArc<Self>) {}
|
||||
fn cancel(self: DArc<Self>) {
|
||||
let _drop_outside_lock;
|
||||
let mut owner_inner = self.owner.inner.lock();
|
||||
|
||||
// We only do something on BINDER_THREAD_EXIT, not process exit.
|
||||
if owner_inner.is_dead {
|
||||
return;
|
||||
}
|
||||
|
||||
// If BINDER_THREAD_EXIT is invoked on a thread with a pending node refcount update, we
|
||||
// should move ourselves to ensure the refcount update is still delivered.
|
||||
if let Some(node) = ListArc::try_from_arc_borrow(self.as_arc_borrow()) {
|
||||
_drop_outside_lock = owner_inner.push_work(&self.owner, node);
|
||||
}
|
||||
}
|
||||
|
||||
fn should_sync_wakeup(&self) -> bool {
|
||||
false
|
||||
|
|
|
|||
|
|
@ -57,7 +57,39 @@ fn do_work(
|
|||
node.do_work_locked(writer, owner_inner)
|
||||
}
|
||||
|
||||
fn cancel(self: DArc<Self>) {}
|
||||
fn cancel(self: DArc<Self>) {
|
||||
let _drop_outside_lock;
|
||||
let node = &self.node;
|
||||
let mut owner_inner = node.owner.inner.lock();
|
||||
|
||||
// We only do something on BINDER_THREAD_EXIT, not process exit.
|
||||
if owner_inner.is_dead {
|
||||
return;
|
||||
}
|
||||
|
||||
// We transfer the responsibility of the node refcount update to the scheduled Node because
|
||||
// NodeWrapper has no way to re-create the ListArc.
|
||||
let inner = node.inner.access_mut(&mut owner_inner);
|
||||
|
||||
let ds = &mut inner.delivery_state;
|
||||
assert!(ds.has_pushed_wrapper);
|
||||
assert!(ds.has_strong_zero2one);
|
||||
ds.has_pushed_wrapper = false;
|
||||
|
||||
// We are changing the state to one where the Node is the strong zero2one update instead of
|
||||
// the wrapper.
|
||||
ds.has_weak_zero2one = false;
|
||||
|
||||
if !ds.has_pushed_node {
|
||||
if let Some(node2) = ListArc::try_from_arc_borrow(node.as_arc_borrow()) {
|
||||
ds.has_pushed_node = true;
|
||||
_drop_outside_lock = owner_inner.push_work(&node.owner, node2);
|
||||
} else {
|
||||
// This can't actually happen.
|
||||
ds.has_strong_zero2one = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn should_sync_wakeup(&self) -> bool {
|
||||
false
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ struct binder_features {
|
|||
bool oneway_spam_detection;
|
||||
bool extended_error;
|
||||
bool freeze_notification;
|
||||
bool transaction_report;
|
||||
};
|
||||
|
||||
static const struct constant_table binderfs_param_stats[] = {
|
||||
|
|
@ -89,6 +90,7 @@ static struct binder_features binder_features = {
|
|||
.oneway_spam_detection = true,
|
||||
.extended_error = true,
|
||||
.freeze_notification = true,
|
||||
.transaction_report = true,
|
||||
};
|
||||
|
||||
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
|
||||
|
|
@ -566,6 +568,12 @@ static int init_binder_features(struct super_block *sb)
|
|||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
dentry = rust_binderfs_create_file(dir, "transaction_report",
|
||||
&binder_features_fops,
|
||||
&binder_features.transaction_report);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -686,6 +686,12 @@ pub(crate) fn push_return_work(&self, reply: u32) {
|
|||
self.inner.lock().push_return_work(reply);
|
||||
}
|
||||
|
||||
pub(crate) fn pop_work_even_if_deferred(&self) -> Option<DLArc<dyn DeliverToRead>> {
|
||||
let mut thread_inner = self.inner.lock();
|
||||
thread_inner.process_work_list = true;
|
||||
thread_inner.pop_work()
|
||||
}
|
||||
|
||||
fn translate_object(
|
||||
&self,
|
||||
obj_index: usize,
|
||||
|
|
@ -1678,7 +1684,7 @@ pub(crate) fn release(self: &Arc<Self>) {
|
|||
self.unwind_transaction_stack();
|
||||
|
||||
// Cancel all pending work items.
|
||||
while let Ok(Some(work)) = self.get_work_local(false) {
|
||||
while let Some(work) = self.pop_work_even_if_deferred() {
|
||||
work.into_arc().cancel();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,12 +189,11 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
|
|||
goto err;
|
||||
}
|
||||
inode->i_private = device;
|
||||
binder_add_device(device);
|
||||
d_make_persistent(dentry, inode);
|
||||
fsnotify_create(root->d_inode, dentry);
|
||||
simple_done_creating(dentry);
|
||||
|
||||
binder_add_device(device);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -3059,10 +3059,15 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
|
|||
if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
|
||||
qc->dev->sdev->locked = 0;
|
||||
|
||||
if (cmd->result)
|
||||
ata_scsi_qc_done(qc, false, 0);
|
||||
else
|
||||
ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION);
|
||||
/*
|
||||
* Report CHECK CONDITION unless the command was terminated
|
||||
* with a host byte set. Only set the status byte, so that the
|
||||
* SCSI midlayer internal byte, which scsi_check_sense() may
|
||||
* have set from the sense data, is preserved.
|
||||
*/
|
||||
if (get_host_byte(cmd) == DID_OK)
|
||||
set_status_byte(cmd, SAM_STAT_CHECK_CONDITION);
|
||||
ata_scsi_qc_done(qc, false, 0);
|
||||
goto schedule_deferred;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -638,10 +638,6 @@ const struct genl_split_ops drbd_nl_ops[32] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct genl_multicast_group drbd_nl_mcgrps[] = {
|
||||
[DRBD_NLGRP_EVENTS] = { "events", },
|
||||
};
|
||||
|
||||
static int __drbd_cfg_context_from_attrs(struct drbd_cfg_context *s,
|
||||
struct nlattr ***ret_nested_attribute_table,
|
||||
struct genl_info *info)
|
||||
|
|
|
|||
|
|
@ -743,6 +743,7 @@ static int virtblk_read_zoned_limits(struct virtio_blk *vblk,
|
|||
dev_warn(&vdev->dev, "zero write granularity reported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
lim->zone_write_granularity = wg;
|
||||
lim->physical_block_size = wg;
|
||||
lim->io_min = wg;
|
||||
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ static int btintel_pcie_send_sync(struct btintel_pcie_data *data,
|
|||
|
||||
tfd_index = data->ia.tr_hia[BTINTEL_PCIE_TXQ_NUM];
|
||||
|
||||
if (tfd_index > txq->count)
|
||||
if (tfd_index >= txq->count)
|
||||
return -ERANGE;
|
||||
|
||||
if (skb->len > BTINTEL_PCIE_BUFFER_SIZE - BTINTEL_PCIE_HCI_TYPE_LEN) {
|
||||
|
|
@ -1777,7 +1777,7 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
static int btintel_pcie_setup_irq(struct btintel_pcie_data *data)
|
||||
{
|
||||
int err;
|
||||
int num_irqs, i;
|
||||
int num_irqs, i, j;
|
||||
|
||||
for (i = 0; i < BTINTEL_PCIE_MSIX_VEC_MAX; i++)
|
||||
data->msix_entries[i].entry = i;
|
||||
|
|
@ -1806,6 +1806,10 @@ static int btintel_pcie_setup_irq(struct btintel_pcie_data *data)
|
|||
KBUILD_MODNAME,
|
||||
msix_entry);
|
||||
if (err) {
|
||||
for (j = 0; j < i; j++)
|
||||
devm_free_irq(&data->pdev->dev,
|
||||
data->msix_entries[j].vector,
|
||||
&data->msix_entries[j]);
|
||||
pci_free_irq_vectors(data->pdev);
|
||||
data->alloc_vecs = 0;
|
||||
return err;
|
||||
|
|
@ -1877,6 +1881,13 @@ static int btintel_pcie_config_pcie(struct pci_dev *pdev,
|
|||
if (IS_ERR(data->base_addr))
|
||||
return PTR_ERR(data->base_addr);
|
||||
|
||||
/* Do shared hardware reset to ensure a clean start before
|
||||
* configuring interrupts.
|
||||
*/
|
||||
err = btintel_pcie_reset_bt(data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = btintel_pcie_setup_irq(data);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -3138,7 +3149,7 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
|
|||
struct msix_entry *msix_entry;
|
||||
|
||||
msix_entry = &data->msix_entries[i];
|
||||
free_irq(msix_entry->vector, msix_entry);
|
||||
devm_free_irq(&pdev->dev, msix_entry->vector, msix_entry);
|
||||
}
|
||||
|
||||
pci_free_irq_vectors(pdev);
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ static int mmap_zero_prepare(struct vm_area_desc *desc)
|
|||
#ifndef CONFIG_MMU
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
if (vma_desc_test(desc, VMA_SHARED_BIT))
|
||||
if (vma_desc_test(desc, VMA_MAYSHARE_BIT))
|
||||
return shmem_zero_setup_desc(desc);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
|
|||
int err;
|
||||
ssize_t len;
|
||||
|
||||
len = tpm_transmit(chip, buf->data, PAGE_SIZE);
|
||||
len = tpm_transmit(chip, buf->data, buf->capacity);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
|
|
|
|||
|
|
@ -281,8 +281,10 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
|
|||
}
|
||||
tpm_buf_append_u16(buf, num_bytes);
|
||||
err = tpm_buf_fill_hmac_session(chip, buf);
|
||||
if (err)
|
||||
if (err) {
|
||||
tpm2_end_auth_session(chip);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tpm_transmit_cmd(chip, buf,
|
||||
offsetof(struct tpm2_get_random_out,
|
||||
|
|
@ -305,7 +307,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
|
|||
out = (struct tpm2_get_random_out *)&buf->data[offset];
|
||||
recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
|
||||
if (tpm_buf_length(buf) <
|
||||
TPM_HEADER_SIZE +
|
||||
offset +
|
||||
offsetof(struct tpm2_get_random_out, buffer) +
|
||||
recd) {
|
||||
tpm2_end_auth_session(chip);
|
||||
|
|
|
|||
|
|
@ -975,6 +975,7 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
|
|||
/* Deduce from the name change TPM interference: */
|
||||
dev_err(&chip->dev, "null key integrity check failed\n");
|
||||
tpm2_flush_context(chip, tmp_null_key);
|
||||
rc = -ENODEV;
|
||||
|
||||
err:
|
||||
if (rc) {
|
||||
|
|
|
|||
|
|
@ -3010,8 +3010,6 @@ static const u32 gcc_eliza_critical_cbcrs[] = {
|
|||
0x26034, /* GCC_CAMERA_XO_CLK */
|
||||
0x27004, /* GCC_DISP_AHB_CLK */
|
||||
0x71004, /* GCC_GPU_CFG_AHB_CLK */
|
||||
0x52010, /* GCC_PCIE_RSCC_CFG_AHB_CLK */
|
||||
0x52010, /* GCC_PCIE_RSCC_XO_CLK */
|
||||
0x32004, /* GCC_VIDEO_AHB_CLK */
|
||||
0x32038, /* GCC_VIDEO_XO_CLK */
|
||||
};
|
||||
|
|
@ -3045,6 +3043,10 @@ static const struct regmap_config gcc_eliza_regmap_config = {
|
|||
|
||||
static void clk_eliza_regs_configure(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
/* Keep clocks always enabled */
|
||||
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); /* GCC_PCIE_RSCC_CFG_AHB_CLK */
|
||||
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); /* GCC_PCIE_RSCC_XO_CLK */
|
||||
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true);
|
||||
|
|
|
|||
|
|
@ -3692,8 +3692,6 @@ static const u32 gcc_hawi_critical_cbcrs[] = {
|
|||
0x67084, /* GCC_PCIE_1_RSC_CORE_CLK */
|
||||
0x43014, /* GCC_PCIE_LINK_XO_CLK */
|
||||
0x6b088, /* GCC_PCIE_RSC_CORE_CLK */
|
||||
0x52010, /* GCC_PCIE_RSCC_CFG_AHB_CLK */
|
||||
0x52010, /* GCC_PCIE_RSCC_XO_CLK */
|
||||
0x32004, /* GCC_VIDEO_AHB_CLK */
|
||||
0x32028, /* GCC_VIDEO_XO_CLK */
|
||||
};
|
||||
|
|
@ -3763,6 +3761,10 @@ static const struct regmap_config gcc_hawi_regmap_config = {
|
|||
|
||||
static void clk_hawi_regs_configure(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
/* Keep clocks always enabled */
|
||||
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); /* GCC_PCIE_RSCC_CFG_AHB_CLK */
|
||||
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); /* GCC_PCIE_RSCC_XO_CLK */
|
||||
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3464,8 +3464,6 @@ static const u32 gcc_kaanapali_critical_cbcrs[] = {
|
|||
0x9f004, /* GCC_EVA_AHB_CLK */
|
||||
0x9f024, /* GCC_EVA_XO_CLK */
|
||||
0x71004, /* GCC_GPU_CFG_AHB_CLK */
|
||||
0x52010, /* GCC_PCIE_RSCC_CFG_AHB_CLK */
|
||||
0x52010, /* GCC_PCIE_RSCC_XO_CLK */
|
||||
0x32004, /* GCC_VIDEO_AHB_CLK */
|
||||
0x32040, /* GCC_VIDEO_XO_CLK */
|
||||
};
|
||||
|
|
@ -3480,6 +3478,10 @@ static const struct regmap_config gcc_kaanapali_regmap_config = {
|
|||
|
||||
static void clk_kaanapali_regs_configure(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
/* Keep clocks always enabled */
|
||||
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); /* GCC_PCIE_RSCC_CFG_AHB_CLK */
|
||||
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); /* GCC_PCIE_RSCC_XO_CLK */
|
||||
|
||||
/* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
|
||||
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ static struct gdsc gpu_cc_cx_gdsc = {
|
|||
.name = "gpu_cc_cx_gdsc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
|
||||
.flags = RETAIN_FF_ENABLE | VOTABLE,
|
||||
};
|
||||
|
||||
static struct clk_regmap *gpu_cc_glymur_clocks[] = {
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ static struct gdsc gpu_cc_cx_gdsc = {
|
|||
.name = "gpu_cc_cx_gdsc",
|
||||
},
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
|
||||
.flags = RETAIN_FF_ENABLE | VOTABLE,
|
||||
};
|
||||
|
||||
static struct clk_regmap *gpu_cc_kaanapali_clocks[] = {
|
||||
|
|
|
|||
|
|
@ -30,14 +30,87 @@ static const struct ccu_pll_rate_tbl pll2_rate_tbl[] = {
|
|||
};
|
||||
|
||||
static const struct ccu_pll_rate_tbl pll3_rate_tbl[] = {
|
||||
CCU_PLLA_RATE(1050000000UL, 0x0b2b3000, 0x00000000, 0xa0458080),
|
||||
CCU_PLLA_RATE(1100000000UL, 0x0b2d3555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1150000000UL, 0x0b2f3aaa, 0x0000ab00, 0xa0458181),
|
||||
CCU_PLLA_RATE(1200000000UL, 0x0b320000, 0x00000000, 0xa0458181),
|
||||
CCU_PLLA_RATE(1250000000UL, 0x0b340555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1300000000UL, 0x0b360aaa, 0x0000ab00, 0xa0458282),
|
||||
CCU_PLLA_RATE(1350000000UL, 0x0b381000, 0x00000000, 0xa0458282),
|
||||
CCU_PLLA_RATE(1400000000UL, 0x0b3a1555, 0x00005500, 0xa0458282),
|
||||
CCU_PLLA_RATE(1450000000UL, 0x0b3c1aaa, 0x0000ab00, 0xa0458383),
|
||||
CCU_PLLA_RATE(1500000000UL, 0x0b3e2000, 0x00000000, 0xa0458383),
|
||||
CCU_PLLA_RATE(1550000000UL, 0x0b402555, 0x00005500, 0xa0458383),
|
||||
CCU_PLLA_RATE(1600000000UL, 0x0b422aaa, 0x0000ab00, 0xa0458484),
|
||||
CCU_PLLA_RATE(1650000000UL, 0x0b443000, 0x00000000, 0xa0458484),
|
||||
CCU_PLLA_RATE(1700000000UL, 0x0b463555, 0x00005500, 0xa0458484),
|
||||
CCU_PLLA_RATE(1750000000UL, 0x0b483aaa, 0x0000ab00, 0xa0458585),
|
||||
CCU_PLLA_RATE(1800000000UL, 0x0b4b0000, 0x00000000, 0xa0458585),
|
||||
CCU_PLLA_RATE(1850000000UL, 0x0b4d0555, 0x00005500, 0xa0458585),
|
||||
CCU_PLLA_RATE(1900000000UL, 0x0b4f0aaa, 0x0000ab00, 0xa0458686),
|
||||
CCU_PLLA_RATE(1950000000UL, 0x0b511000, 0x00000000, 0xa0458686),
|
||||
CCU_PLLA_RATE(2000000000UL, 0x0b292aaa, 0x0000ab00, 0xa0558686),
|
||||
CCU_PLLA_RATE(2050000000UL, 0x0b2a2d55, 0x00005500, 0xa0558686),
|
||||
CCU_PLLA_RATE(2100000000UL, 0x0b2b3000, 0x00000000, 0xa0558787),
|
||||
CCU_PLLA_RATE(2150000000UL, 0x0b2c32aa, 0x0000ab00, 0xa0558787),
|
||||
CCU_PLLA_RATE(2200000000UL, 0x0b2d3555, 0x00005500, 0xa0558787),
|
||||
CCU_PLLA_RATE(2250000000UL, 0x0b2e3800, 0x00000000, 0xa0558888),
|
||||
CCU_PLLA_RATE(2300000000UL, 0x0b2f3aaa, 0x0000ab00, 0xa0558888),
|
||||
CCU_PLLA_RATE(2350000000UL, 0x0b303d55, 0x00005500, 0xa0558888),
|
||||
CCU_PLLA_RATE(2400000000UL, 0x0b320000, 0x00000000, 0xa0558989),
|
||||
};
|
||||
|
||||
static const struct ccu_pll_rate_tbl pll4_rate_tbl[] = {
|
||||
CCU_PLLA_RATE(1050000000UL, 0x0b2b3000, 0x00000000, 0xa0458080),
|
||||
CCU_PLLA_RATE(1100000000UL, 0x0b2d3555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1150000000UL, 0x0b2f3aaa, 0x0000ab00, 0xa0458181),
|
||||
CCU_PLLA_RATE(1200000000UL, 0x0b320000, 0x00000000, 0xa0458181),
|
||||
CCU_PLLA_RATE(1250000000UL, 0x0b340555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1300000000UL, 0x0b360aaa, 0x0000ab00, 0xa0458282),
|
||||
CCU_PLLA_RATE(1350000000UL, 0x0b381000, 0x00000000, 0xa0458282),
|
||||
CCU_PLLA_RATE(1400000000UL, 0x0b3a1555, 0x00005500, 0xa0458282),
|
||||
CCU_PLLA_RATE(1450000000UL, 0x0b3c1aaa, 0x0000ab00, 0xa0458383),
|
||||
CCU_PLLA_RATE(1500000000UL, 0x0b3e2000, 0x00000000, 0xa0458383),
|
||||
CCU_PLLA_RATE(1550000000UL, 0x0b402555, 0x00005500, 0xa0458383),
|
||||
CCU_PLLA_RATE(1600000000UL, 0x0b422aaa, 0x0000ab00, 0xa0458484),
|
||||
CCU_PLLA_RATE(1650000000UL, 0x0b443000, 0x00000000, 0xa0458484),
|
||||
CCU_PLLA_RATE(1700000000UL, 0x0b463555, 0x00005500, 0xa0458484),
|
||||
CCU_PLLA_RATE(1750000000UL, 0x0b483aaa, 0x0000ab00, 0xa0458585),
|
||||
CCU_PLLA_RATE(1800000000UL, 0x0b4b0000, 0x00000000, 0xa0458585),
|
||||
CCU_PLLA_RATE(1850000000UL, 0x0b4d0555, 0x00005500, 0xa0458585),
|
||||
CCU_PLLA_RATE(1900000000UL, 0x0b4f0aaa, 0x0000ab00, 0xa0458686),
|
||||
CCU_PLLA_RATE(1950000000UL, 0x0b511000, 0x00000000, 0xa0458686),
|
||||
CCU_PLLA_RATE(2000000000UL, 0x0b292aaa, 0x0000ab00, 0xa0558686),
|
||||
CCU_PLLA_RATE(2050000000UL, 0x0b2a2d55, 0x00005500, 0xa0558686),
|
||||
CCU_PLLA_RATE(2100000000UL, 0x0b2b3000, 0x00000000, 0xa0558787),
|
||||
CCU_PLLA_RATE(2150000000UL, 0x0b2c32aa, 0x0000ab00, 0xa0558787),
|
||||
CCU_PLLA_RATE(2200000000UL, 0x0b2d3555, 0x00005500, 0xa0558787),
|
||||
CCU_PLLA_RATE(2250000000UL, 0x0b2e3800, 0x00000000, 0xa0558888),
|
||||
CCU_PLLA_RATE(2300000000UL, 0x0b2f3aaa, 0x0000ab00, 0xa0558888),
|
||||
CCU_PLLA_RATE(2350000000UL, 0x0b303d55, 0x00005500, 0xa0558888),
|
||||
CCU_PLLA_RATE(2400000000UL, 0x0b320000, 0x00000000, 0xa0558989),
|
||||
};
|
||||
|
||||
static const struct ccu_pll_rate_tbl pll5_rate_tbl[] = {
|
||||
CCU_PLLA_RATE(1050000000UL, 0x0b2b3000, 0x00000000, 0xa0458080),
|
||||
CCU_PLLA_RATE(1100000000UL, 0x0b2d3555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1150000000UL, 0x0b2f3aaa, 0x0000ab00, 0xa0458181),
|
||||
CCU_PLLA_RATE(1200000000UL, 0x0b320000, 0x00000000, 0xa0458181),
|
||||
CCU_PLLA_RATE(1250000000UL, 0x0b340555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1300000000UL, 0x0b360aaa, 0x0000ab00, 0xa0458282),
|
||||
CCU_PLLA_RATE(1350000000UL, 0x0b381000, 0x00000000, 0xa0458282),
|
||||
CCU_PLLA_RATE(1400000000UL, 0x0b3a1555, 0x00005500, 0xa0458282),
|
||||
CCU_PLLA_RATE(1450000000UL, 0x0b3c1aaa, 0x0000ab00, 0xa0458383),
|
||||
CCU_PLLA_RATE(1500000000UL, 0x0b3e2000, 0x00000000, 0xa0458383),
|
||||
CCU_PLLA_RATE(1550000000UL, 0x0b402555, 0x00005500, 0xa0458383),
|
||||
CCU_PLLA_RATE(1600000000UL, 0x0b422aaa, 0x0000ab00, 0xa0458484),
|
||||
CCU_PLLA_RATE(1650000000UL, 0x0b443000, 0x00000000, 0xa0458484),
|
||||
CCU_PLLA_RATE(1700000000UL, 0x0b463555, 0x00005500, 0xa0458484),
|
||||
CCU_PLLA_RATE(1750000000UL, 0x0b483aaa, 0x0000ab00, 0xa0458585),
|
||||
CCU_PLLA_RATE(1800000000UL, 0x0b4b0000, 0x00000000, 0xa0458585),
|
||||
CCU_PLLA_RATE(1850000000UL, 0x0b4d0555, 0x00005500, 0xa0458585),
|
||||
CCU_PLLA_RATE(1900000000UL, 0x0b4f0aaa, 0x0000ab00, 0xa0458686),
|
||||
CCU_PLLA_RATE(1950000000UL, 0x0b511000, 0x00000000, 0xa0458686),
|
||||
CCU_PLLA_RATE(2000000000UL, 0x0b292aaa, 0x0000ab00, 0xa0558686),
|
||||
};
|
||||
|
||||
|
|
@ -50,6 +123,25 @@ static const struct ccu_pll_rate_tbl pll7_rate_tbl[] = {
|
|||
};
|
||||
|
||||
static const struct ccu_pll_rate_tbl pll8_rate_tbl[] = {
|
||||
CCU_PLLA_RATE(1050000000UL, 0x0b2b3000, 0x00000000, 0xa0458080),
|
||||
CCU_PLLA_RATE(1100000000UL, 0x0b2d3555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1150000000UL, 0x0b2f3aaa, 0x0000ab00, 0xa0458181),
|
||||
CCU_PLLA_RATE(1200000000UL, 0x0b320000, 0x00000000, 0xa0458181),
|
||||
CCU_PLLA_RATE(1250000000UL, 0x0b340555, 0x00005500, 0xa0458181),
|
||||
CCU_PLLA_RATE(1300000000UL, 0x0b360aaa, 0x0000ab00, 0xa0458282),
|
||||
CCU_PLLA_RATE(1350000000UL, 0x0b381000, 0x00000000, 0xa0458282),
|
||||
CCU_PLLA_RATE(1400000000UL, 0x0b3a1555, 0x00005500, 0xa0458282),
|
||||
CCU_PLLA_RATE(1450000000UL, 0x0b3c1aaa, 0x0000ab00, 0xa0458383),
|
||||
CCU_PLLA_RATE(1500000000UL, 0x0b3e2000, 0x00000000, 0xa0458383),
|
||||
CCU_PLLA_RATE(1550000000UL, 0x0b402555, 0x00005500, 0xa0458383),
|
||||
CCU_PLLA_RATE(1600000000UL, 0x0b422aaa, 0x0000ab00, 0xa0458484),
|
||||
CCU_PLLA_RATE(1650000000UL, 0x0b443000, 0x00000000, 0xa0458484),
|
||||
CCU_PLLA_RATE(1700000000UL, 0x0b463555, 0x00005500, 0xa0458484),
|
||||
CCU_PLLA_RATE(1750000000UL, 0x0b483aaa, 0x0000ab00, 0xa0458585),
|
||||
CCU_PLLA_RATE(1800000000UL, 0x0b4b0000, 0x00000000, 0xa0458585),
|
||||
CCU_PLLA_RATE(1850000000UL, 0x0b4d0555, 0x00005500, 0xa0458585),
|
||||
CCU_PLLA_RATE(1900000000UL, 0x0b4f0aaa, 0x0000ab00, 0xa0458686),
|
||||
CCU_PLLA_RATE(1950000000UL, 0x0b511000, 0x00000000, 0xa0458686),
|
||||
CCU_PLLA_RATE(2000000000UL, 0x0b292aaa, 0x0000ab00, 0xa0558686),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static const struct clk_ops ti_composite_gate_ops = {
|
|||
|
||||
struct component_clk {
|
||||
int num_parents;
|
||||
struct clk_parent_data *parent_data;
|
||||
const char **parent_names;
|
||||
struct device_node *node;
|
||||
int type;
|
||||
struct clk_hw *hw;
|
||||
|
|
@ -116,7 +116,7 @@ static void __init _register_composite(void *user,
|
|||
struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw);
|
||||
struct component_clk *comp;
|
||||
int num_parents = 0;
|
||||
struct clk_parent_data *parent_data = NULL;
|
||||
const char **parent_names = NULL;
|
||||
const char *name;
|
||||
int i;
|
||||
int ret;
|
||||
|
|
@ -155,7 +155,7 @@ static void __init _register_composite(void *user,
|
|||
continue;
|
||||
if (comp->num_parents) {
|
||||
num_parents = comp->num_parents;
|
||||
parent_data = comp->parent_data;
|
||||
parent_names = comp->parent_names;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -166,8 +166,8 @@ static void __init _register_composite(void *user,
|
|||
}
|
||||
|
||||
name = ti_dt_clk_name(node);
|
||||
clk = clk_register_composite_pdata(NULL, name,
|
||||
parent_data, num_parents,
|
||||
clk = clk_register_composite(NULL, name,
|
||||
parent_names, num_parents,
|
||||
_get_hw(cclk, CLK_COMPONENT_TYPE_MUX),
|
||||
&ti_clk_mux_ops,
|
||||
_get_hw(cclk, CLK_COMPONENT_TYPE_DIVIDER),
|
||||
|
|
@ -190,7 +190,7 @@ static void __init _register_composite(void *user,
|
|||
if (!cclk->comp_clks[i])
|
||||
continue;
|
||||
list_del(&cclk->comp_clks[i]->link);
|
||||
kfree(cclk->comp_clks[i]->parent_data);
|
||||
kfree(cclk->comp_clks[i]->parent_names);
|
||||
kfree(cclk->comp_clks[i]);
|
||||
}
|
||||
|
||||
|
|
@ -237,9 +237,8 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
|
|||
int type)
|
||||
{
|
||||
unsigned int num_parents;
|
||||
struct clk_parent_data *parent_data;
|
||||
const char **parent_names;
|
||||
struct component_clk *clk;
|
||||
unsigned int i;
|
||||
|
||||
num_parents = of_clk_get_parent_count(node);
|
||||
|
||||
|
|
@ -248,21 +247,20 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
parent_data = kzalloc_objs(*parent_data, num_parents);
|
||||
if (!parent_data)
|
||||
parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
|
||||
if (!parent_names)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_parents; i++)
|
||||
parent_data[i].index = i;
|
||||
of_clk_parent_fill(node, parent_names, num_parents);
|
||||
|
||||
clk = kzalloc_obj(*clk);
|
||||
if (!clk) {
|
||||
kfree(parent_data);
|
||||
kfree(parent_names);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk->num_parents = num_parents;
|
||||
clk->parent_data = parent_data;
|
||||
clk->parent_names = parent_names;
|
||||
clk->hw = hw;
|
||||
clk->node = node;
|
||||
clk->type = type;
|
||||
|
|
|
|||
|
|
@ -2590,8 +2590,8 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
|
|||
|
||||
cpu = cpumask_first(policy->related_cpus);
|
||||
max_freq = arch_scale_freq_ref(cpu);
|
||||
if (!max_freq)
|
||||
max_freq = policy->cpuinfo.max_freq;
|
||||
if (!max_freq && cpufreq_driver->scale_freq_ref)
|
||||
max_freq = cpufreq_driver->scale_freq_ref(policy);
|
||||
|
||||
capped_freq = policy->max;
|
||||
|
||||
|
|
|
|||
|
|
@ -1135,6 +1135,14 @@ static bool hybrid_clear_max_perf_cpu(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int intel_pstate_scale_freq_ref(struct cpufreq_policy *policy)
|
||||
{
|
||||
if (READ_ONCE(all_cpu_data[policy->cpu]->capacity_perf))
|
||||
return policy->cpuinfo.max_freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_pstate_update_freq_limits(struct cpudata *cpu)
|
||||
{
|
||||
int scaling = cpu->pstate.scaling;
|
||||
|
|
@ -3088,6 +3096,7 @@ static struct cpufreq_driver intel_pstate = {
|
|||
.offline = intel_pstate_cpu_offline,
|
||||
.online = intel_pstate_cpu_online,
|
||||
.update_limits = intel_pstate_update_limits,
|
||||
.scale_freq_ref = intel_pstate_scale_freq_ref,
|
||||
.name = "intel_pstate",
|
||||
};
|
||||
|
||||
|
|
@ -3411,6 +3420,7 @@ static struct cpufreq_driver intel_cpufreq = {
|
|||
.suspend = intel_cpufreq_suspend,
|
||||
.resume = intel_pstate_resume,
|
||||
.update_limits = intel_pstate_update_limits,
|
||||
.scale_freq_ref = intel_pstate_scale_freq_ref,
|
||||
.name = "intel_cpufreq",
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -453,15 +453,6 @@ static int altr_sdram_probe(struct platform_device *pdev)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void altr_sdram_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mem_ctl_info *mci = platform_get_drvdata(pdev);
|
||||
|
||||
edac_mc_del_mc(&pdev->dev);
|
||||
edac_mc_free(mci);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If you want to suspend, need to disable EDAC by removing it
|
||||
* from the device tree or defconfig.
|
||||
|
|
@ -481,13 +472,13 @@ static const struct dev_pm_ops altr_sdram_pm_ops = {
|
|||
|
||||
static struct platform_driver altr_sdram_edac_driver = {
|
||||
.probe = altr_sdram_probe,
|
||||
.remove = altr_sdram_remove,
|
||||
.driver = {
|
||||
.name = "altr_sdram_edac",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &altr_sdram_pm_ops,
|
||||
#endif
|
||||
.of_match_table = altr_sdram_ctrl_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -517,6 +508,7 @@ static struct platform_driver altr_edac_driver = {
|
|||
.driver = {
|
||||
.name = "socfpga_ecc_manager",
|
||||
.of_match_table = altr_edac_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
module_platform_driver(altr_edac_driver);
|
||||
|
|
@ -803,22 +795,12 @@ static int altr_edac_device_probe(struct platform_device *pdev)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void altr_edac_device_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
|
||||
struct altr_edac_device_dev *drvdata = dci->pvt_info;
|
||||
|
||||
debugfs_remove_recursive(drvdata->debugfs_dir);
|
||||
edac_device_del_device(&pdev->dev);
|
||||
edac_device_free_ctl_info(dci);
|
||||
}
|
||||
|
||||
static struct platform_driver altr_edac_device_driver = {
|
||||
.probe = altr_edac_device_probe,
|
||||
.remove = altr_edac_device_remove,
|
||||
.driver = {
|
||||
.name = "altr_edac_device",
|
||||
.of_match_table = altr_edac_device_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
module_platform_driver(altr_edac_device_driver);
|
||||
|
|
@ -944,7 +926,7 @@ static int __maybe_unused altr_init_memory_port(void __iomem *ioaddr, int port)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static __init int __maybe_unused
|
||||
static int __maybe_unused
|
||||
altr_init_a10_ecc_block(struct device_node *np, u32 irq_mask,
|
||||
u32 ecc_ctrl_en_mask, bool dual_port)
|
||||
{
|
||||
|
|
@ -1019,7 +1001,7 @@ altr_init_a10_ecc_block(struct device_node *np, u32 irq_mask,
|
|||
|
||||
static int validate_parent_available(struct device_node *np);
|
||||
static const struct of_device_id altr_edac_a10_device_of_match[];
|
||||
static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat)
|
||||
static int __maybe_unused altr_init_a10_ecc_device_type(char *compat)
|
||||
{
|
||||
int irq;
|
||||
struct device_node *child, *np;
|
||||
|
|
@ -1348,7 +1330,7 @@ static const struct edac_device_prv_data a10_l2ecc_data = {
|
|||
|
||||
#ifdef CONFIG_EDAC_ALTERA_ETHERNET
|
||||
|
||||
static int __init socfpga_init_ethernet_ecc(struct altr_edac_device_dev *dev)
|
||||
static int socfpga_init_ethernet_ecc(struct altr_edac_device_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1378,7 +1360,7 @@ static const struct edac_device_prv_data a10_enetecc_data = {
|
|||
|
||||
#ifdef CONFIG_EDAC_ALTERA_NAND
|
||||
|
||||
static int __init socfpga_init_nand_ecc(struct altr_edac_device_dev *device)
|
||||
static int socfpga_init_nand_ecc(struct altr_edac_device_dev *device)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1408,7 +1390,7 @@ static const struct edac_device_prv_data a10_nandecc_data = {
|
|||
|
||||
#ifdef CONFIG_EDAC_ALTERA_DMA
|
||||
|
||||
static int __init socfpga_init_dma_ecc(struct altr_edac_device_dev *device)
|
||||
static int socfpga_init_dma_ecc(struct altr_edac_device_dev *device)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1438,7 +1420,7 @@ static const struct edac_device_prv_data a10_dmaecc_data = {
|
|||
|
||||
#ifdef CONFIG_EDAC_ALTERA_USB
|
||||
|
||||
static int __init socfpga_init_usb_ecc(struct altr_edac_device_dev *device)
|
||||
static int socfpga_init_usb_ecc(struct altr_edac_device_dev *device)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1468,7 +1450,7 @@ static const struct edac_device_prv_data a10_usbecc_data = {
|
|||
|
||||
#ifdef CONFIG_EDAC_ALTERA_QSPI
|
||||
|
||||
static int __init socfpga_init_qspi_ecc(struct altr_edac_device_dev *device)
|
||||
static int socfpga_init_qspi_ecc(struct altr_edac_device_dev *device)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1524,6 +1506,7 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
|||
dci = edac_device_alloc_ctl_info(sizeof(*altdev), ecc_name, 1,
|
||||
ecc_name, 1, 0, edac_idx);
|
||||
if (!dci) {
|
||||
of_node_put(np);
|
||||
edac_printk(KERN_ERR, EDAC_DEVICE,
|
||||
"%s: Unable to allocate PortB EDAC device\n",
|
||||
ecc_name);
|
||||
|
|
@ -1534,8 +1517,11 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
|||
altdev = dci->pvt_info;
|
||||
*altdev = *device;
|
||||
|
||||
if (!devres_open_group(device->edac->dev, altr_portb_setup, GFP_KERNEL))
|
||||
if (!devres_open_group(device->edac->dev, altr_portb_setup, GFP_KERNEL)) {
|
||||
edac_device_free_ctl_info(dci);
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Update PortB specific values */
|
||||
altdev->edac_dev_name = ecc_name;
|
||||
|
|
@ -1600,6 +1586,8 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
|||
rc = -ENOMEM;
|
||||
goto err_release_group_1;
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
altr_create_edacdev_dbgfs(dci, prv);
|
||||
|
||||
list_add(&altdev->next, &altdev->edac->a10_ecc_devices);
|
||||
|
|
@ -1609,14 +1597,20 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
|||
return 0;
|
||||
|
||||
err_release_group_1:
|
||||
edac_device_free_ctl_info(dci);
|
||||
/*
|
||||
* Release the devres group first so the managed IRQs are
|
||||
* unregistered before dci (which contains the IRQ handler's
|
||||
* data via dci->pvt_info) is freed, avoiding a use-after-free.
|
||||
*/
|
||||
devres_release_group(device->edac->dev, altr_portb_setup);
|
||||
edac_device_free_ctl_info(dci);
|
||||
of_node_put(np);
|
||||
edac_printk(KERN_ERR, EDAC_DEVICE,
|
||||
"%s:Error setting up EDAC device: %d\n", ecc_name, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __init socfpga_init_sdmmc_ecc(struct altr_edac_device_dev *device)
|
||||
static int socfpga_init_sdmmc_ecc(struct altr_edac_device_dev *device)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
struct device_node *child;
|
||||
|
|
@ -1638,7 +1632,7 @@ static int __init socfpga_init_sdmmc_ecc(struct altr_edac_device_dev *device)
|
|||
goto exit;
|
||||
|
||||
/* Setup portB */
|
||||
return altr_portb_setup(device);
|
||||
rc = altr_portb_setup(device);
|
||||
|
||||
exit:
|
||||
of_node_put(child);
|
||||
|
|
@ -2013,9 +2007,17 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
|
|||
return 0;
|
||||
|
||||
err_release_group1:
|
||||
/*
|
||||
* Release the devres group first so the managed IRQs are
|
||||
* unregistered before dci (which contains the IRQ handler's
|
||||
* data via dci->pvt_info) is freed, avoiding a use-after-free.
|
||||
*/
|
||||
devres_release_group(edac->dev, NULL);
|
||||
edac_device_free_ctl_info(dci);
|
||||
goto err_print;
|
||||
err_release_group:
|
||||
devres_release_group(edac->dev, NULL);
|
||||
err_print:
|
||||
edac_printk(KERN_ERR, EDAC_DEVICE,
|
||||
"%s:Error setting up EDAC device: %d\n", ecc_name, rc);
|
||||
|
||||
|
|
@ -2214,6 +2216,7 @@ static struct platform_driver altr_edac_a10_driver = {
|
|||
.driver = {
|
||||
.name = "socfpga_a10_ecc_manager",
|
||||
.of_match_table = altr_edac_a10_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
module_platform_driver(altr_edac_a10_driver);
|
||||
|
|
|
|||
|
|
@ -953,6 +953,7 @@ static void mc_remove(struct platform_device *pdev)
|
|||
remove_versalnet(priv);
|
||||
rproc_shutdown(priv->mcdi->r5_rproc);
|
||||
cdx_mcdi_finish(priv->mcdi);
|
||||
rproc_put(priv->mcdi->r5_rproc);
|
||||
kfree(priv->mcdi);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
|
|||
index = ida_alloc(&ida_index, GFP_KERNEL);
|
||||
if (index < 0)
|
||||
return index;
|
||||
exar_gpio->index = index;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, exar_devm_ida_free, exar_gpio);
|
||||
if (ret)
|
||||
|
|
@ -214,7 +215,6 @@ static int gpio_exar_probe(struct platform_device *pdev)
|
|||
exar_gpio->gpio_chip.set = exar_set_value;
|
||||
exar_gpio->gpio_chip.base = -1;
|
||||
exar_gpio->gpio_chip.ngpio = ngpios;
|
||||
exar_gpio->index = index;
|
||||
exar_gpio->first_pin = first_pin;
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &exar_gpio->gpio_chip, exar_gpio);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/cleanup.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ struct mpsse_priv {
|
|||
raw_spinlock_t irq_spin; /* protects worker list */
|
||||
atomic_t irq_type[16]; /* pin -> edge detection type */
|
||||
atomic_t irq_enabled;
|
||||
atomic_t dying; /* no new workers after disconnect */
|
||||
int id;
|
||||
|
||||
u8 gpio_outputs[2]; /* Output states for GPIOs [L, H] */
|
||||
|
|
@ -46,6 +48,7 @@ struct mpsse_worker {
|
|||
atomic_t cancelled;
|
||||
struct list_head list; /* linked list */
|
||||
struct list_head destroy; /* teardown linked list */
|
||||
struct rcu_head rcu; /* deferred free for dying path */
|
||||
};
|
||||
|
||||
struct bulk_desc {
|
||||
|
|
@ -525,10 +528,24 @@ static void gpio_mpsse_irq_enable(struct irq_data *irqd)
|
|||
worker->priv = priv;
|
||||
INIT_LIST_HEAD(&worker->list);
|
||||
INIT_WORK(&worker->work, gpio_mpsse_poll);
|
||||
schedule_work(&worker->work);
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &priv->irq_spin)
|
||||
scoped_guard(raw_spinlock_irqsave, &priv->irq_spin) {
|
||||
if (atomic_read(&priv->dying)) {
|
||||
/*
|
||||
* Cannot kfree() here: this callback
|
||||
* runs with the IRQ descriptor's raw
|
||||
* spinlock held and kfree() may sleep
|
||||
* on PREEMPT_RT. The worker is not
|
||||
* yet published, so the deferred free
|
||||
* is unobservable.
|
||||
*/
|
||||
kfree_rcu(worker, rcu);
|
||||
return;
|
||||
}
|
||||
|
||||
list_add(&worker->list, &priv->workers);
|
||||
schedule_work(&worker->work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -704,6 +721,9 @@ static void gpio_mpsse_disconnect(struct usb_interface *intf)
|
|||
{
|
||||
struct mpsse_priv *priv = usb_get_intfdata(intf);
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &priv->irq_spin)
|
||||
atomic_set(&priv->dying, 1);
|
||||
|
||||
/*
|
||||
* Lock prevents double-free of worker from here and the teardown
|
||||
* step at the beginning of gpio_mpsse_poll
|
||||
|
|
|
|||
|
|
@ -271,14 +271,7 @@ static void xgpio_save_regs(struct xgpio_instance *chip)
|
|||
|
||||
static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(chip->parent);
|
||||
/*
|
||||
* If the device is already active pm_runtime_get() will return 1 on
|
||||
* success, but gpio_request still needs to return 0.
|
||||
*/
|
||||
return ret < 0 ? ret : 0;
|
||||
return pm_runtime_resume_and_get(chip->parent);
|
||||
}
|
||||
|
||||
static void xgpio_free(struct gpio_chip *chip, unsigned int offset)
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
|
||||
acp_genpd_add_device);
|
||||
if (r)
|
||||
goto failure;
|
||||
goto failure_remove_mfd;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -443,7 +443,7 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
|
||||
acp_genpd_add_device);
|
||||
if (r)
|
||||
goto failure;
|
||||
goto failure_remove_mfd;
|
||||
}
|
||||
|
||||
/* Assert Soft reset of ACP */
|
||||
|
|
@ -461,7 +461,7 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (--count == 0) {
|
||||
dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
|
||||
r = -ETIMEDOUT;
|
||||
goto failure;
|
||||
goto failure_remove_mfd;
|
||||
}
|
||||
udelay(100);
|
||||
}
|
||||
|
|
@ -479,7 +479,7 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (--count == 0) {
|
||||
dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
|
||||
r = -ETIMEDOUT;
|
||||
goto failure;
|
||||
goto failure_remove_mfd;
|
||||
}
|
||||
udelay(100);
|
||||
}
|
||||
|
|
@ -489,6 +489,11 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
|
||||
return 0;
|
||||
|
||||
failure_remove_mfd:
|
||||
device_for_each_child(adev->acp.parent, NULL,
|
||||
acp_genpd_remove_device);
|
||||
mfd_remove_devices(adev->acp.parent);
|
||||
|
||||
failure:
|
||||
kfree(adev->acp.i2s_pdata);
|
||||
kfree(adev->acp.acp_res);
|
||||
|
|
|
|||
|
|
@ -1325,6 +1325,8 @@ static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
|
|||
ip_hw_instance->kobj.kset = &ip_hw_id->hw_id_kset;
|
||||
res = kobject_add(&ip_hw_instance->kobj, NULL,
|
||||
"%d", ip_hw_instance->num_instance);
|
||||
if (res)
|
||||
kobject_put(&ip_hw_instance->kobj);
|
||||
next_ip:
|
||||
if (reg_base_64)
|
||||
ip_offset += struct_size(ip, base_address_64,
|
||||
|
|
|
|||
|
|
@ -2664,6 +2664,14 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev)
|
|||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
int r;
|
||||
|
||||
/*
|
||||
* A GPU parked by vga_switcheroo has no power and no PCIe link, so the
|
||||
* ASIC reset below would fail and abort the whole noirq suspend phase.
|
||||
* Bail out like amdgpu_device_prepare/suspend/resume() already do.
|
||||
*/
|
||||
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
if (amdgpu_acpi_should_gpu_reset(adev)) {
|
||||
amdgpu_device_lock_reset_domain(adev->reset_domain);
|
||||
r = amdgpu_asic_reset(adev);
|
||||
|
|
|
|||
|
|
@ -724,8 +724,14 @@ void amdgpu_ring_set_fence_errors_and_reemit(struct amdgpu_ring *ring,
|
|||
bool is_guilty_fence;
|
||||
bool is_guilty_context;
|
||||
|
||||
last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask;
|
||||
seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask;
|
||||
last_seq = amdgpu_fence_read(ring);
|
||||
seq = ring->fence_drv.sync_seq;
|
||||
|
||||
/* Hardware completion can precede the interrupt which signals fences. */
|
||||
if (last_seq == seq) {
|
||||
amdgpu_fence_process(ring);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is nothing to reemit, return early and set an error on the fence
|
||||
* if applicable. If all of the fences are siganlled, this will be a nop.
|
||||
|
|
@ -733,7 +739,9 @@ void amdgpu_ring_set_fence_errors_and_reemit(struct amdgpu_ring *ring,
|
|||
* we are skipping it on purpose.
|
||||
*/
|
||||
if (!ring->ring_backup_entries_to_copy) {
|
||||
amdgpu_fence_driver_force_completion(ring, &guilty_fence->base);
|
||||
if (guilty_fence)
|
||||
amdgpu_fence_driver_force_completion(ring,
|
||||
&guilty_fence->base);
|
||||
return;
|
||||
}
|
||||
ring->reemit = true;
|
||||
|
|
@ -741,9 +749,8 @@ void amdgpu_ring_set_fence_errors_and_reemit(struct amdgpu_ring *ring,
|
|||
spin_lock_irqsave(&ring->fence_drv.lock, flags);
|
||||
do {
|
||||
last_seq++;
|
||||
last_seq &= ring->fence_drv.num_fences_mask;
|
||||
|
||||
ptr = &ring->fence_drv.fences[last_seq];
|
||||
ptr = &ring->fence_drv.fences[last_seq & ring->fence_drv.num_fences_mask];
|
||||
rcu_read_lock();
|
||||
unprocessed = rcu_dereference(*ptr);
|
||||
|
||||
|
|
@ -800,26 +807,24 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
|
|||
struct amdgpu_fence *fence;
|
||||
u32 seq, last_seq;
|
||||
|
||||
last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask;
|
||||
seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask;
|
||||
last_seq = amdgpu_fence_read(ring);
|
||||
seq = ring->fence_drv.sync_seq;
|
||||
ring->ring_backup_entries_to_copy = 0;
|
||||
|
||||
/* if we've already seen this fence, return early.
|
||||
* ring->ring_backup_entries_to_copy is set to 0 so
|
||||
* the reemit helper will return early as well to
|
||||
* avoid getting stuck in a reemit loop.
|
||||
/*
|
||||
* Avoid replay loops for a repeated guilty fence. NULL identifies a
|
||||
* collateral ring, whose pending commands still need backup.
|
||||
*/
|
||||
if (ring->guilty_fence == guilty_fence) {
|
||||
if (guilty_fence && ring->guilty_fence == guilty_fence) {
|
||||
ring->guilty_fence = NULL;
|
||||
return;
|
||||
}
|
||||
ring->guilty_fence = guilty_fence;
|
||||
|
||||
do {
|
||||
while (last_seq != seq) {
|
||||
last_seq++;
|
||||
last_seq &= ring->fence_drv.num_fences_mask;
|
||||
|
||||
ptr = &ring->fence_drv.fences[last_seq];
|
||||
ptr = &ring->fence_drv.fences[last_seq & ring->fence_drv.num_fences_mask];
|
||||
rcu_read_lock();
|
||||
unprocessed = rcu_dereference(*ptr);
|
||||
|
||||
|
|
@ -829,7 +834,7 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
|
|||
amdgpu_ring_backup_unprocessed_command(ring, fence);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
} while (last_seq != seq);
|
||||
}
|
||||
}
|
||||
|
||||
struct amdgpu_fence *
|
||||
|
|
|
|||
|
|
@ -2342,7 +2342,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
|||
void amdgpu_ttm_enable_buffer_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
u32 num_clear_entities, num_move_entities;
|
||||
u32 num_clear_entities, num_move_entities, sdma_ip_version;
|
||||
int r, i, j;
|
||||
|
||||
if (!adev->mman.initialized || amdgpu_in_reset(adev) ||
|
||||
|
|
@ -2367,6 +2367,12 @@ void amdgpu_ttm_enable_buffer_funcs(struct amdgpu_device *adev)
|
|||
|
||||
num_clear_entities = MIN(adev->mman.num_buffer_funcs_scheds, TTM_NUM_MOVE_FENCES);
|
||||
num_move_entities = MIN(adev->mman.num_buffer_funcs_scheds, TTM_NUM_MOVE_FENCES);
|
||||
/* TODO: workaround for DCC corruption when moving BOs from multiple queues at
|
||||
* the same time: use a single queue until the root cause is identified and fixed.
|
||||
*/
|
||||
sdma_ip_version = amdgpu_ip_version(adev, SDMA0_HWIP, 0);
|
||||
if (sdma_ip_version == IP_VERSION(7, 0, 0) || sdma_ip_version == IP_VERSION(7, 0, 1))
|
||||
num_move_entities = 1;
|
||||
|
||||
adev->mman.clear_entities = kzalloc_objs(struct amdgpu_ttm_buffer_entity,
|
||||
num_clear_entities);
|
||||
|
|
|
|||
|
|
@ -3808,6 +3808,7 @@ static int gfx_v11_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
rb_bufsz = order_base_2(ring->ring_size / 8);
|
||||
tmp = REG_SET_FIELD(0, CP_RB0_CNTL, RB_BUFSZ, rb_bufsz);
|
||||
tmp = REG_SET_FIELD(tmp, CP_RB0_CNTL, RB_BLKSZ, rb_bufsz - 2);
|
||||
tmp = REG_SET_FIELD(tmp, CP_RB0_CNTL, KMD_QUEUE, 1);
|
||||
WREG32_SOC15(GC, 0, regCP_RB0_CNTL, tmp);
|
||||
|
||||
/* Initialize the ring buffer's write pointers */
|
||||
|
|
@ -4216,6 +4217,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
|
|||
tmp = regCP_GFX_HQD_CNTL_DEFAULT;
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz);
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2);
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, KMD_QUEUE, prop->kernel_queue);
|
||||
#ifdef __BIG_ENDIAN
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, BUF_SWAP, 1);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2767,6 +2767,7 @@ static int gfx_v12_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
rb_bufsz = order_base_2(ring->ring_size / 8);
|
||||
tmp = REG_SET_FIELD(0, CP_RB0_CNTL, RB_BUFSZ, rb_bufsz);
|
||||
tmp = REG_SET_FIELD(tmp, CP_RB0_CNTL, RB_BLKSZ, rb_bufsz - 2);
|
||||
tmp = REG_SET_FIELD(tmp, CP_RB0_CNTL, KMD_QUEUE, 1);
|
||||
WREG32_SOC15(GC, 0, regCP_RB0_CNTL, tmp);
|
||||
|
||||
/* Initialize the ring buffer's write pointers */
|
||||
|
|
@ -3059,6 +3060,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m,
|
|||
tmp = regCP_GFX_HQD_CNTL_DEFAULT;
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz);
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2);
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, KMD_QUEUE, prop->kernel_queue);
|
||||
#ifdef __BIG_ENDIAN
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, BUF_SWAP, 1);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -322,6 +322,14 @@ static const u32 verde_rlc_save_restore_register_list[] =
|
|||
0x00000000
|
||||
};
|
||||
|
||||
static void gfx_v6_0_free_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_ucode_release(&adev->gfx.pfp_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.me_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.ce_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.rlc_fw);
|
||||
}
|
||||
|
||||
static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
|
|
@ -3249,6 +3257,7 @@ static int gfx_v6_0_sw_fini(struct amdgpu_ip_block *ip_block)
|
|||
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
|
||||
|
||||
amdgpu_gfx_rlc_fini(adev);
|
||||
gfx_v6_0_free_microcode(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ static void gmc_v12_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
|||
return;
|
||||
}
|
||||
|
||||
gmc_v12_0_flush_vm_hub(adev, vmid, vmhub, 0);
|
||||
gmc_v12_0_flush_vm_hub(adev, vmid, vmhub, flush_type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user