Add op 0x9, 0xa-0xf to instruction invtlb to support vm level 1.
Signed-off-by: SignKirigami <[email protected]>
Signed-off-by: Hengyu Yu <[email protected]>
---
.../tcg/insn_trans/trans_privileged.c.inc | 34 +++++++++++++
target/loongarch/tcg/tlb_helper.c | 51 ++++++++++++++++---
2 files changed, 77 insertions(+), 8 deletions(-)
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index 493ed7f24b..00e8f61e42 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -328,6 +328,10 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
return false;
}
+ if (!avail_LVZ(ctx) && a->imm > 0x6) {
+ return false;
+ }
+
switch (a->imm) {
case 0x0:
case 0x1:
@@ -352,6 +356,36 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
gen_helper_invtlb_page_asid_or_g(tcg_env, rj, rk,
tcg_constant_i32(0));
break;
+ case 0x9:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ //TODO: refine 0x9-0x16
+ gen_helper_invtlb_all(tcg_env, rj, tcg_constant_i32(0),
+ tcg_constant_i32(0));
+ break;
+ case 0xa:
+ gen_helper_invtlb_all_g(tcg_env, rj, tcg_constant_i32(1),
+ tcg_constant_i32(1));
+ break;
+ case 0xb:
+ gen_helper_invtlb_all_g(tcg_env, rj, tcg_constant_i32(0),
+ tcg_constant_i32(1));
+ break;
+ case 0xc:
+ gen_helper_invtlb_all_asid(tcg_env, rj, tcg_constant_i32(1));
+ break;
+ case 0xd:
+ gen_helper_invtlb_page_asid(tcg_env, rj, rk, tcg_constant_i32(1));
+ break;
+ case 0xe:
+ gen_helper_invtlb_page_asid_or_g(tcg_env, rj, rk,
+ tcg_constant_i32(1));
+ break;
default:
return false;
}
diff --git a/target/loongarch/tcg/tlb_helper.c
b/target/loongarch/tcg/tlb_helper.c
index 60c7193283..c02b7c2472 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -599,9 +599,18 @@ void helper_tlbflush(CPULoongArchState *env, uint32_t
vm_level)
void helper_invtlb_all(CPULoongArchState *env, target_ulong info, uint32_t op,
uint32_t to_guest)
{
+ uint16_t gid = to_guest ? (info & 0xff) : get_tgid(env);
+
+ if (to_guest && env_vm_level(env) == VM_LEVEL1) {
+ do_raise_exception(env, EXCCODE_IPE, GETPC());
+ }
+
+ to_guest |= env_vm_level(env) == VM_LEVEL1;
+
for (int i = 0; i < LOONGARCH_TLB_MAX; i++) {
- env->tlb[i].tlb_misc = FIELD_DP64(env->tlb[i].tlb_misc,
- TLB_MISC, E, 0);
+ LoongArchTLB *tlb = &env->tlb[i];
+ if ((op == 0 && to_guest == 0) || tlb_entry_matches_gid(tlb, gid))
+ tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
}
tlb_flush(env_cpu(env));
}
@@ -609,11 +618,19 @@ void helper_invtlb_all(CPULoongArchState *env,
target_ulong info, uint32_t op,
void helper_invtlb_all_g(CPULoongArchState *env, target_ulong info, uint32_t g,
uint32_t to_guest)
{
+ uint16_t gid = to_guest ? (info & 0xff) : get_tgid(env);
+
+ if (to_guest && env_vm_level(env) == VM_LEVEL1) {
+ do_raise_exception(env, EXCCODE_IPE, GETPC());
+ }
+
+ to_guest |= env_vm_level(env) == VM_LEVEL1;
+
for (int i = 0; i < LOONGARCH_TLB_MAX; i++) {
LoongArchTLB *tlb = &env->tlb[i];
uint8_t tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
- if (tlb_g == g) {
+ if (tlb_g == g && tlb_entry_matches_gid(tlb, gid)) {
tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
}
}
@@ -624,13 +641,19 @@ void helper_invtlb_all_asid(CPULoongArchState *env,
target_ulong info,
uint32_t to_guest)
{
uint16_t asid = info & R_CSR_ASID_ASID_MASK;
+ uint16_t gid = to_guest ? ((info >> 16) & 0xff) : get_tgid(env);
+
+ if (to_guest) {
+ do_raise_exception(env, EXCCODE_IPE, GETPC());
+ }
+ to_guest |= env_vm_level(env);
for (int i = 0; i < LOONGARCH_TLB_MAX; i++) {
LoongArchTLB *tlb = &env->tlb[i];
uint8_t tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- if (!tlb_g && (tlb_asid == asid)) {
+ if (!tlb_g && tlb_asid == asid && tlb_entry_matches_gid(tlb, gid)) {
tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
}
}
@@ -640,12 +663,19 @@ void helper_invtlb_all_asid(CPULoongArchState *env,
target_ulong info,
void helper_invtlb_page_asid(CPULoongArchState *env, target_ulong info,
target_ulong addr, uint32_t to_guest)
{
- int asid = info & 0x3ff;
+
+ uint16_t asid = info & R_CSR_ASID_ASID_MASK;
+ uint16_t gid = to_guest ? ((info >> 16) & 0xff) : get_tgid(env);
const LoongArchTLB *tlb;
tlb_match func;
+ if (to_guest && env_vm_level(env)) {
+ do_raise_exception(env, EXCCODE_IPE, GETPC());
+ }
+ to_guest |= env_vm_level(env);
+
func = tlb_match_asid;
- tlb = loongarch_tlb_search_cb(env, addr, asid, func, to_guest, 0);
+ tlb = loongarch_tlb_search_cb(env, addr, asid, func, to_guest, gid);
if (tlb) {
invalidate_tlb(env, tlb - env->tlb, to_guest);
}
@@ -654,13 +684,18 @@ void helper_invtlb_page_asid(CPULoongArchState *env,
target_ulong info,
void helper_invtlb_page_asid_or_g(CPULoongArchState *env, target_ulong info,
target_ulong addr, uint32_t to_guest)
{
- int asid = info & 0x3ff;
+ uint16_t asid = info & R_CSR_ASID_ASID_MASK;
+ uint16_t gid = to_guest ? ((info >> 16) & 0xff) : get_tgid(env);
const LoongArchTLB *tlb;
tlb_match func;
func = tlb_match_any;
+ if (to_guest) {
+ do_raise_exception(env, EXCCODE_IPE, GETPC());
+ }
+ to_guest |= env_vm_level(env);
tlb = loongarch_tlb_search_cb(env, addr, asid, func,
- to_guest, 0);
+ to_guest, gid);
if (tlb) {
invalidate_tlb(env, tlb - env->tlb, to_guest);
}
--
2.55.0