Skip to content

Commit 83ab598

Browse files
Simon SchusterDinh Nguyen
authored andcommitted
nios2: do not introduce conflicting mappings when flushing tlb entries
The NIOS2 hardware does not support conflicting mappings for the same virtual address (see Nios II Processor Reference Guide from 2023.08.28): "The operating system software is responsible for guaranteeing that multiple TLB entries do not map the same virtual address. The hardware behavior is undefined when multiple entries map the same virtual address." When flushing tlb-entries, the kernel may violate this invariant for virtual addresses related to PID 0 as flushing is currently implemented by assigning physical address, pid and flags to 0. A small example: Before flushing TLB mappings for pid:0x42: dump tlb-entries for line=0xd (addr 000d0000): -- way:09 vpn:0x0006d000 phys:0x01145000 pid:0x00 flags:rw--c ... -- way:0d vpn:0x0006d000 phys:0x02020000 pid:0x42 flags:rw--c After flushing TLB mappings for pid:0x42: dump tlb-entries for line=0xd (addr 000d0000): -- way:09 vpn:0x0006d000 phys:0x01145000 pid:0x00 flags:rw--c ... -- way:0d vpn:0x0006d000 phys:0x00000000 pid:0x00 flags:----- As functions such as replace_tlb_one_pid operate on the assumption of unique mappings, this can cause repeated pagefaults for a single address that are not covered by the existing spurious pagefault handling. This commit fixes this issue by keeping the pid field of the entries when flushing. That way, no conflicting mappings are introduced as the pair of <address,pid> is now kept unique: Fixed example after flushing TLB mappings for pid:0x42: dump tlb-entries for line=0xd (addr 000d0000): -- way:09 vpn:0x0006d000 phys:0x01145000 pid:0x00 flags:rw--c ... -- way:0d vpn:0x0006d000 phys:0x00000000 pid:0x42 flags:----- When flushing the complete tlb/initialising all entries, the way is used as a substitute mmu pid value for the "invalid" entries. Signed-off-by: Simon Schuster <schuster.simon@siemens-energy.com> Signed-off-by: Andreas Oetken <andreas.oetken@siemens-energy.com> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
1 parent 2d8a317 commit 83ab598

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

arch/nios2/mm/tlb.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,11 @@ static void flush_tlb_one(unsigned long addr)
144144
if (((pteaddr >> 2) & 0xfffff) != (addr >> PAGE_SHIFT))
145145
continue;
146146

147+
tlbmisc = RDCTL(CTL_TLBMISC);
147148
pr_debug("Flush entry by writing way=%dl pid=%ld\n",
148-
way, (pid_misc >> TLBMISC_PID_SHIFT));
149+
way, ((tlbmisc >> TLBMISC_PID_SHIFT) & TLBMISC_PID_MASK));
149150

150-
tlbmisc = TLBMISC_WE | (way << TLBMISC_WAY_SHIFT);
151+
tlbmisc = TLBMISC_WE | (way << TLBMISC_WAY_SHIFT) | (tlbmisc & TLBMISC_PID);
151152
WRCTL(CTL_TLBMISC, tlbmisc);
152153
WRCTL(CTL_PTEADDR, pteaddr_invalid(addr));
153154
WRCTL(CTL_TLBACC, 0);
@@ -237,7 +238,8 @@ void flush_tlb_pid(unsigned long mmu_pid)
237238
if (pid != mmu_pid)
238239
continue;
239240

240-
tlbmisc = TLBMISC_WE | (way << TLBMISC_WAY_SHIFT);
241+
tlbmisc = TLBMISC_WE | (way << TLBMISC_WAY_SHIFT) |
242+
(pid << TLBMISC_PID_SHIFT);
241243
WRCTL(CTL_TLBMISC, tlbmisc);
242244
WRCTL(CTL_TLBACC, 0);
243245
}
@@ -272,15 +274,17 @@ void flush_tlb_all(void)
272274
/* remember pid/way until we return */
273275
get_misc_and_pid(&org_misc, &pid_misc);
274276

275-
/* Start at way 0, way is auto-incremented after each TLBACC write */
276-
WRCTL(CTL_TLBMISC, TLBMISC_WE);
277-
278277
/* Map each TLB entry to physcal address 0 with no-access and a
279278
bad ptbase */
280279
for (line = 0; line < cpuinfo.tlb_num_lines; line++) {
281280
WRCTL(CTL_PTEADDR, pteaddr_invalid(addr));
282-
for (way = 0; way < cpuinfo.tlb_num_ways; way++)
281+
for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
282+
// Code such as replace_tlb_one_pid assumes that no duplicate entries exist
283+
// for a single address across ways, so also use way as a dummy PID
284+
WRCTL(CTL_TLBMISC, TLBMISC_WE | (way << TLBMISC_WAY_SHIFT) |
285+
(way << TLBMISC_PID_SHIFT));
283286
WRCTL(CTL_TLBACC, 0);
287+
}
284288

285289
addr += PAGE_SIZE;
286290
}

0 commit comments

Comments
 (0)