MLK-16005-2 arm64: tlb: add the SW workaround for i.MX8QM TKT340553
on i.MX8QM 1.0/1.1,TLB maintenance through DVM messages over ARADDR channel, some bits (see the following) will be corrupted: ASID[15:12] VA[48:45] VA[44:41] VA[39:36] This issue will result in the TLB aintenance across the clusters not working as expected due to some VA and ASID bits get corrupted The SW workaround is: use the vmalle1is if VA larger than 36bits or ASID[15:12] is not zero, otherwise, we use original TLB maintenance path. Note: To simplify the code, we did not check VA[40] bit specifically Signed-off-by: Jason Liu <jason.hui.liu@nxp.com> Reviewed-by: Anson Huang <anson.huang@nxp.com>5.4-rM2-2.2.x-imx-squashed
parent
fbfe972a07
commit
593bea4e36
|
@ -15,6 +15,8 @@
|
|||
#include <asm/cputype.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
extern bool TKT340553_SW_WORKAROUND;
|
||||
|
||||
/*
|
||||
* Raw TLBI operations.
|
||||
*
|
||||
|
@ -149,8 +151,12 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
|
|||
unsigned long asid = __TLBI_VADDR(0, ASID(mm));
|
||||
|
||||
dsb(ishst);
|
||||
__tlbi(aside1is, asid);
|
||||
__tlbi_user(aside1is, asid);
|
||||
if (TKT340553_SW_WORKAROUND && ASID(mm) >> 12) {
|
||||
__tlbi(vmalle1is);
|
||||
} else {
|
||||
__tlbi(aside1is, asid);
|
||||
__tlbi_user(aside1is, asid);
|
||||
}
|
||||
dsb(ish);
|
||||
}
|
||||
|
||||
|
@ -160,8 +166,12 @@ static inline void flush_tlb_page_nosync(struct vm_area_struct *vma,
|
|||
unsigned long addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm));
|
||||
|
||||
dsb(ishst);
|
||||
__tlbi(vale1is, addr);
|
||||
__tlbi_user(vale1is, addr);
|
||||
if (TKT340553_SW_WORKAROUND && (uaddr >> 36 || (ASID(vma->vm_mm) >> 12))) {
|
||||
__tlbi(vmalle1is);
|
||||
} else {
|
||||
__tlbi(vale1is, addr);
|
||||
__tlbi_user(vale1is, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void flush_tlb_page(struct vm_area_struct *vma,
|
||||
|
@ -183,6 +193,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
|
|||
{
|
||||
unsigned long asid = ASID(vma->vm_mm);
|
||||
unsigned long addr;
|
||||
unsigned long mask = (1 << 20) - 1;
|
||||
|
||||
start = round_down(start, stride);
|
||||
end = round_up(end, stride);
|
||||
|
@ -197,10 +208,13 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
|
|||
|
||||
start = __TLBI_VADDR(start, asid);
|
||||
end = __TLBI_VADDR(end, asid);
|
||||
mask <<= 24;
|
||||
|
||||
dsb(ishst);
|
||||
for (addr = start; addr < end; addr += stride) {
|
||||
if (last_level) {
|
||||
if (TKT340553_SW_WORKAROUND && (addr & mask || (ASID(vma->vm_mm) >> 12))) {
|
||||
__tlbi(vmalle1is);
|
||||
} else if (last_level) {
|
||||
__tlbi(vale1is, addr);
|
||||
__tlbi_user(vale1is, addr);
|
||||
} else {
|
||||
|
@ -234,8 +248,12 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
|
|||
end = __TLBI_VADDR(end, 0);
|
||||
|
||||
dsb(ishst);
|
||||
for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))
|
||||
__tlbi(vaale1is, addr);
|
||||
for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) {
|
||||
if (TKT340553_SW_WORKAROUND && addr >> 24)
|
||||
__tlbi(vmalle1is);
|
||||
else
|
||||
__tlbi(vaale1is, addr);
|
||||
}
|
||||
dsb(ish);
|
||||
isb();
|
||||
}
|
||||
|
@ -249,7 +267,10 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
|
|||
unsigned long addr = __TLBI_VADDR(kaddr, 0);
|
||||
|
||||
dsb(ishst);
|
||||
__tlbi(vaae1is, addr);
|
||||
if (TKT340553_SW_WORKAROUND && addr >> 24)
|
||||
__tlbi(vmalle1is);
|
||||
else
|
||||
__tlbi(vaae1is, addr);
|
||||
dsb(ish);
|
||||
isb();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#define IMX_SCU_SOC_DRIVER_NAME "imx-scu-soc"
|
||||
|
||||
bool TKT340553_SW_WORKAROUND;
|
||||
|
||||
static struct imx_sc_ipc *soc_ipc_handle;
|
||||
|
||||
struct imx_sc_msg_misc_get_soc_id {
|
||||
|
@ -114,9 +116,10 @@ static int imx_scu_soc_probe(struct platform_device *pdev)
|
|||
|
||||
/* format soc_id value passed from SCU firmware */
|
||||
val = id & 0x1f;
|
||||
if (of_machine_is_compatible("fsl,imx8qm"))
|
||||
if (of_machine_is_compatible("fsl,imx8qm")) {
|
||||
soc_dev_attr->soc_id = "i.MX8QM";
|
||||
else if (of_machine_is_compatible("fsl,imx8qxp"))
|
||||
TKT340553_SW_WORKAROUND = true;
|
||||
} else if (of_machine_is_compatible("fsl,imx8qxp"))
|
||||
soc_dev_attr->soc_id = "i.MX8QXP";
|
||||
|
||||
/* format revision value passed from SCU firmware */
|
||||
|
|
Loading…
Reference in New Issue