pull-loongarch-20240320
-----BEGIN PGP SIGNATURE----- iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZfpIrAAKCRBAov/yOSY+ 35awBADHgwP1HHS+fo4myPqDzcH2JMiGH9ra3ORSvEe036whqdttzx4tkxey7sTj 2QKd326tUJ1jBxnVabN9on0csM4xl6AGBBjRTmEEBaCFp0Nulu4W4tMxeTTdfkZK jUUs+1VVQLwmcFULGtbB91uiYF7RsJzVIBpAD5oVe/pF9046Hg== =Y6la -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20240320' of https://gitlab.com/gaosong/qemu into staging pull-loongarch-20240320 # -----BEGIN PGP SIGNATURE----- # # iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZfpIrAAKCRBAov/yOSY+ # 35awBADHgwP1HHS+fo4myPqDzcH2JMiGH9ra3ORSvEe036whqdttzx4tkxey7sTj # 2QKd326tUJ1jBxnVabN9on0csM4xl6AGBBjRTmEEBaCFp0Nulu4W4tMxeTTdfkZK # jUUs+1VVQLwmcFULGtbB91uiYF7RsJzVIBpAD5oVe/pF9046Hg== # =Y6la # -----END PGP SIGNATURE----- # gpg: Signature made Wed 20 Mar 2024 02:23:40 GMT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF * tag 'pull-loongarch-20240320' of https://gitlab.com/gaosong/qemu: target/loongarch: Fix qemu-loongarch64 hang when executing 'll.d $t0, $t0, 0' target/loongarch: Fix tlb huge page loading issue hw/intc/loongarch_extioi: Fix interrupt routing update Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e4ef2a09f3
@ -151,7 +151,7 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (notify && test_bit(irq, (unsigned long *)s->isr)) {
|
||||
if (notify && test_bit(irq + i, (unsigned long *)s->isr)) {
|
||||
/*
|
||||
* lower irq at old cpu and raise irq at new cpu
|
||||
*/
|
||||
|
@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1)
|
||||
FIELD(TLBENTRY, PLV, 2, 2)
|
||||
FIELD(TLBENTRY, MAT, 4, 2)
|
||||
FIELD(TLBENTRY, G, 6, 1)
|
||||
FIELD(TLBENTRY, HUGE, 6, 1)
|
||||
FIELD(TLBENTRY, HGLOBAL, 12, 1)
|
||||
FIELD(TLBENTRY, LEVEL, 13, 2)
|
||||
FIELD(TLBENTRY_32, PPN, 8, 24)
|
||||
FIELD(TLBENTRY_64, PPN, 12, 36)
|
||||
FIELD(TLBENTRY_64, NR, 61, 1)
|
||||
|
@ -16,11 +16,6 @@
|
||||
#define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
|
||||
#define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
|
||||
|
||||
/* Global bit used for lddir/ldpte */
|
||||
#define LOONGARCH_PAGE_HUGE_SHIFT 6
|
||||
/* Global bit for huge page */
|
||||
#define LOONGARCH_HGLOBAL_SHIFT 12
|
||||
|
||||
void loongarch_translate_init(void);
|
||||
|
||||
void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||
|
@ -5,14 +5,14 @@
|
||||
|
||||
static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop)
|
||||
{
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv t0 = make_address_i(ctx, src1, a->imm);
|
||||
|
||||
tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop);
|
||||
tcg_gen_qemu_ld_i64(t1, t0, ctx->mem_idx, mop);
|
||||
tcg_gen_st_tl(t0, tcg_env, offsetof(CPULoongArchState, lladdr));
|
||||
tcg_gen_st_tl(dest, tcg_env, offsetof(CPULoongArchState, llval));
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
tcg_gen_st_tl(t1, tcg_env, offsetof(CPULoongArchState, llval));
|
||||
gen_set_gpr(a->rd, t1, EXT_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -17,6 +17,34 @@
|
||||
#include "exec/log.h"
|
||||
#include "cpu-csr.h"
|
||||
|
||||
static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
|
||||
uint64_t *dir_width, target_ulong level)
|
||||
{
|
||||
switch (level) {
|
||||
case 1:
|
||||
*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
|
||||
*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
|
||||
break;
|
||||
case 2:
|
||||
*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
|
||||
*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
|
||||
break;
|
||||
case 3:
|
||||
*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
|
||||
*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
|
||||
break;
|
||||
case 4:
|
||||
*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
|
||||
*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
|
||||
break;
|
||||
default:
|
||||
/* level may be zero for ldpte */
|
||||
*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
|
||||
*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
|
||||
MMUAccessType access_type, int tlb_error)
|
||||
{
|
||||
@ -485,7 +513,25 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
|
||||
target_ulong badvaddr, index, phys, ret;
|
||||
int shift;
|
||||
uint64_t dir_base, dir_width;
|
||||
bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
|
||||
|
||||
if (unlikely((level == 0) || (level > 4))) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"Attepted LDDIR with level %"PRId64"\n", level);
|
||||
return base;
|
||||
}
|
||||
|
||||
if (FIELD_EX64(base, TLBENTRY, HUGE)) {
|
||||
if (unlikely(level == 4)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"Attempted use of level 4 huge page\n");
|
||||
}
|
||||
|
||||
if (FIELD_EX64(base, TLBENTRY, LEVEL)) {
|
||||
return base;
|
||||
} else {
|
||||
return FIELD_DP64(base, TLBENTRY, LEVEL, level);
|
||||
}
|
||||
}
|
||||
|
||||
badvaddr = env->CSR_TLBRBADV;
|
||||
base = base & TARGET_PHYS_MASK;
|
||||
@ -494,30 +540,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
|
||||
shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
|
||||
shift = (shift + 1) * 3;
|
||||
|
||||
if (huge) {
|
||||
return base;
|
||||
}
|
||||
switch (level) {
|
||||
case 1:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
|
||||
break;
|
||||
case 2:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
|
||||
break;
|
||||
case 3:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
|
||||
break;
|
||||
case 4:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
|
||||
break;
|
||||
default:
|
||||
do_raise_exception(env, EXCCODE_INE, GETPC());
|
||||
return 0;
|
||||
}
|
||||
get_dir_base_width(env, &dir_base, &dir_width, level);
|
||||
index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
|
||||
phys = base | index << shift;
|
||||
ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
|
||||
@ -530,20 +553,42 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
|
||||
CPUState *cs = env_cpu(env);
|
||||
target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv;
|
||||
int shift;
|
||||
bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
|
||||
uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
|
||||
uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
|
||||
uint64_t dir_base, dir_width;
|
||||
|
||||
/*
|
||||
* The parameter "base" has only two types,
|
||||
* one is the page table base address,
|
||||
* whose bit 6 should be 0,
|
||||
* and the other is the huge page entry,
|
||||
* whose bit 6 should be 1.
|
||||
*/
|
||||
base = base & TARGET_PHYS_MASK;
|
||||
if (FIELD_EX64(base, TLBENTRY, HUGE)) {
|
||||
/*
|
||||
* Gets the huge page level and Gets huge page size.
|
||||
* Clears the huge page level information in the entry.
|
||||
* Clears huge page bit.
|
||||
* Move HGLOBAL bit to GLOBAL bit.
|
||||
*/
|
||||
get_dir_base_width(env, &dir_base, &dir_width,
|
||||
FIELD_EX64(base, TLBENTRY, LEVEL));
|
||||
|
||||
if (huge) {
|
||||
/* Huge Page. base is paddr */
|
||||
tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT);
|
||||
/* Move Global bit */
|
||||
tmp0 = ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT)) >>
|
||||
LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT |
|
||||
(tmp0 & (~(1 << LOONGARCH_HGLOBAL_SHIFT)));
|
||||
ps = ptbase + ptwidth - 1;
|
||||
base = FIELD_DP64(base, TLBENTRY, LEVEL, 0);
|
||||
base = FIELD_DP64(base, TLBENTRY, HUGE, 0);
|
||||
if (FIELD_EX64(base, TLBENTRY, HGLOBAL)) {
|
||||
base = FIELD_DP64(base, TLBENTRY, HGLOBAL, 0);
|
||||
base = FIELD_DP64(base, TLBENTRY, G, 1);
|
||||
}
|
||||
|
||||
ps = dir_base + dir_width - 1;
|
||||
/*
|
||||
* Huge pages are evenly split into parity pages
|
||||
* when loaded into the tlb,
|
||||
* so the tlb page size needs to be divided by 2.
|
||||
*/
|
||||
tmp0 = base;
|
||||
if (odd) {
|
||||
tmp0 += MAKE_64BIT_MASK(ps, 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user