From nobody Sun May 12 21:32:11 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1710382010158475.7830474895321; Wed, 13 Mar 2024 19:06:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rkaTm-00074p-RH; Wed, 13 Mar 2024 22:05:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rkaTk-00074f-IL for qemu-devel@nongnu.org; Wed, 13 Mar 2024 22:05:56 -0400 Received: from mail.loongson.cn ([114.242.206.163]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rkaTh-0001Rl-Rf for qemu-devel@nongnu.org; Wed, 13 Mar 2024 22:05:56 -0400 Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8Dxfet6W_Jl4u4YAA--.60135S3; Thu, 14 Mar 2024 10:05:46 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8AxRMx4W_JlOGpZAA--.30074S2; Thu, 14 Mar 2024 10:05:44 +0800 (CST) From: Xianglai Li To: qemu-devel@nongnu.org, gaosong@loongson.cn Cc: richard.henderson@linaro.org, maobibo@loongson.cn, yangxiaojuan@loongson.cn, zhaotianrui@loongson.cn, yijun@loongson.cn, wuruiyang@loongson.cn, lixianglai@loongson.cn Subject: [PATCH V4] target/loongarch: Fixed tlb huge page loading issue Date: Thu, 14 Mar 2024 10:05:44 +0800 Message-Id: <20240314020544.672907-1-lixianglai@loongson.cn> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8AxRMx4W_JlOGpZAA--.30074S2 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=114.242.206.163; envelope-from=lixianglai@loongson.cn; helo=mail.loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1710382011208100001 Content-Type: text/plain; charset="utf-8" When we use qemu tcg simulation, the page size of bios is 4KB. When using the level 2 super large page (page size is 1G) to create the pag= e table, it is found that the content of the corresponding address space is abnormal, resulting in the bios can not start the operating system and graphical inte= rface normally. The lddir and ldpte instruction emulation has a problem with the use of super large page processing above level 2. The page size is not correctly calculated, resulting in the wrong page size of the table entry found by tlb. Signed-off-by: Xianglai Li --- target/loongarch/cpu-csr.h | 3 + target/loongarch/internals.h | 5 -- target/loongarch/tcg/tlb_helper.c | 105 ++++++++++++++++++++---------- 3 files changed, 74 insertions(+), 39 deletions(-) Changes log: V3->V4: Optimize the huge page calculation method, use the FIELD macro for bit calculation. V2->V3: Delete the intermediate variable LDDIR_PS, and implement lddir and ldpte huge pages by referring to the latest architecture reference manual. V1->V2: Modified the patch title format and Enrich the commit mesg description diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h index c59d7a9fcb..b0775cf6bf 100644 --- a/target/loongarch/cpu-csr.h +++ b/target/loongarch/cpu-csr.h @@ -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, HG, 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) diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index a2fc54c8a7..944153b180 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -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) =20 -/* 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); =20 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_h= elper.c index 22be031ac7..b9a8633791 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -17,6 +17,34 @@ #include "exec/log.h" #include "cpu-csr.h" =20 +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 =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE); + *dir_width =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); + break; + case 2: + *dir_base =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE); + *dir_width =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH); + break; + case 3: + *dir_base =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE); + *dir_width =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); + break; + case 4: + *dir_base =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE); + *dir_width =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH); + break; + default: + /* level may be zero for ldpte */ + *dir_base =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); + *dir_width =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + break; + } +} + static void raise_mmu_exception(CPULoongArchState *env, target_ulong addre= ss, MMUAccessType access_type, int tlb_error) { @@ -485,7 +513,23 @@ target_ulong helper_lddir(CPULoongArchState *env, targ= et_ulong base, target_ulong badvaddr, index, phys, ret; int shift; uint64_t dir_base, dir_width; - bool huge =3D (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1; + + if (unlikely((level =3D=3D 0) || (level > 4))) { + return base; + } + + if (FIELD_EX64(base, TLBENTRY, HUGE)) { + if (FIELD_EX64(base, TLBENTRY, LEVEL)) { + return base; + } else { + return FIELD_DP64(base, TLBENTRY, LEVEL, level); + } + + if (unlikely(level =3D=3D 4)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Attempted use of level %lu huge page\n", level); + } + } =20 badvaddr =3D env->CSR_TLBRBADV; base =3D base & TARGET_PHYS_MASK; @@ -494,33 +538,12 @@ target_ulong helper_lddir(CPULoongArchState *env, tar= get_ulong base, shift =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH); shift =3D (shift + 1) * 3; =20 - if (huge) { - return base; - } - switch (level) { - case 1: - dir_base =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE); - dir_width =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); - break; - case 2: - dir_base =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE); - dir_width =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH); - break; - case 3: - dir_base =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE); - dir_width =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); - break; - case 4: - dir_base =3D FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE); - dir_width =3D 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 =3D (badvaddr >> dir_base) & ((1 << dir_width) - 1); phys =3D base | index << shift; ret =3D ldq_phys(cs->as, phys) & TARGET_PHYS_MASK; + return ret; } =20 @@ -530,20 +553,34 @@ void helper_ldpte(CPULoongArchState *env, target_ulon= g base, target_ulong odd, CPUState *cs =3D env_cpu(env); target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv; int shift; - bool huge =3D (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1; uint64_t ptbase =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); uint64_t ptwidth =3D FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + uint64_t dir_base, dir_width; =20 base =3D 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 address + * Clears huge page bit + */ + get_dir_base_width(env, &dir_base, &dir_width, + FIELD_EX64(base, TLBENTRY, LEVEL)); + + FIELD_DP64(base, TLBENTRY, LEVEL, 0); + FIELD_DP64(base, TLBENTRY, HUGE, 0); + if (FIELD_EX64(base, TLBENTRY, HG)) { + FIELD_DP64(base, TLBENTRY, HG, 0); + FIELD_DP64(base, TLBENTRY, G, 1); + } =20 - if (huge) { - /* Huge Page. base is paddr */ - tmp0 =3D base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT); - /* Move Global bit */ - tmp0 =3D ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT)) >> - LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT | - (tmp0 & (~(1 << LOONGARCH_HGLOBAL_SHIFT))); - ps =3D ptbase + ptwidth - 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. + */ + ps =3D dir_base + dir_width - 1; + tmp0 =3D base; if (odd) { tmp0 +=3D MAKE_64BIT_MASK(ps, 1); } --=20 2.39.1