Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Documentation/arch/arm64/silicon-errata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,13 @@ stable kernels.
| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A |
| | Hip09 SMMU PMCG | | |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | TSV{110,200} | #1980005 | HISILICON_ERRATUM_1980005 |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | LINXICORE9100 | #162100125 | HISILICON_ERRATUM_162100125 |
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | SMMUv3 | #162100602 | HISILICON_ERRATUM_162100602 |
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
+----------------+-----------------+-----------------+-----------------------------+
Expand Down
42 changes: 42 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,48 @@ config HISILICON_ERRATUM_162102203

If unsure, say N.

config HISILICON_ERRATUM_1980005
bool "Hisilicon erratum IDC support"
default n
help
The HiSilicon TSV100/200 SoC support idc but report wrong value to
kernel.

If unsure, say N.

config HISILICON_ERRATUM_162100801
bool "Hip09 162100801 erratum support"
default y
help
When enabled GICv4.1 in hip09, there are some invalid vPE config
in configuration tables for some situation, which will cause vSGI
interrupts lost. So fix it by sending vinvall commands after vmovp.

If unsure, say Y.

config HISILICON_ERRATUM_162100125
bool "Hisilicon erratum 162100125"
default y
help
On Hisilicon LINXICORE9100 cores, sharing tlb entries on two cores when
TTBRx.CNP=1 differs from the standard ARM core. This causes issues when
tlb entries sharing between CPU cores. Avoid these issues by disabling
CNP support for Hisilicon LINXICORE9100 cores.

If unsure, say Y.

config HISILICON_ERRATUM_162100602
bool "Hisilicon erratum 162100602"
depends on ARM_SMMU_V3 && ARCH_HISI
default y
help
SMMU pagetable prefetch features may prefetch and use a invalid PTE even
the PTE is valid at that time. This will cause the device trigger fake
pagefaults. If the SMMU works in terminate mode, transactions which occur
fake pagefaults will be aborted, and could result in unexpected errors.

If unsure, say Y.

config QCOM_FALKOR_ERRATUM_1003
bool "Falkor E1003: Incorrect translation due to ASID change"
default y
Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/cputype.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
#define FUJITSU_CPU_PART_A64FX 0x001

#define HISI_CPU_PART_TSV110 0xD01
#define HISI_CPU_PART_LINXICORE9100 0xD02

#define APPLE_CPU_PART_M1_ICESTORM 0x022
#define APPLE_CPU_PART_M1_FIRESTORM 0x023
Expand Down Expand Up @@ -202,6 +203,7 @@
#define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
#define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)
#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
#define MIDR_HISI_LINXICORE9100 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_LINXICORE9100)
#define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
#define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
#define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
Expand Down
46 changes: 46 additions & 0 deletions arch/arm64/kernel/cpu_errata.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@ is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
return model == entry->midr_range.model;
}

#ifdef CONFIG_HISILICON_ERRATUM_1980005
static bool
hisilicon_1980005_match(const struct arm64_cpu_capabilities *entry,
int scope)
{
static const struct midr_range idc_support_list[] = {
MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
MIDR_REV(MIDR_HISI_TSV200, 1, 0),
{ /* sentinel */ }
};

return is_midr_in_range_list(read_cpuid_id(), idc_support_list);
}

static void
hisilicon_1980005_enable(const struct arm64_cpu_capabilities *__unused)
{
cpus_set_cap(ARM64_HAS_CACHE_IDC);
arm64_ftr_reg_ctrel0.sys_val |= BIT(CTR_IDC_SHIFT);
sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
}
#endif

static bool
has_mismatched_cache_type(const struct arm64_cpu_capabilities *entry,
int scope)
Expand Down Expand Up @@ -266,6 +289,13 @@ static const struct midr_range cavium_erratum_30115_cpus[] = {
};
#endif

#ifdef CONFIG_HISILICON_ERRATUM_162100125
static const struct midr_range hisilicon_erratum_162100125_cpus[] = {
MIDR_REV(MIDR_HISI_LINXICORE9100, 0, 0),
{},
};
#endif

#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
static const struct arm64_cpu_capabilities qcom_erratum_1003_list[] = {
{
Expand Down Expand Up @@ -541,6 +571,22 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
.cpu_enable = cpu_enable_trap_ctr_access,
},
#ifdef CONFIG_HISILICON_ERRATUM_1980005
{
.desc = "Taishan IDC coherence workaround",
.capability = ARM64_WORKAROUND_HISILICON_1980005,
.matches = hisilicon_1980005_match,
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.cpu_enable = hisilicon_1980005_enable,
},
#endif
#ifdef CONFIG_HISILICON_ERRATUM_162100125
{
.desc = "Hisilicon erratum 162100125",
.capability = ARM64_WORKAROUND_HISILICON_ERRATUM_162100125,
ERRATA_MIDR_RANGE_LIST(hisilicon_erratum_162100125_cpus),
},
#endif
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
{
.desc = "Qualcomm Technologies Falkor/Kryo erratum 1003",
Expand Down
3 changes: 3 additions & 0 deletions arch/arm64/kernel/cpufeature.c
Original file line number Diff line number Diff line change
Expand Up @@ -1629,6 +1629,9 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
if (is_kdump_kernel())
return false;

if (cpus_have_final_cap(ARM64_WORKAROUND_HISILICON_ERRATUM_162100125))
return false;

if (cpus_have_cap(ARM64_WORKAROUND_NVIDIA_CARMEL_CNP))
return false;

Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/tools/cpucaps
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ WORKAROUND_CAVIUM_TX2_219_PRFM
WORKAROUND_CAVIUM_TX2_219_TVM
WORKAROUND_CLEAN_CACHE
WORKAROUND_DEVICE_LOAD_ACQUIRE
WORKAROUND_HISILICON_1980005
WORKAROUND_HISILICON_ERRATUM_162100125
WORKAROUND_NVIDIA_CARMEL_CNP
WORKAROUND_QCOM_FALKOR_E1003
WORKAROUND_REPEAT_TLBI
Expand Down
3 changes: 3 additions & 0 deletions config.aarch64
Original file line number Diff line number Diff line change
Expand Up @@ -391,13 +391,16 @@ CONFIG_CAVIUM_TX2_ERRATUM_219=y
CONFIG_FUJITSU_ERRATUM_010001=y
CONFIG_HISILICON_ERRATUM_161600802=y
CONFIG_HISILICON_ERRATUM_162102203=y
CONFIG_HISILICON_ERRATUM_162100602=y
CONFIG_QCOM_FALKOR_ERRATUM_1003=y
CONFIG_QCOM_FALKOR_ERRATUM_1009=y
CONFIG_QCOM_QDF2400_ERRATUM_0065=y
CONFIG_QCOM_FALKOR_ERRATUM_E1041=y
CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=y
CONFIG_ROCKCHIP_ERRATUM_3588001=y
CONFIG_SOCIONEXT_SYNQUACER_PREITS=y
CONFIG_HISILICON_ERRATUM_162100801=y
CONFIG_HISILICON_ERRATUM_162100125=y
# end of ARM errata workarounds via the alternatives framework

CONFIG_ARM64_4K_PAGES=y
Expand Down
75 changes: 75 additions & 0 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,14 @@ static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather,
static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
size_t granule, void *cookie)
{
#ifdef CONFIG_HISILICON_ERRATUM_162100602
struct arm_smmu_domain *smmu_domain = cookie;

if (!size && smmu_domain->smmu->options & ARM_SMMU_OPT_SYNC_BATCH) {
arm_smmu_tlb_inv_range_domain(iova, granule, granule, true, cookie);
return;
}
#endif
arm_smmu_tlb_inv_range_domain(iova, size, granule, false, cookie);
}

Expand Down Expand Up @@ -2525,6 +2533,26 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
gather->pgsize, true, smmu_domain);
}

#ifdef CONFIG_HISILICON_ERRATUM_162100602
static void arm_smmu_iotlb_sync_map(struct iommu_domain *domain,
unsigned long iova, size_t size)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
size_t granule_size;

if (!(smmu_domain->smmu->options & ARM_SMMU_OPT_SYNC_MAP))
return;

if (smmu_domain->smmu->options & ARM_SMMU_OPT_SYNC_BATCH)
return;

granule_size = 1 << __ffs(smmu_domain->domain.pgsize_bitmap);

/* Add a SYNC command to sync io-pgtale to avoid errors in pgtable prefetch*/
arm_smmu_tlb_inv_range_domain(iova, granule_size, granule_size, true, smmu_domain);
}
#endif

static phys_addr_t
arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
{
Expand Down Expand Up @@ -2880,6 +2908,9 @@ static struct iommu_ops arm_smmu_ops = {
.unmap_pages = arm_smmu_unmap_pages,
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
.iotlb_sync = arm_smmu_iotlb_sync,
#ifdef CONFIG_HISILICON_ERRATUM_162100602
.iotlb_sync_map = arm_smmu_iotlb_sync_map,
#endif
.iova_to_phys = arm_smmu_iova_to_phys,
.enable_nesting = arm_smmu_enable_nesting,
.free = arm_smmu_domain_free,
Expand Down Expand Up @@ -3467,6 +3498,46 @@ static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
}
}

#ifdef CONFIG_HISILICON_ERRATUM_162100602
static void hisi_smmu_check_errata(struct arm_smmu_device *smmu)
{
u32 reg, i;

/* IIDR */
reg = readl_relaxed(smmu->base + ARM_SMMU_IIDR);
if (!(FIELD_GET(IIDR_VARIANT, reg) == 0x3) ||
!(FIELD_GET(IIDR_REVISION, reg) == 0x2))
return;

smmu->options |= ARM_SMMU_OPT_SYNC_MAP;

reg = readl_relaxed(smmu->base + ARM_SMMU_USER_CFG1);
reg = reg & GENMASK(15, 0);
for (i = 0; i < 8; i++) {
unsigned long val;

val = (reg >> 2 * i) & GENMASK(1, 0);
switch (PAGE_SIZE) {
case SZ_4K:
if (!val)
return;
break;
case SZ_16K:
if (!val || val == 0x1)
return;
break;
case SZ_64K:
if (!val || val == 0x1 || val == 0x3)
return;
break;
default:
return;
}
}
smmu->options |= ARM_SMMU_OPT_SYNC_BATCH;
}
#endif

static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
{
u32 reg;
Expand Down Expand Up @@ -3661,6 +3732,10 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
smmu->oas = 48;
}

#ifdef CONFIG_HISILICON_ERRATUM_162100602
hisi_smmu_check_errata(smmu);
#endif

if (arm_smmu_ops.pgsize_bitmap == -1UL)
arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
else
Expand Down
4 changes: 4 additions & 0 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@
#define ARM_SMMU_GERROR_IRQ_CFG1 0x70
#define ARM_SMMU_GERROR_IRQ_CFG2 0x74

#define ARM_SMMU_USER_CFG1 0xe04

#define ARM_SMMU_STRTAB_BASE 0x80
#define STRTAB_BASE_RA (1UL << 62)
#define STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6)
Expand Down Expand Up @@ -652,6 +654,8 @@ struct arm_smmu_device {
#define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1)
#define ARM_SMMU_OPT_MSIPOLL (1 << 2)
#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3)
#define ARM_SMMU_OPT_SYNC_MAP (1 << 4)
#define ARM_SMMU_OPT_SYNC_BATCH (1 << 5)
u32 options;

struct arm_smmu_cmdq cmdq;
Expand Down
4 changes: 4 additions & 0 deletions drivers/iommu/io-pgtable-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
pte = arm_lpae_install_table(cptep, ptep, 0, data);
if (pte)
__arm_lpae_free_pages(cptep, tblsz, cfg);
#ifdef CONFIG_HISILICON_ERRATUM_162100602
if (lvl <= 2)
io_pgtable_tlb_flush_walk(&data->iop, iova, 0, ARM_LPAE_GRANULE(data));
#endif
} else if (!cfg->coherent_walk && !(pte & ARM_LPAE_PTE_SW_SYNC)) {
__arm_lpae_sync_pte(ptep, 1, cfg);
}
Expand Down
36 changes: 28 additions & 8 deletions drivers/irqchip/irq-gic-v3-its.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
#define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3)
#define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 4)

#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
Expand Down Expand Up @@ -1313,6 +1314,14 @@ static void its_send_vmapp(struct its_node *its,
its_send_single_vcommand(its, its_build_vmapp_cmd, &desc);
}

static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
{
struct its_cmd_desc desc;

desc.its_vinvall_cmd.vpe = vpe;
its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
}

static void its_send_vmovp(struct its_vpe *vpe)
{
struct its_cmd_desc desc = {};
Expand Down Expand Up @@ -1352,19 +1361,14 @@ static void its_send_vmovp(struct its_vpe *vpe)

desc.its_vmovp_cmd.col = &its->collections[col_id];
its_send_single_vcommand(its, its_build_vmovp_cmd, &desc);
if (is_v4_1(its) && (its->flags &
ITS_FLAGS_WORKAROUND_HISILICON_162100801))
its_send_vinvall(its, vpe);
}

raw_spin_unlock_irqrestore(&vmovp_lock, flags);
}

static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
{
struct its_cmd_desc desc;

desc.its_vinvall_cmd.vpe = vpe;
its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
}

static void its_send_vinv(struct its_device *dev, u32 event_id)
{
struct its_cmd_desc desc;
Expand Down Expand Up @@ -4764,6 +4768,14 @@ static bool its_set_non_coherent(void *data)
return true;
}

static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
{
struct its_node *its = data;

its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100801;
return true;
}

static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375
{
Expand Down Expand Up @@ -4817,6 +4829,14 @@ static const struct gic_quirk its_quirks[] = {
.mask = 0xffffffff,
.init = its_enable_rk3588001,
},
#endif
#ifdef CONFIG_HISILICON_ERRATUM_162100801
{
.desc = "ITS: Hip09 erratum 162100801",
.iidr = 0x00051736,
.mask = 0xffffffff,
.init = its_enable_quirk_hip09_162100801,
},
#endif
{
.desc = "ITS: non-coherent attribute",
Expand Down