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:
Peter Maydell 2024-03-20 12:01:45 +00:00
commit e4ef2a09f3
5 changed files with 87 additions and 44 deletions

View file

@ -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
*/

View file

@ -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)

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}