Skip to content

Commit 9216f88

Browse files
xxkentabrodkin
authored andcommitted
ARC: Fix an issue when changing RTP1 register and don't invalidate TLB
Add local_flush_tlb_all() function after changing RTP1 register from early_pg_dir to swapper_pg_dir - main Linux kernel page table. After this, we need to provide mapping for peripheral (UART for example) to swapper_pg_dir which is done in early_fixmap_shutdown(). Before this patch there was an issue because we used cached UART mapping from early_pg_dir but actual RTP1 pointed to new table swapper_pg_dir. This issue was found in QEMU because it doesn't simulate TLB while on nSIM and RTL all worked fine because they simulate/use TLB.
1 parent cc4be07 commit 9216f88

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

arch/arc/mm/tlb-arcv3.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ void early_fixmap_shutdown(void)
191191
pgd_t *pgd;
192192
p4d_t *p4d;
193193
pud_t *pud;
194+
pmd_t *pmd;
194195

195196
addr = FIXADDR_START;
196197

@@ -206,6 +207,11 @@ void early_fixmap_shutdown(void)
206207
pud = pud_offset(p4d, addr);
207208
if (pud_none(*pud) || !pud_present(*pud))
208209
set_pud(pud, pfn_pud(virt_to_pfn(fixmap_pmd), PAGE_TABLE));
210+
211+
pmd = pmd_offset(pud, addr);
212+
if (pmd_none(*pmd) || !pmd_present(*pmd))
213+
set_pmd(pmd, pfn_pmd(virt_to_pfn(fixmap_pte), PAGE_TABLE));
214+
ptw_flush(pmd);
209215
}
210216

211217
void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
@@ -282,11 +288,9 @@ void arc_paging_init(void)
282288
swapper_pud[idx] = pfn_pud(virt_to_pfn(swapper_pmd), PAGE_TABLE);
283289
ptw_flush(&swapper_pud[idx]);
284290

285-
if(CONFIG_LINUX_MAP_SIZE > 0x40000000) { //Mapping from 1Gb..2Gb
286-
idx = pud_index(PAGE_OFFSET + 0x40000000);
287-
swapper_pud[idx] = pfn_pud(virt_to_pfn(&swapper_pmd[PTRS_PER_PMD]), PAGE_TABLE);
288-
ptw_flush(&swapper_pud[idx]);
289-
}
291+
idx = pud_index(PAGE_OFFSET + 0x40000000);
292+
swapper_pud[idx] = pfn_pud(virt_to_pfn(&swapper_pmd[PTRS_PER_PMD]), PAGE_TABLE);
293+
ptw_flush(&swapper_pud[idx]);
290294

291295
#elif CONFIG_PGTABLE_LEVELS == 3
292296
unsigned int idx;
@@ -295,17 +299,17 @@ void arc_paging_init(void)
295299
swapper_pg_dir[idx] = pfn_pgd(virt_to_pfn(swapper_pmd), PAGE_TABLE);
296300
ptw_flush(&swapper_pg_dir[idx]);
297301

298-
if(CONFIG_LINUX_MAP_SIZE > 0x40000000) { //Mapping from 1Gb..2Gb
299-
idx = pgd_index(PAGE_OFFSET + 0x40000000);
300-
swapper_pg_dir[idx] = pfn_pgd(virt_to_pfn(&swapper_pmd[PTRS_PER_PMD]), PAGE_TABLE);
301-
ptw_flush(&swapper_pg_dir[idx]);
302-
}
302+
idx = pgd_index(PAGE_OFFSET + 0x40000000);
303+
swapper_pg_dir[idx] = pfn_pgd(virt_to_pfn(&swapper_pmd[PTRS_PER_PMD]), PAGE_TABLE);
304+
ptw_flush(&swapper_pg_dir[idx]);
305+
303306
#endif
304307

305308
arc_map_kernel_in_mm(&init_mm);
306309

307310
arc_mmu_rtp_set(0, 0, 0);
308311
arc_mmu_rtp_set(1, __pa(swapper_pg_dir), 0);
312+
local_flush_tlb_all();
309313
}
310314

311315
void arc_mmu_init(void)

0 commit comments

Comments
 (0)