KVM: s390: A few more misc gmap fixes.

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoWuZBM6M3lCBSfTnuARItAMU6BMFAmoqvdUACgkQuARItAMU
 6BNHOA/8CSEH30EeXobbblnAiywthizP8z3gQ5LPnTjDNb4tS/UlPCwwapqFOrDs
 iPS48rv9SowmVFqXfUX1C47d5V4zDApD2699eRa5MOoXLTY9JtpafC8zsSKgKevY
 LW0OwiC7lDGXop9WmHwcy6vc6zgns3DMvUxyrxzVykVArA5ghZ2eMl/ElNDsRAJS
 1v1Z8V/vvBLU4XCIuNFeGSx+y8qaymhIeD7LkLFqUsfTb261dzIIHeD+WSMJeYG0
 tuc1UK9cSBu8zh5BLcNZ5EVh4LKJInOyju0bgeLtysQXGUBx/j9SM/kP9O6WMYiD
 krOeQMHPLpyh5N00lxVg3h2xyuvD3/95YbmZEKB1sOQZjp6zdP1lNZZ/cuzJKmMo
 l8LTQ4oHKFJW3GgzrAU5jKyg5DlJxvzatL8oMsHeEDMI8W5RP7wcb3jTF78meKsT
 uCkeYCdGiISF/l8vJeNjPFBXJZkP6M6bdIEFrJMRahlDFkOL9K3PRa5g3UnKZQqh
 ZczANXRBJoazSwM9i7x4J75NmV3hUeC6VFqEfg1oiiNqDIhmQDz9rYoRp+Kj9AZd
 /MjuaOozFOKK+Zkhg6hm5aVgYMkdfkdZPByvOzNOypFckNyV0yITCOqhGISTXKvb
 9tmLNdphYA3SAlu/rhqFCrJ0K4aF+qR/5rn5PU2y/CZg15qymDM=
 =y8Ea
 -----END PGP SIGNATURE-----

Merge tag 'kvm-s390-master-7.1-4' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: A few more misc gmap fixes.
This commit is contained in:
Paolo Bonzini 2026-06-12 09:55:30 +02:00
commit 94e6ddf9a0
338 changed files with 3558 additions and 1638 deletions

View File

@ -126,6 +126,7 @@ Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@linaro.org>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@spreadtrum.com>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@unisoc.com>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang7@gmail.com>
Baoquan He <baoquan.he@linux.dev> <bhe@redhat.com>
Barry Song <baohua@kernel.org> <21cnbao@gmail.com>
Barry Song <baohua@kernel.org> <v-songbaohua@oppo.com>
Barry Song <baohua@kernel.org> <song.bao.hua@hisilicon.com>

View File

@ -30,6 +30,16 @@ properties:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- const: core
- const: iface
power-domains:
maxItems: 1
operating-points-v2: true
@ -44,6 +54,25 @@ required:
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,eliza-inline-crypto-engine
- qcom,milos-inline-crypto-engine
then:
required:
- power-domains
- clock-names
properties:
clocks:
minItems: 2
clock-names:
minItems: 2
examples:
- |
#include <dt-bindings/clock/qcom,sm8550-gcc.h>
@ -52,7 +81,11 @@ examples:
compatible = "qcom,sm8550-inline-crypto-engine",
"qcom,inline-crypto-engine";
reg = <0x01d88000 0x8000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>;
clock-names = "core",
"iface";
power-domains = <&gcc UFS_PHY_GDSC>;
operating-points-v2 = <&ice_opp_table>;

View File

@ -84,7 +84,8 @@ properties:
This reference is provided for background information only.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- minItems: 4
items:
- description: Phandle to HSP(High-Speed Peripheral) device
- description: Offset of phy control register for internal
or external clock selection

View File

@ -6535,7 +6535,7 @@ F: include/linux/blk-cgroup.h
CONTROL GROUP - CPUSET
M: Waiman Long <longman@redhat.com>
R: Chen Ridong <chenridong@huaweicloud.com>
R: Ridong Chen <ridong.chen@linux.dev>
L: cgroups@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
@ -13865,7 +13865,7 @@ F: scripts/Makefile.kcsan
KDUMP
M: Andrew Morton <akpm@linux-foundation.org>
M: Baoquan He <bhe@redhat.com>
M: Baoquan He <baoquan.he@linux.dev>
M: Mike Rapoport <rppt@kernel.org>
M: Pasha Tatashin <pasha.tatashin@soleen.com>
M: Pratyush Yadav <pratyush@kernel.org>
@ -14184,7 +14184,7 @@ F: include/linux/kernfs.h
KEXEC
M: Andrew Morton <akpm@linux-foundation.org>
M: Baoquan He <bhe@redhat.com>
M: Baoquan He <baoquan.he@linux.dev>
M: Mike Rapoport <rppt@kernel.org>
M: Pasha Tatashin <pasha.tatashin@soleen.com>
M: Pratyush Yadav <pratyush@kernel.org>
@ -17037,7 +17037,7 @@ M: Chris Li <chrisl@kernel.org>
M: Kairui Song <kasong@tencent.com>
R: Kemeng Shi <shikemeng@huaweicloud.com>
R: Nhat Pham <nphamcs@gmail.com>
R: Baoquan He <bhe@redhat.com>
R: Baoquan He <baoquan.he@linux.dev>
R: Barry Song <baohua@kernel.org>
R: Youngjun Park <youngjun.park@lge.com>
L: linux-mm@kvack.org

View File

@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 1
SUBLEVEL = 0
EXTRAVERSION = -rc6
EXTRAVERSION = -rc7
NAME = Baby Opossum Posse
# *DOCUMENTATION*
@ -607,6 +607,7 @@ KBUILD_RUSTFLAGS := $(rust_common_flags) \
-Crelocation-model=static \
-Zfunction-sections=n \
-Wclippy::float_arithmetic
KBUILD_RUSTFLAGS_OPTION_CHKS :=
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
@ -643,7 +644,7 @@ export KBUILD_USERCFLAGS KBUILD_USERLDFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE
export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE KBUILD_RUSTFLAGS_OPTION_CHKS
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_RUSTFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL

View File

@ -136,7 +136,7 @@ config ARM
select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RSEQ
select HAVE_RUST if CPU_LITTLE_ENDIAN && CPU_32v7
select HAVE_RUST if CPU_LITTLE_ENDIAN && CPU_32v7 && !KASAN
select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_UID16

View File

@ -146,7 +146,7 @@ flash@30000000 {
partitions {
compatible = "redboot-fis";
/* Eraseblock at 0xfe0000 */
fis-index-block = <0x1fc>;
fis-index-block = <0x7f>;
};
};

View File

@ -134,7 +134,7 @@ flash@30000000 {
partitions {
compatible = "redboot-fis";
/* Eraseblock at 0xfe0000 */
fis-index-block = <0x1fc>;
fis-index-block = <0x7f>;
};
};

View File

@ -990,9 +990,9 @@ gmac: ethernet@f802c000 {
<62 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 3 */
<63 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 4 */
<64 IRQ_TYPE_LEVEL_HIGH 3>; /* Queue 5 */
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>, <&pmc PMC_TYPE_GCK 67>;
clock-names = "hclk", "pclk", "tx_clk", "tsu_clk";
assigned-clocks = <&pmc PMC_TYPE_GCK 67>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>;
clock-names = "hclk", "pclk", "tsu_clk";
assigned-clocks = <&pmc PMC_TYPE_GCK 24>;
assigned-clock-rates = <266666666>;
status = "disabled";
};

View File

@ -78,6 +78,7 @@ static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
}
socfpga_scu_base_addr = of_iomap(np, 0);
of_node_put(np);
if (!socfpga_scu_base_addr)
return;
scu_enable(socfpga_scu_base_addr);

View File

@ -63,6 +63,9 @@ else
KBUILD_CFLAGS += -fasynchronous-unwind-tables
KBUILD_AFLAGS += -fasynchronous-unwind-tables
KBUILD_RUSTFLAGS += -Cforce-unwind-tables=y -Zuse-sync-unwind=n
# Work around rustc bug on compilers without
# https://github.com/rust-lang/rust/pull/156973.
KBUILD_RUSTFLAGS += $(if $(call rustc-min-version,109800),,-Zllvm_module_flag=uwtable:u32:2:max)
endif
ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)

View File

@ -843,7 +843,11 @@ ice: crypto@1d88000 {
"qcom,inline-crypto-engine";
reg = <0x0 0x01d88000 0x0 0x18000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>;
clock-names = "core",
"iface";
power-domains = <&gcc GCC_UFS_PHY_GDSC>;
};
tcsr_mutex: hwlock@1f40000 {

View File

@ -2314,11 +2314,9 @@ usb_mp_qmpphy0: phy@fa3000 {
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
<&tcsr TCSR_USB3_0_CLKREF_EN>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>;
clock-names = "aux",
"clkref",
"ref",
"com_aux",
"pipe";
@ -2343,11 +2341,9 @@ usb_mp_qmpphy1: phy@fa5000 {
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
<&tcsr TCSR_USB3_1_CLKREF_EN>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>;
clock-names = "aux",
"clkref",
"ref",
"com_aux",
"pipe";
@ -2482,15 +2478,13 @@ usb_1_qmpphy: phy@fde000 {
reg = <0x0 0x00fde000 0x0 0x8000>;
clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
<&tcsr TCSR_USB4_1_CLKREF_EN>,
<&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_SEC_PHY_PIPE_CLK>,
<&tcsr TCSR_USB4_1_CLKREF_EN>;
<&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
clock-names = "aux",
"ref",
"com_aux",
"usb3_pipe",
"clkref";
"usb3_pipe";
power-domains = <&gcc GCC_USB_1_PHY_GDSC>;
@ -3750,15 +3744,13 @@ usb_2_qmpphy: phy@88e1000 {
reg = <0x0 0x088e1000 0x0 0x8000>;
clocks = <&gcc GCC_USB3_TERT_PHY_AUX_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
<&tcsr TCSR_USB4_2_CLKREF_EN>,
<&gcc GCC_USB3_TERT_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_TERT_PHY_PIPE_CLK>,
<&tcsr TCSR_USB4_2_CLKREF_EN>;
<&gcc GCC_USB3_TERT_PHY_PIPE_CLK>;
clock-names = "aux",
"ref",
"com_aux",
"usb3_pipe",
"clkref";
"usb3_pipe";
power-domains = <&gcc GCC_USB_2_PHY_GDSC>;

View File

@ -1275,7 +1275,11 @@ ice: crypto@1d88000 {
"qcom,inline-crypto-engine";
reg = <0x0 0x01d88000 0x0 0x18000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>;
clock-names = "core",
"iface";
power-domains = <&gcc UFS_PHY_GDSC>;
};
tcsr_mutex: hwlock@1f40000 {

View File

@ -982,12 +982,6 @@ &i2c8 {
status = "okay";
};
&i2c20 {
clock-frequency = <400000>;
status = "okay";
};
&lpass_tlmm {
spkr_01_sd_n_active: spkr-01-sd-n-active-state {
pins = "gpio12";
@ -1308,6 +1302,7 @@ right_tweeter: speaker@0,1 {
&tlmm {
gpio-reserved-ranges = <44 4>, /* SPI11 (TPM) */
<76 4>, /* SPI19 (TZ Protected) */
<80 2>, /* I2C20 (Battery SMBus) */
<238 1>; /* UFS Reset */
cam_rgb_default: cam-rgb-default-state {

View File

@ -260,6 +260,7 @@ CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
CONFIG_PCI_PWRCTRL_GENERIC=m
CONFIG_POWER_SEQUENCING_PCIE_M2=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y

View File

@ -132,7 +132,7 @@ static inline bool kvm_s2_trans_exec_el0(struct kvm *kvm, struct kvm_s2_trans *t
u8 xn = FIELD_GET(KVM_PTE_LEAF_ATTR_HI_S2_XN, trans->desc);
if (!kvm_has_xnx(kvm))
xn &= FIELD_PREP(KVM_PTE_LEAF_ATTR_HI_S2_XN, 0b10);
xn &= 0b10;
switch (xn) {
case 0b00:
@ -148,7 +148,7 @@ static inline bool kvm_s2_trans_exec_el1(struct kvm *kvm, struct kvm_s2_trans *t
u8 xn = FIELD_GET(KVM_PTE_LEAF_ATTR_HI_S2_XN, trans->desc);
if (!kvm_has_xnx(kvm))
xn &= FIELD_PREP(KVM_PTE_LEAF_ATTR_HI_S2_XN, 0b10);
xn &= 0b10;
switch (xn) {
case 0b00:

View File

@ -1569,7 +1569,8 @@ int __kvm_at_s12(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
/* Do the stage-2 translation */
ipa = (par & GENMASK_ULL(47, 12)) | (vaddr & GENMASK_ULL(11, 0));
out.esr = 0;
ret = kvm_walk_nested_s2(vcpu, ipa, &out);
scoped_guard(srcu, &vcpu->kvm->srcu)
ret = kvm_walk_nested_s2(vcpu, ipa, &out);
if (ret < 0)
return ret;
@ -1665,7 +1666,8 @@ int __kvm_find_s1_desc_level(struct kvm_vcpu *vcpu, u64 va, u64 ipa, int *level)
}
/* Walk the guest's PT, looking for a match along the way */
ret = walk_s1(vcpu, &wi, &wr, va);
scoped_guard(srcu, &vcpu->kvm->srcu)
ret = walk_s1(vcpu, &wi, &wr, va);
switch (ret) {
case -EINTR:
/* We interrupted the walk on a match, return the level */

View File

@ -181,6 +181,8 @@ static inline void __deactivate_cptr_traps_vhe(struct kvm_vcpu *vcpu)
val |= CPACR_EL1_ZEN;
if (cpus_have_final_cap(ARM64_SME))
val |= CPACR_EL1_SMEN;
if (cpus_have_final_cap(ARM64_HAS_S1POE))
val |= CPACR_EL1_E0POE;
write_sysreg(val, cpacr_el1);
}

View File

@ -925,7 +925,9 @@ static bool stage2_pte_cacheable(struct kvm_pgtable *pgt, kvm_pte_t pte)
static bool stage2_pte_executable(kvm_pte_t pte)
{
return kvm_pte_valid(pte) && !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
enum kvm_pgtable_prot prot = kvm_pgtable_stage2_pte_prot(pte);
return prot & (KVM_PGTABLE_PROT_UX | KVM_PGTABLE_PROT_PX);
}
static u64 stage2_map_walker_phys_addr(const struct kvm_pgtable_visit_ctx *ctx,

View File

@ -89,21 +89,28 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
* again, and there is no reason to affect the whole VM for this.
*/
num_mmus = atomic_read(&kvm->online_vcpus) * S2_MMU_PER_VCPU;
tmp = kvrealloc(kvm->arch.nested_mmus,
size_mul(sizeof(*kvm->arch.nested_mmus), num_mmus),
GFP_KERNEL_ACCOUNT | __GFP_ZERO);
if (!tmp)
return -ENOMEM;
swap(kvm->arch.nested_mmus, tmp);
if (num_mmus > kvm->arch.nested_mmus_size) {
tmp = kvcalloc(num_mmus, sizeof(*tmp), GFP_KERNEL_ACCOUNT);
if (!tmp)
return -ENOMEM;
/*
* If we went through a realocation, adjust the MMU back-pointers in
* the previously initialised kvm_pgtable structures.
*/
if (kvm->arch.nested_mmus != tmp)
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i];
write_lock(&kvm->mmu_lock);
if (kvm->arch.nested_mmus_size) {
memcpy(tmp, kvm->arch.nested_mmus,
size_mul(sizeof(*tmp), kvm->arch.nested_mmus_size));
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
tmp[i].pgt->mmu = &tmp[i];
}
swap(kvm->arch.nested_mmus, tmp);
write_unlock(&kvm->mmu_lock);
kvfree(tmp);
}
for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++)
ret = init_nested_s2_mmu(kvm, &kvm->arch.nested_mmus[i]);

View File

@ -597,8 +597,10 @@ static void vgic_its_invalidate_cache(struct vgic_its *its)
unsigned long idx;
xa_for_each(&its->translation_cache, idx, irq) {
xa_erase(&its->translation_cache, idx);
vgic_put_irq(kvm, irq);
/* Only the context that erases the entry drops its cache ref. */
irq = xa_erase(&its->translation_cache, idx);
if (irq)
vgic_put_irq(kvm, irq);
}
}

View File

@ -1441,6 +1441,7 @@ static void free_hotplug_page_range(struct page *page, size_t size,
static void free_hotplug_pgtable_page(struct page *page)
{
pagetable_dtor(page_ptdesc(page));
free_hotplug_page_range(page, PAGE_SIZE, NULL);
}

View File

@ -50,6 +50,7 @@ void set_indir_lp_status(struct task_struct *task, bool enable);
void set_indir_lp_lock(struct task_struct *task, bool lock);
#define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE)
#define PR_CFI_SUPPORTED_STATUS_MASK (PR_CFI_ENABLE | PR_CFI_DISABLE | PR_CFI_LOCK)
#else

View File

@ -413,7 +413,7 @@ static struct user_regset riscv_user_regset[] __ro_after_init = {
#endif
#ifdef CONFIG_RISCV_USER_CFI
[REGSET_CFI] = {
.core_note_type = NT_RISCV_USER_CFI,
USER_REGSET_NOTE_TYPE(RISCV_USER_CFI),
.align = sizeof(__u64),
.n = sizeof(struct user_cfi_state) / sizeof(__u64),
.size = sizeof(__u64),

View File

@ -235,17 +235,6 @@ static void set_unaligned_access_static_branches(void)
modify_unaligned_access_branches(&fast_and_online, num_online_cpus());
}
static int __init lock_and_set_unaligned_access_static_branch(void)
{
cpus_read_lock();
set_unaligned_access_static_branches();
cpus_read_unlock();
return 0;
}
arch_initcall_sync(lock_and_set_unaligned_access_static_branch);
static int riscv_online_cpu(unsigned int cpu)
{
int ret = cpu_online_unaligned_access_init(cpu);
@ -440,6 +429,10 @@ static int __init check_unaligned_access_all_cpus(void)
cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online",
riscv_online_cpu_vec, NULL);
cpus_read_lock();
set_unaligned_access_static_branches();
cpus_read_unlock();
return 0;
}

View File

@ -467,6 +467,9 @@ int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long
if (!is_user_lpad_enabled())
return -EINVAL;
if (state & ~PR_CFI_SUPPORTED_STATUS_MASK)
return -EINVAL;
/* indirect branch tracking is locked and further can't be modified by user */
if (is_indir_lp_locked(t))
return -EINVAL;

View File

@ -56,6 +56,10 @@ CONFIG_EXPOLINE_AUTO=y
CONFIG_CHSC_SCH=y
CONFIG_VFIO_CCW=m
CONFIG_VFIO_AP=m
CONFIG_VFIO_DEVICE_CDEV=y
CONFIG_IOMMUFD_DRIVER=y
CONFIG_IOMMUFD_DRIVER_CORE=y
CONFIG_IOMMUFD=y
CONFIG_CMM=m
CONFIG_APPLDATA_BASE=y
CONFIG_S390_HYPFS_FS=y

View File

@ -54,6 +54,10 @@ CONFIG_EXPOLINE_AUTO=y
CONFIG_CHSC_SCH=y
CONFIG_VFIO_CCW=m
CONFIG_VFIO_AP=m
CONFIG_VFIO_DEVICE_CDEV=y
CONFIG_IOMMUFD_DRIVER=y
CONFIG_IOMMUFD_DRIVER_CORE=y
CONFIG_IOMMUFD=y
CONFIG_CMM=m
CONFIG_APPLDATA_BASE=y
CONFIG_S390_HYPFS_FS=y

View File

@ -4,6 +4,7 @@ menu "Accelerated Cryptographic Algorithms for CPU (s390)"
config CRYPTO_AES_S390
tristate "Ciphers: AES, modes: ECB, CBC, CTR, XTS, GCM"
select CRYPTO_AEAD
select CRYPTO_SKCIPHER
help
AEAD cipher: AES with GCM

View File

@ -12,12 +12,11 @@
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define __BUG_ENTRY_VERBOSE(format, file, line) \
" .long " format " - . # bug_entry::format\n" \
#define __BUG_ENTRY_VERBOSE(file, line) \
" .long " file " - . # bug_entry::file\n" \
" .short " line " # bug_entry::line\n"
#else
#define __BUG_ENTRY_VERBOSE(format, file, line)
#define __BUG_ENTRY_VERBOSE(file, line)
#endif
#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
@ -28,9 +27,10 @@
#define __BUG_ENTRY(format, file, line, flags, size) \
" .section __bug_table,\"aw\"\n" \
"1: .long 0b - . # bug_entry::bug_addr\n" \
__BUG_ENTRY_VERBOSE(format, file, line) \
" .short "flags" # bug_entry::flags\n" \
"1: .long 0b - . # bug_entry::bug_addr\n"\
" .long " format " - . # bug_entry::format\n" \
__BUG_ENTRY_VERBOSE(file, line) \
" .short "flags" # bug_entry::flags\n" \
" .org 1b+"size"\n" \
" .previous"

View File

@ -12,5 +12,6 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr);
void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned long end);
int gmap_helper_disable_cow_sharing(void);
void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr);
pte_t *try_get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl);
#endif /* _ASM_S390_GMAP_HELPERS_H */

View File

@ -7,4 +7,6 @@
#define __ALIGN .balign CONFIG_FUNCTION_ALIGNMENT, 0x07
#define __ALIGN_STR __stringify(__ALIGN)
#define _THIS_IP_ ({ unsigned long __ip; asm volatile("larl %0, ." : "=d" (__ip)); __ip; })
#endif

View File

@ -45,7 +45,7 @@ int kvm_s390_mmu_cache_topup(struct kvm_s390_mmu_cache *mc)
mc->pts[mc->n_pts] = o;
}
for ( ; mc->n_rmaps < KVM_S390_MMU_CACHE_N_RMAPS; mc->n_rmaps++) {
o = kzalloc_obj(*mc->rmaps[0], GFP_KERNEL_ACCOUNT);
o = kzalloc_obj(struct vsie_rmap, GFP_KERNEL_ACCOUNT);
if (!o)
return -ENOMEM;
mc->rmaps[mc->n_rmaps] = o;

View File

@ -36,7 +36,8 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
struct kvm_s390_mmu_cache *mc = NULL;
struct kvm_memory_slot *slot;
unsigned long inv_seq;
int foll, rc = 0;
int rc = -EAGAIN;
int foll;
foll = f->write_attempt ? FOLL_WRITE : 0;
foll |= f->attempt_pfault ? FOLL_NOWAIT : 0;
@ -53,7 +54,14 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
return 0;
}
while (1) {
if (!mc) {
local_mc = kvm_s390_new_mmu_cache();
if (!local_mc)
return -ENOMEM;
mc = local_mc;
}
while (rc == -EAGAIN) {
f->valid = false;
inv_seq = kvm->mmu_invalidate_seq;
/* Pairs with the smp_wmb() in kvm_mmu_invalidate_end(). */
@ -93,14 +101,7 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
if (is_error_pfn(f->pfn))
return -EFAULT;
if (!mc) {
local_mc = kvm_s390_new_mmu_cache();
if (!local_mc)
return -ENOMEM;
mc = local_mc;
}
/* Loop, will automatically release the faulted page. */
/* Loop, release the faulted page. */
if (mmu_invalidate_retry_gfn_unsafe(kvm, inv_seq, f->gfn)) {
kvm_release_faultin_page(kvm, f->page, true, false);
continue;
@ -110,20 +111,19 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
if (!mmu_invalidate_retry_gfn(kvm, inv_seq, f->gfn)) {
f->valid = true;
rc = gmap_link(mc, kvm->arch.gmap, f, slot);
kvm_release_faultin_page(kvm, f->page, !!rc, f->write_attempt);
f->page = NULL;
}
kvm_release_faultin_page(kvm, f->page, !!rc, f->write_attempt);
}
kvm_release_faultin_page(kvm, f->page, true, false);
if (rc == -ENOMEM) {
rc = kvm_s390_mmu_cache_topup(mc);
if (rc)
return rc;
} else if (rc != -EAGAIN) {
return rc;
rc = -EAGAIN;
}
}
return rc;
}
int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w)

View File

@ -1419,8 +1419,8 @@ static int walk_guest_tables(struct gmap *sg, unsigned long saddr, struct pgtwal
return kvm_s390_get_guest_page(kvm, entries + LEVEL_MEM, table.pte.pfra, wr);
}
static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union pte *ptep,
struct guest_fault *f, bool p)
static int _do_shadow_pte(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gpa_t raddr,
union pte *ptep_h, union pte *ptep, struct guest_fault *f, bool p)
{
union pgste pgste;
union pte newpte;
@ -1430,7 +1430,7 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
lockdep_assert_held(&sg->parent->children_lock);
scoped_guard(spinlock, &sg->host_to_rmap_lock)
rc = gmap_insert_rmap(sg, f->gfn, gpa_to_gfn(raddr), TABLE_TYPE_PAGE_TABLE);
rc = gmap_insert_rmap(mc, sg, f->gfn, gpa_to_gfn(raddr), TABLE_TYPE_PAGE_TABLE);
if (rc)
return rc;
@ -1462,19 +1462,21 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
return 0;
}
static int _do_shadow_crste(struct gmap *sg, gpa_t raddr, union crste *host, union crste *table,
struct guest_fault *f, bool p)
static int _do_shadow_crste(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gpa_t raddr,
union crste *host, union crste *table, struct guest_fault *f, bool p)
{
union crste newcrste, oldcrste;
gfn_t gfn;
unsigned long mask;
gfn_t r_gfn;
int rc;
lockdep_assert_held(&sg->kvm->mmu_lock);
lockdep_assert_held(&sg->parent->children_lock);
gfn = f->gfn & (is_pmd(*table) ? _SEGMENT_FR_MASK : _REGION3_FR_MASK);
mask = is_pmd(*table) ? _SEGMENT_FR_MASK : _REGION3_FR_MASK;
r_gfn = gpa_to_gfn(raddr) & mask;
scoped_guard(spinlock, &sg->host_to_rmap_lock)
rc = gmap_insert_rmap(sg, gfn, gpa_to_gfn(raddr), host->h.tt);
rc = gmap_insert_rmap(mc, sg, f->gfn & mask, r_gfn, host->h.tt);
if (rc)
return rc;
@ -1497,8 +1499,7 @@ static int _do_shadow_crste(struct gmap *sg, gpa_t raddr, union crste *host, uni
return -EAGAIN;
newcrste = _crste_fc1(f->pfn, oldcrste.h.tt, 0, !p);
gfn = gpa_to_gfn(raddr);
while (!dat_crstep_xchg_atomic(table, READ_ONCE(*table), newcrste, gfn, sg->asce))
while (!dat_crstep_xchg_atomic(table, READ_ONCE(*table), newcrste, r_gfn, sg->asce))
;
return 0;
}
@ -1577,39 +1578,52 @@ static int _gaccess_do_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *sg,
if (KVM_BUG_ON(l > TABLE_TYPE_REGION3, sg->kvm))
return -EFAULT;
if (l == TABLE_TYPE_PAGE_TABLE)
return _do_shadow_pte(sg, saddr, ptep_h, ptep, entries + LEVEL_MEM, w->p);
return _do_shadow_crste(sg, saddr, host, table, entries + LEVEL_MEM, w->p);
return _do_shadow_pte(mc, sg, saddr, ptep_h, ptep, entries + LEVEL_MEM, w->p);
return _do_shadow_crste(mc, sg, saddr, host, table, entries + LEVEL_MEM, w->p);
}
static inline int ___gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, gpa_t saddr,
unsigned long seq, struct pgtwalk *walk)
{
struct gmap *parent;
int rc;
if (kvm_s390_array_needs_retry_safe(vcpu->kvm, seq, walk->raw_entries))
return -EAGAIN;
parent = READ_ONCE(sg->parent);
if (!parent)
return -EAGAIN;
scoped_guard(spinlock, &parent->children_lock) {
if (READ_ONCE(sg->parent) != parent)
return -EAGAIN;
sg->invalidated = false;
rc = _gaccess_do_shadow(vcpu->arch.mc, sg, saddr, walk);
}
if (!rc)
kvm_s390_release_faultin_array(vcpu->kvm, walk->raw_entries, false);
return rc;
}
static inline int _gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, gpa_t saddr,
unsigned long seq, struct pgtwalk *walk)
{
struct gmap *parent;
int rc;
if (kvm_s390_array_needs_retry_unsafe(vcpu->kvm, seq, walk->raw_entries))
return -EAGAIN;
again:
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
if (rc)
return rc;
scoped_guard(read_lock, &vcpu->kvm->mmu_lock) {
if (kvm_s390_array_needs_retry_safe(vcpu->kvm, seq, walk->raw_entries))
return -EAGAIN;
parent = READ_ONCE(sg->parent);
if (!parent)
return -EAGAIN;
scoped_guard(spinlock, &parent->children_lock) {
if (READ_ONCE(sg->parent) != parent)
return -EAGAIN;
sg->invalidated = false;
rc = _gaccess_do_shadow(vcpu->arch.mc, sg, saddr, walk);
}
if (rc == -ENOMEM)
goto again;
if (!rc)
kvm_s390_release_faultin_array(vcpu->kvm, walk->raw_entries, false);
}
do {
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
if (rc)
return rc;
rc = radix_tree_preload(GFP_KERNEL);
if (rc)
return rc;
scoped_guard(read_lock, &vcpu->kvm->mmu_lock)
rc = ___gaccess_shadow_fault(vcpu, sg, saddr, seq, walk);
radix_tree_preload_end();
} while (rc == -ENOMEM);
return rc;
}

View File

@ -395,15 +395,28 @@ static long _gmap_unmap_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct
struct gmap_unmap_priv *priv = walk->priv;
struct folio *folio = NULL;
union crste old = *crstep;
bool ok;
if (!old.h.fc)
return 0;
if (old.s.fc1.pr && test_bit(GMAP_FLAG_EXPORT_ON_UNMAP, &priv->gmap->flags))
folio = phys_to_folio(crste_origin_large(old));
/* No races should happen because kvm->mmu_lock is held in write mode */
KVM_BUG_ON(!gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn),
priv->gmap->kvm);
/*
* No races should happen because kvm->mmu_lock is held in write mode,
* but the unmap operation could have triggered an unshadow, which
* causes gmap_crstep_xchg_atomic() to return false and clear the
* vsie_notif bit. Allow the operation to fail once, if the old crste
* had the vsie_notif bit set. A second failure is not allowed, for
* the reasons above.
*/
ok = gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn);
if (!ok) {
KVM_BUG_ON(!old.s.fc1.vsie_notif, priv->gmap->kvm);
old.s.fc1.vsie_notif = 0;
ok = gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn);
KVM_BUG_ON(!ok, priv->gmap->kvm);
}
if (folio)
uv_convert_from_secure_folio(folio);
@ -987,7 +1000,8 @@ int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interr
return 0;
}
int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level)
int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn,
gfn_t r_gfn, int level)
{
struct vsie_rmap *rmap __free(kvfree) = NULL;
struct vsie_rmap *temp;
@ -997,7 +1011,7 @@ int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level)
KVM_BUG_ON(!is_shadow(sg), sg->kvm);
lockdep_assert_held(&sg->host_to_rmap_lock);
rmap = kzalloc_obj(*rmap, GFP_ATOMIC);
rmap = kvm_s390_mmu_cache_alloc_rmap(mc);
if (!rmap)
return -ENOMEM;
@ -1044,7 +1058,7 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf
if (level <= TABLE_TYPE_REGION1) {
bitmask = -1UL << (8 + 11 * level);
scoped_guard(spinlock, &sg->host_to_rmap_lock)
rc = gmap_insert_rmap(sg, p_gfn, r_gfn & bitmask, level);
rc = gmap_insert_rmap(mc, sg, p_gfn, r_gfn & bitmask, level);
}
if (rc)
return rc;

View File

@ -100,7 +100,8 @@ int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long cou
void gmap_ucas_unmap(struct gmap *gmap, gfn_t c_gfn, unsigned long count);
int gmap_enable_skeys(struct gmap *gmap);
int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interruptible);
int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level);
int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn,
gfn_t r_gfn, int level);
int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,
kvm_pfn_t pfn, int level, bool wr);
void gmap_set_cmma_all_dirty(struct gmap *gmap);
@ -273,11 +274,23 @@ static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, unio
gmap_unmap_prefix(gmap, gfn, gfn + align);
}
if (crste_leaf(oldcrste) && crste_needs_unshadow(oldcrste, newcrste)) {
newcrste = oldcrste;
newcrste.s.fc1.vsie_notif = 0;
if (needs_lock)
gmap_handle_vsie_unshadow_event(gmap, gfn);
else
_gmap_handle_vsie_unshadow_event(gmap, gfn);
if (!dat_crstep_xchg_atomic(crstep, oldcrste, newcrste, gfn, gmap->asce))
return false;
/*
* Return false even if the swap was successful, as it only
* indicates that the best effort clearing of the vsie_notif
* bit was successful. The caller will have to try again
* regardless, since the desired value has not been set.
* This pointless check is needed to silence a potential
* __must_check warning.
*/
return false;
}
if (!oldcrste.s.fc1.d && newcrste.s.fc1.d && !newcrste.s.fc1.s)
SetPageDirty(phys_to_page(crste_origin_large(newcrste)));

View File

@ -999,7 +999,10 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
break;
}
case KVM_S390_VM_MEM_LIMIT_SIZE: {
struct kvm_memslots *slots;
struct kvm_memory_slot *ms;
unsigned long new_limit;
int bkt;
if (kvm_is_ucontrol(kvm))
return -EINVAL;
@ -1007,6 +1010,9 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
if (get_user(new_limit, (u64 __user *)attr->addr))
return -EFAULT;
guard(mutex)(&kvm->lock);
new_limit = ALIGN(new_limit, HPAGE_SIZE);
if (kvm->arch.mem_limit != KVM_S390_NO_MEM_LIMIT &&
new_limit > kvm->arch.mem_limit)
return -E2BIG;
@ -1014,12 +1020,27 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
if (!new_limit)
return -EINVAL;
ret = -EBUSY;
if (!kvm->created_vcpus)
ret = gmap_set_limit(kvm->arch.gmap, gpa_to_gfn(new_limit));
if (kvm->created_vcpus)
return -EBUSY;
ret = 0;
scoped_guard(mutex, &kvm->slots_lock) {
slots = kvm_memslots(kvm);
if (slots && !kvm_memslots_empty(slots)) {
kvm_for_each_memslot(ms, bkt, slots) {
if (gpa_to_gfn(new_limit) < ms->base_gfn + ms->npages) {
ret = -EBUSY;
break;
}
}
}
if (!ret)
ret = gmap_set_limit(kvm->arch.gmap, gpa_to_gfn(new_limit));
}
if (ret)
break;
VM_EVENT(kvm, 3, "SET: max guest address: %lu", new_limit);
VM_EVENT(kvm, 3, "New guest asce: 0x%p",
(void *)kvm->arch.gmap->asce.val);
VM_EVENT(kvm, 3, "New guest asce: 0x%p", (void *)kvm->arch.gmap->asce.val);
break;
}
default:
@ -5672,6 +5693,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
return -EINVAL;
if ((new->base_gfn + new->npages) * PAGE_SIZE > kvm->arch.mem_limit)
return -EINVAL;
if (!asce_contains_gfn(kvm->arch.gmap->asce, new->base_gfn + new->npages - 1))
return -EINVAL;
}
if (!kvm->arch.migration_mode)

View File

@ -1188,6 +1188,7 @@ static void _essa_clear_cbrl(struct kvm_vcpu *vcpu, unsigned long *cbrl, int len
union crste *crstep;
union pgste pgste;
union pte *ptep;
hva_t hva;
int i;
lockdep_assert_held(&vcpu->kvm->mmu_lock);
@ -1199,8 +1200,11 @@ static void _essa_clear_cbrl(struct kvm_vcpu *vcpu, unsigned long *cbrl, int len
if (!ptep || ptep->s.pr)
continue;
pgste = pgste_get_lock(ptep);
if (pgste.usage == PGSTE_GPS_USAGE_UNUSED || pgste.zero)
gmap_helper_zap_one_page(vcpu->kvm->mm, cbrl[i]);
if (pgste.usage == PGSTE_GPS_USAGE_UNUSED || pgste.zero) {
hva = gpa_to_hva(vcpu->kvm, cbrl[i]);
if (!kvm_is_error_hva(hva))
gmap_helper_zap_one_page(vcpu->kvm->mm, hva);
}
pgste_set_unlock(ptep, pgste);
}
}

View File

@ -17,6 +17,7 @@
#include <linux/pagewalk.h>
#include <linux/sched/mm.h>
#include <linux/mmu_notifier.h>
#include <asm/gmap_helpers.h>
#include "kvm-s390.h"
#include "dat.h"
#include "gaccess.h"
@ -73,6 +74,7 @@ static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_str
struct pv_make_secure {
void *uvcb;
struct folio *folio;
struct kvm *kvm;
int rc;
bool needs_export;
};
@ -103,9 +105,21 @@ static void _kvm_s390_pv_make_secure(struct guest_fault *f)
{
struct pv_make_secure *priv = f->priv;
struct folio *folio;
spinlock_t *ptl; /* pte lock from try_get_locked_pte() */
pte_t *ptep;
folio = pfn_folio(f->pfn);
priv->rc = -EAGAIN;
if (!mmap_read_trylock(priv->kvm->mm))
return;
ptep = try_get_locked_pte(priv->kvm->mm, gfn_to_hva(priv->kvm, f->gfn), &ptl);
if (IS_ERR_VALUE(ptep)) {
priv->rc = PTR_ERR(ptep);
goto out;
}
if (folio_trylock(folio)) {
priv->rc = __kvm_s390_pv_make_secure(f, folio);
if (priv->rc == -E2BIG || priv->rc == -EBUSY) {
@ -114,6 +128,11 @@ static void _kvm_s390_pv_make_secure(struct guest_fault *f)
}
folio_unlock(folio);
}
if (ptep)
pte_unmap_unlock(ptep, ptl);
out:
mmap_read_unlock(priv->kvm->mm);
}
/**
@ -127,7 +146,7 @@ static void _kvm_s390_pv_make_secure(struct guest_fault *f)
*/
int kvm_s390_pv_make_secure(struct kvm *kvm, unsigned long gaddr, void *uvcb)
{
struct pv_make_secure priv = { .uvcb = uvcb };
struct pv_make_secure priv = { .uvcb = uvcb, .kvm = kvm, };
struct guest_fault f = {
.write_attempt = true,
.gfn = gpa_to_gfn(gaddr),

View File

@ -17,22 +17,68 @@
#include <asm/gmap_helpers.h>
/**
* ptep_zap_softleaf_entry() - discard a software leaf entry.
* try_get_locked_pte() - like get_locked_pte(), but atomic and with trylock
* @mm: the mm
* @entry: the software leaf entry that needs to be zapped
* @vmaddr: the userspace virtual address whose pte is to be found
* @ptl: will be set to the pointer to the lock used to lock the pte in case
* of success.
*
* Discards the given software leaf entry. If the leaf entry was an actual
* swap entry (and not a migration entry, for example), the actual swapped
* page is also discarded from swap.
* This function returns the pointer to the pte corresponding to @addr in @mm,
* similarly to get_locked_pte(). Unlike get_locked_pte(), no attempt is made
* to allocate missing page tables. If a missing or large entry is found, the
* function will return NULL. If the ptl lock is contended, %-EAGAIN is
* returned.
*
* In case of success, *@ptl will point to the locked pte lock for the returned
* pte, like get_locked_pte() does.
*
* Context: mmap_lock or vma lock for read or for write needs to be held.
* Return:
* * %NULL if the pte cannot be reached.
* * %-EAGAIN if the pte can be reached, but cannot be locked.
* * the pointer to the pte corresponding to @addr in @mm, if it can be reached
* and locked.
*/
static void ptep_zap_softleaf_entry(struct mm_struct *mm, softleaf_t entry)
pte_t *try_get_locked_pte(struct mm_struct *mm, unsigned long vmaddr, spinlock_t **ptl)
{
if (softleaf_is_swap(entry))
dec_mm_counter(mm, MM_SWAPENTS);
else if (softleaf_is_migration(entry))
dec_mm_counter(mm, mm_counter(softleaf_to_folio(entry)));
swap_put_entries_direct(entry, 1);
pmd_t *pmdp, pmd, pmdval;
pud_t *pudp, pud;
p4d_t *p4dp, p4d;
pgd_t *pgdp, pgd;
pte_t *ptep;
pgdp = pgd_offset(mm, vmaddr);
pgd = pgdp_get(pgdp);
if (pgd_none(pgd) || !pgd_present(pgd))
return NULL;
p4dp = p4d_offset_lockless(pgdp, pgd, vmaddr);
p4d = p4dp_get(p4dp);
if (p4d_none(p4d) || !p4d_present(p4d))
return NULL;
pudp = pud_offset_lockless(p4dp, p4d, vmaddr);
pud = pudp_get(pudp);
if (pud_none(pud) || pud_leaf(pud) || !pud_present(pud))
return NULL;
pmdp = pmd_offset_lockless(pudp, pud, vmaddr);
pmd = pmdp_get_lockless(pmdp);
if (pmd_none(pmd) || pmd_leaf(pmd) || !pmd_present(pmd))
return NULL;
ptep = pte_offset_map_rw_nolock(mm, pmdp, vmaddr, &pmdval, ptl);
if (!ptep)
return NULL;
if (spin_trylock(*ptl)) {
if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmdp)))) {
pte_unmap_unlock(ptep, *ptl);
return ERR_PTR(-EAGAIN);
}
return ptep;
}
pte_unmap(ptep);
return ERR_PTR(-EAGAIN);
}
EXPORT_SYMBOL_GPL(try_get_locked_pte);
/**
* gmap_helper_zap_one_page() - discard a page if it was swapped.
@ -46,7 +92,8 @@ static void ptep_zap_softleaf_entry(struct mm_struct *mm, softleaf_t entry)
void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
{
struct vm_area_struct *vma;
spinlock_t *ptl;
spinlock_t *ptl; /* Lock for the host (userspace) page table */
softleaf_t sl;
pte_t *ptep;
mmap_assert_locked(mm);
@ -57,11 +104,13 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
return;
/* Get pointer to the page table entry */
ptep = get_locked_pte(mm, vmaddr, &ptl);
if (unlikely(!ptep))
ptep = try_get_locked_pte(mm, vmaddr, &ptl);
if (IS_ERR_OR_NULL(ptep))
return;
if (pte_swap(*ptep)) {
ptep_zap_softleaf_entry(mm, softleaf_from_pte(*ptep));
sl = softleaf_from_pte(*ptep);
if (pte_swap(*ptep) && softleaf_is_swap(sl)) {
dec_mm_counter(mm, MM_SWAPENTS);
swap_put_entries_direct(sl, 1);
pte_clear(mm, vmaddr, ptep);
}
pte_unmap_unlock(ptep, ptl);
@ -113,37 +162,9 @@ EXPORT_SYMBOL_GPL(gmap_helper_discard);
*/
void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
{
pmd_t *pmdp, pmd, pmdval;
pud_t *pudp, pud;
p4d_t *p4dp, p4d;
pgd_t *pgdp, pgd;
spinlock_t *ptl; /* Lock for the host (userspace) page table */
pte_t *ptep;
pgdp = pgd_offset(mm, vmaddr);
pgd = pgdp_get(pgdp);
if (pgd_none(pgd) || !pgd_present(pgd))
return;
p4dp = p4d_offset(pgdp, vmaddr);
p4d = p4dp_get(p4dp);
if (p4d_none(p4d) || !p4d_present(p4d))
return;
pudp = pud_offset(p4dp, vmaddr);
pud = pudp_get(pudp);
if (pud_none(pud) || pud_leaf(pud) || !pud_present(pud))
return;
pmdp = pmd_offset(pudp, vmaddr);
pmd = pmdp_get_lockless(pmdp);
if (pmd_none(pmd) || pmd_leaf(pmd) || !pmd_present(pmd))
return;
ptep = pte_offset_map_rw_nolock(mm, pmdp, vmaddr, &pmdval, &ptl);
if (!ptep)
return;
/*
* Several paths exists that takes the ptl lock and then call the
* mmu_notifier, which takes the mmu_lock. The unmap path, instead,
@ -156,21 +177,12 @@ void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
* If the lock is contended the bit is not set and the deadlock is
* avoided.
*/
if (spin_trylock(ptl)) {
/*
* Make sure the pte we are touching is still the correct
* one. In theory this check should not be needed, but
* better safe than sorry.
* Disabling interrupts or holding the mmap lock is enough to
* guarantee that no concurrent updates to the page tables
* are possible.
*/
if (likely(pmd_same(pmdval, pmdp_get_lockless(pmdp))))
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
spin_unlock(ptl);
}
ptep = try_get_locked_pte(mm, vmaddr, &ptl);
if (IS_ERR_OR_NULL(ptep))
return;
pte_unmap(ptep);
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
pte_unmap_unlock(ptep, ptl);
}
EXPORT_SYMBOL_GPL(gmap_helper_try_set_pte_unused);

View File

@ -77,6 +77,10 @@ KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-sse4a
KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json
KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2
# The target.json file is not available when invoking rustc-option, so use the
# built-in target when checking whether flags are supported instead.
KBUILD_RUSTFLAGS_OPTION_CHKS += --target=x86_64-unknown-none
#
# CFLAGS for compiling floating point code inside the kernel.
#

View File

@ -14,6 +14,14 @@ endif
KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json
# The target.json file is not available when invoking rustc-option, so use the
# built-in target when checking whether flags are supported instead.
ifeq ($(CONFIG_X86_32),y)
KBUILD_RUSTFLAGS_OPTION_CHKS += --target=i686-unknown-linux-gnu
else
KBUILD_RUSTFLAGS_OPTION_CHKS += --target=x86_64-unknown-linux-gnu
endif
ifeq ($(CONFIG_X86_32),y)
START := 0x8048000

View File

@ -518,7 +518,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
break;
case 0x50 ... 0x5f:
case 0x80 ... 0xaf:
case 0xc0 ... 0xcf:
case 0xc0 ... 0xef:
setup_force_cpu_cap(X86_FEATURE_ZEN6);
break;
default:

View File

@ -377,7 +377,12 @@ static const struct x86_cpu_id snc_cpu_ids[] __initconst = {
static __init int snc_get_config(void)
{
int ret = topology_num_nodes_per_package();
int ret;
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return 1;
ret = topology_num_nodes_per_package();
if (ret > 1 && !x86_match_cpu(snc_cpu_ids)) {
pr_warn("CoD enabled system? Resctrl not supported\n");

View File

@ -2,6 +2,7 @@
/* Copyright 2025 Arm, Ltd. */
#include <linux/err.h>
#include <linux/overflow.h>
#include <linux/slab.h>
#include <drm/ethosu_accel.h>
@ -163,17 +164,30 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
s8 mode = dma_st->mode;
u64 len = dma->len;
if (len == U64_MAX)
return U64_MAX;
if (mode >= 1) {
if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len)
return U64_MAX;
len += dma->stride[0];
len *= dma_st->size0;
if (check_mul_overflow(len, (u64)dma_st->size0, &len))
return U64_MAX;
}
if (mode == 2) {
if (dma->stride[1] < 0 && (u64)(-dma->stride[1]) > len)
return U64_MAX;
len += dma->stride[1];
len *= dma_st->size1;
if (check_mul_overflow(len, (u64)dma_st->size1, &len))
return U64_MAX;
}
if (dma->region >= 0) {
u64 end;
if (check_add_overflow(len, dma->offset, &end))
return U64_MAX;
info->region_size[dma->region] = max(info->region_size[dma->region], end);
}
if (dma->region >= 0)
info->region_size[dma->region] = max(info->region_size[dma->region],
len + dma->offset);
return len;
}
@ -387,6 +401,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
return -EFAULT;
i++;
if (i >= size / 4)
return -EINVAL;
bocmds[i] = cmds[1];
addr = cmd_to_addr(cmds);
}
@ -395,6 +411,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
case NPU_OP_DMA_START:
srclen = dma_length(info, &st.dma, &st.dma.src);
dstlen = dma_length(info, &st.dma, &st.dma.dst);
if (srclen == U64_MAX || dstlen == U64_MAX)
return -EINVAL;
if (st.dma.dst.region >= 0)
info->output_region[st.dma.dst.region] = true;
@ -431,8 +449,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
return ret;
break;
case NPU_OP_RESIZE: // U85 only
WARN_ON(1); // TODO
break;
return -EINVAL;
case NPU_SET_KERNEL_WIDTH_M1:
st.ifm.width = param;
break;
@ -464,7 +481,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
st.ifm.broadcast = param;
break;
case NPU_SET_IFM_REGION:
st.ifm.region = param & 0x7f;
st.ifm.region = param & 0x7;
break;
case NPU_SET_IFM_WIDTH0_M1:
st.ifm.width0 = param;
@ -599,7 +616,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
if (ethosu_is_u65(edev))
st.scale[1].length = cmds[1];
else
st.weight[1].length = cmds[1];
st.weight[2].length = cmds[1];
break;
case NPU_SET_WEIGHT3_BASE:
st.weight[3].base = addr;

View File

@ -259,6 +259,22 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
return -EINVAL;
}
if (!PAGE_ALIGNED(runtime_addr)) {
ivpu_err(vdev, "Runtime address 0x%llx not page aligned\n", runtime_addr);
return -EINVAL;
}
if (!PAGE_ALIGNED(runtime_size)) {
ivpu_err(vdev, "Runtime size %llu not page aligned\n", runtime_size);
return -EINVAL;
}
if (runtime_size < image_size) {
ivpu_err(vdev, "Runtime size too small: %llu, image size: %llu\n",
runtime_size, image_size);
return -EINVAL;
}
if (!ivpu_is_within_range(image_load_addr, image_size, &vdev->hw->ranges.runtime)) {
ivpu_err(vdev, "Invalid firmware load address: 0x%llx and size %llu\n",
image_load_addr, image_size);

View File

@ -98,6 +98,11 @@ static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const cha
u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0;
u32 log_end = READ_ONCE(log->write_index);
if (log_start >= data_size)
log_start = 0;
if (log_end > data_size)
log_end = data_size;
if (log->wrap_count == log->read_wrap_count) {
if (log_end <= log_start) {
drm_printf(p, "==== %s \"%s\" log empty ====\n", prefix, log->name);

View File

@ -291,6 +291,13 @@ int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *
if (ret)
goto unlock;
if (info_size > ivpu_bo_size(bo)) {
ivpu_warn_ratelimited(vdev, "MS info overflow: %#llx > %#zx\n",
info_size, ivpu_bo_size(bo));
ret = -EOVERFLOW;
goto unlock;
}
if (args->buffer_size < info_size) {
ret = -ENOSPC;
goto unlock;

View File

@ -327,7 +327,7 @@ config PANEL_CHANGE_MESSAGE
say 'N' and keep the default message with the version.
config PANEL_BOOT_MESSAGE
depends on PANEL_CHANGE_MESSAGE="y"
depends on PANEL_CHANGE_MESSAGE
string "New initialization message"
default ""
help

View File

@ -173,7 +173,7 @@ static int linedisp_display(struct linedisp *linedisp, const char *msg,
count = strlen(msg);
/* if the string ends with a newline, trim it */
if (msg[count - 1] == '\n')
if (count && msg[count - 1] == '\n')
count--;
if (!count) {

View File

@ -86,10 +86,7 @@ static const struct linedisp_ops max6959_linedisp_ops = {
static int max6959_enable(struct max6959_priv *priv, bool enable)
{
u8 mask = REG_CONFIGURATION_S_BIT;
u8 value = enable ? mask : 0;
return regmap_update_bits(priv->regmap, REG_CONFIGURATION, mask, value);
return regmap_assign_bits(priv->regmap, REG_CONFIGURATION, REG_CONFIGURATION_S_BIT, enable);
}
static void max6959_power_off(void *priv)

View File

@ -2337,7 +2337,7 @@ static int zram_bvec_write_partial(struct zram *zram, struct bio_vec *bvec,
if (!page)
return -ENOMEM;
ret = zram_read_page(zram, page, index, bio);
ret = zram_read_page(zram, page, index, NULL);
if (!ret) {
memcpy_from_bvec(page_address(page) + offset, bvec);
ret = zram_write_page(zram, page, index);

View File

@ -1428,7 +1428,7 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
epp = cpudata->epp_default_dc;
}
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
pr_debug("EPP cannot be set under performance policy\n");
return -EBUSY;
}

View File

@ -84,7 +84,6 @@ struct amd_aperf_mperf {
* @hw_prefcore: check whether HW supports preferred core featue.
* Only when hw_prefcore and early prefcore param are true,
* AMD P-State driver supports preferred core featue.
* @epp_cached: Cached CPPC energy-performance preference value
* @policy: Cpufreq policy value
* @suspended: If CPU core if offlined
* @epp_default_ac: Default EPP value for AC power source

View File

@ -31,6 +31,9 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
if (response) {
xfer->rxcnt = cmdlen;
xfer->rxd = cmd;
} else {
xfer->rxcnt = 0;
xfer->rxd = NULL;
}
}

View File

@ -7,11 +7,12 @@
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/bits.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/container_of.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/find.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@ -104,12 +105,15 @@ struct acpm_queue {
*
* @cmd: pointer to where the data shall be saved.
* @n_cmd: number of 32-bit commands.
* @response: true if the client expects the RX data.
* @rxcnt: expected length of the response in 32-bit words.
* @completed: flag indicating if the firmware response has been fully
* processed.
*/
struct acpm_rx_data {
u32 *cmd;
size_t n_cmd;
bool response;
size_t rxcnt;
bool completed;
};
#define ACPM_SEQNUM_MAX 64
@ -199,31 +203,33 @@ static void acpm_get_saved_rx(struct acpm_chan *achan,
const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
u32 rx_seqnum;
if (!rx_data->response)
if (!rx_data->rxcnt)
return;
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
if (rx_seqnum == tx_seqnum) {
if (rx_seqnum == tx_seqnum)
memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
}
}
/**
* acpm_get_rx() - get response from RX queue.
* @achan: ACPM channel info.
* @xfer: reference to the transfer to get response for.
* @native_match: pointer to a boolean set to true if the thread natively
* processed its own sequence number during this call.
*
* Return: 0 on success, -errno otherwise.
*/
static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer,
bool *native_match)
{
u32 rx_front, rx_seqnum, tx_seqnum, seqnum;
const void __iomem *base, *addr;
struct acpm_rx_data *rx_data;
u32 i, val, mlen;
bool rx_set = false;
*native_match = false;
guard(mutex)(&achan->rx_lock);
@ -232,10 +238,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
if (i == rx_front) {
acpm_get_saved_rx(achan, xfer, tx_seqnum);
if (i == rx_front)
return 0;
}
base = achan->rx.base;
mlen = achan->mlen;
@ -256,11 +260,16 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
seqnum = rx_seqnum - 1;
rx_data = &achan->rx_data[seqnum];
if (rx_data->response) {
if (rx_data->rxcnt) {
if (rx_seqnum == tx_seqnum) {
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
rx_set = true;
clear_bit(seqnum, achan->bitmap_seqnum);
/*
* Signal completion to the polling thread.
* Pairs with smp_load_acquire() in polling
* loop.
*/
smp_store_release(&rx_data->completed, true);
*native_match = true;
} else {
/*
* The RX data corresponds to another request.
@ -268,10 +277,23 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
* clear yet the bitmap. It will be cleared
* after the response is copied to the request.
*/
__ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
__ioread32_copy(rx_data->cmd, addr,
rx_data->rxcnt);
/*
* Signal completion to the polling thread.
* Pairs with smp_load_acquire() in polling
* loop.
*/
smp_store_release(&rx_data->completed, true);
}
} else {
clear_bit(seqnum, achan->bitmap_seqnum);
/*
* Signal completion to the polling thread.
* Pairs with smp_load_acquire() in polling loop.
*/
smp_store_release(&rx_data->completed, true);
if (rx_seqnum == tx_seqnum)
*native_match = true;
}
i = (i + 1) % achan->qlen;
@ -280,13 +302,6 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
/* We saved all responses, mark RX empty. */
writel(rx_front, achan->rx.rear);
/*
* If the response was not in this iteration of the queue, check if the
* RX data was previously saved.
*/
if (!rx_set)
acpm_get_saved_rx(achan, xfer, tx_seqnum);
return 0;
}
@ -301,6 +316,7 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
const struct acpm_xfer *xfer)
{
struct device *dev = achan->acpm->dev;
bool native_match;
ktime_t timeout;
u32 seqnum;
int ret;
@ -309,12 +325,25 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
do {
ret = acpm_get_rx(achan, xfer);
ret = acpm_get_rx(achan, xfer, &native_match);
if (ret)
return ret;
if (!test_bit(seqnum - 1, achan->bitmap_seqnum))
/*
* Safely check if our specific transaction has been processed.
* smp_load_acquire prevents the CPU from speculatively
* executing subsequent instructions before the transaction is
* synchronized.
*/
if (smp_load_acquire(&achan->rx_data[seqnum - 1].completed)) {
/* Retrieve payload if another thread cached it for us */
if (!native_match)
acpm_get_saved_rx(achan, xfer, seqnum);
/* Relinquish ownership of the sequence slot */
clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum);
return 0;
}
/* Determined experimentally. */
udelay(20);
@ -362,29 +391,48 @@ static int acpm_wait_for_queue_slots(struct acpm_chan *achan, u32 next_tx_front)
* TX queue.
* @achan: ACPM channel info.
* @xfer: reference to the transfer being prepared.
*
* Return: 0 on success, -errno otherwise.
*/
static void acpm_prepare_xfer(struct acpm_chan *achan,
const struct acpm_xfer *xfer)
static int acpm_prepare_xfer(struct acpm_chan *achan,
const struct acpm_xfer *xfer)
{
struct acpm_rx_data *rx_data;
u32 *txd = (u32 *)xfer->txd;
unsigned long size = ACPM_SEQNUM_MAX - 1;
unsigned long bit = achan->seqnum;
/* Prevent chan->seqnum from being re-used */
do {
if (++achan->seqnum == ACPM_SEQNUM_MAX)
achan->seqnum = 1;
} while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum));
bit = find_next_zero_bit(achan->bitmap_seqnum, size, bit);
if (bit >= size) {
bit = find_first_zero_bit(achan->bitmap_seqnum, size);
if (bit >= size) {
dev_err_ratelimited(achan->acpm->dev,
"ACPM sequence number pool exhausted\n");
return -EBUSY;
}
}
/*
* Execute the atomic set to formally claim the bit and establish
* LKMM Acquire semantics against the RX thread's clear_bit_unlock().
* A loop is unnecessary because allocations are strictly serialized
* by tx_lock.
*/
if (WARN_ON_ONCE(test_and_set_bit_lock(bit, achan->bitmap_seqnum)))
return -EIO;
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
achan->seqnum = bit + 1;
txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum);
/* Clear data for upcoming responses */
rx_data = &achan->rx_data[achan->seqnum - 1];
rx_data = &achan->rx_data[bit];
rx_data->completed = false;
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
if (xfer->rxd)
rx_data->response = true;
/* zero means no response expected */
rx_data->rxcnt = xfer->rxcnt;
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
return 0;
}
/**
@ -444,7 +492,9 @@ int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer)
if (ret)
return ret;
acpm_prepare_xfer(achan, xfer);
ret = acpm_prepare_xfer(achan, xfer);
if (ret)
return ret;
/* Write TX command. */
__iowrite32_copy(achan->tx.base + achan->mlen * tx_front,
@ -526,10 +576,11 @@ static int acpm_achan_alloc_cmds(struct acpm_chan *achan)
/**
* acpm_free_mbox_chans() - free mailbox channels.
* @acpm: pointer to driver data.
* @data: pointer to driver data.
*/
static void acpm_free_mbox_chans(struct acpm_info *acpm)
static void acpm_free_mbox_chans(void *data)
{
struct acpm_info *acpm = data;
int i;
for (i = 0; i < acpm->num_chans; i++)
@ -557,6 +608,10 @@ static int acpm_channels_init(struct acpm_info *acpm)
if (!acpm->chans)
return -ENOMEM;
ret = devm_add_action_or_reset(dev, acpm_free_mbox_chans, acpm);
if (ret)
return dev_err_probe(dev, ret, "Failed to add mbox free action.\n");
chans_shmem = acpm->sram_base + readl(&shmem->chans);
for (i = 0; i < acpm->num_chans; i++) {
@ -578,10 +633,8 @@ static int acpm_channels_init(struct acpm_info *acpm)
cl->dev = dev;
achan->chan = mbox_request_channel(cl, 0);
if (IS_ERR(achan->chan)) {
acpm_free_mbox_chans(acpm);
if (IS_ERR(achan->chan))
return PTR_ERR(achan->chan);
}
}
return 0;

View File

@ -394,7 +394,8 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
uint64_t start_page, uint64_t num_pages,
uint64_t flags, void *dst)
{
u32 i, idx;
u32 i, j, t, idx;
u64 page_base;
/* The SYSTEM flag indicates the pages aren't in VRAM. */
WARN_ON_ONCE(flags & AMDGPU_PTE_SYSTEM);
@ -402,9 +403,12 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return;
for (i = 0; i < num_pages; ++i) {
amdgpu_gmc_set_pte_pde(adev, dst,
start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags);
page_base = pa;
for (i = 0, t = 0; i < num_pages; i++) {
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
amdgpu_gmc_set_pte_pde(adev, dst, start_page + t, page_base, flags);
page_base += AMDGPU_GPU_PAGE_SIZE;
}
}
drm_dev_exit(idx);

View File

@ -170,7 +170,7 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
/*
* The following is for PTE only. GART does not have PDEs.
*/
value = addr & 0x0000FFFFFFFFF000ULL;
value = addr & adev->gmc.pte_addr_mask;
value |= flags;
writeq(value, ptr + (gpu_page_idx * 8));
@ -1003,7 +1003,7 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
gc_ver == IP_VERSION(9, 4, 3) ||
gc_ver == IP_VERSION(9, 4, 4) ||
gc_ver == IP_VERSION(9, 5, 0) ||
gc_ver >= IP_VERSION(10, 3, 0));
gc_ver >= IP_VERSION(10, 1, 0));
if (!amdgpu_sriov_xnack_support(adev))
gmc->noretry = 1;

View File

@ -280,6 +280,7 @@ struct amdgpu_gmc {
u64 real_vram_size;
int vram_mtrr;
u64 mc_mask;
uint64_t pte_addr_mask;
const struct firmware *fw; /* MC firmware */
uint32_t fw_version;
struct amdgpu_irq_src vm_fault;

View File

@ -203,7 +203,7 @@ int amdgpu_gtt_mgr_alloc_entries(struct amdgpu_gtt_mgr *mgr,
int r;
/* Align to TLB L2 cache entry size to work around "V bit HW bug" */
if (adev->asic_type == CHIP_TAHITI) {
if (adev->family == AMDGPU_FAMILY_SI) {
alignment = 32 * 1024 / AMDGPU_GPU_PAGE_SIZE;
num_pages = ALIGN(num_pages, alignment);
}

View File

@ -67,6 +67,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
{
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo;
long r;
if (!mmu_notifier_range_blockable(range))
@ -77,8 +78,9 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
mmu_interval_set_seq(mni, cur_seq);
amdgpu_vm_bo_invalidate(bo, false);
r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP,
false, MAX_SCHEDULE_TIMEOUT);
r = dma_resv_wait_timeout(vm_root->tbo.base.resv,
DMA_RESV_USAGE_BOOKKEEP, false,
MAX_SCHEDULE_TIMEOUT);
mutex_unlock(&adev->notifier_lock);
if (r <= 0)
DRM_ERROR("(%ld) failed to wait for user bo\n", r);

View File

@ -173,16 +173,17 @@ void amdgpu_seq64_unmap(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv)
int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *va,
u64 *gpu_addr, u64 **cpu_addr)
{
unsigned long bit_pos;
unsigned long bit_pos = 0;
for (;;) {
bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem);
do {
bit_pos = find_next_zero_bit(adev->seq64.used,
adev->seq64.num_sem, bit_pos);
if (bit_pos >= adev->seq64.num_sem)
return -ENOSPC;
if (!test_and_set_bit(bit_pos, adev->seq64.used))
break;
}
bit_pos++;
} while (1);
*va = bit_pos * sizeof(u64) + amdgpu_seq64_get_va_base(adev);

View File

@ -532,10 +532,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
amdgpu_bo_unreserve(queue->db_obj.obj);
amdgpu_bo_unref(&queue->db_obj.obj);
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
amdgpu_bo_unpin(queue->wptr_obj.obj);
amdgpu_bo_unreserve(queue->wptr_obj.obj);
amdgpu_bo_unref(&queue->wptr_obj.obj);
kfree(queue);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@ -887,7 +883,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
continue;
}
r = amdgpu_userq_restore_helper(queue);
r = amdgpu_userq_map_helper(queue);
if (r)
ret = r;
@ -1124,7 +1120,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
/* Try to unmap all the queues in this process ctx */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
r = amdgpu_userq_preempt_helper(queue);
r = amdgpu_userq_unmap_helper(queue);
if (r)
ret = r;
}
@ -1344,8 +1340,7 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
}
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t saddr)
struct amdgpu_bo_va_mapping *mapping)
{
u32 ip_mask = amdgpu_userq_get_supported_ip_mask(adev);
struct amdgpu_bo_va *bo_va = mapping->bo_va;
@ -1354,12 +1349,9 @@ void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
if (!ip_mask)
return;
dev_warn_once(adev->dev, "now unmapping a vital queue va:%llx\n", saddr);
/**
* The userq VA mapping reservation should include the eviction fence,
* if the eviction fence can't signal successfully during unmapping,
* then driver will warn to flag this improper unmap of the userq VA.
* Note: The eviction fence may be attached to different BOs, and this
* The userq VA mapping reservation should include the eviction fence.
* Note: The eviction fence may be attached to different BOs and this
* unmap is only for one kind of userq VAs, so at this point suppose
* the eviction fence is always unsignaled.
*/

View File

@ -182,6 +182,5 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
u64 addr, u64 expected_size, u64 *va_out);
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t saddr);
struct amdgpu_bo_va_mapping *mapping);
#endif

View File

@ -2006,7 +2006,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
* from user space.
*/
if (unlikely(bo_va->userq_va_mapped))
amdgpu_userq_gem_va_unmap_validate(adev, mapping, saddr);
amdgpu_userq_gem_va_unmap_validate(adev, mapping);
list_del(&mapping->list);
amdgpu_vm_it_remove(mapping, &vm->va);

View File

@ -449,12 +449,10 @@ static void gfxhub_v11_5_0_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -454,12 +454,10 @@ static void gfxhub_v12_0_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -633,19 +633,17 @@ static void gfxhub_v12_1_xcc_set_fault_enable_default(struct amdgpu_device *adev
tmp = REG_SET_FIELD(tmp,
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
OTHER_CLIENT_ID_NO_RETRY_FAULT_INTERRUPT, value);
if (!value)
tmp = REG_SET_FIELD(tmp,
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp,
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
CRASH_ON_NO_RETRY_FAULT, !value);
WREG32_SOC15(GC, GET_INST(GC, i),
regGCVM_L2_PROTECTION_FAULT_CNTL_LO32, tmp);
tmp = RREG32_SOC15(GC, GET_INST(GC, i),
regGCVM_L2_PROTECTION_FAULT_CNTL_HI32);
if (!value)
tmp = REG_SET_FIELD(tmp,
GCVM_L2_PROTECTION_FAULT_CNTL_HI32,
CRASH_ON_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp,
GCVM_L2_PROTECTION_FAULT_CNTL_HI32,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, GET_INST(GC, i),
regGCVM_L2_PROTECTION_FAULT_CNTL_HI32, tmp);
}

View File

@ -403,12 +403,10 @@ static void gfxhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -516,12 +516,10 @@ static void gfxhub_v1_2_xcc_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL, tmp);
}
}

View File

@ -418,12 +418,10 @@ static void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -449,12 +449,10 @@ static void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -446,12 +446,10 @@ static void gfxhub_v3_0_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -434,12 +434,10 @@ static void gfxhub_v3_0_3_set_fault_enable_default(struct amdgpu_device *adev,
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
if (!value) {
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, 1);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, 1);
}
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_NO_RETRY_FAULT, !value);
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
CRASH_ON_RETRY_FAULT, !value);
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
}

View File

@ -847,6 +847,7 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
* internal address space.
*/
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
if (r) {

View File

@ -821,6 +821,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
* internal address space.
*/
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
if (r) {

View File

@ -812,8 +812,9 @@ static int gmc_v12_0_gart_init(struct amdgpu_device *adev)
static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
{
int r, vram_width = 0, vram_type = 0, vram_vendor = 0;
int r, vram_width = 0, vram_type = 0, vram_vendor = 0, dma_addr_bits;
struct amdgpu_device *adev = ip_block->adev;
uint64_t pte_addr_mask = 0;
int i;
adev->mmhub.funcs->init(adev);
@ -843,6 +844,8 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
* block size 512 (9bit)
*/
amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
dma_addr_bits = 44;
break;
case IP_VERSION(12, 1, 0):
bitmap_set(adev->vmhubs_mask, AMDGPU_GFXHUB(0),
@ -855,9 +858,13 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
* block size 512 (9bit)
*/
amdgpu_vm_adjust_size(adev, 128 * 1024 * 1024, 9, 4, 57);
pte_addr_mask = 0x000FFFFFFFFFF000ULL; /* 52 bit PA */
dma_addr_bits = 52;
break;
default:
break;
dev_warn(adev->dev, "Unrecognized GC IP version: 0x%08x\n",
amdgpu_ip_version(adev, GC_HWIP, 0));
return -EINVAL;
}
/* This interrupt is VMC page fault.*/
@ -911,14 +918,15 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
* internal address space.
*/
adev->gmc.mc_mask = AMDGPU_GMC_HOLE_MASK;
adev->gmc.pte_addr_mask = pte_addr_mask;
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits));
if (r) {
drm_warn(adev_to_drm(adev), "No suitable DMA available.\n");
return r;
}
adev->need_swiotlb = drm_need_swiotlb(44);
adev->need_swiotlb = drm_need_swiotlb(dma_addr_bits);
r = gmc_v12_0_mc_init(adev);
if (r)

View File

@ -836,6 +836,7 @@ static int gmc_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
amdgpu_vm_adjust_size(adev, 64, 9, 1, 40);
adev->gmc.mc_mask = 0xffffffffffULL;
adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL;
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
if (r) {

View File

@ -1016,6 +1016,7 @@ static int gmc_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
* internal address space.
*/
adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */
adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; /* 40 bit PA */
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
if (r) {

View File

@ -1131,6 +1131,7 @@ static int gmc_v8_0_sw_init(struct amdgpu_ip_block *ip_block)
* internal address space.
*/
adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */
adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; /* 40 bit PA */
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
if (r) {

View File

@ -1994,6 +1994,7 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
* internal address space.
*/
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
dma_addr_bits = amdgpu_ip_version(adev, GC_HWIP, 0) >=
IP_VERSION(9, 4, 2) ?

View File

@ -467,6 +467,11 @@ static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
kfree(queue->userq_prop);
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
amdgpu_bo_unpin(queue->wptr_obj.obj);
amdgpu_bo_unreserve(queue->wptr_obj.obj);
amdgpu_bo_unref(&queue->wptr_obj.obj);
}
static int mes_userq_preempt(struct amdgpu_usermode_queue *queue)

View File

@ -1316,6 +1316,7 @@ static int sdma_v7_1_sw_init(struct amdgpu_ip_block *ip_block)
ring->ring_obj = NULL;
ring->use_doorbell = true;
ring->me = i;
ring->no_user_submission = adev->sdma.no_user_submission;
for (xcc_id = 0; xcc_id < fls(adev->gfx.xcc_mask); xcc_id++) {
if (adev->sdma.instance[i].xcc_id == GET_INST(GC, xcc_id))

View File

@ -2502,6 +2502,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm,
if (pdd->qpd.is_debug)
return ret;
if (q->properties.is_being_destroyed)
return -EBUSY;
q->properties.is_being_destroyed = true;
if (pdd->process->debug_trap_enabled && q->properties.is_suspended) {
@ -2514,6 +2517,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm,
dqm_lock(dqm);
}
if (ret)
q->properties.is_being_destroyed = false;
return ret;
}
@ -2607,7 +2613,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
return retval;
failed_try_destroy_debugged_queue:
q->properties.is_being_destroyed = false;
dqm_unlock(dqm);
return retval;
}
@ -3309,7 +3315,7 @@ static void copy_context_work_handler(struct work_struct *work)
static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array)
{
if (!usr_queue_id_array)
return NULL;
return num_queues ? ERR_PTR(-EINVAL) : NULL;
if (num_queues > KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
return ERR_PTR(-EINVAL);

View File

@ -320,8 +320,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
static void restore_mqd(struct mqd_manager *mm, void **mqd,
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
struct queue_properties *qp,
const void *mqd_src,
struct queue_properties *qp, const void *mqd_src,
const void *ctl_stack_src, const u32 ctl_stack_size)
{
uint64_t addr;
@ -337,14 +336,48 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
*gart_addr = addr;
m->cp_hqd_pq_doorbell_control =
qp->doorbell_off <<
CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
m->cp_hqd_pq_doorbell_control);
qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", m->cp_hqd_pq_doorbell_control);
qp->is_active = 0;
}
static void checkpoint_mqd_sdma(struct mqd_manager *mm,
void *mqd,
void *mqd_dst,
void *ctl_stack_dst)
{
struct v11_sdma_mqd *m;
m = get_sdma_mqd(mqd);
memcpy(mqd_dst, m, sizeof(struct v11_sdma_mqd));
}
static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd,
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
struct queue_properties *qp,
const void *mqd_src,
const void *ctl_stack_src,
const u32 ctl_stack_size)
{
uint64_t addr;
struct v11_sdma_mqd *m;
m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr;
addr = mqd_mem_obj->gpu_addr;
memcpy(m, mqd_src, sizeof(*m));
m->sdmax_rlcx_doorbell_offset =
qp->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
*mqd = m;
if (gart_addr)
*gart_addr = addr;
qp->is_active = 0;
}
static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
@ -529,8 +562,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
mqd->update_mqd = update_mqd_sdma;
mqd->destroy_mqd = kfd_destroy_mqd_sdma;
mqd->is_occupied = kfd_is_occupied_sdma;
mqd->checkpoint_mqd = checkpoint_mqd;
mqd->restore_mqd = restore_mqd;
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
mqd->restore_mqd = restore_mqd_sdma;
mqd->mqd_size = sizeof(struct v11_sdma_mqd);
mqd->mqd_stride = kfd_mqd_stride;
#if defined(CONFIG_DEBUG_FS)

View File

@ -1344,8 +1344,13 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b
if (size == 0)
return 0;
if (!connector->base.state || !connector->base.state->crtc)
return -ENODEV;
acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);
write_size = min_t(size_t, size, sizeof(data));
r = copy_from_user(data, buf, write_size);
write_size -= r;

View File

@ -289,8 +289,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
if (capacity <= vector->capacity)
return true;
new_container = krealloc(vector->container,
capacity * vector->struct_size, GFP_KERNEL);
new_container = krealloc_array(vector->container,
capacity, vector->struct_size, GFP_KERNEL);
if (new_container) {
vector->container = new_container;

View File

@ -222,6 +222,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
ATOM_COMMON_RECORD_HEADER *header;
ATOM_I2C_RECORD *record;
struct bios_parser *bp = BP_FROM_DCB(dcb);
int i;
if (!info)
return BP_RESULT_BADINPUT;
@ -234,7 +235,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
offset = le16_to_cpu(object->usRecordOffset)
+ bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
if (!header)
@ -293,11 +294,12 @@ static enum bp_result bios_parser_get_device_tag_record(
{
ATOM_COMMON_RECORD_HEADER *header;
uint32_t offset;
int i;
offset = le16_to_cpu(object->usRecordOffset)
+ bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
if (!header)
@ -966,6 +968,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
{
ATOM_COMMON_RECORD_HEADER *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -975,7 +978,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
offset = le16_to_cpu(object->usRecordOffset)
+ bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
if (!header)
@ -1670,6 +1673,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
{
ATOM_COMMON_RECORD_HEADER *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -1679,7 +1683,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
offset = le16_to_cpu(object->usRecordOffset)
+ bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
if (!header)
@ -2769,6 +2773,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
{
(void)i;
unsigned int j;
unsigned int n;
struct bios_parser *bp;
ATOM_BRACKET_LAYOUT_RECORD *record;
ATOM_COMMON_RECORD_HEADER *record_header;
@ -2778,7 +2783,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
record = NULL;
record_header = NULL;
for (;;) {
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
if (record_header == NULL) {

View File

@ -396,6 +396,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
struct atom_i2c_record *record;
struct atom_i2c_record dummy_record = {0};
struct bios_parser *bp = BP_FROM_DCB(dcb);
int i;
if (!info)
return BP_RESULT_BADINPUT;
@ -429,7 +430,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
break;
}
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -534,6 +535,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
{
struct atom_common_record_header *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -542,7 +544,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -611,6 +613,7 @@ static struct atom_hpd_int_record *get_hpd_record(
{
struct atom_common_record_header *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -620,7 +623,7 @@ static struct atom_hpd_int_record *get_hpd_record(
offset = le16_to_cpu(object->disp_recordoffset)
+ bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -701,8 +704,10 @@ static enum bp_result bios_parser_get_gpio_pin_info(
info->offset_en = info->offset + 1;
info->offset_mask = info->offset - 1;
info->mask = (uint32_t) (1 <<
header->gpio_pin[i].gpio_bitshift);
if (header->gpio_pin[i].gpio_bitshift >= 32)
return BP_RESULT_BADBIOSTABLE;
info->mask = 1u << header->gpio_pin[i].gpio_bitshift;
info->mask_y = info->mask + 2;
info->mask_en = info->mask + 1;
info->mask_mask = info->mask - 1;
@ -2193,6 +2198,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
{
struct atom_common_record_header *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -2201,7 +2207,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -2230,6 +2236,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
{
struct atom_common_record_header *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -2238,7 +2245,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -2266,6 +2273,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
{
struct atom_common_record_header *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -2274,7 +2282,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -2352,6 +2360,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
{
struct atom_common_record_header *header;
uint32_t offset;
int i;
if (!object) {
BREAK_TO_DEBUGGER(); /* Invalid object */
@ -2360,7 +2369,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
for (;;) {
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
@ -2600,14 +2609,16 @@ static enum bp_result get_integrated_info_v11(
info_v11->extdispconninfo.checksum;
info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2616,14 +2627,16 @@ static enum bp_result get_integrated_info_v11(
}
info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2632,14 +2645,16 @@ static enum bp_result get_integrated_info_v11(
}
info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2648,14 +2663,16 @@ static enum bp_result get_integrated_info_v11(
}
info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2805,14 +2822,16 @@ static enum bp_result get_integrated_info_v2_1(
info->ext_disp_conn_info.checksum =
info_v2_1->extdispconninfo.checksum;
info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2820,14 +2839,16 @@ static enum bp_result get_integrated_info_v2_1(
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
}
info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2835,14 +2856,16 @@ static enum bp_result get_integrated_info_v2_1(
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
}
info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2850,14 +2873,16 @@ static enum bp_result get_integrated_info_v2_1(
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
}
info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -3245,6 +3270,7 @@ static enum bp_result update_slot_layout_info(
{
unsigned int record_offset;
unsigned int j;
unsigned int n;
struct atom_display_object_path_v2 *object;
struct atom_bracket_layout_record *record;
struct atom_common_record_header *record_header;
@ -3266,7 +3292,7 @@ static enum bp_result update_slot_layout_info(
(object->disp_recordoffset) +
(unsigned int)(bp->object_info_tbl_offset);
for (;;) {
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
record_header = (struct atom_common_record_header *)
GET_IMAGE(struct atom_common_record_header,
@ -3360,6 +3386,7 @@ static enum bp_result update_slot_layout_info_v2(
struct slot_layout_info *slot_layout_info)
{
unsigned int record_offset;
unsigned int n;
struct atom_display_object_path_v3 *object;
struct atom_bracket_layout_record_v2 *record;
struct atom_common_record_header *record_header;
@ -3382,7 +3409,7 @@ static enum bp_result update_slot_layout_info_v2(
(object->disp_recordoffset) +
(unsigned int)(bp->object_info_tbl_offset);
for (;;) {
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
record_header = (struct atom_common_record_header *)
GET_IMAGE(struct atom_common_record_header,

View File

@ -37,4 +37,9 @@ void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
#define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
/* Upper bound on the number of records in a VBIOS record chain. Prevents
* unbounded looping if the VBIOS image is malformed and lacks a terminator.
*/
#define BIOS_MAX_NUM_RECORD 256
#endif

View File

@ -1217,7 +1217,7 @@ struct dc_lttpr_caps {
union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding;
union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;
union dp_alpm_lttpr_cap alpm;
uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1];
uint8_t aux_rd_interval[MAX_REPEATER_CNT];
uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host
uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host
};

View File

@ -110,7 +110,15 @@ static const struct out_csc_color_matrix global_color_matrix[] = {
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
{ COLOR_SPACE_2020_RGB_FULLRANGE,
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868,
0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }
};
static bool setup_scaling_configuration(

View File

@ -88,7 +88,15 @@ static const struct out_csc_color_matrix global_color_matrix[] = {
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
{ COLOR_SPACE_2020_RGB_FULLRANGE,
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868,
0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }
};
enum csc_color_mode {

View File

@ -529,7 +529,8 @@ enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp)
} else {
status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
hdcp->auth.msg.hdcp2.rx_id_list,
hdcp->auth.msg.hdcp2.rx_id_list_size);
MIN(hdcp->auth.msg.hdcp2.rx_id_list_size,
sizeof(hdcp->auth.msg.hdcp2.rx_id_list)));
}
return status;
}

View File

@ -2390,28 +2390,30 @@ static int smu_v13_0_0_enable_mgpu_fan_boost(struct smu_context *smu)
}
static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
uint32_t *current_power_limit,
uint32_t *default_power_limit,
uint32_t *max_power_limit,
uint32_t *min_power_limit)
uint32_t *current_power_limit,
uint32_t *default_power_limit,
uint32_t *max_power_limit,
uint32_t *min_power_limit)
{
struct smu_table_context *table_context = &smu->smu_table;
struct smu_13_0_0_powerplay_table *powerplay_table =
(struct smu_13_0_0_powerplay_table *)table_context->power_play_table;
PPTable_t *pptable = table_context->driver_pptable;
SkuTable_t *skutable = &pptable->SkuTable;
uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
if (smu_v13_0_get_current_power_limit(smu, &power_limit))
power_limit = smu->adev->pm.ac_power ?
uint32_t pp_limit = smu->adev->pm.ac_power ?
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
int ret;
if (current_power_limit) {
ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
if (ret)
*current_power_limit = pp_limit;
}
if (current_power_limit)
*current_power_limit = power_limit;
if (default_power_limit)
*default_power_limit = power_limit;
*default_power_limit = pp_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@ -2425,15 +2427,15 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
}
dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
od_percent_upper, od_percent_lower, power_limit);
od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
*max_power_limit = msg_limit * (100 + od_percent_upper);
*max_power_limit = pp_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
*min_power_limit = power_limit * (100 - od_percent_lower);
*min_power_limit = pp_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}
@ -2801,11 +2803,19 @@ static void smu_v13_0_0_i2c_control_fini(struct smu_context *smu)
static int smu_v13_0_0_set_mp1_state(struct smu_context *smu,
enum pp_mp1_state mp1_state)
{
uint32_t param;
int ret;
switch (mp1_state) {
case PP_MP1_STATE_UNLOAD:
ret = smu_cmn_set_mp1_state(smu, mp1_state);
/*
* NOTE: Param 0x55 comes from PMFW 80.31.0, ignored in older versions.
* No PMFW version check required.
*/
param = amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) ?
0x55 : 0x00;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PrepareMp1ForUnload,
param, NULL);
break;
default:
/* Ignore others */

View File

@ -2372,28 +2372,32 @@ static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu)
}
static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
uint32_t *current_power_limit,
uint32_t *default_power_limit,
uint32_t *max_power_limit,
uint32_t *min_power_limit)
uint32_t *current_power_limit,
uint32_t *default_power_limit,
uint32_t *max_power_limit,
uint32_t *min_power_limit)
{
struct smu_table_context *table_context = &smu->smu_table;
struct smu_13_0_7_powerplay_table *powerplay_table =
(struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
PPTable_t *pptable = table_context->driver_pptable;
SkuTable_t *skutable = &pptable->SkuTable;
uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
if (smu_v13_0_get_current_power_limit(smu, &power_limit))
power_limit = smu->adev->pm.ac_power ?
uint32_t pp_limit = smu->adev->pm.ac_power ?
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
int ret;
if (current_power_limit) {
ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
if (ret)
power_limit = pp_limit;
if (current_power_limit)
*current_power_limit = power_limit;
}
if (default_power_limit)
*default_power_limit = power_limit;
*default_power_limit = pp_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@ -2407,15 +2411,15 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
}
dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
od_percent_upper, od_percent_lower, power_limit);
od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
*max_power_limit = msg_limit * (100 + od_percent_upper);
*max_power_limit = pp_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
*min_power_limit = power_limit * (100 - od_percent_lower);
*min_power_limit = pp_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}

View File

@ -1231,7 +1231,8 @@ static int smu_v14_0_0_set_soft_freq_limited_range(struct smu_context *smu,
switch (clk_type) {
case SMU_GFXCLK:
case SMU_SCLK:
msg_set_min = SMU_MSG_SetHardMinGfxClk;
/* SoftMin lets PMFW throttle gfxclk; HardMin would override SoftMax. */
msg_set_min = SMU_MSG_SetSoftMinGfxclk;
msg_set_max = SMU_MSG_SetSoftMaxGfxClk;
break;
case SMU_FCLK:

View File

@ -2152,7 +2152,6 @@ static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;

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