162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef __ASM_TLB_H
662306a36Sopenharmony_ci#define __ASM_TLB_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/mm_types.h>
962306a36Sopenharmony_ci#include <asm/cpu-features.h>
1062306a36Sopenharmony_ci#include <asm/loongarch.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * TLB Invalidate Flush
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_cistatic inline void tlbclr(void)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	__asm__ __volatile__("tlbclr");
1862306a36Sopenharmony_ci}
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic inline void tlbflush(void)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	__asm__ __volatile__("tlbflush");
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * TLB R/W operations.
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_cistatic inline void tlb_probe(void)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	__asm__ __volatile__("tlbsrch");
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic inline void tlb_read(void)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	__asm__ __volatile__("tlbrd");
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic inline void tlb_write_indexed(void)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	__asm__ __volatile__("tlbwr");
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic inline void tlb_write_random(void)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	__asm__ __volatile__("tlbfill");
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cienum invtlb_ops {
4962306a36Sopenharmony_ci	/* Invalid all tlb */
5062306a36Sopenharmony_ci	INVTLB_ALL = 0x0,
5162306a36Sopenharmony_ci	/* Invalid current tlb */
5262306a36Sopenharmony_ci	INVTLB_CURRENT_ALL = 0x1,
5362306a36Sopenharmony_ci	/* Invalid all global=1 lines in current tlb */
5462306a36Sopenharmony_ci	INVTLB_CURRENT_GTRUE = 0x2,
5562306a36Sopenharmony_ci	/* Invalid all global=0 lines in current tlb */
5662306a36Sopenharmony_ci	INVTLB_CURRENT_GFALSE = 0x3,
5762306a36Sopenharmony_ci	/* Invalid global=0 and matched asid lines in current tlb */
5862306a36Sopenharmony_ci	INVTLB_GFALSE_AND_ASID = 0x4,
5962306a36Sopenharmony_ci	/* Invalid addr with global=0 and matched asid in current tlb */
6062306a36Sopenharmony_ci	INVTLB_ADDR_GFALSE_AND_ASID = 0x5,
6162306a36Sopenharmony_ci	/* Invalid addr with global=1 or matched asid in current tlb */
6262306a36Sopenharmony_ci	INVTLB_ADDR_GTRUE_OR_ASID = 0x6,
6362306a36Sopenharmony_ci	/* Invalid matched gid in guest tlb */
6462306a36Sopenharmony_ci	INVGTLB_GID = 0x9,
6562306a36Sopenharmony_ci	/* Invalid global=1, matched gid in guest tlb */
6662306a36Sopenharmony_ci	INVGTLB_GID_GTRUE = 0xa,
6762306a36Sopenharmony_ci	/* Invalid global=0, matched gid in guest tlb */
6862306a36Sopenharmony_ci	INVGTLB_GID_GFALSE = 0xb,
6962306a36Sopenharmony_ci	/* Invalid global=0, matched gid and asid in guest tlb */
7062306a36Sopenharmony_ci	INVGTLB_GID_GFALSE_ASID = 0xc,
7162306a36Sopenharmony_ci	/* Invalid global=0 , matched gid, asid and addr in guest tlb */
7262306a36Sopenharmony_ci	INVGTLB_GID_GFALSE_ASID_ADDR = 0xd,
7362306a36Sopenharmony_ci	/* Invalid global=1 , matched gid, asid and addr in guest tlb */
7462306a36Sopenharmony_ci	INVGTLB_GID_GTRUE_ASID_ADDR = 0xe,
7562306a36Sopenharmony_ci	/* Invalid all gid gva-->gpa guest tlb */
7662306a36Sopenharmony_ci	INVGTLB_ALLGID_GVA_TO_GPA = 0x10,
7762306a36Sopenharmony_ci	/* Invalid all gid gpa-->hpa tlb */
7862306a36Sopenharmony_ci	INVTLB_ALLGID_GPA_TO_HPA = 0x11,
7962306a36Sopenharmony_ci	/* Invalid all gid tlb, including  gva-->gpa and gpa-->hpa */
8062306a36Sopenharmony_ci	INVTLB_ALLGID = 0x12,
8162306a36Sopenharmony_ci	/* Invalid matched gid gva-->gpa guest tlb */
8262306a36Sopenharmony_ci	INVGTLB_GID_GVA_TO_GPA = 0x13,
8362306a36Sopenharmony_ci	/* Invalid matched gid gpa-->hpa tlb */
8462306a36Sopenharmony_ci	INVTLB_GID_GPA_TO_HPA = 0x14,
8562306a36Sopenharmony_ci	/* Invalid matched gid tlb,including gva-->gpa and gpa-->hpa */
8662306a36Sopenharmony_ci	INVTLB_GID_ALL = 0x15,
8762306a36Sopenharmony_ci	/* Invalid matched gid and addr gpa-->hpa tlb */
8862306a36Sopenharmony_ci	INVTLB_GID_ADDR = 0x16,
8962306a36Sopenharmony_ci};
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic __always_inline void invtlb(u32 op, u32 info, u64 addr)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	__asm__ __volatile__(
9462306a36Sopenharmony_ci		"invtlb %0, %1, %2\n\t"
9562306a36Sopenharmony_ci		:
9662306a36Sopenharmony_ci		: "i"(op), "r"(info), "r"(addr)
9762306a36Sopenharmony_ci		: "memory"
9862306a36Sopenharmony_ci		);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic __always_inline void invtlb_addr(u32 op, u32 info, u64 addr)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0);
10462306a36Sopenharmony_ci	__asm__ __volatile__(
10562306a36Sopenharmony_ci		"invtlb %0, $zero, %1\n\t"
10662306a36Sopenharmony_ci		:
10762306a36Sopenharmony_ci		: "i"(op), "r"(addr)
10862306a36Sopenharmony_ci		: "memory"
10962306a36Sopenharmony_ci		);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic __always_inline void invtlb_info(u32 op, u32 info, u64 addr)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0);
11562306a36Sopenharmony_ci	__asm__ __volatile__(
11662306a36Sopenharmony_ci		"invtlb %0, %1, $zero\n\t"
11762306a36Sopenharmony_ci		:
11862306a36Sopenharmony_ci		: "i"(op), "r"(info)
11962306a36Sopenharmony_ci		: "memory"
12062306a36Sopenharmony_ci		);
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic __always_inline void invtlb_all(u32 op, u32 info, u64 addr)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0);
12662306a36Sopenharmony_ci	BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0);
12762306a36Sopenharmony_ci	__asm__ __volatile__(
12862306a36Sopenharmony_ci		"invtlb %0, $zero, $zero\n\t"
12962306a36Sopenharmony_ci		:
13062306a36Sopenharmony_ci		: "i"(op)
13162306a36Sopenharmony_ci		: "memory"
13262306a36Sopenharmony_ci		);
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic void tlb_flush(struct mmu_gather *tlb);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci#define tlb_flush tlb_flush
14062306a36Sopenharmony_ci#include <asm-generic/tlb.h>
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic inline void tlb_flush(struct mmu_gather *tlb)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	struct vm_area_struct vma;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	vma.vm_mm = tlb->mm;
14762306a36Sopenharmony_ci	vm_flags_init(&vma, 0);
14862306a36Sopenharmony_ci	if (tlb->fullmm) {
14962306a36Sopenharmony_ci		flush_tlb_mm(tlb->mm);
15062306a36Sopenharmony_ci		return;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	flush_tlb_range(&vma, tlb->start, tlb->end);
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ciextern void handle_tlb_load(void);
15762306a36Sopenharmony_ciextern void handle_tlb_store(void);
15862306a36Sopenharmony_ciextern void handle_tlb_modify(void);
15962306a36Sopenharmony_ciextern void handle_tlb_refill(void);
16062306a36Sopenharmony_ciextern void handle_tlb_protect(void);
16162306a36Sopenharmony_ciextern void handle_tlb_load_ptw(void);
16262306a36Sopenharmony_ciextern void handle_tlb_store_ptw(void);
16362306a36Sopenharmony_ciextern void handle_tlb_modify_ptw(void);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ciextern void dump_tlb_all(void);
16662306a36Sopenharmony_ciextern void dump_tlb_regs(void);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci#endif /* __ASM_TLB_H */
169