From patchwork Tue Oct 19 07:34:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568831 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD2E3C433FE for ; Tue, 19 Oct 2021 07:37:34 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 523CF60FDA for ; Tue, 19 Oct 2021 07:37:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 523CF60FDA Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:36172 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjgj-000414-FQ for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:37:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55848) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjew-0001GP-MD for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:43 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34670 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjes-0004Ni-DU for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S4; Tue, 19 Oct 2021 15:35:25 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 02/31] target/loongarch: Add CSR registers definition Date: Tue, 19 Oct 2021 15:34:48 +0800 Message-Id: <1634628917-10031-3-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S4 X-Coremail-Antispam: 1UD129KBjvAXoWfJFW5Kw4UCw1xZr4rXryfCrg_yoW8AFyrJo W8Wa13Gw45Jw4a9wsrGry7Xa1UAryxC3WkZ3WDWFy0v3Z7Ga98WFn0y3yUZa13XryYgryr uFnrKFn5CayDAryDn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch define All the CSR registers and its field. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu-csr.h | 493 +++++++++++++++++++++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 target/loongarch/cpu-csr.h diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h new file mode 100644 index 0000000000..26fef4079d --- /dev/null +++ b/target/loongarch/cpu-csr.h @@ -0,0 +1,493 @@ +/* + * QEMU LoongArch CPU CSR registers + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_CPU_CSR_H +#define LOONGARCH_CPU_CSR_H + +/* Base on: kernal: arch/loongarch/include/asm/loongarch.h */ + +/* Basic CSR register */ +#define LOONGARCH_CSR_CRMD 0x0 /* Current mode info */ +FIELD(CSR_CRMD, PLV, 0, 2) +FIELD(CSR_CRMD, IE, 2, 1) +FIELD(CSR_CRMD, DA, 3, 1) +FIELD(CSR_CRMD, PG, 4, 1) +FIELD(CSR_CRMD, DATF, 5, 2) +FIELD(CSR_CRMD, DATM, 7, 2) +FIELD(CSR_CRMD, WE, 9, 1) + +#define LOONGARCH_CSR_PRMD 0x1 /* Prev-exception mode info */ +FIELD(CSR_PRMD, PPLV, 0, 2) +FIELD(CSR_PRMD, PIE, 2, 1) +FIELD(CSR_PRMD, PWE, 3, 1) + +#define LOONGARCH_CSR_EUEN 0x2 /* Extended unit enable */ +FIELD(CSR_EUEN, FPE, 0, 1) +FIELD(CSR_EUEN, SXE, 1, 1) +FIELD(CSR_EUEN, ASXE, 2, 1) +FIELD(CSR_EUEN, BTE, 3, 1) + +#define LOONGARCH_CSR_MISC 0x3 /* Misc config */ + +#define LOONGARCH_CSR_ECFG 0x4 /* Exception config */ +FIELD(CSR_ECFG, LIE, 0, 13) +FIELD(CSR_ECFG, VS, 16, 3) + +#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */ +FIELD(CSR_ESTAT, IS, 0, 13) +FIELD(CSR_ESTAT, ECODE, 16, 6) +FIELD(CSR_ESTAT, ESUBCODE, 22, 9) + +#define EXCODE_IP 64 +#define EXCCODE_INT 0 +#define EXCCODE_PIL 1 +#define EXCCODE_PIS 2 +#define EXCCODE_PIF 3 +#define EXCCODE_PME 4 +#define EXCCODE_PNR 5 +#define EXCCODE_PNX 6 +#define EXCCODE_PPI 7 +#define EXCCODE_ADEF 8 /* Have different expsubcode */ +#define EXCCODE_ADEM 8 +#define EXCCODE_ALE 9 +#define EXCCODE_BCE 10 +#define EXCCODE_SYS 11 +#define EXCCODE_BRK 12 +#define EXCCODE_INE 13 +#define EXCCODE_IPE 14 +#define EXCCODE_FPD 15 +#define EXCCODE_SXD 16 +#define EXCCODE_ASXD 17 +#define EXCCODE_FPE 18 /* Have different expsubcode */ +#define EXCCODE_VFPE 18 +#define EXCCODE_WPEF 19 /* Have different expsubcode */ +#define EXCCODE_WPEM 19 +#define EXCCODE_BTD 20 +#define EXCCODE_BTE 21 + +#define LOONGARCH_CSR_ERA 0x6 /* ERA */ + +#define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */ + +#define LOONGARCH_CSR_BADI 0x8 /* Bad instruction */ + +#define LOONGARCH_CSR_EENTRY 0xc /* Exception enter base address */ + +/* TLB related CSR register */ +#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */ +FIELD(CSR_TLBIDX, INDEX, 0, 12) +FIELD(CSR_TLBIDX, PS, 24, 6) +FIELD(CSR_TLBIDX, NE, 31, 1) + +#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi without ASID */ + +#define LOONGARCH_CSR_TLBELO0 0x12 /* TLB EntryLo0 */ +FIELD(CSR_TLBELO0, V, 0, 1) +FIELD(CSR_TLBELO0, D, 1, 1) +FIELD(CSR_TLBELO0, PLV, 2, 2) +FIELD(CSR_TLBELO0, MAT, 4, 2) +FIELD(CSR_TLBELO0, G, 6, 1) +FIELD(CSR_TLBELO0, PPN, 12, 36) +FIELD(CSR_TLBELO0, NR, 61, 1) +FIELD(CSR_TLBELO0, NX, 62, 1) +FIELD(CSR_TLBELO0, RPLV, 63, 1) + +#define LOONGARCH_CSR_TLBELO1 0x13 /* 64 TLB EntryLo1 */ +FIELD(CSR_TLBELO1, V, 0, 1) +FIELD(CSR_TLBELO1, D, 1, 1) +FIELD(CSR_TLBELO1, PLV, 2, 2) +FIELD(CSR_TLBELO1, MAT, 4, 2) +FIELD(CSR_TLBELO1, G, 6, 1) +FIELD(CSR_TLBELO1, PPN, 12, 36) +FIELD(CSR_TLBELO1, NR, 61, 1) +FIELD(CSR_TLBELO1, NX, 62, 1) +FIELD(CSR_TLBELO1, RPLV, 63, 1) + +#define LOONGARCH_CSR_ASID 0x18 /* ASID */ +FIELD(CSR_ASID, ASID, 0, 10) +FIELD(CSR_ASID, ASIDBITS, 16, 8) + +/* Page table base address when badv[47] = 0 */ +#define LOONGARCH_CSR_PGDL 0x19 +/* Page table base address when badv[47] = 1 */ +#define LOONGARCH_CSR_PGDH 0x1a + +#define LOONGARCH_CSR_PGD 0x1b /* Page table base */ + +#define LOONGARCH_CSR_PWCL 0x1c /* PWCl */ +FIELD(CSR_PWCL, PTBASE, 0, 5) +FIELD(CSR_PWCL, PTWIDTH, 5, 5) +FIELD(CSR_PWCL, DIR1_BASE, 10, 5) +FIELD(CSR_PWCL, DIR1_WIDTH, 15, 5) +FIELD(CSR_PWCL, DIR2_BASE, 20, 5) +FIELD(CSR_PWCL, DIR2_WIDTH, 25, 5) +FIELD(CSR_PWCL, PTEWIDTH, 30, 2) + +#define LOONGARCH_CSR_PWCH 0x1d /* PWCh */ +FIELD(CSR_PWCH, DIR3_BASE, 0, 6) +FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6) +FIELD(CSR_PWCH, DIR4_BASE, 12, 6) +FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6) + +#define LOONGARCH_CSR_STLBPS 0x1e /* 64 */ + +#define LOONGARCH_CSR_RVACFG 0x1f + +/* Config CSR registers */ +#define LOONGARCH_CSR_CPUID 0x20 /* CPU core id */ + +#define LOONGARCH_CSR_PRCFG1 0x21 /* Config1 */ +FIELD(CSR_PRCFG1, SAVE_NUM, 0, 4) +FIELD(CSR_PRCFG1, TIMER_BITS, 4, 8) +FIELD(CSR_PRCFG1, VSMAX, 12, 3) + +#define LOONGARCH_CSR_PRCFG2 0x22 /* Config2 */ + +#define LOONGARCH_CSR_PRCFG3 0x23 /* Config3 */ +FIELD(CSR_PRCFG3, TLB_TYPE, 0, 4) +FIELD(CSR_PRCFG3, MTLB_ENTRY, 4, 8) +FIELD(CSR_PRCFG3, STLB_WAYS, 12, 8) +FIELD(CSR_PRCFG3, STLB_SETS, 20, 8) + +/* Kscratch registers */ +#define LOONGARCH_CSR_KS0 0x30 +#define LOONGARCH_CSR_KS1 0x31 +#define LOONGARCH_CSR_KS2 0x32 +#define LOONGARCH_CSR_KS3 0x33 +#define LOONGARCH_CSR_KS4 0x34 +#define LOONGARCH_CSR_KS5 0x35 +#define LOONGARCH_CSR_KS6 0x36 +#define LOONGARCH_CSR_KS7 0x37 +#define LOONGARCH_CSR_KS8 0x38 + +/* Timer registers */ +#define LOONGARCH_CSR_TMID 0x40 /* Timer ID */ + +#define LOONGARCH_CSR_TCFG 0x41 /* Timer config */ +FIELD(CSR_TCFG, EN, 0, 1) +FIELD(CSR_TCFG, PERIODIC, 1, 1) +FIELD(CSR_TCFG, INIT_VAL, 2, 46) + +#define LOONGARCH_CSR_TVAL 0x42 /* Timer ticks remain */ + +#define LOONGARCH_CSR_CNTC 0x43 /* Timer offset */ + +#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */ + +/* LLBCTL register */ +#define LOONGARCH_CSR_LLBCTL 0x60 /* LLBit control */ + +/* Implement dependent */ +#define LOONGARCH_CSR_IMPCTL1 0x80 /* Loongarch config1 */ + +#define LOONGARCH_CSR_IMPCTL2 0x81 /* Loongarch config2*/ + +/* TLB Refill registers */ +#define LOONGARCH_CSR_TLBRENTRY 0x88 /* TLB refill exception address */ +#define LOONGARCH_CSR_TLBRBADV 0x89 /* TLB refill badvaddr */ +#define LOONGARCH_CSR_TLBRERA 0x8a /* TLB refill ERA */ +#define LOONGARCH_CSR_TLBRSAVE 0x8b /* KScratch for TLB refill */ +#define LOONGARCH_CSR_TLBRELO0 0x8c /* TLB refill entrylo0 */ +#define LOONGARCH_CSR_TLBRELO1 0x8d /* TLB refill entrylo1 */ +#define LOONGARCH_CSR_TLBREHI 0x8e /* TLB refill entryhi */ +#define LOONGARCH_CSR_TLBRPRMD 0x8f /* TLB refill mode info */ +FIELD(CSR_TLBRPRMD, PPLV, 0, 2) +FIELD(CSR_TLBRPRMD, PIE, 2, 1) +FIELD(CSR_TLBRPRMD, PWE, 4, 1) + +/* Machine Error registers */ +#define LOONGARCH_CSR_MERRCTL 0x90 /* ERRCTL */ +#define LOONGARCH_CSR_MERRINFO 0x91 +#define LOONGARCH_CSR_MERRINFO1 0x92 +#define LOONGARCH_CSR_MERRENT 0x93 /* MError exception base */ +#define LOONGARCH_CSR_MERRERA 0x94 /* MError exception PC */ +#define LOONGARCH_CSR_MERRSAVE 0x95 /* KScratch for error exception */ + +#define LOONGARCH_CSR_CTAG 0x98 /* TagLo + TagHi */ + +/* Direct map windows */ +#define LOONGARCH_CSR_DMWIN0 0x180 /* 64 direct map win0: MEM & IF */ +#define LOONGARCH_CSR_DMWIN1 0x181 /* 64 direct map win1: MEM & IF */ +#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ +#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ +#define CSR_DMW_BASE_SH 48 +#define dmwin_va2pa(va) \ + (va & (((unsigned long)1 << CSR_DMW_BASE_SH) - 1)) + +/* Performance Counter registers */ +#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ +#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ +#define LOONGARCH_CSR_PERFCTRL1 0x202 /* 32 perf event 1 config */ +#define LOONGARCH_CSR_PERFCNTR1 0x203 /* 64 perf event 1 count value */ +#define LOONGARCH_CSR_PERFCTRL2 0x204 /* 32 perf event 2 config */ +#define LOONGARCH_CSR_PERFCNTR2 0x205 /* 64 perf event 2 count value */ +#define LOONGARCH_CSR_PERFCTRL3 0x206 /* 32 perf event 3 config */ +#define LOONGARCH_CSR_PERFCNTR3 0x207 /* 64 perf event 3 count value */ + +/* Debug registers */ +#define LOONGARCH_CSR_MWPC 0x300 /* data breakpoint config */ +#define LOONGARCH_CSR_MWPS 0x301 /* data breakpoint status */ + +#define LOONGARCH_CSR_DB0ADDR 0x310 /* data breakpoint 0 address */ +#define LOONGARCH_CSR_DB0MASK 0x311 /* data breakpoint 0 mask */ +#define LOONGARCH_CSR_DB0CTL 0x312 /* data breakpoint 0 control */ +#define LOONGARCH_CSR_DB0ASID 0x313 /* data breakpoint 0 asid */ + +#define LOONGARCH_CSR_DB1ADDR 0x318 /* data breakpoint 1 address */ +#define LOONGARCH_CSR_DB1MASK 0x319 /* data breakpoint 1 mask */ +#define LOONGARCH_CSR_DB1CTL 0x31a /* data breakpoint 1 control */ +#define LOONGARCH_CSR_DB1ASID 0x31b /* data breakpoint 1 asid */ + +#define LOONGARCH_CSR_DB2ADDR 0x320 /* data breakpoint 2 address */ +#define LOONGARCH_CSR_DB2MASK 0x321 /* data breakpoint 2 mask */ +#define LOONGARCH_CSR_DB2CTL 0x322 /* data breakpoint 2 control */ +#define LOONGARCH_CSR_DB2ASID 0x323 /* data breakpoint 2 asid */ + +#define LOONGARCH_CSR_DB3ADDR 0x328 /* data breakpoint 3 address */ +#define LOONGARCH_CSR_DB3MASK 0x329 /* data breakpoint 3 mask */ +#define LOONGARCH_CSR_DB3CTL 0x32a /* data breakpoint 3 control */ +#define LOONGARCH_CSR_DB3ASID 0x32b /* data breakpoint 3 asid */ + +#define LOONGARCH_CSR_DB4ADDR 0x330 /* data breakpoint 4 address */ +#define LOONGARCH_CSR_DB4MASK 0x331 /* data breakpoint 4 maks */ +#define LOONGARCH_CSR_DB4CTL 0x332 /* data breakpoint 4 control */ +#define LOONGARCH_CSR_DB4ASID 0x333 /* data breakpoint 4 asid */ + +#define LOONGARCH_CSR_DB5ADDR 0x338 /* data breakpoint 5 address */ +#define LOONGARCH_CSR_DB5MASK 0x339 /* data breakpoint 5 mask */ +#define LOONGARCH_CSR_DB5CTL 0x33a /* data breakpoint 5 control */ +#define LOONGARCH_CSR_DB5ASID 0x33b /* data breakpoint 5 asid */ + +#define LOONGARCH_CSR_DB6ADDR 0x340 /* data breakpoint 6 address */ +#define LOONGARCH_CSR_DB6MASK 0x341 /* data breakpoint 6 mask */ +#define LOONGARCH_CSR_DB6CTL 0x342 /* data breakpoint 6 control */ +#define LOONGARCH_CSR_DB6ASID 0x343 /* data breakpoint 6 asid */ + +#define LOONGARCH_CSR_DB7ADDR 0x348 /* data breakpoint 7 address */ +#define LOONGARCH_CSR_DB7MASK 0x349 /* data breakpoint 7 mask */ +#define LOONGARCH_CSR_DB7CTL 0x34a /* data breakpoint 7 control */ +#define LOONGARCH_CSR_DB7ASID 0x34b /* data breakpoint 7 asid */ + +#define LOONGARCH_CSR_FWPC 0x380 /* instruction breakpoint config */ +#define LOONGARCH_CSR_FWPS 0x381 /* instruction breakpoint status */ + +#define LOONGARCH_CSR_IB0ADDR 0x390 /* inst breakpoint 0 address */ +#define LOONGARCH_CSR_IB0MASK 0x391 /* inst breakpoint 0 mask */ +#define LOONGARCH_CSR_IB0CTL 0x392 /* inst breakpoint 0 control */ +#define LOONGARCH_CSR_IB0ASID 0x393 /* inst breakpoint 0 asid */ + +#define LOONGARCH_CSR_IB1ADDR 0x398 /* inst breakpoint 1 address */ +#define LOONGARCH_CSR_IB1MASK 0x399 /* inst breakpoint 1 mask */ +#define LOONGARCH_CSR_IB1CTL 0x39a /* inst breakpoint 1 control */ +#define LOONGARCH_CSR_IB1ASID 0x39b /* inst breakpoint 1 asid */ + +#define LOONGARCH_CSR_IB2ADDR 0x3a0 /* inst breakpoint 2 address */ +#define LOONGARCH_CSR_IB2MASK 0x3a1 /* inst breakpoint 2 mask */ +#define LOONGARCH_CSR_IB2CTL 0x3a2 /* inst breakpoint 2 control */ +#define LOONGARCH_CSR_IB2ASID 0x3a3 /* inst breakpoint 2 asid */ + +#define LOONGARCH_CSR_IB3ADDR 0x3a8 /* inst breakpoint 3 address */ +#define LOONGARCH_CSR_IB3MASK 0x3a9 /* inst breakpoint 3 mask */ +#define LOONGARCH_CSR_IB3CTL 0x3aa /* inst breakpoint 3 control */ +#define LOONGARCH_CSR_IB3ASID 0x3ab /* inst breakpoint 3 asid */ + +#define LOONGARCH_CSR_IB4ADDR 0x3b0 /* inst breakpoint 4 address */ +#define LOONGARCH_CSR_IB4MASK 0x3b1 /* inst breakpoint 4 mask */ +#define LOONGARCH_CSR_IB4CTL 0x3b2 /* inst breakpoint 4 control */ +#define LOONGARCH_CSR_IB4ASID 0x3b3 /* inst breakpoint 4 asid */ + +#define LOONGARCH_CSR_IB5ADDR 0x3b8 /* inst breakpoint 5 address */ +#define LOONGARCH_CSR_IB5MASK 0x3b9 /* inst breakpoint 5 mask */ +#define LOONGARCH_CSR_IB5CTL 0x3ba /* inst breakpoint 5 control */ +#define LOONGARCH_CSR_IB5ASID 0x3bb /* inst breakpoint 5 asid */ + +#define LOONGARCH_CSR_IB6ADDR 0x3c0 /* inst breakpoint 6 address */ +#define LOONGARCH_CSR_IB6MASK 0x3c1 /* inst breakpoint 6 mask */ +#define LOONGARCH_CSR_IB6CTL 0x3c2 /* inst breakpoint 6 control */ +#define LOONGARCH_CSR_IB6ASID 0x3c3 /* inst breakpoint 6 asid */ + +#define LOONGARCH_CSR_IB7ADDR 0x3c8 /* inst breakpoint 7 address */ +#define LOONGARCH_CSR_IB7MASK 0x3c9 /* inst breakpoint 7 mask */ +#define LOONGARCH_CSR_IB7CTL 0x3ca /* inst breakpoint 7 control */ +#define LOONGARCH_CSR_IB7ASID 0x3cb /* inst breakpoint 7 asid */ + +#define LOONGARCH_CSR_DBG 0x500 /* debug config */ +FIELD(CSR_DBG, DST, 0, 1) +FIELD(CSR_DBG, DREV, 1, 7) +FIELD(CSR_DBG, DEI, 8, 1) +FIELD(CSR_DBG, DCL, 9, 1) +FIELD(CSR_DBG, DFW, 10, 1) +FIELD(CSR_DBG, DMW, 11, 1) +FIELD(CSR_DBG, ECODE, 16, 6) + +#define LOONGARCH_CSR_DERA 0x501 /* Debug era */ +#define LOONGARCH_CSR_DESAVE 0x502 /* Debug save */ + +#define LOONGARCH_PAGE_HUGE 0x40 +#define LOONGARCH_HUGE_GLOBAL 0x1000 +#define LOONGARCH_HUGE_GLOBAL_SH 12 + +/* + * All Possible CSR registers used by tcg + * + * default value in target/loongarch/cpu.c + * + * This macro will be used only in: + * > target/loongarch/cpu.h:CPULoongArchState + * + * during translate: + * > helper_csr_rdq() + * > helper_csr_wrq() + * > helper_csr_xchgq() + * > helper_csr_xchgq_r0() + */ +#define CPU_LOONGARCH_CSR \ + uint64_t CSR_CRMD; \ + uint64_t CSR_PRMD; \ + uint64_t CSR_EUEN; \ + uint64_t CSR_MISC; \ + uint64_t CSR_ECFG; \ + uint64_t CSR_ESTAT; \ + uint64_t CSR_ERA; \ + uint64_t CSR_BADV; \ + uint64_t CSR_BADI; \ + uint64_t CSR_EENTRY; \ + uint64_t CSR_TLBIDX; \ + uint64_t CSR_TLBEHI; \ + uint64_t CSR_TLBELO0; \ + uint64_t CSR_TLBELO1; \ + uint64_t CSR_ASID; \ + uint64_t CSR_PGDL; \ + uint64_t CSR_PGDH; \ + uint64_t CSR_PGD; \ + uint64_t CSR_PWCL; \ + uint64_t CSR_PWCH; \ + uint64_t CSR_STLBPS; \ + uint64_t CSR_RVACFG; \ + uint64_t CSR_CPUID; \ + uint64_t CSR_PRCFG1; \ + uint64_t CSR_PRCFG2; \ + uint64_t CSR_PRCFG3; \ + uint64_t CSR_KS0; \ + uint64_t CSR_KS1; \ + uint64_t CSR_KS2; \ + uint64_t CSR_KS3; \ + uint64_t CSR_KS4; \ + uint64_t CSR_KS5; \ + uint64_t CSR_KS6; \ + uint64_t CSR_KS7; \ + uint64_t CSR_KS8; \ + uint64_t CSR_TMID; \ + uint64_t CSR_TCFG; \ + uint64_t CSR_TVAL; \ + uint64_t CSR_CNTC; \ + uint64_t CSR_TINTCLR; \ + uint64_t CSR_LLBCTL; \ + uint64_t CSR_IMPCTL1; \ + uint64_t CSR_IMPCTL2; \ + uint64_t CSR_TLBRENTRY; \ + uint64_t CSR_TLBRBADV; \ + uint64_t CSR_TLBRERA; \ + uint64_t CSR_TLBRSAVE; \ + uint64_t CSR_TLBRELO0; \ + uint64_t CSR_TLBRELO1; \ + uint64_t CSR_TLBREHI; \ + uint64_t CSR_TLBRPRMD; \ + uint64_t CSR_MERRCTL; \ + uint64_t CSR_MERRINFO; \ + uint64_t CSR_MERRINFO1; \ + uint64_t CSR_MERRENT; \ + uint64_t CSR_MERRERA; \ + uint64_t CSR_MERRSAVE; \ + uint64_t CSR_CTAG; \ + uint64_t CSR_MCSR0; \ + uint64_t CSR_MCSR1; \ + uint64_t CSR_MCSR2; \ + uint64_t CSR_MCSR3; \ + uint64_t CSR_MCSR8; \ + uint64_t CSR_MCSR9; \ + uint64_t CSR_MCSR10; \ + uint64_t CSR_MCSR24; \ + uint64_t CSR_UCAWIN; \ + uint64_t CSR_UCAWIN0_LO; \ + uint64_t CSR_UCAWIN0_HI; \ + uint64_t CSR_UCAWIN1_LO; \ + uint64_t CSR_UCAWIN1_HI; \ + uint64_t CSR_UCAWIN2_LO; \ + uint64_t CSR_UCAWIN2_HI; \ + uint64_t CSR_UCAWIN3_LO; \ + uint64_t CSR_UCAWIN3_HI; \ + uint64_t CSR_DMWIN0; \ + uint64_t CSR_DMWIN1; \ + uint64_t CSR_DMWIN2; \ + uint64_t CSR_DMWIN3; \ + uint64_t CSR_PERFCTRL0; \ + uint64_t CSR_PERFCNTR0; \ + uint64_t CSR_PERFCTRL1; \ + uint64_t CSR_PERFCNTR1; \ + uint64_t CSR_PERFCTRL2; \ + uint64_t CSR_PERFCNTR2; \ + uint64_t CSR_PERFCTRL3; \ + uint64_t CSR_PERFCNTR3; \ + uint64_t CSR_MWPC; \ + uint64_t CSR_MWPS; \ + uint64_t CSR_DB0ADDR; \ + uint64_t CSR_DB0MASK; \ + uint64_t CSR_DB0CTL; \ + uint64_t CSR_DB0ASID; \ + uint64_t CSR_DB1ADDR; \ + uint64_t CSR_DB1MASK; \ + uint64_t CSR_DB1CTL; \ + uint64_t CSR_DB1ASID; \ + uint64_t CSR_DB2ADDR; \ + uint64_t CSR_DB2MASK; \ + uint64_t CSR_DB2CTL; \ + uint64_t CSR_DB2ASID; \ + uint64_t CSR_DB3ADDR; \ + uint64_t CSR_DB3MASK; \ + uint64_t CSR_DB3CTL; \ + uint64_t CSR_DB3ASID; \ + uint64_t CSR_FWPC; \ + uint64_t CSR_FWPS; \ + uint64_t CSR_IB0ADDR; \ + uint64_t CSR_IB0MASK; \ + uint64_t CSR_IB0CTL; \ + uint64_t CSR_IB0ASID; \ + uint64_t CSR_IB1ADDR; \ + uint64_t CSR_IB1MASK; \ + uint64_t CSR_IB1CTL; \ + uint64_t CSR_IB1ASID; \ + uint64_t CSR_IB2ADDR; \ + uint64_t CSR_IB2MASK; \ + uint64_t CSR_IB2CTL; \ + uint64_t CSR_IB2ASID; \ + uint64_t CSR_IB3ADDR; \ + uint64_t CSR_IB3MASK; \ + uint64_t CSR_IB3CTL; \ + uint64_t CSR_IB3ASID; \ + uint64_t CSR_IB4ADDR; \ + uint64_t CSR_IB4MASK; \ + uint64_t CSR_IB4CTL; \ + uint64_t CSR_IB4ASID; \ + uint64_t CSR_IB5ADDR; \ + uint64_t CSR_IB5MASK; \ + uint64_t CSR_IB5CTL; \ + uint64_t CSR_IB5ASID; \ + uint64_t CSR_IB6ADDR; \ + uint64_t CSR_IB6MASK; \ + uint64_t CSR_IB6CTL; \ + uint64_t CSR_IB6ASID; \ + uint64_t CSR_IB7ADDR; \ + uint64_t CSR_IB7MASK; \ + uint64_t CSR_IB7CTL; \ + uint64_t CSR_IB7ASID; \ + uint64_t CSR_DBG; \ + uint64_t CSR_DERA; \ + uint64_t CSR_DESAVE; \ + +#endif /* LOONGARCH_CPU_CSR_H */ From patchwork Tue Oct 19 07:34:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568881 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65AA9C433EF for ; Tue, 19 Oct 2021 07:46:45 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1CCB3611EF for ; Tue, 19 Oct 2021 07:46:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1CCB3611EF Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:33798 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjpc-0004Wf-4O for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:46:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55852) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjex-0001GQ-4t for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:43 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34692 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjes-0004OH-DQ for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S5; Tue, 19 Oct 2021 15:35:26 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 03/31] target/loongarch: Set default csr values. Date: Tue, 19 Oct 2021 15:34:49 +0800 Message-Id: <1634628917-10031-4-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S5 X-Coremail-Antispam: 1UD129KBjvJXoWxGry5Gr1fXFyrZFy8Gw13CFg_yoW5Xw4xpr 9rur90yr4xtrsrA3s3Aas8Wrn8Zw4xC34Iva9Ikw1vkFW7Xr1fXFWkt397GF9rA34rAFWI 9Fn7AayUWF4DZ3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch set default csr values Mainly used for cpu_initfn and cpu_reset. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++++ target/loongarch/cpu.h | 6 ++++++ 2 files changed, 46 insertions(+) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index e9f67cf976..57f9264c1f 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -106,6 +106,40 @@ static void set_loongarch_cpucfg(CPULoongArchState *env) env->cpucfg[20] = 0x60f000f; } +#ifndef CONFIG_USER_ONLY +static void set_loongarch_csr(CPULoongArchState *env) +{ + uint64_t t; + + t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8); + t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f); + t = FIELD_DP64(t, CSR_PRCFG1, VSMAX, 0x7); + env->CSR_PRCFG1 = t; + + env->CSR_PRCFG2 = 0x3ffff000; + + t = FIELD_DP64(0, CSR_PRCFG3, TLB_TYPE, 2); + t = FIELD_DP64(t, CSR_PRCFG3, MTLB_ENTRY, 0x3f); + t = FIELD_DP64(t, CSR_PRCFG3, STLB_WAYS, 0x7); + t = FIELD_DP64(t, CSR_PRCFG3, STLB_SETS, 0x8); + env->CSR_PRCFG3 = t; + + t = FIELD_DP64(0, CSR_CRMD, PLV, 0); + t = FIELD_DP64(t, CSR_CRMD, IE, 0); + t = FIELD_DP64(t, CSR_CRMD, DA, 1); + t = FIELD_DP64(t, CSR_CRMD, PG, 0); + t = FIELD_DP64(t, CSR_CRMD, DATF, 1); + t = FIELD_DP64(t, CSR_CRMD, DATM, 1); + env->CSR_CRMD = t; + + env->CSR_ECFG = FIELD_DP64(0, CSR_ECFG, VS, 7); + env->CSR_STLBPS = 0xe; + env->CSR_RVACFG = 0x0; + env->CSR_ASID = 0xa0000; + env->CSR_ERA = env->pc; +} +#endif + /* LoongArch CPU definitions */ static void loongarch_3a5000_initfn(Object *obj) { @@ -113,6 +147,9 @@ static void loongarch_3a5000_initfn(Object *obj) CPULoongArchState *env = &cpu->env; set_loongarch_cpucfg(env); +#ifndef CONFIG_USER_ONLY + set_loongarch_csr(env); +#endif } static void loongarch_cpu_list_entry(gpointer data, gpointer user_data) @@ -140,6 +177,9 @@ static void loongarch_cpu_reset(DeviceState *dev) lacc->parent_reset(dev); set_loongarch_cpucfg(env); +#ifndef CONFIG_USER_ONLY + set_loongarch_csr(env); +#endif env->fcsr0_mask = 0x1f1f031f; env->fcsr0 = 0x0; diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index a4991f9481..5aa0c75ad9 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -12,6 +12,7 @@ #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" #include "hw/registerfields.h" +#include "cpu-csr.h" #define TCG_GUEST_DEFAULT_MO (0) @@ -68,6 +69,11 @@ struct CPULoongArchState { uint64_t llval; uint64_t badaddr; + +#ifndef CONFIG_USER_ONLY + /* LoongArch CSR registers */ + CPU_LOONGARCH_CSR +#endif }; /** From patchwork Tue Oct 19 07:34:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568855 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0920DC433FE for ; Tue, 19 Oct 2021 07:40:38 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B7A6061374 for ; Tue, 19 Oct 2021 07:40:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B7A6061374 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:44996 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjjg-0001Qu-NK for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:40:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55838) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjew-0001G5-B0 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34736 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjes-0004PH-F7 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S6; Tue, 19 Oct 2021 15:35:27 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU. Date: Tue, 19 Oct 2021 15:34:50 +0800 Message-Id: <1634628917-10031-5-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S6 X-Coremail-Antispam: 1UD129KBjvJXoW3KF4UJr47Ww4fCw18uF1kuFg_yoWDCF1xpr y3uF17tFZFvrWxZw48G3s8Wrs8GF4jg3WSkayYkr1kGr1kGw4DWr10vw1UXr1rJ34Yg342 yr4rXasrW3WjyrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch introduce vmstate_loongarch_cpu Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.c | 12 +++ target/loongarch/internals.h | 4 + target/loongarch/machine.c | 155 +++++++++++++++++++++++++++++++++++ target/loongarch/meson.build | 6 ++ 4 files changed, 177 insertions(+) create mode 100644 target/loongarch/machine.c diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 57f9264c1f..14352fb139 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -13,6 +13,7 @@ #include "sysemu/qtest.h" #include "exec/exec-all.h" #include "qapi/qapi-commands-machine-target.h" +#include "migration/vmstate.h" #include "cpu.h" #include "internals.h" #include "fpu/softfloat-helpers.h" @@ -260,6 +261,14 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) } } +#ifndef CONFIG_USER_ONLY +#include "hw/core/sysemu-cpu-ops.h" + +static const struct SysemuCPUOps loongarch_sysemu_ops = { + .legacy_vmsd = &vmstate_loongarch_cpu, +}; +#endif + #ifdef CONFIG_TCG #include "hw/core/tcg-cpu-ops.h" @@ -296,6 +305,9 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data) cc->has_work = loongarch_cpu_has_work; cc->dump_state = loongarch_cpu_dump_state; cc->set_pc = loongarch_cpu_set_pc; +#ifndef CONFIG_USER_ONLY + cc->sysemu_ops = &loongarch_sysemu_ops; +#endif cc->disas_set_info = loongarch_cpu_disas_set_info; #ifdef CONFIG_TCG cc->tcg_ops = &loongarch_tcg_ops; diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index b408aed6ec..50eb58a62e 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -26,4 +26,8 @@ const char *loongarch_exception_name(int32_t exception); void restore_fp_status(CPULoongArchState *env); +#ifndef CONFIG_USER_ONLY +extern const VMStateDescription vmstate_loongarch_cpu; +#endif + #endif diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c new file mode 100644 index 0000000000..8855e6bbf9 --- /dev/null +++ b/target/loongarch/machine.c @@ -0,0 +1,155 @@ +/* + * QEMU LoongArch machine State + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "migration/cpu.h" + +/* LoongArch CPU state */ + +const VMStateDescription vmstate_loongarch_cpu = { + .name = "cpu", + .version_id = 20, + .minimum_version_id = 20, + .fields = (VMStateField[]) { + + VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32), + VMSTATE_UINTTL(env.pc, LoongArchCPU), + VMSTATE_UINT64_ARRAY(env.fpr, LoongArchCPU, 32), + VMSTATE_UINT32(env.fcsr0, LoongArchCPU), + + /* Remaining CSR registers */ + VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU), + VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU), + VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU), + VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU), + VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU), + VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU), + VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU), + VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU), + VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU), + VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU), + VMSTATE_UINT64(env.CSR_CPUID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS0, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS2, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS3, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS4, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS5, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS6, LoongArchCPU), + VMSTATE_UINT64(env.CSR_KS7, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TMID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TINTCLR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU), + VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MERRINFO, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MERRENT, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU), + VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DMWIN0, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DMWIN1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DMWIN2, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DMWIN3, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL0, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR0, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR1, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL2, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR2, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL3, LoongArchCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR3, LoongArchCPU), + /* debug */ + VMSTATE_UINT64(env.CSR_MWPC, LoongArchCPU), + VMSTATE_UINT64(env.CSR_MWPS, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB0ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB0MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB0CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB0ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB1ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB1MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB1CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB1ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB2ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB2MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB2CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB2ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB3ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB3MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB3CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DB3ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_FWPC, LoongArchCPU), + VMSTATE_UINT64(env.CSR_FWPS, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB0ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB0MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB0CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB0ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB1ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB1MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB1CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB1ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB2ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB2MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB2CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB2ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB3ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB3MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB3CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB3ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB4ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB4MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB4CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB4ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB5ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB5MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB5CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB5ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB6ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB6MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB6CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB6ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB7ADDR, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB7MASK, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB7CTL, LoongArchCPU), + VMSTATE_UINT64(env.CSR_IB7ASID, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DBG, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU), + VMSTATE_UINT64(env.CSR_DESAVE, LoongArchCPU), + + VMSTATE_END_OF_LIST() + }, +}; diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build index 31f9e9fa5f..98bf83b499 100644 --- a/target/loongarch/meson.build +++ b/target/loongarch/meson.build @@ -13,6 +13,12 @@ loongarch_tcg_ss.add(files( )) loongarch_tcg_ss.add(zlib) +loongarch_softmmu_ss = ss.source_set() +loongarch_softmmu_ss.add(files( + 'machine.c', +)) + loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss]) target_arch += {'loongarch': loongarch_ss} +target_softmmu_arch += {'loongarch': loongarch_softmmu_ss} From patchwork Tue Oct 19 07:34:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568875 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97270C433F5 for ; Tue, 19 Oct 2021 07:43:17 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0FEA4611EF for ; Tue, 19 Oct 2021 07:43:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0FEA4611EF Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:53402 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjmG-000777-3x for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:43:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55844) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjew-0001G9-En for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34738 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjes-0004PW-Ia for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S7; Tue, 19 Oct 2021 15:35:29 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions() Date: Tue, 19 Oct 2021 15:34:51 +0800 Message-Id: <1634628917-10031-6-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S7 X-Coremail-Antispam: 1UD129KBjvJXoW7AFWxZFWxAw45tr15KrW8Xrb_yoW8Zr4xpF sxZrZxKr48JrZxKw1fJFW8urnI9ws7W34jyFs3J3yv9a13X3y8uF1vkryjk3W8WrW8WrWx uF4DAF15uF4DJ3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch introduce qmp_query_cpu_definitions interface. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao Reviewed-by: Richard Henderson --- qapi/machine-target.json | 6 ++++-- target/loongarch/cpu.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/qapi/machine-target.json b/qapi/machine-target.json index f5ec4bc172..682dc86b42 100644 --- a/qapi/machine-target.json +++ b/qapi/machine-target.json @@ -324,7 +324,8 @@ 'TARGET_ARM', 'TARGET_I386', 'TARGET_S390X', - 'TARGET_MIPS' ] } } + 'TARGET_MIPS', + 'TARGET_LOONGARCH64' ] } } ## # @query-cpu-definitions: @@ -340,4 +341,5 @@ 'TARGET_ARM', 'TARGET_I386', 'TARGET_S390X', - 'TARGET_MIPS' ] } } + 'TARGET_MIPS', + 'TARGET_LOONGARCH64' ] } } diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 14352fb139..dcd951c377 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -336,3 +336,31 @@ static const TypeInfo loongarch_cpu_type_infos[] = { }; DEFINE_TYPES(loongarch_cpu_type_infos) + +static void loongarch_cpu_add_definition(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + CpuDefinitionInfoList **cpu_list = user_data; + CpuDefinitionInfo *info; + const char *typename; + + typename = object_class_get_name(oc); + info = g_malloc0(sizeof(*info)); + info->name = g_strndup(typename, + strlen(typename) - strlen("-" TYPE_LOONGARCH_CPU)); + info->q_typename = g_strdup(typename); + + QAPI_LIST_PREPEND(*cpu_list, info); +} + +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + CpuDefinitionInfoList *cpu_list = NULL; + GSList *list; + + list = object_class_get_list(TYPE_LOONGARCH_CPU, false); + g_slist_foreach(list, loongarch_cpu_add_definition, &cpu_list); + g_slist_free(list); + + return cpu_list; +} From patchwork Tue Oct 19 07:34:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568829 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2BDE3C433EF for ; Tue, 19 Oct 2021 07:37:34 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C6B6B60FDA for ; Tue, 19 Oct 2021 07:37:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C6B6B60FDA Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:36046 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjgi-0003wH-IM for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:37:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55832) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjev-0001G4-Qw for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:42 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34766 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjes-0004S1-7x for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:41 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S10; Tue, 19 Oct 2021 15:35:31 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 08/31] target/loongarch: Add tlb instruction support Date: Tue, 19 Oct 2021 15:34:54 +0800 Message-Id: <1634628917-10031-9-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S10 X-Coremail-Antispam: 1UD129KBjvAXoWfAF1fWw4UKFW7Cw4DtFyxKrg_yoW8tr18to Wava1rt3WfGr4S9F9Fyw1qqa12qryUCan3CrnI9w45Way8Gr9rK34rKas5Aw4xCrn0qFyr A3W2va45JF13Jrn3n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This includes: - TLBSRCH - TLBRD - TLBWR - TLBFILL - TLBCLR - TLBFLUSH - INVTLB Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.c | 19 + target/loongarch/helper.h | 8 + target/loongarch/insn_trans/trans_core.c | 54 +++ target/loongarch/insns.decode | 14 + target/loongarch/internals.h | 18 + target/loongarch/tlb_helper.c | 468 +++++++++++++++++++++++ 6 files changed, 581 insertions(+) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index f145afb603..afd186abac 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -118,6 +118,7 @@ static void set_loongarch_cpucfg(CPULoongArchState *env) static void set_loongarch_csr(CPULoongArchState *env) { uint64_t t; + CPUState *cs = env_cpu(env); t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8); t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f); @@ -145,6 +146,9 @@ static void set_loongarch_csr(CPULoongArchState *env) env->CSR_RVACFG = 0x0; env->CSR_ASID = 0xa0000; env->CSR_ERA = env->pc; + env->CSR_CPUID = (cs->cpu_index & 0x1ff); + env->CSR_EENTRY |= (uint64_t)0x80000000; + env->CSR_TLBRENTRY |= (uint64_t)0x80000000; } #endif @@ -265,6 +269,21 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) } } +#ifndef CONFIG_USER_ONLY + qemu_fprintf(f, "EUEN 0x%lx\n", env->CSR_EUEN); + qemu_fprintf(f, "ESTAT 0x%lx\n", env->CSR_ESTAT); + qemu_fprintf(f, "ERA 0x%lx\n", env->CSR_ERA); + qemu_fprintf(f, "CRMD 0x%lx\n", env->CSR_CRMD); + qemu_fprintf(f, "PRMD 0x%lx\n", env->CSR_PRMD); + qemu_fprintf(f, "BadVAddr 0x%lx\n", env->CSR_BADV); + qemu_fprintf(f, "TLB refill ERA 0x%lx\n", env->CSR_TLBRERA); + qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV); + qemu_fprintf(f, "EENTRY 0x%lx\n", env->CSR_EENTRY); + qemu_fprintf(f, "BadInstr 0x%lx\n", env->CSR_BADI); + qemu_fprintf(f, "PRCFG1 0x%lx\nPRCFG2 0x%lx\nPRCFG3 0x%lx\n", + env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3); +#endif + /* fpr */ if (flags & CPU_DUMP_FPU) { for (i = 0; i < 32; i++) { diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index d1f18d71f7..1bb1df91b3 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -102,6 +102,14 @@ DEF_HELPER_2(csr_rdq, i64, env, i64) DEF_HELPER_3(csr_wrq, i64, env, tl, i64) DEF_HELPER_4(csr_xchgq, i64, env, tl, tl, i64) DEF_HELPER_3(csr_xchgq_r0, void, env, tl, i64) + +DEF_HELPER_1(tlbwr, void, env) +DEF_HELPER_1(tlbfill, void, env) +DEF_HELPER_1(tlbsrch, void, env) +DEF_HELPER_1(tlbrd, void, env) +DEF_HELPER_1(tlbclr, void, env) +DEF_HELPER_1(tlbflush, void, env) +DEF_HELPER_4(invtlb, void, env, tl, tl, tl) DEF_HELPER_2(iocsr_read, i64, env, tl) DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32) #endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c index b1ca2faf04..f8a72436dd 100644 --- a/target/loongarch/insn_trans/trans_core.c +++ b/target/loongarch/insn_trans/trans_core.c @@ -27,6 +27,13 @@ GEN_FALSE_TRANS(iocsrwr_b) GEN_FALSE_TRANS(iocsrwr_h) GEN_FALSE_TRANS(iocsrwr_w) GEN_FALSE_TRANS(iocsrwr_d) +GEN_FALSE_TRANS(tlbsrch) +GEN_FALSE_TRANS(tlbrd) +GEN_FALSE_TRANS(tlbwr) +GEN_FALSE_TRANS(tlbfill) +GEN_FALSE_TRANS(tlbclr) +GEN_FALSE_TRANS(tlbflush) +GEN_FALSE_TRANS(invtlb) #else static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr) @@ -165,4 +172,51 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(oi)); return true; } + +static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a) +{ + gen_helper_tlbsrch(cpu_env); + return true; +} + +static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a) +{ + gen_helper_tlbrd(cpu_env); + return true; +} + +static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a) +{ + gen_helper_tlbwr(cpu_env); + return true; +} + +static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a) +{ + gen_helper_tlbfill(cpu_env); + return true; +} + +static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a) +{ + gen_helper_tlbclr(cpu_env); + return true; +} + +static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a) +{ + gen_helper_tlbflush(cpu_env); + return true; +} + +static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a) +{ + TCGv addr = gpr_src(ctx, a->addr, EXT_NONE); + TCGv info = gpr_src(ctx, a->info, EXT_NONE); + TCGv op = tcg_constant_tl(a->invop); + + gen_helper_invtlb(cpu_env, addr, info, op); + return true; +} + #endif diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index a4a6df4f1a..aa40ecfca7 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -42,6 +42,9 @@ %offs16 10:s16 %offs 0:s10 10:16 %csr 10:14 +%addr 10:5 +%info 5:5 +%invop 0:5 # # Argument sets @@ -84,6 +87,8 @@ &fmt_offs offs &fmt_rjrdoffs16 rj rd offs16 &fmt_rdrjcsr rd rj csr +&fmt_empty +&fmt_invtlb addr info invop # # Formats @@ -126,6 +131,8 @@ @fmt_offs .... .. .......................... &fmt_offs %offs @fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16 @fmt_rdrjcsr .... .... .............. ..... ..... &fmt_rdrjcsr %rd %rj %csr +@fmt_empty .... ........ ..... ..... ..... ..... &fmt_empty +@fmt_invtlb ...... ...... ..... ..... ..... ..... &fmt_invtlb %addr %info %invop # # Fixed point arithmetic operation instruction @@ -494,3 +501,10 @@ iocsrwr_b 0000 01100100 10000 00100 ..... ..... @fmt_rdrj iocsrwr_h 0000 01100100 10000 00101 ..... ..... @fmt_rdrj iocsrwr_w 0000 01100100 10000 00110 ..... ..... @fmt_rdrj iocsrwr_d 0000 01100100 10000 00111 ..... ..... @fmt_rdrj +tlbsrch 0000 01100100 10000 01010 00000 00000 @fmt_empty +tlbrd 0000 01100100 10000 01011 00000 00000 @fmt_empty +tlbwr 0000 01100100 10000 01100 00000 00000 @fmt_empty +tlbfill 0000 01100100 10000 01101 00000 00000 @fmt_empty +tlbclr 0000 01100100 10000 01000 00000 00000 @fmt_empty +tlbflush 0000 01100100 10000 01001 00000 00000 @fmt_empty +invtlb 0000 01100100 10011 ..... ..... ..... @fmt_invtlb diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index 1251e7f21c..916c675680 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -76,6 +76,14 @@ struct CPULoongArchTLBContext { int (*map_address)(struct CPULoongArchState *env, hwaddr *physical, int *prot, target_ulong address, MMUAccessType access_type); + void (*helper_tlbwr)(struct CPULoongArchState *env); + void (*helper_tlbfill)(struct CPULoongArchState *env); + void (*helper_tlbsrch)(struct CPULoongArchState *env); + void (*helper_tlbrd)(struct CPULoongArchState *env); + void (*helper_tlbclr)(struct CPULoongArchState *env); + void (*helper_tlbflush)(struct CPULoongArchState *env); + void (*helper_invtlb)(struct CPULoongArchState *env, target_ulong addr, + target_ulong info, int op); struct { uint64_t stlb_mask; uint32_t stlb_size; /* at most : 8 * 256 = 2048 */ @@ -89,6 +97,16 @@ int ls3a5k_map_address(CPULoongArchState *env, hwaddr *physical, int *prot, void ls3a5k_mmu_init(CPULoongArchState *env); hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); +void ls3a5k_helper_tlbwr(CPULoongArchState *env); +void ls3a5k_helper_tlbfill(CPULoongArchState *env); +void ls3a5k_helper_tlbsrch(CPULoongArchState *env); +void ls3a5k_helper_tlbrd(CPULoongArchState *env); +void ls3a5k_helper_tlbclr(CPULoongArchState *env); +void ls3a5k_helper_tlbflush(CPULoongArchState *env); +void ls3a5k_invalidate_tlb(CPULoongArchState *env, int idx); +void ls3a5k_helper_invtlb(CPULoongArchState *env, target_ulong addr, + target_ulong info, int op); +void cpu_loongarch_tlb_flush(CPULoongArchState *env); #endif #endif diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c index 70105cdced..fd844d5a46 100644 --- a/target/loongarch/tlb_helper.c +++ b/target/loongarch/tlb_helper.c @@ -10,6 +10,7 @@ #include "cpu.h" #include "internals.h" +#include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/log.h" @@ -277,6 +278,428 @@ static void raise_mmu_exception(CPULoongArchState *env, target_ulong address, env->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1); } +void cpu_loongarch_tlb_flush(CPULoongArchState *env) +{ + /* Flush qemu's TLB and discard all shadowed entries. */ + tlb_flush(env_cpu(env)); +} + +static void ls3a5k_invalidate_tlb_entry(CPULoongArchState *env, + ls3a5k_tlb_t *tlb) +{ + CPUState *cs = env_cpu(env); + target_ulong addr; + target_ulong end; + target_ulong mask; + + mask = tlb->PageMask; /* 000...000111...111 */ + + if (tlb->V0) { + addr = tlb->VPN & ~mask; /* xxx...xxx[0]000..0000 */ + end = addr | (mask >> 1); /* xxx...xxx[0]111..1111 */ + while (addr < end) { + tlb_flush_page(cs, addr); + addr += TARGET_PAGE_SIZE; + } + } + + if (tlb->V1) { + /* xxx...xxx[1]000..0000 */ + addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); + end = addr | mask; /* xxx...xxx[1]111..1111 */ + while (addr - 1 < end) { + tlb_flush_page(cs, addr); + addr += TARGET_PAGE_SIZE; + } + } +} + +void ls3a5k_invalidate_tlb(CPULoongArchState *env, int idx) +{ + ls3a5k_tlb_t *tlb; + uint16_t asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + + tlb = &env->tlb->ls3a5k.tlb[idx]; + if (tlb->G == 0 && tlb->ASID != asid) { + return; + } + ls3a5k_invalidate_tlb_entry(env, tlb); +} + +static uint64_t ls3a5k_pagesize_to_mask(int pagesize) +{ + /* 4KB - 1GB */ + if (pagesize < 12 && pagesize > 30) { + qemu_log_mask(CPU_LOG_MMU, "unsupported page size %d\n", pagesize); + exit(-1); + } + + return (1 << (pagesize + 1)) - 1; +} + +static void ls3a5k_fill_tlb_entry(CPULoongArchState *env, + ls3a5k_tlb_t *tlb, int is_stlb) +{ + uint64_t page_mask; /* 0000...00001111...1111 */ + uint32_t page_size; + uint64_t entryhi; + uint64_t lo0, lo1; + + if (env->CSR_TLBRERA & 0x1) { + page_size = env->CSR_TLBREHI & 0x3f; + entryhi = env->CSR_TLBREHI; + lo0 = env->CSR_TLBRELO0; + lo1 = env->CSR_TLBRELO1; + } else { + page_size = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); + entryhi = env->CSR_TLBEHI; + lo0 = env->CSR_TLBELO0; + lo1 = env->CSR_TLBELO1; + } + + if (page_size == 0) { + qemu_log_mask(CPU_LOG_MMU, "page size is 0\n"); + } + + /* + * 15-12 11-8 7-4 3-0 + * 4KB: 0001 1111 1111 1111 // double 4KB mask [12:0] + * 16KB: 0111 1111 1111 1111 // double 16KB mask [14:0] + */ + if (is_stlb) { + page_mask = env->tlb->ls3a5k.stlb_mask; + } else { + page_mask = ls3a5k_pagesize_to_mask(page_size); + } + + tlb->VPN = entryhi & 0xffffffffe000 & ~page_mask; + + tlb->ASID = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + tlb->NE = 0; + tlb->G = FIELD_EX64(env->CSR_TLBELO0, CSR_TLBELO0, G) & + FIELD_EX64(env->CSR_TLBELO1, CSR_TLBELO1, G); + + tlb->PageMask = page_mask; + tlb->PageSize = page_size; + + tlb->V0 = FIELD_EX64(lo0, CSR_TLBELO0, V); /* [0] */ + tlb->D0 = FIELD_EX64(lo0, CSR_TLBELO0, D); /* [1] */ + tlb->PLV0 = FIELD_EX64(lo0, CSR_TLBELO0, PLV); /* [3:2] */ + tlb->MAT0 = FIELD_EX64(lo0, CSR_TLBELO0, MAT); /* [5:4] */ + tlb->PPN0 = (lo0 & 0xfffffffff000 & ~(page_mask >> 1)); + tlb->NR0 = FIELD_EX64(lo0, CSR_TLBELO0, NR); /* [61] */ + tlb->NX0 = FIELD_EX64(lo0, CSR_TLBELO0, NX); /* [62] */ + tlb->RPLV0 = FIELD_EX64(lo0, CSR_TLBELO0, RPLV);/* [63] */ + + tlb->V1 = FIELD_EX64(lo1, CSR_TLBELO1, V); /* [0] */ + tlb->D1 = FIELD_EX64(lo1, CSR_TLBELO1, D); /* [1] */ + tlb->PLV1 = FIELD_EX64(lo1, CSR_TLBELO1, PLV); /* [3:2] */ + tlb->MAT1 = FIELD_EX64(lo1, CSR_TLBELO1, MAT); /* [5:4] */ + tlb->PPN1 = (lo1 & 0xfffffffff000 & ~(page_mask >> 1)); + tlb->NR1 = FIELD_EX64(lo1, CSR_TLBELO1, NR); /* [61] */ + tlb->NX1 = FIELD_EX64(lo1, CSR_TLBELO1, NX); /* [62] */ + tlb->RPLV1 = FIELD_EX64(lo1, CSR_TLBELO1, RPLV);/* [63] */ +} + +static void ls3a5k_fill_tlb(CPULoongArchState *env, int idx, bool tlbwr) +{ + ls3a5k_tlb_t *tlb; + + tlb = &env->tlb->ls3a5k.tlb[idx]; + if (tlbwr) { + if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { + tlb->NE = 1; + return; + } + } + + if (idx < 2048) { + ls3a5k_fill_tlb_entry(env, tlb, 1); + } else { + ls3a5k_fill_tlb_entry(env, tlb, 0); + } +} + +/* return random value in [low, high] */ +static uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high) +{ + static uint32_t seed = 5; + static uint32_t prev_idx; + uint32_t idx; + uint32_t nb_rand_tlb = high - low + 1; + + do { + seed = 1103515245 * seed + 12345; + idx = (seed >> 16) % nb_rand_tlb + low; + } while (idx == prev_idx); + prev_idx = idx; + + return idx; +} + +void ls3a5k_helper_tlbsrch(CPULoongArchState *env) +{ + uint64_t mask; + uint64_t vpn; + uint64_t tag; + uint16_t asid; + + int stlb_size = env->tlb->ls3a5k.stlb_size; + int mtlb_size = env->tlb->ls3a5k.mtlb_size; + int i; + ls3a5k_tlb_t *tlb; + asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + + /* search MTLB + STLB */ + for (i = 0; i < stlb_size + mtlb_size; ++i) { + tlb = &env->tlb->ls3a5k.tlb[i]; + mask = tlb->PageMask; + vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; + tag = tlb->VPN & ~mask; + + if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->NE != 1) { + env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, + INDEX, (i & 0xfff)); + env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, + PS, (tlb->PageSize & 0x3f)); + return; + } + } + + env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 1); +} + +void ls3a5k_helper_tlbrd(CPULoongArchState *env) +{ + ls3a5k_tlb_t *tlb; + int idx; + uint16_t asid; + + idx = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + tlb = &env->tlb->ls3a5k.tlb[idx]; + + asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + + if (asid != tlb->ASID) { + cpu_loongarch_tlb_flush(env); + } + + if (tlb->NE) { + /* invalid TLB entry */ + env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 1); + env->CSR_TLBEHI = 0; + env->CSR_TLBELO0 = 0; + env->CSR_TLBELO1 = 0; + } else { + /* valid TLB entry */ + env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, + INDEX, (idx & 0xfff)); + env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, + PS, (tlb->PageSize & 0x3f)); + env->CSR_TLBEHI = tlb->VPN; + + env->CSR_TLBELO0 = FIELD_DP64(0, CSR_TLBELO0, V, tlb->V0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, D, tlb->D0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, PLV, tlb->PLV0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, MAT, tlb->MAT0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, G, tlb->G); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, PPN, tlb->PPN0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, NR, tlb->NR0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, NX, tlb->NX0); + env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, RPLV, tlb->RPLV0); + + env->CSR_TLBELO1 = FIELD_DP64(0, CSR_TLBELO1, V, tlb->V1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, D, tlb->D1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, PLV, tlb->PLV1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, MAT, tlb->MAT1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, G, tlb->G); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, PPN, tlb->PPN1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, NR, tlb->NR1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, NX, tlb->NX1); + env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, RPLV, tlb->RPLV1); + + env->CSR_ASID = FIELD_DP64(env->CSR_ASID, CSR_ASID, ASID, tlb->ASID); + } +} + +void ls3a5k_helper_tlbwr(CPULoongArchState *env) +{ + int idx = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); /* 0-11 */ + + ls3a5k_invalidate_tlb(env, idx); + ls3a5k_fill_tlb(env, idx, true); +} + +void ls3a5k_helper_tlbfill(CPULoongArchState *env) +{ + uint64_t mask; + uint64_t address; + int idx; + int set, stlb_idx; + + uint64_t entryhi; + uint32_t pagesize; + + if (env->CSR_TLBRERA & 0x1) { + entryhi = env->CSR_TLBREHI & ~0x3f; + pagesize = env->CSR_TLBREHI & 0x3f; + } else { + entryhi = env->CSR_TLBEHI; + pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); + } + + uint32_t stlb_size = env->tlb->ls3a5k.stlb_size; + uint32_t mtlb_size = env->tlb->ls3a5k.mtlb_size; + + mask = ls3a5k_pagesize_to_mask(pagesize); + + if (mask == env->tlb->ls3a5k.stlb_mask && + env->tlb->ls3a5k.stlb_size > 0) { + /* only write into STLB */ + address = entryhi & 0xffffffffe000; /* [47:13] */ + + /* choose one set ramdomly */ + set = cpu_loongarch_get_random_ls3a5k_tlb(0, 7); + + /* index in one set */ + stlb_idx = (address >> 15) & 0xff; /* [0,255] */ + + idx = set * 256 + stlb_idx; + } else { + /* only write into MTLB */ + idx = cpu_loongarch_get_random_ls3a5k_tlb( + stlb_size, stlb_size + mtlb_size - 1); + } + + ls3a5k_invalidate_tlb(env, idx); + ls3a5k_fill_tlb(env, idx, false); +} + +void ls3a5k_helper_tlbclr(CPULoongArchState *env) +{ + int i; + uint16_t asid; + int msize, ssize, index; + ls3a5k_tlb_t *tlb; + + asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + msize = env->tlb->ls3a5k.mtlb_size; + ssize = env->tlb->ls3a5k.stlb_size; + index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + + if (index < ssize) { + /* STLB. One line per operation */ + for (i = 0; i < 8; i++) { + tlb = &env->tlb->ls3a5k.tlb[i * 256 + (index % 256)]; + if (!tlb->G && tlb->ASID == asid) { + tlb->NE = 1; + } + } + } else if (index < (ssize + msize)) { + /* MTLB. All entries */ + for (i = ssize; i < ssize + msize; i++) { + tlb = &env->tlb->ls3a5k.tlb[i]; + if (!tlb->G && tlb->ASID == asid) { + tlb->NE = 1; + } + } + } + + cpu_loongarch_tlb_flush(env); +} + +void ls3a5k_helper_tlbflush(CPULoongArchState *env) +{ + int i; + int msize, ssize, index; + + msize = env->tlb->ls3a5k.mtlb_size; + ssize = env->tlb->ls3a5k.stlb_size; + index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + + if (index < ssize) { + /* STLB. One line per operation */ + for (i = 0; i < 8; i++) { + int idx = i * 256 + (index % 256); + env->tlb->ls3a5k.tlb[idx].NE = 1; + } + } else if (index < (ssize + msize)) { + /* MTLB. All entries */ + for (i = ssize; i < ssize + msize; i++) { + env->tlb->ls3a5k.tlb[i].NE = 1; + } + } + + cpu_loongarch_tlb_flush(env); +} + +void ls3a5k_helper_invtlb(CPULoongArchState *env, target_ulong addr, + target_ulong info, int op) +{ + uint32_t asid = info & 0x3ff; + int i; + + switch (op) { + case 0: + case 1: + for (i = 0; i < env->tlb->nb_tlb; i++) { + env->tlb->ls3a5k.tlb[i].NE = 1; + } + break; + case 2: + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i]; + + if (tlb->G) { + tlb->NE = 1; + } + } + break; + case 3: + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i]; + + if (!tlb->G) { + tlb->NE = 1; + } + } + break; + case 4: + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i]; + + if (!tlb->G && tlb->ASID == asid) { + tlb->NE = 1; + } + } + break; + case 5: + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i]; + uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; + + if (!tlb->G && tlb->ASID == asid && vpn == tlb->VPN) { + tlb->NE = 1; + } + } + break; + case 6: + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i]; + uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; + + if ((tlb->G || tlb->ASID == asid) && vpn == tlb->VPN) { + tlb->NE = 1; + } + } + break; + default: + do_raise_exception(env, EXCP_INE, GETPC()); + } + + cpu_loongarch_tlb_flush(env); +} + void ls3a5k_mmu_init(CPULoongArchState *env) { env->tlb = g_malloc0(sizeof(CPULoongArchTLBContext)); @@ -324,6 +747,51 @@ void ls3a5k_mmu_init(CPULoongArchState *env) } env->tlb->map_address = &ls3a5k_map_address; + + /* TLB's helper functions */ + env->tlb->helper_tlbsrch = ls3a5k_helper_tlbsrch; + env->tlb->helper_tlbrd = ls3a5k_helper_tlbrd; + env->tlb->helper_tlbwr = ls3a5k_helper_tlbwr; + env->tlb->helper_tlbfill = ls3a5k_helper_tlbfill; + env->tlb->helper_tlbclr = ls3a5k_helper_tlbclr; + env->tlb->helper_tlbflush = ls3a5k_helper_tlbflush; + env->tlb->helper_invtlb = ls3a5k_helper_invtlb; +} + +void helper_tlbwr(CPULoongArchState *env) +{ + env->tlb->helper_tlbwr(env); +} + +void helper_tlbfill(CPULoongArchState *env) +{ + env->tlb->helper_tlbfill(env); +} + +void helper_tlbsrch(CPULoongArchState *env) +{ + env->tlb->helper_tlbsrch(env); +} + +void helper_tlbrd(CPULoongArchState *env) +{ + env->tlb->helper_tlbrd(env); +} + +void helper_tlbclr(CPULoongArchState *env) +{ + env->tlb->helper_tlbclr(env); +} + +void helper_tlbflush(CPULoongArchState *env) +{ + env->tlb->helper_tlbflush(env); +} + +void helper_invtlb(CPULoongArchState *env, target_ulong addr, + target_ulong info, target_ulong op) +{ + env->tlb->helper_invtlb(env, addr, info, op); } bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, From patchwork Tue Oct 19 07:34:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568877 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93859C433EF for ; Tue, 19 Oct 2021 07:43:17 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 12F466136F for ; Tue, 19 Oct 2021 07:43:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 12F466136F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:53410 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjmG-00077N-45 for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:43:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55904) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjf0-0001IA-3V for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:46 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34868 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjev-0004Un-Oo for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:45 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S11; Tue, 19 Oct 2021 15:35:32 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 09/31] target/loongarch: Add other core instructions support Date: Tue, 19 Oct 2021 15:34:55 +0800 Message-Id: <1634628917-10031-10-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S11 X-Coremail-Antispam: 1UD129KBjvJXoWfJryUWw4kXw4UCF48JFyUAwb_yoWkWr1kpF 42krW7Cr48JFZ3Zwnrt3WYyFn8Xr4xCa1xZayft34FvF47XFykXrW8X3y3KF4UXwn5ZrWU ZFn8AryjvFyUXaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This includes: -CACOP -LDDIR -LDPTE -ERTN -DBCL -IDLE Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.c | 1 + target/loongarch/cpu.h | 5 +- target/loongarch/helper.h | 4 ++ target/loongarch/insn_trans/trans_core.c | 57 ++++++++++++++++ target/loongarch/insns.decode | 15 +++++ target/loongarch/op_helper.c | 48 ++++++++++++++ target/loongarch/tlb_helper.c | 83 ++++++++++++++++++++++++ 7 files changed, 212 insertions(+), 1 deletion(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index afd186abac..7fa3851251 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -45,6 +45,7 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_TLBPE] = "TLB priviledged error", [EXCP_TLBNX] = "TLB execute-inhibit", [EXCP_TLBNR] = "TLB read-inhibit", + [EXCP_DBP] = "debug breakpoint", }; const char *loongarch_exception_name(int32_t exception) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 567fc7620d..d39c618d6b 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -166,10 +166,13 @@ enum { EXCP_TLBPE, EXCP_TLBNX, EXCP_TLBNR, + EXCP_DBP, - EXCP_LAST = EXCP_TLBNR, + EXCP_LAST = EXCP_DBP, }; +#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 + #define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 1bb1df91b3..8544771790 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -112,4 +112,8 @@ DEF_HELPER_1(tlbflush, void, env) DEF_HELPER_4(invtlb, void, env, tl, tl, tl) DEF_HELPER_2(iocsr_read, i64, env, tl) DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32) +DEF_HELPER_4(lddir, tl, env, tl, tl, i32) +DEF_HELPER_4(ldpte, void, env, tl, tl, i32) +DEF_HELPER_1(ertn, void, env) +DEF_HELPER_1(idle, void, env) #endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c index f8a72436dd..7fa13e65b9 100644 --- a/target/loongarch/insn_trans/trans_core.c +++ b/target/loongarch/insn_trans/trans_core.c @@ -34,6 +34,12 @@ GEN_FALSE_TRANS(tlbfill) GEN_FALSE_TRANS(tlbclr) GEN_FALSE_TRANS(tlbflush) GEN_FALSE_TRANS(invtlb) +GEN_FALSE_TRANS(cacop) +GEN_FALSE_TRANS(ldpte) +GEN_FALSE_TRANS(lddir) +GEN_FALSE_TRANS(ertn) +GEN_FALSE_TRANS(dbcl) +GEN_FALSE_TRANS(idle) #else static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr) @@ -173,6 +179,11 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) return true; } +static bool trans_cacop(DisasContext *ctx, arg_cacop *a) +{ + return false; +} + static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a) { gen_helper_tlbsrch(cpu_env); @@ -219,4 +230,50 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a) return true; } +static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) +{ + TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx); + TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + + gen_helper_ldpte(cpu_env, src1, tcg_constant_tl(a->seq), mem_idx); + return true; +} + +static bool trans_lddir(DisasContext *ctx, arg_lddir *a) +{ + TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx); + TCGv src = gpr_src(ctx, a->rj, EXT_NONE); + TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + + gen_helper_lddir(dest, cpu_env, src, tcg_constant_tl(a->level), mem_idx); + return true; +} + +static bool trans_ertn(DisasContext *ctx, arg_ertn *a) +{ + gen_helper_ertn(cpu_env); + ctx->base.is_jmp = DISAS_EXIT; + return true; +} + +static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a) +{ + /* + * XXX: not clear which exception should be raised + * when in debug mode... + */ + generate_exception(ctx, EXCP_DBP); + return true; +} + +static bool trans_idle(DisasContext *ctx, arg_idle *a) +{ + ctx->base.pc_next += 4; + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + ctx->base.pc_next -= 4; + gen_helper_idle(cpu_env); + ctx->base.is_jmp = DISAS_NORETURN; + return true; +} + #endif diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index aa40ecfca7..2b18b27c88 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -42,9 +42,12 @@ %offs16 10:s16 %offs 0:s10 10:16 %csr 10:14 +%cop 0:5 %addr 10:5 %info 5:5 %invop 0:5 +%level 10:8 +%seq 10:8 # # Argument sets @@ -87,8 +90,11 @@ &fmt_offs offs &fmt_rjrdoffs16 rj rd offs16 &fmt_rdrjcsr rd rj csr +&fmt_coprjsi12 cop rj si12 &fmt_empty &fmt_invtlb addr info invop +&fmt_rdrjlevel rd rj level +&fmt_rjseq rj seq # # Formats @@ -131,8 +137,11 @@ @fmt_offs .... .. .......................... &fmt_offs %offs @fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16 @fmt_rdrjcsr .... .... .............. ..... ..... &fmt_rdrjcsr %rd %rj %csr +@fmt_coprjsi12 .... ...... ............ ..... ..... &fmt_coprjsi12 %cop %rj %si12 @fmt_empty .... ........ ..... ..... ..... ..... &fmt_empty @fmt_invtlb ...... ...... ..... ..... ..... ..... &fmt_invtlb %addr %info %invop +@fmt_rdrjlevel .... ........ .. ........ ..... ..... &fmt_rdrjlevel %rd %rj %level +@fmt_rjseq .... ........ .. ........ ..... ..... &fmt_rjseq %rj %seq # # Fixed point arithmetic operation instruction @@ -501,6 +510,7 @@ iocsrwr_b 0000 01100100 10000 00100 ..... ..... @fmt_rdrj iocsrwr_h 0000 01100100 10000 00101 ..... ..... @fmt_rdrj iocsrwr_w 0000 01100100 10000 00110 ..... ..... @fmt_rdrj iocsrwr_d 0000 01100100 10000 00111 ..... ..... @fmt_rdrj +cacop 0000 011000 ............ ..... ..... @fmt_coprjsi12 tlbsrch 0000 01100100 10000 01010 00000 00000 @fmt_empty tlbrd 0000 01100100 10000 01011 00000 00000 @fmt_empty tlbwr 0000 01100100 10000 01100 00000 00000 @fmt_empty @@ -508,3 +518,8 @@ tlbfill 0000 01100100 10000 01101 00000 00000 @fmt_empty tlbclr 0000 01100100 10000 01000 00000 00000 @fmt_empty tlbflush 0000 01100100 10000 01001 00000 00000 @fmt_empty invtlb 0000 01100100 10011 ..... ..... ..... @fmt_invtlb +lddir 0000 01100100 00 ........ ..... ..... @fmt_rdrjlevel +ldpte 0000 01100100 01 ........ ..... 00000 @fmt_rjseq +ertn 0000 01100100 10000 01110 00000 00000 @fmt_empty +idle 0000 01100100 10001 ............... @fmt_whint +dbcl 0000 00000010 10101 ............... @fmt_code diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c index c560a9be26..4547880c8f 100644 --- a/target/loongarch/op_helper.c +++ b/target/loongarch/op_helper.c @@ -83,3 +83,51 @@ target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj) { return env->cpucfg[rj]; } + +#ifndef CONFIG_USER_ONLY +static inline void exception_return(CPULoongArchState *env) +{ + if (env->CSR_TLBRERA & 0x1) { + env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, + FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV)); + env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, + FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE)); + /* Clear Refill flag and set pc */ + env->CSR_TLBRERA &= (~0x1); + env->pc = env->CSR_TLBRERA; + if (qemu_loglevel_mask(CPU_LOG_INT)) { + qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA); + } + } else { + env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, + FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV)); + env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, + FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE)); + /* set pc*/ + env->pc = env->CSR_ERA; + if (qemu_loglevel_mask(CPU_LOG_INT)) { + qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA); + } + } +} + +void helper_ertn(CPULoongArchState *env) +{ + exception_return(env); + env->lladdr = 1; +} + +void helper_idle(CPULoongArchState *env) +{ + CPUState *cs = env_cpu(env); + + cs->halted = 1; + cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); + /* + * Last instruction in the block, PC was updated before + * - no need to recover PC and icount + */ + do_raise_exception(env, EXCP_HLT, 0); +} + +#endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c index fd844d5a46..1eea4e1dc4 100644 --- a/target/loongarch/tlb_helper.c +++ b/target/loongarch/tlb_helper.c @@ -833,3 +833,86 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, do_raise_exception(env, cs->exception_index, retaddr); } } + +target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, + target_ulong level, uint32_t mem_idx) +{ + target_ulong badvaddr; + target_ulong index; + target_ulong vaddr; + int shift; + uint64_t dir1_base, dir1_width; + uint64_t dir3_base, dir3_width; + + badvaddr = env->CSR_TLBRBADV; + + /* 0:8B, 1:16B, 2:32B, 3:64B */ + shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH); + shift = (shift + 1) * 3; + + switch (level) { + case 1: + dir1_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE); + dir1_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); + index = (badvaddr >> dir1_base) & ((1 << dir1_width) - 1); + break; + case 3: + dir3_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE); + dir3_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); + index = (badvaddr >> dir3_base) & ((1 << dir3_width) - 1); + break; + default: + do_raise_exception(env, EXCP_INE, GETPC()); + return 0; + } + + vaddr = base | index << shift; + return cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC()); +} + +void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd, + uint32_t mem_idx) +{ + target_ulong vaddr; + target_ulong tmp0; + target_ulong ptindex, ptoffset0, ptoffset1; + target_ulong pagesize; + target_ulong badv; + int shift; + bool huge = base & LOONGARCH_PAGE_HUGE; + uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); + uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + + if (huge) { + /* Huge Page. base is paddr */ + tmp0 = base ^ LOONGARCH_PAGE_HUGE; + /* move Global bit */ + tmp0 |= ((tmp0 & LOONGARCH_HUGE_GLOBAL) + >> (LOONGARCH_HUGE_GLOBAL_SH - R_CSR_TLBELO0_G_SHIFT)); + pagesize = ptbase + ptwidth - 1; + if (odd) { + tmp0 += (1 << pagesize); + } + } else { + /* 0:8B, 1:16B, 2:32B, 3:64B */ + shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH); + shift = (shift + 1) * 3; + badv = env->CSR_TLBRBADV; + + ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1); + ptindex = ptindex & ~0x1; /* clear bit 0 */ + ptoffset0 = ptindex << shift; + ptoffset1 = (ptindex + 1) << shift; + + vaddr = base | (odd ? ptoffset1 : ptoffset0); + tmp0 = cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC()); + pagesize = ptbase; + } + if (odd) { + env->CSR_TLBRELO1 = tmp0; + } else { + env->CSR_TLBRELO0 = tmp0; + } + env->CSR_TLBREHI = env->CSR_TLBREHI & (~0x3f); + env->CSR_TLBREHI = env->CSR_TLBREHI | pagesize; +} From patchwork Tue Oct 19 07:34:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568851 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6B89C433F5 for ; Tue, 19 Oct 2021 07:40:35 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A299E60FD9 for ; Tue, 19 Oct 2021 07:40:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org A299E60FD9 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:44854 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjje-0001Ll-It for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:40:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55924) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjf1-0001L8-5b for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:47 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34918 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjex-0004WB-9y for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:46 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S12; Tue, 19 Oct 2021 15:35:35 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle Date: Tue, 19 Oct 2021 15:34:56 +0800 Message-Id: <1634628917-10031-11-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S12 X-Coremail-Antispam: 1UD129KBjvJXoW3uFW3AF4fCr13ury3XryrWFg_yoWDAF1UpF 1IkrW2yr9xXrZ3Aw13Jws0vrn5Zw18Kwn2qasxG3WFyrWxXr1F9rWvq3srZF9xCrW5Aw47 uFs3ArW5WF1UZFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch Add loongarch interrupt and exception handle. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.c | 293 +++++++++++++++++++++++++++++++++++++++++ target/loongarch/cpu.h | 6 +- 2 files changed, 298 insertions(+), 1 deletion(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 7fa3851251..3e3cf233db 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -45,7 +45,10 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_TLBPE] = "TLB priviledged error", [EXCP_TLBNX] = "TLB execute-inhibit", [EXCP_TLBNR] = "TLB read-inhibit", + [EXCP_EXT_INTERRUPT] = "interrupt", [EXCP_DBP] = "debug breakpoint", + [EXCP_IBE] = "instruction bus error", + [EXCP_DBE] = "data bus error", }; const char *loongarch_exception_name(int32_t exception) @@ -79,6 +82,275 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) env->pc = value; } +#if !defined(CONFIG_USER_ONLY) +static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env) +{ + bool ret = 0; + + ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) && + !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST))); + + return ret; +} + +/* Check if there is pending and not masked out interrupt */ +static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env) +{ + uint32_t pending; + uint32_t status; + bool r; + + pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS); + status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE); + + r = (pending & status) != 0; + return r; +} + +static inline unsigned int get_vint_size(CPULoongArchState *env) +{ + unsigned int size = 0; + uint64_t vs = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS); + + switch (vs) { + case 0: + break; + case 1: + size = 2 * 4; /* #Insts * inst_size */ + break; + case 2: + size = 4 * 4; + break; + case 3: + size = 8 * 4; + break; + case 4: + size = 16 * 4; + break; + case 5: + size = 32 * 4; + break; + case 6: + size = 64 * 4; + break; + case 7: + size = 128 * 4; + break; + default: + qemu_log("%s: unexpected value", __func__); + assert(0); + } + + return size; +} + +#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \ + || (cs->exception_index == EXCP_TLBS)) \ + && (env->error_code & EXCP_TLB_NOMATCH)) + +static void loongarch_cpu_do_interrupt(CPUState *cs) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + bool update_badinstr = 0; + int cause = -1; + const char *name; + + if (qemu_loglevel_mask(CPU_LOG_INT) + && cs->exception_index != EXCP_EXT_INTERRUPT) { + if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) { + name = "unknown"; + } else { + name = excp_names[cs->exception_index]; + } + + qemu_log("%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx + " TLBRERA 0x%016lx" " %s exception\n", __func__, + env->pc, env->CSR_ERA, env->CSR_TLBRERA, name); + } + + switch (cs->exception_index) { + case EXCP_SYSCALL: + cause = EXCCODE_SYS; + update_badinstr = 1; + break; + case EXCP_BREAK: + cause = EXCCODE_BRK; + update_badinstr = 1; + break; + case EXCP_INE: + cause = EXCCODE_INE; + update_badinstr = 1; + break; + case EXCP_FPE: + cause = EXCCODE_FPE; + update_badinstr = 1; + break; + case EXCP_ADEL: + cause = EXCCODE_ADEF; + update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); + break; + case EXCP_ADES: + cause = EXCCODE_ADEM; + update_badinstr = 1; + break; + case EXCP_DBP: + env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1); + env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC); + env->CSR_DERA = env->pc; + env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1); + env->pc = env->exception_base + 0x480; + break; + case EXCP_EXT_INTERRUPT: + cause = 0; + break; + case EXCP_TLBL: + if (env->error_code & EXCP_INST_NOTAVAIL) { + cause = EXCCODE_PIF; + } else { + cause = EXCCODE_PIL; + } + update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); + break; + case EXCP_TLBS: + cause = EXCCODE_PIS; + update_badinstr = 1; + break; + case EXCP_TLBM: + cause = EXCCODE_PME; + break; + case EXCP_TLBPE: + cause = EXCCODE_PPI; + break; + case EXCP_TLBNX: + cause = EXCCODE_PNX; + break; + case EXCP_TLBNR: + cause = EXCCODE_PNR; + update_badinstr = 1; + break; + case EXCP_IBE: + cause = EXCCODE_ADEF; + break; + case EXCP_DBE: + cause = EXCCODE_ADEM; + break; + default: + qemu_log("Error: exception(%d) '%s' has not been supported\n", + cs->exception_index, excp_names[cs->exception_index]); + abort(); + } + + if (is_refill(cs, env)) { + env->CSR_TLBRERA = env->pc; + env->CSR_TLBRERA |= 1; + } else { + env->CSR_ERA = env->pc; + } + + if (update_badinstr) { + env->CSR_BADI = cpu_ldl_code(env, env->pc); + } + + /* save PLV and IE */ + if (is_refill(cs, env)) { + env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV, + FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV)); + env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE, + FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE)); + } else { + env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV, + FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV)); + env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PIE, + FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE)); + } + + env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0); + env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0); + + uint32_t vec_size = get_vint_size(env); + env->pc = env->CSR_EENTRY; + env->pc += cause * vec_size; + if (is_refill(cs, env)) { + /* TLB Refill */ + env->pc = env->CSR_TLBRENTRY; + } + if (cs->exception_index == EXCP_EXT_INTERRUPT) { + /* Interrupt */ + uint32_t vector = 0; + uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS); + pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE); + + /* Find the highest-priority interrupt. */ + while (pending >>= 1) { + vector++; + } + env->pc = env->CSR_EENTRY + (EXCODE_IP + vector) * vec_size; + if (qemu_loglevel_mask(CPU_LOG_INT)) { + qemu_log("%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx + " cause %d\n" " A " TARGET_FMT_lx " D " + TARGET_FMT_lx " vector = %d ExC %08lx ExS %08lx\n", + __func__, env->pc, env->CSR_ERA, + cause, env->CSR_BADV, env->CSR_DERA, vector, + env->CSR_ECFG, env->CSR_ESTAT); + } + } + + /* Excode */ + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, cause); + + if (qemu_loglevel_mask(CPU_LOG_INT) && cs->exception_index != EXCP_EXT_INTERRUPT) { + qemu_log("%s: PC " TARGET_FMT_lx " ERA 0x%08lx" " cause %d%s\n" + " ESTAT %08lx EXCFG 0x%08lx BADVA 0x%08lx BADI 0x%08lx \ + SYS_NUM %lu cpu %d asid 0x%lx" "\n", + __func__, env->pc, + is_refill(cs, env) ? env->CSR_TLBRERA : env->CSR_ERA, + cause, + is_refill(cs, env) ? "(refill)" : "", + env->CSR_ESTAT, env->CSR_ECFG, + is_refill(cs, env) ? env->CSR_TLBRBADV : env->CSR_BADV, + env->CSR_BADI, env->gpr[11], cs->cpu_index, + env->CSR_ASID + ); + } + cs->exception_index = EXCP_NONE; +} + +static void loongarch_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr addr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, uintptr_t retaddr) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + + if (access_type == MMU_INST_FETCH) { + do_raise_exception(env, EXCP_IBE, retaddr); + } else { + do_raise_exception(env, EXCP_DBE, retaddr); + } +} + +static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + if (interrupt_request & CPU_INTERRUPT_HARD) { + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + + if (cpu_loongarch_hw_interrupts_enabled(env) && + cpu_loongarch_hw_interrupts_pending(env)) { + /* Raise it */ + cs->exception_index = EXCP_EXT_INTERRUPT; + env->error_code = 0; + loongarch_cpu_do_interrupt(cs); + return true; + } + } + return false; +} +#endif + #ifdef CONFIG_TCG static void loongarch_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) @@ -92,7 +364,20 @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs, static bool loongarch_cpu_has_work(CPUState *cs) { +#ifdef CONFIG_USER_ONLY return true; +#else + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + bool has_work = false; + + if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && + cpu_loongarch_hw_interrupts_pending(env)) { + has_work = true; + } + + return has_work; +#endif } static void set_loongarch_cpucfg(CPULoongArchState *env) @@ -192,6 +477,7 @@ static void loongarch_cpu_reset(DeviceState *dev) set_loongarch_cpucfg(env); #ifndef CONFIG_USER_ONLY set_loongarch_csr(env); + env->pc = env->exception_base; #endif env->fcsr0_mask = 0x1f1f031f; env->fcsr0 = 0x0; @@ -223,6 +509,7 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) #ifndef CONFIG_USER_ONLY ls3a5k_mmu_init(env); + env->exception_base = 0x1C000000; #endif cpu_reset(cs); @@ -330,6 +617,12 @@ static struct TCGCPUOps loongarch_tcg_ops = { .initialize = loongarch_translate_init, .synchronize_from_tb = loongarch_cpu_synchronize_from_tb, .tlb_fill = loongarch_cpu_tlb_fill, + +#if !defined(CONFIG_USER_ONLY) + .cpu_exec_interrupt = loongarch_cpu_exec_interrupt, + .do_interrupt = loongarch_cpu_do_interrupt, + .do_transaction_failed = loongarch_cpu_do_transaction_failed, +#endif /* !CONFIG_USER_ONLY */ }; #endif /* CONFIG_TCG */ diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index d39c618d6b..182b03fb33 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -82,6 +82,7 @@ struct CPULoongArchState { CPU_LOONGARCH_CSR CPULoongArchTLBContext *tlb; int error_code; + target_ulong exception_base; #endif }; @@ -166,9 +167,12 @@ enum { EXCP_TLBPE, EXCP_TLBNX, EXCP_TLBNR, + EXCP_EXT_INTERRUPT, EXCP_DBP, + EXCP_IBE, + EXCP_DBE, - EXCP_LAST = EXCP_DBP, + EXCP_LAST = EXCP_DBE, }; #define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 From patchwork Tue Oct 19 07:34:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568853 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A0F2C433EF for ; Tue, 19 Oct 2021 07:40:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2000161374 for ; Tue, 19 Oct 2021 07:40:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 2000161374 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:44924 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjjf-0001O1-6R for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:40:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55898) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjf0-0001I6-2q for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:46 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34916 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjex-0004W9-9l for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:45 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S13; Tue, 19 Oct 2021 15:35:36 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 11/31] target/loongarch: Add stabletimer support Date: Tue, 19 Oct 2021 15:34:57 +0800 Message-Id: <1634628917-10031-12-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S13 X-Coremail-Antispam: 1UD129KBjvJXoW3Gr48JFWktFWxXFW7Ary7Wrg_yoWxKF47pF W7CFy3tr4rtrZ2y3s7tas0qr1DXw47G342qan29rZ2kanrJrs7Z34vvwsrXFyUJa1YgrWx ZF95Z3WagF47Z3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch add a stabletimer support. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/cpu.c | 1 + target/loongarch/cpu.h | 10 +++++ target/loongarch/csr_helper.c | 26 +++++++++++++ target/loongarch/meson.build | 1 + target/loongarch/stabletimer.c | 71 ++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+) create mode 100644 target/loongarch/stabletimer.c diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 3e3cf233db..2886dbd642 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -435,6 +435,7 @@ static void set_loongarch_csr(CPULoongArchState *env) env->CSR_CPUID = (cs->cpu_index & 0x1ff); env->CSR_EENTRY |= (uint64_t)0x80000000; env->CSR_TLBRENTRY |= (uint64_t)0x80000000; + env->CSR_TMID = cs->cpu_index; } #endif diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 182b03fb33..e77517d375 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -46,6 +46,9 @@ FIELD(FCSR0, CAUSE, 24, 5) extern const char * const regnames[]; extern const char * const fregnames[]; +#define N_IRQS 14 +#define IRQ_TIMER 11 + #define LOONGARCH_HFLAG_KU 0x00003 /* kernel/user mode mask */ #define LOONGARCH_HFLAG_UM 0x00003 /* user mode flag */ #define LOONGARCH_HFLAG_KM 0x00000 /* kernel mode flag */ @@ -84,6 +87,8 @@ struct CPULoongArchState { int error_code; target_ulong exception_base; #endif + void *irq[N_IRQS]; + QEMUTimer *timer; /* Internal timer */ }; /** @@ -181,4 +186,9 @@ enum { #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU +void cpu_loongarch_clock_init(LoongArchCPU *cpu); +uint64_t cpu_loongarch_get_stable_counter(CPULoongArchState *env); +uint64_t cpu_loongarch_get_stable_timer_ticks(CPULoongArchState *env); +void cpu_loongarch_store_stable_timer_config(CPULoongArchState *env, + uint64_t value); #endif /* LOONGARCH_CPU_H */ diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c index 9251bfa2a6..6cfb910799 100644 --- a/target/loongarch/csr_helper.c +++ b/target/loongarch/csr_helper.c @@ -14,6 +14,7 @@ #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "hw/irq.h" #include "cpu-csr.h" #include "tcg/tcg-ldst.h" @@ -78,7 +79,12 @@ target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t csr) CASE_CSR_RDQ(KS7) CASE_CSR_RDQ(KS8) CASE_CSR_RDQ(TMID) + CASE_CSR_RDQ(TCFG) + case LOONGARCH_CSR_TVAL: + v = cpu_loongarch_get_stable_timer_ticks(env); + break; CASE_CSR_RDQ(CNTC) + CASE_CSR_RDQ(TINTCLR) CASE_CSR_RDQ(LLBCTL) CASE_CSR_RDQ(IMPCTL1) CASE_CSR_RDQ(IMPCTL2) @@ -223,8 +229,16 @@ target_ulong helper_csr_wrq(CPULoongArchState *env, target_ulong val, CASE_CSR_WRQ(KS7) CASE_CSR_WRQ(KS8) CASE_CSR_WRQ(TMID) + case LOONGARCH_CSR_TCFG: + old_v = env->CSR_TCFG; + cpu_loongarch_store_stable_timer_config(env, val); + break; CASE_CSR_WRQ(TVAL) CASE_CSR_WRQ(CNTC) + case LOONGARCH_CSR_TINTCLR: + old_v = 0; + qemu_irq_lower(env->irq[IRQ_TIMER]); + break; CASE_CSR_WRQ(LLBCTL) CASE_CSR_WRQ(IMPCTL1) CASE_CSR_WRQ(IMPCTL2) @@ -373,8 +387,12 @@ void helper_csr_xchgq_r0(CPULoongArchState *env, target_ulong mask, uint64_t csr CASE_CSR_XCHGQ(KS7) CASE_CSR_XCHGQ(KS8) CASE_CSR_XCHGQ(TMID) + case LOONGARCH_CSR_TCFG: + cpu_loongarch_store_stable_timer_config(env, env->CSR_TCFG & (~mask)); + break; CASE_CSR_XCHGQ(TVAL) CASE_CSR_XCHGQ(CNTC) + CASE_CSR_XCHGQ(TINTCLR) CASE_CSR_XCHGQ(LLBCTL) CASE_CSR_XCHGQ(IMPCTL1) CASE_CSR_XCHGQ(IMPCTL2) @@ -471,6 +489,7 @@ void helper_csr_xchgq_r0(CPULoongArchState *env, target_ulong mask, uint64_t csr target_ulong helper_csr_xchgq(CPULoongArchState *env, target_ulong val, target_ulong mask, uint64_t csr) { + target_ulong tmp; target_ulong v = val & mask; #define CASE_CSR_XCHGQ(csr) \ @@ -523,8 +542,15 @@ target_ulong helper_csr_xchgq(CPULoongArchState *env, target_ulong val, CASE_CSR_XCHGQ(KS7) CASE_CSR_XCHGQ(KS8) CASE_CSR_XCHGQ(TMID) + case LOONGARCH_CSR_TCFG: + val = env->CSR_TCFG; + tmp = val & ~mask; + tmp |= v; + cpu_loongarch_store_stable_timer_config(env, tmp); + break; CASE_CSR_XCHGQ(TVAL) CASE_CSR_XCHGQ(CNTC) + CASE_CSR_XCHGQ(TINTCLR) CASE_CSR_XCHGQ(LLBCTL) CASE_CSR_XCHGQ(IMPCTL1) CASE_CSR_XCHGQ(IMPCTL2) diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build index 74f4a63d15..fd0365cffd 100644 --- a/target/loongarch/meson.build +++ b/target/loongarch/meson.build @@ -18,6 +18,7 @@ loongarch_softmmu_ss.add(files( 'machine.c', 'tlb_helper.c', 'csr_helper.c', + 'stabletimer.c', )) loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss]) diff --git a/target/loongarch/stabletimer.c b/target/loongarch/stabletimer.c new file mode 100644 index 0000000000..a3bf32a865 --- /dev/null +++ b/target/loongarch/stabletimer.c @@ -0,0 +1,71 @@ +/* + * QEMU LoongArch timer support + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "hw/irq.h" +#include "hw/loongarch/loongarch.h" +#include "qemu/timer.h" +#include "cpu.h" + +#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ +#define STABLETIMER_TICK_MASK 0xfffffffffffcUL +#define STABLETIMER_ENABLE 0x1UL + +/* LoongArch timer */ +uint64_t cpu_loongarch_get_stable_counter(CPULoongArchState *env) +{ + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD; +} + +uint64_t cpu_loongarch_get_stable_timer_ticks(CPULoongArchState *env) +{ + uint64_t now, expire; + + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + expire = timer_expire_time_ns(env->timer); + + return (expire - now) / TIMER_PERIOD; +} + +void cpu_loongarch_store_stable_timer_config(CPULoongArchState *env, + uint64_t value) +{ + uint64_t now, next; + + env->CSR_TCFG = value; + if (value & STABLETIMER_ENABLE) { + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + next = now + (value & STABLETIMER_TICK_MASK) * TIMER_PERIOD; + timer_mod(env->timer, next); + } +} + +static void loongarch_stable_timer_cb(void *opaque) +{ + CPULoongArchState *env; + uint64_t now, next; + + env = opaque; + if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) { + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + next = now + (env->CSR_TCFG & STABLETIMER_TICK_MASK) * TIMER_PERIOD; + timer_mod(env->timer, next); + } else { + env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0); + } + + qemu_irq_raise(env->irq[IRQ_TIMER]); +} + +void cpu_loongarch_clock_init(LoongArchCPU *cpu) +{ + CPULoongArchState *env = &cpu->env; + + env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + &loongarch_stable_timer_cb, env); +} From patchwork Tue Oct 19 07:34:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568883 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A47B4C433F5 for ; Tue, 19 Oct 2021 07:46:46 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 71F9961374 for ; Tue, 19 Oct 2021 07:46:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 71F9961374 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:33748 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjpd-0004V7-Gs for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:46:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55996) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfC-0001nM-ED for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:59 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35008 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjf9-0004YK-OV for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:58 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S14; Tue, 19 Oct 2021 15:35:37 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 12/31] target/loongarch: Add timer related instructions support. Date: Tue, 19 Oct 2021 15:34:58 +0800 Message-Id: <1634628917-10031-13-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S14 X-Coremail-Antispam: 1UD129KBjvJXoWxGryUAryxWryxAr4UXrW7twb_yoW5KFWrpF 42krWUGrWUKrZ3XayfJws0grn8Xa18Kw4Iqa9ayw4rCF47XwnFvF10q3sIkFy5Jw1kWrya vFs5A34DGF47X3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This includes: -RDTIME{L/H}.W -RDTIME.D Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- target/loongarch/helper.h | 2 ++ target/loongarch/insn_trans/trans_core.c | 23 +++++++++++++++++++++ target/loongarch/insn_trans/trans_extra.c | 2 ++ target/loongarch/op_helper.c | 25 +++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 8544771790..b4ed62896f 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -116,4 +116,6 @@ DEF_HELPER_4(lddir, tl, env, tl, tl, i32) DEF_HELPER_4(ldpte, void, env, tl, tl, i32) DEF_HELPER_1(ertn, void, env) DEF_HELPER_1(idle, void, env) +DEF_HELPER_4(rdtime_w, void, env, tl, tl, i64) +DEF_HELPER_3(rdtime_d, void, env, tl, tl) #endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c index 7fa13e65b9..24eb12b97a 100644 --- a/target/loongarch/insn_trans/trans_core.c +++ b/target/loongarch/insn_trans/trans_core.c @@ -276,4 +276,27 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a) return true; } +static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a) +{ + TCGv t0 = tcg_constant_tl(a->rd); + TCGv t1 = tcg_constant_tl(a->rj); + gen_helper_rdtime_w(cpu_env, t0, t1, tcg_constant_tl(0)); + return true; +} + +static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a) +{ + TCGv t0 = tcg_constant_tl(a->rd); + TCGv t1 = tcg_constant_tl(a->rj); + gen_helper_rdtime_w(cpu_env, t0, t1, tcg_constant_tl(1)); + return true; +} + +static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) +{ + TCGv t0 = tcg_constant_tl(a->rd); + TCGv t1 = tcg_constant_tl(a->rj); + gen_helper_rdtime_d(cpu_env, t0, t1); + return true; +} #endif diff --git a/target/loongarch/insn_trans/trans_extra.c b/target/loongarch/insn_trans/trans_extra.c index 8da3b404f3..426b67f154 100644 --- a/target/loongarch/insn_trans/trans_extra.c +++ b/target/loongarch/insn_trans/trans_extra.c @@ -36,6 +36,7 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) return true; } +#ifdef CONFIG_USER_ONLY static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a) { tcg_gen_movi_tl(cpu_gpr[a->rd], 0); @@ -53,6 +54,7 @@ static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) tcg_gen_movi_tl(cpu_gpr[a->rd], 0); return true; } +#endif static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) { diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c index 4547880c8f..41b1ec2f1b 100644 --- a/target/loongarch/op_helper.c +++ b/target/loongarch/op_helper.c @@ -130,4 +130,29 @@ void helper_idle(CPULoongArchState *env) do_raise_exception(env, EXCP_HLT, 0); } +void helper_rdtime_w(CPULoongArchState *env, target_ulong rd, + target_ulong rj, target_ulong high) +{ + if (rd) { + if (high) { + env->gpr[rd] = cpu_loongarch_get_stable_counter(env) >> 32; + } else { + env->gpr[rd] = cpu_loongarch_get_stable_counter(env) & 0xffffffff; + } + } + if (rj) { + env->gpr[rj] = env->CSR_TMID; + } +} + +void helper_rdtime_d(CPULoongArchState *env, target_ulong rd, target_ulong rj) +{ + if (rd) { + env->gpr[rd] = cpu_loongarch_get_stable_counter(env); + } + if (rj) { + env->gpr[rj] = env->CSR_TMID; + } +} + #endif /* !CONFIG_USER_ONLY */ From patchwork Tue Oct 19 07:34:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568899 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F204C433EF for ; Tue, 19 Oct 2021 07:49:57 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DBB8A611EF for ; Tue, 19 Oct 2021 07:49:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org DBB8A611EF Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:42344 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjsh-0001t5-EF for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:49:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56034) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfE-0001qA-33 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:00 -0400 Received: from mail.loongson.cn ([114.242.206.163]:34974 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjf8-0004XH-PJ for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:35:59 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S15; Tue, 19 Oct 2021 15:35:37 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform Date: Tue, 19 Oct 2021 15:34:59 +0800 Message-Id: <1634628917-10031-14-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S15 X-Coremail-Antispam: 1UD129KBjvJXoW3Xr1rKr43GF1xXr1rtrykuFg_yoWfAFW8pF n5CasakF4UtFW7J393JFn7WF1rXFs3C34UJrW7uw1Iyayxtw1qvrnrKFWUt3y7GrWqqF45 XaykG3W2ga18JaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This is a model of the PCIe Host Bridge found on a Loongson-5000 processor. It includes a interrupt controller, some interface for pci and nonpci devices we only emulate part devices for tcg mode. It support for MSI and MSIX interrupt sources. For more detailed info about ls7a1000 you can see the doc at https://github.com/loongson/LoongArch-Documentation/releases/latest/ download/Loongson-7A1000-usermanual-2.00-EN.pdf Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/pci-host/Kconfig | 4 + hw/pci-host/ls7a.c | 188 +++++++++++++++++++++++++++++++++++++ hw/pci-host/meson.build | 1 + include/hw/pci-host/ls7a.h | 48 ++++++++++ 4 files changed, 241 insertions(+) create mode 100644 hw/pci-host/ls7a.c create mode 100644 include/hw/pci-host/ls7a.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index 2b5f7d58cc..b02a9d1454 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -77,3 +77,7 @@ config MV64361 bool select PCI select I8259 + +config PCI_EXPRESS_7A + bool + select PCI_EXPRESS diff --git a/hw/pci-host/ls7a.c b/hw/pci-host/ls7a.c new file mode 100644 index 0000000000..1d6d5ea35a --- /dev/null +++ b/hw/pci-host/ls7a.c @@ -0,0 +1,188 @@ +/* + * QEMU Loongson 7A1000 North Bridge Emulation + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" + +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "qapi/error.h" +#include "hw/irq.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pci_bus.h" +#include "sysemu/reset.h" +#include "hw/pci-host/ls7a.h" +#include "migration/vmstate.h" + +static const VMStateDescription vmstate_ls7a_pcie = { + .name = "LS7A_PCIE", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, LS7APCIState), + VMSTATE_END_OF_LIST() + } +}; + +static void pci_ls7a_config_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + pci_data_write(opaque, addr, val, size); +} + +static uint64_t pci_ls7a_config_read(void *opaque, + hwaddr addr, unsigned size) +{ + uint64_t val; + + val = pci_data_read(opaque, addr, size); + + return val; +} + +static const MemoryRegionOps pci_ls7a_config_ops = { + .read = pci_ls7a_config_read, + .write = pci_ls7a_config_write, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void ls7a_pciehost_realize(DeviceState *dev, Error **errp) +{ + LS7APCIEHost *pciehost = LS7A_PCIE_HOST_BRIDGE(dev); + PCIExpressHost *e = PCIE_HOST_BRIDGE(dev); + PCIHostState *phb = PCI_HOST_BRIDGE(e); + + phb->bus = pci_register_root_bus(dev, "pcie.0", NULL, + NULL, pciehost, + get_system_memory(), get_system_io(), + PCI_DEVFN(1, 0), 128, TYPE_PCIE_BUS); + + memory_region_init_io(&pciehost->pci_conf, OBJECT(dev), + &pci_ls7a_config_ops, phb->bus, + "ls7a_pci_conf", HT1LO_PCICFG_SIZE); + memory_region_add_subregion(get_system_memory(), HT1LO_PCICFG_BASE, + &pciehost->pci_conf); + + /* Add ls7a pci-io */ + memory_region_init_alias(&pciehost->pci_io, OBJECT(dev), "ls7a-pci-io", + get_system_io(), 0, LS7A_PCI_IO_SIZE); + memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE, + &pciehost->pci_io); + + pcie_host_mmcfg_update(e, true, LS_PCIECFG_BASE, LS_PCIECFG_SIZE); +} + +PCIBus *ls7a_init(MachineState *machine, qemu_irq *pic) +{ + DeviceState *dev; + PCIHostState *phb; + LS7APCIState *pbs; + LS7APCIEHost *pciehost; + PCIDevice *pci_dev; + PCIExpressHost *e; + + dev = qdev_new(TYPE_LS7A_PCIE_HOST_BRIDGE); + e = PCIE_HOST_BRIDGE(dev); + phb = PCI_HOST_BRIDGE(e); + pciehost = LS7A_PCIE_HOST_BRIDGE(dev); + pciehost->pic = pic; + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + pci_dev = pci_new(PCI_DEVFN(0, 0), TYPE_LS7A_PCIE); + pbs = LS7A_PCIE(pci_dev); + pbs->pciehost = pciehost; + pbs->pciehost->pci_dev = pbs; + + pci_realize_and_unref(pci_dev, phb->bus, &error_fatal); + + return phb->bus; +} + +static void ls7a_reset(DeviceState *qdev) +{ + uint64_t wmask; + wmask = ~(-1); + PCIDevice *dev = PCI_DEVICE(qdev); + + pci_set_word(dev->config + PCI_STATUS, 0x0010); + pci_set_word(dev->wmask + PCI_STATUS, wmask & 0xffff); + pci_set_word(dev->cmask + PCI_STATUS, 0xffff); + pci_set_byte(dev->config + PCI_HEADER_TYPE, 0x1); + pci_set_byte(dev->wmask + PCI_HEADER_TYPE, wmask & 0xff); + pci_set_byte(dev->cmask + PCI_HEADER_TYPE, 0xff); + pci_set_word(dev->config + PCI_SUBSYSTEM_VENDOR_ID, 0x0014); + pci_set_word(dev->wmask + PCI_SUBSYSTEM_VENDOR_ID, wmask & 0xffff); + pci_set_word(dev->cmask + PCI_SUBSYSTEM_VENDOR_ID, 0xffff); + pci_set_word(dev->config + PCI_SUBSYSTEM_ID, 0x7a00); + pci_set_word(dev->wmask + PCI_SUBSYSTEM_ID, wmask & 0xffff); + pci_set_word(dev->cmask + PCI_SUBSYSTEM_ID, 0xffff); + pci_set_byte(dev->config + PCI_CAPABILITY_LIST, 0x40); + pci_set_byte(dev->wmask + PCI_CAPABILITY_LIST, wmask & 0xff); + pci_set_byte(dev->cmask + PCI_CAPABILITY_LIST, 0xff); +} + +static void ls7a_pcie_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->vendor_id = 0x0014; + k->device_id = 0x7a00; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->reset = ls7a_reset; + dc->desc = "LS7A1000 PCIE Host bridge"; + dc->vmsd = &vmstate_ls7a_pcie; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->user_creatable = false; +} + +static const TypeInfo ls7a_pcie_device_info = { + .name = TYPE_LS7A_PCIE, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(LS7APCIState), + .class_init = ls7a_pcie_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void ls7a_pciehost_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + dc->realize = ls7a_pciehost_realize; + dc->fw_name = "pci"; + dc->user_creatable = false; +} + +static const TypeInfo ls7a_pciehost_info = { + .name = TYPE_LS7A_PCIE_HOST_BRIDGE, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(LS7APCIEHost), + .class_init = ls7a_pciehost_class_init, +}; + +static void ls7a_register_types(void) +{ + type_register_static(&ls7a_pciehost_info); + type_register_static(&ls7a_pcie_device_info); +} + +type_init(ls7a_register_types) diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index 4c4f39c15c..c4955455fd 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -11,6 +11,7 @@ pci_ss.add(when: 'CONFIG_PCI_SABRE', if_true: files('sabre.c')) pci_ss.add(when: 'CONFIG_XEN_IGD_PASSTHROUGH', if_true: files('xen_igd_pt.c')) pci_ss.add(when: 'CONFIG_REMOTE_PCIHOST', if_true: files('remote.c')) pci_ss.add(when: 'CONFIG_SH_PCI', if_true: files('sh_pci.c')) +pci_ss.add(when: 'CONFIG_PCI_EXPRESS_7A', if_true: files('ls7a.c')) # PPC devices pci_ss.add(when: 'CONFIG_RAVEN_PCI', if_true: files('raven.c')) diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h new file mode 100644 index 0000000000..4c95a11ab8 --- /dev/null +++ b/include/hw/pci-host/ls7a.h @@ -0,0 +1,48 @@ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef HW_LS7A_H +#define HW_LS7A_H + +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/pci-host/pam.h" +#include "qemu/units.h" +#include "qemu/range.h" +#include "qom/object.h" + +#define HT1LO_PCICFG_BASE 0x1a000000 +#define HT1LO_PCICFG_SIZE 0x02000000 + +#define LS_PCIECFG_BASE 0x20000000 +#define LS_PCIECFG_SIZE 0x08000000 + +#define LS7A_PCI_IO_BASE 0x18000000UL +#define LS7A_PCI_IO_SIZE 0x00010000 +typedef struct LS7APCIState LS7APCIState; +typedef struct LS7APCIEHost { + PCIExpressHost parent_obj; + LS7APCIState *pci_dev; + qemu_irq *pic; + MemoryRegion pci_conf; + MemoryRegion pci_io; +} LS7APCIEHost; + +struct LS7APCIState { + PCIDevice dev; + LS7APCIEHost *pciehost; +}; + +#define TYPE_LS7A_PCIE_HOST_BRIDGE "ls7a1000-pciehost" +OBJECT_DECLARE_SIMPLE_TYPE(LS7APCIEHost, LS7A_PCIE_HOST_BRIDGE) + +#define TYPE_LS7A_PCIE "ls7a1000_pcie" +OBJECT_DECLARE_SIMPLE_TYPE(LS7APCIState, LS7A_PCIE) + +PCIBus *ls7a_init(MachineState *machine, qemu_irq *irq); +#endif /* HW_LS7A_H */ From patchwork Tue Oct 19 07:35:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568907 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E22E0C433EF for ; Tue, 19 Oct 2021 07:54:55 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9330F611EF for ; Tue, 19 Oct 2021 07:54:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 9330F611EF Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:51672 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjxW-0008MJ-Nd for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:54:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56122) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfP-0001x5-6K for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:11 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35048 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfA-0004ZP-AX for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:10 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S16; Tue, 19 Oct 2021 15:35:38 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 14/31] hw/loongarch: Add a virt loongarch 3A5000 board support Date: Tue, 19 Oct 2021 15:35:00 +0800 Message-Id: <1634628917-10031-15-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S16 X-Coremail-Antispam: 1UD129KBjvAXoW3Zw4xArykJw4xGw43tFW7XFb_yoW8XryxXo WavFy7Kw48Gr1avrn5KrnxWrW7Kr1vkF45AayfZa98Ga10yF15JFyDKwn0yFy3JFn5tr45 uayagFsrJ34xtr95n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" LoongArch is a new RISC ISA, support 32bit mode or 64bit mode. Now we only add 64bit support. More detailed info you can see https://github.com/loongson/LoongArch-Documentation Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- .../devices/loongarch64-softmmu/default.mak | 3 + configs/targets/loongarch64-softmmu.mak | 2 + hw/Kconfig | 1 + hw/loongarch/Kconfig | 3 + hw/loongarch/ls3a5000_virt.c | 207 ++++++++++++++++++ hw/loongarch/meson.build | 4 + hw/meson.build | 1 + include/exec/poison.h | 2 + include/hw/loongarch/loongarch.h | 47 ++++ include/sysemu/arch_init.h | 1 + qapi/machine.json | 2 +- target/Kconfig | 1 + target/loongarch/Kconfig | 2 + target/loongarch/cpu.c | 8 + target/loongarch/cpu.h | 4 + 15 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 configs/devices/loongarch64-softmmu/default.mak create mode 100644 configs/targets/loongarch64-softmmu.mak create mode 100644 hw/loongarch/Kconfig create mode 100644 hw/loongarch/ls3a5000_virt.c create mode 100644 hw/loongarch/meson.build create mode 100644 include/hw/loongarch/loongarch.h create mode 100644 target/loongarch/Kconfig diff --git a/configs/devices/loongarch64-softmmu/default.mak b/configs/devices/loongarch64-softmmu/default.mak new file mode 100644 index 0000000000..a6705b9e4a --- /dev/null +++ b/configs/devices/loongarch64-softmmu/default.mak @@ -0,0 +1,3 @@ +# Default configuration for loongarch64-softmmu + +CONFIG_LOONGSON_3A5000=y diff --git a/configs/targets/loongarch64-softmmu.mak b/configs/targets/loongarch64-softmmu.mak new file mode 100644 index 0000000000..77c266b3b1 --- /dev/null +++ b/configs/targets/loongarch64-softmmu.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=loongarch64 +TARGET_BASE_ARCH=loongarch diff --git a/hw/Kconfig b/hw/Kconfig index ad20cce0a9..f71b2155ed 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -49,6 +49,7 @@ source avr/Kconfig source cris/Kconfig source hppa/Kconfig source i386/Kconfig +source loongarch/Kconfig source m68k/Kconfig source microblaze/Kconfig source mips/Kconfig diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig new file mode 100644 index 0000000000..720822f32c --- /dev/null +++ b/hw/loongarch/Kconfig @@ -0,0 +1,3 @@ +config LOONGSON_3A5000 + bool + select PCI_EXPRESS_7A diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c new file mode 100644 index 0000000000..71ffc2b81f --- /dev/null +++ b/hw/loongarch/ls3a5000_virt.c @@ -0,0 +1,207 @@ +/* + * QEMU loongson 3a5000 develop board emulation + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/units.h" +#include "qemu/datadir.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" +#include "hw/loongarch/loongarch.h" +#include "hw/pci-host/ls7a.h" + +CPULoongArchState *cpu_states[LOONGARCH_MAX_VCPUS]; + +static void main_cpu_reset(void *opaque) +{ + LoongArchCPU *cpu = opaque; + + cpu_reset(CPU(cpu)); +} + +static uint64_t loongarch_pm_mem_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void loongarch_pm_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + + if (addr != PM_CNT_MODE) { + return; + } + + switch (val) { + case 0x00: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; + case 0xff: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + return; + default: + return; + } +} + +static const MemoryRegionOps loongarch_pm_ops = { + .read = loongarch_pm_mem_read, + .write = loongarch_pm_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +#define LOONGARCH_SIMPLE_MMIO_OPS(ADDR, NAME, SIZE) \ +({\ + MemoryRegion *iomem = g_new(MemoryRegion, 1);\ + memory_region_init_io(iomem, NULL, &loongarch_qemu_ops,\ + (void *)ADDR, NAME, SIZE);\ + memory_region_add_subregion_overlap(address_space_mem, ADDR, iomem, 1);\ +}) + +static void loongarch_qemu_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ +} + +static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size) +{ + uint64_t feature = 0UL; + addr = ((hwaddr)(long)opaque) + addr; + addr = addr & 0xffffffff; + switch (addr) { + case FEATURE_REG: + feature |= 1UL << IOCSRF_MSI | 1UL << IOCSRF_EXTIOI | + 1UL << IOCSRF_CSRIPI; + return feature ; + case VENDOR_REG: + return *(uint64_t *)"Loongson-3A5000"; + case CPUNAME_REG: + return *(uint64_t *)"3A5000"; + } + return 0; +} + +static const MemoryRegionOps loongarch_qemu_ops = { + .read = loongarch_qemu_read, + .write = loongarch_qemu_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, +}; + +static void ls3a5000_virt_init(MachineState *machine) +{ + const char *cpu_model = machine->cpu_type; + LoongArchCPU *cpu; + CPULoongArchState *env; + uint64_t lowram_size = 0, highram_size = 0; + MemoryRegion *lowmem = g_new(MemoryRegion, 1); + char *ramName = NULL; + ram_addr_t ram_size = machine->ram_size; + MemoryRegion *address_space_mem = get_system_memory(); + int i; + MemoryRegion *iomem = NULL; + + if (!cpu_model) { + cpu_model = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000"); + } + if (!strstr(cpu_model, "Loongson-3A5000")) { + error_report("Loongarch/TCG needs cpu type Loongson-3A5000"); + exit(1); + } + + /* init CPUs */ + for (i = 0; i < machine->smp.cpus; i++) { + Object *cpuobj = NULL; + CPUState *cs; + + cpuobj = object_new(machine->cpu_type); + + cs = CPU(cpuobj); + cs->cpu_index = i; + + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); + object_unref(cpuobj); + + cpu = LOONGARCH_CPU(cs); + if (cpu == NULL) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + env = &cpu->env; + cpu_states[i] = env; + + cpu_loongarch_clock_init(cpu); + qemu_register_reset(main_cpu_reset, cpu); + } + + ramName = g_strdup_printf("loongarch.lowram"); + lowram_size = MIN(ram_size, 256 * 0x100000); + memory_region_init_alias(lowmem, NULL, ramName, machine->ram, + 0, lowram_size); + memory_region_add_subregion(address_space_mem, 0, lowmem); + + highram_size = ram_size > lowram_size ? ram_size - 256 * 0x100000 : 0; + if (highram_size > 0) { + MemoryRegion *highmem = g_new(MemoryRegion, 1); + ramName = g_strdup_printf("loongarch.highram"); + memory_region_init_alias(highmem, NULL, ramName, machine->ram, + lowram_size, highram_size); + memory_region_add_subregion(address_space_mem, 0x90000000, highmem); + } + + /*Add PM mmio memory for reboot and shutdown*/ + iomem = g_new(MemoryRegion, 1); + memory_region_init_io(iomem, NULL, &loongarch_pm_ops, NULL, + "loongarch_pm", PM_MMIO_SIZE); + memory_region_add_subregion(address_space_mem, + PM_MMIO_ADDR, iomem); + + LOONGARCH_SIMPLE_MMIO_OPS(FEATURE_REG, "loongarch_feature", 0x8); + LOONGARCH_SIMPLE_MMIO_OPS(VENDOR_REG, "loongarch_vendor", 0x8); + LOONGARCH_SIMPLE_MMIO_OPS(CPUNAME_REG, "loongarch_cpuname", 0x8); + LOONGARCH_SIMPLE_MMIO_OPS(MISC_FUNC_REG, "loongarch_misc", 0x8); + LOONGARCH_SIMPLE_MMIO_OPS(FREQ_REG, "loongarch_freq", 0x8); +} + +static void loongarch_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Loongson-5000 LS7A1000 machine"; + mc->init = ls3a5000_virt_init; + mc->default_ram_size = 1 * GiB; + mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000"); + mc->default_ram_id = "loongarch.ram"; + mc->max_cpus = LOONGARCH_MAX_VCPUS; + mc->is_default = 1; + mc->default_kernel_irqchip_split = false; + mc->block_default_type = IF_VIRTIO; + mc->default_boot_order = "c"; + mc->no_cdrom = 1; +} + +static const TypeInfo loongarch_machine_types[] = { + { + .name = TYPE_LOONGARCH_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(LoongarchMachineState), + .class_init = loongarch_class_init, + } +}; + +DEFINE_TYPES(loongarch_machine_types) diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build new file mode 100644 index 0000000000..1e743cadb8 --- /dev/null +++ b/hw/loongarch/meson.build @@ -0,0 +1,4 @@ +loongarch_ss = ss.source_set() +loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c')) + +hw_arch += {'loongarch': loongarch_ss} diff --git a/hw/meson.build b/hw/meson.build index b3366c888e..95202649b7 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -49,6 +49,7 @@ subdir('avr') subdir('cris') subdir('hppa') subdir('i386') +subdir('loongarch') subdir('m68k') subdir('microblaze') subdir('mips') diff --git a/include/exec/poison.h b/include/exec/poison.h index 7ad4ad18e8..590bc305c7 100644 --- a/include/exec/poison.h +++ b/include/exec/poison.h @@ -14,6 +14,7 @@ #pragma GCC poison TARGET_CRIS #pragma GCC poison TARGET_HEXAGON #pragma GCC poison TARGET_HPPA +#pragma GCC poison TARGET_LOONGARCH64 #pragma GCC poison TARGET_M68K #pragma GCC poison TARGET_MICROBLAZE #pragma GCC poison TARGET_MIPS @@ -73,6 +74,7 @@ #pragma GCC poison CONFIG_HPPA_DIS #pragma GCC poison CONFIG_I386_DIS #pragma GCC poison CONFIG_HEXAGON_DIS +#pragma GCC poison CONFIG_LOONGARCH_DIS #pragma GCC poison CONFIG_M68K_DIS #pragma GCC poison CONFIG_MICROBLAZE_DIS #pragma GCC poison CONFIG_MIPS_DIS diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h new file mode 100644 index 0000000000..087a988c34 --- /dev/null +++ b/include/hw/loongarch/loongarch.h @@ -0,0 +1,47 @@ +/* + * Definitions for loongarch board emulation. + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef HW_LOONGARCH_H +#define HW_LOONGARCH_H + +#include "target/loongarch/cpu.h" +#include "qemu-common.h" +#include "hw/boards.h" +#include "qemu/queue.h" + +#define LOONGARCH_MAX_VCPUS 4 +#define PM_MMIO_ADDR 0x10080000UL +#define PM_MMIO_SIZE 0x100 +#define PM_CNT_MODE 0x10 +#define FEATURE_REG 0x1fe00008 +#define IOCSRF_TEMP 0 +#define IOCSRF_NODECNT 1 +#define IOCSRF_MSI 2 +#define IOCSRF_EXTIOI 3 +#define IOCSRF_CSRIPI 4 +#define IOCSRF_FREQCSR 5 +#define IOCSRF_FREQSCALE 6 +#define IOCSRF_DVFSV1 7 +#define IOCSRF_GMOD 9 +#define IOCSRF_VM 11 + +#define VENDOR_REG 0x1fe00010 +#define CPUNAME_REG 0x1fe00020 +#define MISC_FUNC_REG 0x1fe00420 +#define FREQ_REG 0x1fe001d0 + +typedef struct LoongarchMachineState { + /*< private >*/ + MachineState parent_obj; + +} LoongarchMachineState; + +#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("loongson7a") +DECLARE_INSTANCE_CHECKER(LoongarchMachineState, LOONGARCH_MACHINE, + TYPE_LOONGARCH_MACHINE) +#endif diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 70c579560a..3ac3634bbb 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -24,6 +24,7 @@ enum { QEMU_ARCH_RX = (1 << 20), QEMU_ARCH_AVR = (1 << 21), QEMU_ARCH_HEXAGON = (1 << 22), + QEMU_ARCH_LOONGARCH = (1 << 23), }; extern const uint32_t arch_type; diff --git a/qapi/machine.json b/qapi/machine.json index 5db54df298..0ffe84f074 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -30,7 +30,7 @@ ## { 'enum' : 'SysEmuTarget', 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', - 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', + 'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', 'sh4eb', 'sparc', 'sparc64', 'tricore', diff --git a/target/Kconfig b/target/Kconfig index ae7f24fc66..83da0bd293 100644 --- a/target/Kconfig +++ b/target/Kconfig @@ -4,6 +4,7 @@ source avr/Kconfig source cris/Kconfig source hppa/Kconfig source i386/Kconfig +source loongarch/Kconfig source m68k/Kconfig source microblaze/Kconfig source mips/Kconfig diff --git a/target/loongarch/Kconfig b/target/loongarch/Kconfig new file mode 100644 index 0000000000..46b26b1a85 --- /dev/null +++ b/target/loongarch/Kconfig @@ -0,0 +1,2 @@ +config LOONGARCH64 + bool diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 2886dbd642..532b229c05 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -12,6 +12,7 @@ #include "qemu/module.h" #include "sysemu/qtest.h" #include "exec/exec-all.h" +#include "hw/qdev-properties.h" #include "qapi/qapi-commands-machine-target.h" #include "migration/vmstate.h" #include "cpu.h" @@ -537,6 +538,12 @@ static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) return oc; } +static Property loongarch_cpu_properties[] = { + DEFINE_PROP_INT32("core-id", LoongArchCPU, core_id, -1), + DEFINE_PROP_UINT32("id", LoongArchCPU, id, UNASSIGNED_CPU_ID), + DEFINE_PROP_END_OF_LIST() +}; + void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) { LoongArchCPU *cpu = LOONGARCH_CPU(cs); @@ -636,6 +643,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data) device_class_set_parent_realize(dc, loongarch_cpu_realizefn, &lacc->parent_realize); device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset); + device_class_set_props(dc, loongarch_cpu_properties); cc->class_by_name = loongarch_cpu_class_by_name; cc->has_work = loongarch_cpu_has_work; diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index e77517d375..cfdcf1d4a0 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -16,6 +16,8 @@ #define TCG_GUEST_DEFAULT_MO (0) +#define UNASSIGNED_CPU_ID 0xFFFFFFFF + #define FCSR0_M1 0x1f /* FCSR1 mask, Enables */ #define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */ #define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */ @@ -104,6 +106,8 @@ struct LoongArchCPU { CPUNegativeOffsetState neg; CPULoongArchState env; + uint32_t id; + int32_t core_id; }; #define TYPE_LOONGARCH_CPU "loongarch64-cpu" From patchwork Tue Oct 19 07:35:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568857 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05F67C433F5 for ; Tue, 19 Oct 2021 07:41:01 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ADB1260FD9 for ; Tue, 19 Oct 2021 07:41:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org ADB1260FD9 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:45724 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjk2-0001vr-Ca for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:40:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56138) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfR-00020Y-Cx for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:13 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35052 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfA-0004ZX-F3 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:12 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S17; Tue, 19 Oct 2021 15:35:39 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 15/31] hw/loongarch: Add loongarch cpu interrupt support(CPUINTC) Date: Tue, 19 Oct 2021 15:35:01 +0800 Message-Id: <1634628917-10031-16-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S17 X-Coremail-Antispam: 1UD129KBjvJXoWxWw48AFWkGF13AF45tr4xWFg_yoWrCw18pr y3urnxtF48GrnrXrZ8t345Xrn8Jwn7Wr12vF4SkryIkrsrAr15uw1vyrykZFyUt3yrJFZY gr95K3W7WF4UJw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=loongson.cn X-Spam_score_int: 0 X-Spam_score: -0.0 X-Spam_bar: / X-Spam_report: (-0.0 / 5.0 requ) SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Loongson-3A5000 support 14 interrupts from 64 - 77(Timer->75 IPI->76) Loongson-3A5000 and ls7a form a legacy model and extended model irq hierarchy.Tcg mode emulate a simplified extended model which has no Legacy I/O Interrupt Controller(LIOINTC) and LPC. e.g: | +-----+ +---------+ +-------+ | | | IPI |--> | CPUINTC | <-- | Timer | | | +-----+ +---------+ +-------+ | | ^ | | | | | +---------+ | | EIOINTC | | +---------+ | ^ ^ | | | | | | +---------+ +---------+ | | | PCH-PIC | | PCH-MSI | | | +---------+ +---------+ | | ^ ^ ^ | | | | | | | +---------+ +---------+ +---------+ | | | UARTs | | Devices | | Devices | | | +---------+ +---------+ +---------+ | | ^ | The following series patch will realize the interrupt controller in this model. More detailed info can be found at the kernel doc or manual 1.https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/ linux-loongson.git/tree/Documentation/loongarch?h=loongarch-next 2.https://github.com/loongson/LoongArch-Documentation Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/loongarch/loongarch_int.c | 62 ++++++++++++++++++++++++++++++++ hw/loongarch/ls3a5000_virt.c | 2 ++ hw/loongarch/meson.build | 1 + include/hw/loongarch/loongarch.h | 2 ++ 4 files changed, 67 insertions(+) create mode 100644 hw/loongarch/loongarch_int.c diff --git a/hw/loongarch/loongarch_int.c b/hw/loongarch/loongarch_int.c new file mode 100644 index 0000000000..7282bc28f6 --- /dev/null +++ b/hw/loongarch/loongarch_int.c @@ -0,0 +1,62 @@ +/* + * QEMU LOONGARCH interrupt support + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "hw/irq.h" +#include "hw/loongarch/loongarch.h" +#include "cpu.h" + +static void cpu_loongarch_irq_request(void *opaque, int irq, int level) +{ + LoongArchCPU *cpu = opaque; + CPULoongArchState *env = &cpu->env; + CPUState *cs = CPU(cpu); + bool locked = false; + + if (irq < 0 || irq > N_IRQS) { + return; + } + + /* Make sure locking works even if BQL is already held by the caller */ + if (!qemu_mutex_iothread_locked()) { + locked = true; + qemu_mutex_lock_iothread(); + } + + if (level) { + env->CSR_ESTAT |= 1 << irq; + } else { + env->CSR_ESTAT &= ~(1 << irq); + } + + if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } + + if (locked) { + qemu_mutex_unlock_iothread(); + } +} + +void cpu_loongarch_init_irq(LoongArchCPU *cpu) +{ + CPULoongArchState *env = &cpu->env; + qemu_irq *qi; + int i; + + qi = qemu_allocate_irqs(cpu_loongarch_irq_request, cpu, N_IRQS); + for (i = 0; i < N_IRQS; i++) { + env->irq[i] = qi[i]; + } + g_free(qi); +} + + diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c index 71ffc2b81f..222c76bc0d 100644 --- a/hw/loongarch/ls3a5000_virt.c +++ b/hw/loongarch/ls3a5000_virt.c @@ -145,6 +145,8 @@ static void ls3a5000_virt_init(MachineState *machine) env = &cpu->env; cpu_states[i] = env; + /* Init CPU internal devices */ + cpu_loongarch_init_irq(cpu); cpu_loongarch_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); } diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build index 1e743cadb8..a972210680 100644 --- a/hw/loongarch/meson.build +++ b/hw/loongarch/meson.build @@ -1,4 +1,5 @@ loongarch_ss = ss.source_set() +loongarch_ss.add(files('loongarch_int.c')) loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c')) hw_arch += {'loongarch': loongarch_ss} diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h index 087a988c34..0edc313546 100644 --- a/include/hw/loongarch/loongarch.h +++ b/include/hw/loongarch/loongarch.h @@ -44,4 +44,6 @@ typedef struct LoongarchMachineState { #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("loongson7a") DECLARE_INSTANCE_CHECKER(LoongarchMachineState, LOONGARCH_MACHINE, TYPE_LOONGARCH_MACHINE) + +void cpu_loongarch_init_irq(LoongArchCPU *cpu); #endif From patchwork Tue Oct 19 07:35:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568903 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0EA3C433F5 for ; Tue, 19 Oct 2021 07:51:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5FBFA60F46 for ; Tue, 19 Oct 2021 07:51:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5FBFA60F46 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:45186 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjub-0003uh-8x for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:51:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56050) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfF-0001sV-Sm for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:02 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35074 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfA-0004Zy-NV for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:00 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S18; Tue, 19 Oct 2021 15:35:40 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 16/31] hw/loongarch: Add loongarch ipi interrupt support(IPI) Date: Tue, 19 Oct 2021 15:35:02 +0800 Message-Id: <1634628917-10031-17-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S18 X-Coremail-Antispam: 1UD129KBjvJXoW3XF1rAr1xZry8JF1fJry7ZFb_yoW3WrW3pF 9ruFWkKr48Wrs7Wrs7Jas8XFn3Jwn7GF17ZFWS9a4FkF47tw1Yvw1vyrZFvFyUJ3y0qFyY 9F95Ww12qF4UZw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch realize the IPI interrupt controller. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/loongarch/ipi.c | 145 +++++++++++++++++++++++++++++++ hw/loongarch/ls3a5000_virt.c | 2 + hw/loongarch/meson.build | 2 +- include/hw/loongarch/gipi.h | 38 ++++++++ include/hw/loongarch/loongarch.h | 3 + target/loongarch/cpu.h | 1 + 6 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 hw/loongarch/ipi.c create mode 100644 include/hw/loongarch/gipi.h diff --git a/hw/loongarch/ipi.c b/hw/loongarch/ipi.c new file mode 100644 index 0000000000..a5c82b2143 --- /dev/null +++ b/hw/loongarch/ipi.c @@ -0,0 +1,145 @@ +/* + * Loongarch ipi interrupt support + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "exec/address-spaces.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "sysemu/sysemu.h" +#include "sysemu/cpus.h" +#include "cpu.h" +#include "qemu/log.h" +#include "hw/loongarch/loongarch.h" +#include "migration/vmstate.h" + +static const VMStateDescription vmstate_gipi_core = { + .name = "gipi-single", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(status, gipi_core), + VMSTATE_UINT32(en, gipi_core), + VMSTATE_UINT32(set, gipi_core), + VMSTATE_UINT32(clear, gipi_core), + VMSTATE_UINT64_ARRAY(buf, gipi_core, MAX_GIPI_MBX_NUM), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_gipi = { + .name = "gipi", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(core, gipiState, MAX_GIPI_CORE_NUM, 0, + vmstate_gipi_core, gipi_core), + VMSTATE_END_OF_LIST() + } +}; + +static void gipi_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + gipi_core *s = opaque; + void *pbuf; + + if (size != 4) { + hw_error("size not 4"); + } + addr &= 0xff; + switch (addr) { + case CORE_STATUS_OFF: + hw_error("CORE_SET_OFF Can't be write\n"); + break; + case CORE_EN_OFF: + s->en = val; + break; + case CORE_SET_OFF: + s->status |= val; + if (s->status != 0) { + qemu_irq_raise(s->irq); + } + break; + case CORE_CLEAR_OFF: + s->status ^= val; + if (s->status == 0) { + qemu_irq_lower(s->irq); + } + break; + case CORE_BUF_20 ... CORE_BUF_38: + pbuf = (void *)s->buf + (addr - 0x20); + *(unsigned int *)pbuf = val; + break; + default: + break; + } +} + +static uint64_t gipi_readl(void *opaque, hwaddr addr, unsigned size) +{ + gipi_core *s = opaque; + uint64_t ret = 0; + void *pbuf; + + addr &= 0xff; + if (size != 4) { + hw_error("size not 4 %d\n", size); + } + switch (addr) { + case CORE_STATUS_OFF: + ret = s->status; + break; + case CORE_EN_OFF: + ret = s->en; + break; + case CORE_SET_OFF: + ret = 0; + break; + case CORE_CLEAR_OFF: + ret = 0; + break; + case CORE_BUF_20 ... CORE_BUF_38: + pbuf = (void *)s->buf + (addr - 0x20); + ret = *(unsigned int *)pbuf; + break; + default: + break; + } + + return ret; +} + +static const MemoryRegionOps gipi_ops = { + .read = gipi_readl, + .write = gipi_writel, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +int cpu_init_ipi(LoongarchMachineState *lsms, qemu_irq parent, int cpu) +{ + int core_num = cpu % 4; + hwaddr addr; + MemoryRegion *region; + char str[32]; + + if (lsms->gipi == NULL) { + lsms->gipi = g_malloc0(sizeof(gipiState)); + vmstate_register(NULL, 0, &vmstate_gipi, lsms->gipi); + } + + lsms->gipi->core[cpu].irq = parent; + + addr = SMP_GIPI_MAILBOX + core_num * 0x100; + region = g_new(MemoryRegion, 1); + sprintf(str, "gipi%d", cpu); + memory_region_init_io(region, NULL, &gipi_ops, + &lsms->gipi->core[cpu], str, 0x100); + memory_region_add_subregion(get_system_memory(), addr, region); + return 0; +} diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c index 222c76bc0d..115954033e 100644 --- a/hw/loongarch/ls3a5000_virt.c +++ b/hw/loongarch/ls3a5000_virt.c @@ -113,6 +113,7 @@ static void ls3a5000_virt_init(MachineState *machine) char *ramName = NULL; ram_addr_t ram_size = machine->ram_size; MemoryRegion *address_space_mem = get_system_memory(); + LoongarchMachineState *lsms = LOONGARCH_MACHINE(machine); int i; MemoryRegion *iomem = NULL; @@ -148,6 +149,7 @@ static void ls3a5000_virt_init(MachineState *machine) /* Init CPU internal devices */ cpu_loongarch_init_irq(cpu); cpu_loongarch_clock_init(cpu); + cpu_init_ipi(lsms, env->irq[IRQ_IPI], i); qemu_register_reset(main_cpu_reset, cpu); } diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build index a972210680..1bd209c9eb 100644 --- a/hw/loongarch/meson.build +++ b/hw/loongarch/meson.build @@ -1,5 +1,5 @@ loongarch_ss = ss.source_set() loongarch_ss.add(files('loongarch_int.c')) -loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c')) +loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c', 'ipi.c')) hw_arch += {'loongarch': loongarch_ss} diff --git a/include/hw/loongarch/gipi.h b/include/hw/loongarch/gipi.h new file mode 100644 index 0000000000..9844b6992f --- /dev/null +++ b/include/hw/loongarch/gipi.h @@ -0,0 +1,38 @@ +/* + * Loongarch ipi interrupt header files + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef HW_LOONGARCH_GIPI_H +#define HW_LOONGARCH_GIPI_H + +#define SMP_GIPI_MAILBOX 0x1fe01000ULL +#define CORE_STATUS_OFF 0x000 +#define CORE_EN_OFF 0x004 +#define CORE_SET_OFF 0x008 +#define CORE_CLEAR_OFF 0x00c +#define CORE_BUF_20 0x020 +#define CORE_BUF_28 0x028 +#define CORE_BUF_30 0x030 +#define CORE_BUF_38 0x038 + +#define MAX_GIPI_CORE_NUM 4 +#define MAX_GIPI_MBX_NUM 4 + +typedef struct gipi_core { + uint32_t status; + uint32_t en; + uint32_t set; + uint32_t clear; + uint64_t buf[MAX_GIPI_MBX_NUM]; + qemu_irq irq; +} gipi_core; + +typedef struct gipiState { + gipi_core core[MAX_GIPI_CORE_NUM]; +} gipiState; + +#endif diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h index 0edc313546..8e98430747 100644 --- a/include/hw/loongarch/loongarch.h +++ b/include/hw/loongarch/loongarch.h @@ -13,6 +13,7 @@ #include "qemu-common.h" #include "hw/boards.h" #include "qemu/queue.h" +#include "hw/loongarch/gipi.h" #define LOONGARCH_MAX_VCPUS 4 #define PM_MMIO_ADDR 0x10080000UL @@ -39,6 +40,7 @@ typedef struct LoongarchMachineState { /*< private >*/ MachineState parent_obj; + gipiState *gipi; } LoongarchMachineState; #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("loongson7a") @@ -46,4 +48,5 @@ DECLARE_INSTANCE_CHECKER(LoongarchMachineState, LOONGARCH_MACHINE, TYPE_LOONGARCH_MACHINE) void cpu_loongarch_init_irq(LoongArchCPU *cpu); +int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu); #endif diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index cfdcf1d4a0..4acbc08179 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -50,6 +50,7 @@ extern const char * const fregnames[]; #define N_IRQS 14 #define IRQ_TIMER 11 +#define IRQ_IPI 12 #define LOONGARCH_HFLAG_KU 0x00003 /* kernel/user mode mask */ #define LOONGARCH_HFLAG_UM 0x00003 /* user mode flag */ From patchwork Tue Oct 19 07:35:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568879 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05875C433FE for ; Tue, 19 Oct 2021 07:43:18 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 87CAA61378 for ; Tue, 19 Oct 2021 07:43:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 87CAA61378 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:53424 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjmG-00077r-F0 for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:43:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56054) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfG-0001sl-15 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:02 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35114 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfB-0004aw-Hy for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:01 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S19; Tue, 19 Oct 2021 15:35:41 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 17/31] hw/intc: Add loongarch ls7a interrupt controller support(PCH-PIC) Date: Tue, 19 Oct 2021 15:35:03 +0800 Message-Id: <1634628917-10031-18-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S19 X-Coremail-Antispam: 1UD129KBjvJXoWfGw4rXF4ktF1xur18uw1DGFg_yoWkJF18pF ZrCas0vrs7Jr47WrZ7Ja4rJrn3GFn7u3429anIkFyxCrs3Jry8XFn2yr9rWFyUK3yDJrya qFZ5Gay293WUGaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch realize the PCH-PIC interrupt controller. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/intc/Kconfig | 4 + hw/intc/loongarch_pch_pic.c | 284 ++++++++++++++++++++++++++++ hw/intc/meson.build | 1 + hw/loongarch/Kconfig | 1 + include/hw/intc/loongarch_pch_pic.h | 50 +++++ 5 files changed, 340 insertions(+) create mode 100644 hw/intc/loongarch_pch_pic.c create mode 100644 include/hw/intc/loongarch_pch_pic.h diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 78aed93c45..3b7eca7b03 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -73,3 +73,7 @@ config GOLDFISH_PIC config M68K_IRQC bool + +config LOONGARCH_PCH_PIC + bool + select UNIMP diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c new file mode 100644 index 0000000000..9d0673b98a --- /dev/null +++ b/hw/intc/loongarch_pch_pic.c @@ -0,0 +1,284 @@ +/* + * QEMU Loongson 7A1000 I/O interrupt controller. + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/intc/loongarch_pch_pic.h" +#include "migration/vmstate.h" + +#define DEBUG_LOONGARCH_PCH_PIC 0 + +#define DPRINTF(fmt, ...) \ +do { \ + if (DEBUG_LOONGARCH_PCH_PIC) { \ + fprintf(stderr, "LOONGARCH_PCH_PIC: " fmt , ## __VA_ARGS__); \ + } \ +} while (0) + + #define for_each_set_bit(bit, addr, size) \ + for ((bit) = find_first_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + +static void update_irq(loongarch_pch_pic *s, int mask, int level) +{ + int i; + uint64_t val; + val = mask & s->intirr & (~s->int_mask); + + for_each_set_bit(i, &val, 32) { + if (level == 1) { + if ((s->intisr & (0x1ULL << i)) == 0) { + s->intisr |= 1ULL << i; + qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 1); + } + } else if (level == 0) { + if (s->intisr & (0x1ULL << i)) { + s->intisr &= ~(0x1ULL << i); + qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 0); + } + } + } +} + +static void irq_handler(void *opaque, int irq, int level) +{ + loongarch_pch_pic *s = opaque; + + assert(irq < 32); + uint32_t mask = 1ULL << irq; + DPRINTF("------ %s irq %d %d\n", __func__, irq, level); + + if (s->intedge & mask) { + /* edge triggered */ + if (level) { + if ((s->last_intirr & mask) == 0) { + s->intirr |= mask; + } + s->last_intirr |= mask; + } else { + s->last_intirr &= ~mask; + } + } else { + /* level triggered */ + if (level) { + s->intirr |= mask; + s->last_intirr |= mask; + } else { + s->intirr &= ~mask; + s->last_intirr &= ~mask; + } + + } + update_irq(s, mask, level); +} + +static uint64_t loongarch_pch_pic_reg_read(void *opaque, hwaddr addr, + unsigned size) +{ + loongarch_pch_pic *s = opaque; + uint32_t val = 0; + uint32_t offset; + int32_t offset_tmp; + offset = addr & 0xfff; + if (4 == size) { + switch (offset) { + case PCH_PIC_INT_ID_OFFSET: + val = PCH_PIC_INT_ID_VAL; + break; + case PCH_PIC_INT_MASK_OFFSET: + val = s->int_mask; + break; + case PCH_PIC_INT_STATUS_OFFSET: + val = s->intisr & (~s->int_mask); + break; + case PCH_PIC_INT_EDGE_OFFSET: + val = s->intedge; + break; + case PCH_PIC_INT_POL_OFFSET: + val = s->int_polarity; + break; + case PCH_PIC_HTMSI_EN_OFFSET: + val = s->htmsi_en; + break; + case PCH_PIC_AUTO_CTRL0_OFFSET: + case PCH_PIC_AUTO_CTRL1_OFFSET: + break; + default: + break; + } + } else if (1 == size) { + if (offset >= PCH_PIC_HTMSI_VEC_OFFSET) { + offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 32) { + val = s->htmsi_vector[offset_tmp]; + } + } else if (offset >= PCH_PIC_ROUTE_ENTRY_OFFSET) { + offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 32) { + val = s->route_entry[offset_tmp]; + } + } + } + + return val; +} + +static void loongarch_pch_pic_reg_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + loongarch_pch_pic *s = opaque; + int32_t offset_tmp; + uint32_t offset, old; + offset = addr & 0xfff; + + if (4 == size) { + switch (offset) { + case PCH_PIC_INT_MASK_OFFSET: + old = s->int_mask; + s->int_mask = data; + if (old & ~data) { + update_irq(s, (old & ~data), 1); + } else if (~old & data) { + update_irq(s, (~old & data), 0); + } + break; + case PCH_PIC_INT_STATUS_OFFSET: + s->intisr = data; + break; + case PCH_PIC_INT_EDGE_OFFSET: + s->intedge = data; + break; + case PCH_PIC_INT_CLEAR_OFFSET: + s->intirr &= (~(data & s->intedge)); + update_irq(s, data, 0); + s->intisr &= (~data); + break; + case PCH_PIC_INT_POL_OFFSET: + s->int_polarity = data; + break; + case PCH_PIC_HTMSI_EN_OFFSET: + s->htmsi_en = data; + break; + case PCH_PIC_AUTO_CTRL0_OFFSET: + case PCH_PIC_AUTO_CTRL1_OFFSET: + break; + default: + break; + } + } else if (1 == size) { + if (offset >= PCH_PIC_HTMSI_VEC_OFFSET) { + offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 32) { + s->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff); + } + } else if (offset >= PCH_PIC_ROUTE_ENTRY_OFFSET) { + offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 32) { + s->route_entry[offset_tmp] = (uint8_t)(data & 0xff); + } + } + } +} + +static const MemoryRegionOps loongarch_pch_pic_ops = { + .read = loongarch_pch_pic_reg_read, + .write = loongarch_pch_pic_reg_write, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void loongarch_pch_pic_reset(DeviceState *d) +{ + loongarch_pch_pic *s = LOONGARCH_PCH_PIC(d); + int i; + + s->int_id = 0x0; + s->int_mask = 0xffffffff; + s->htmsi_en = 0x0; + s->intedge = 0x0; + s->intclr = 0x0; + s->auto_crtl0 = 0x0; + s->auto_crtl1 = 0x0; + for (i = 0; i < 32; i++) { + s->route_entry[i] = 0x1; + s->htmsi_vector[i] = 0x0; + } + s->intirr = 0x0; + s->intisr = 0x0; + s->last_intirr = 0x0; + s->int_polarity = 0x0; +} + +static void loongarch_pch_pic_init(Object *obj) +{ + loongarch_pch_pic *s = LOONGARCH_PCH_PIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + int tmp; + + memory_region_init_io(&s->iomem, obj, &loongarch_pch_pic_ops, + s, TYPE_LOONGARCH_PCH_PIC, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + + for (tmp = 0; tmp < 32; tmp++) { + sysbus_init_irq(sbd, &s->parent_irq[tmp]); + } + qdev_init_gpio_in(DEVICE(obj), irq_handler, 32); +} + +static const VMStateDescription vmstate_loongarch_pch_pic = { + .name = TYPE_LOONGARCH_PCH_PIC, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(int_mask, loongarch_pch_pic), + VMSTATE_UINT32(htmsi_en, loongarch_pch_pic), + VMSTATE_UINT32(intedge, loongarch_pch_pic), + VMSTATE_UINT32(intclr, loongarch_pch_pic), + VMSTATE_UINT32(auto_crtl0, loongarch_pch_pic), + VMSTATE_UINT32(auto_crtl1, loongarch_pch_pic), + VMSTATE_UINT8_ARRAY(route_entry, loongarch_pch_pic, 32), + VMSTATE_UINT8_ARRAY(htmsi_vector, loongarch_pch_pic, 32), + VMSTATE_UINT32(last_intirr, loongarch_pch_pic), + VMSTATE_UINT32(intirr, loongarch_pch_pic), + VMSTATE_UINT32(intisr, loongarch_pch_pic), + VMSTATE_UINT32(int_polarity, loongarch_pch_pic), + VMSTATE_END_OF_LIST() + } +}; + +static void loongarch_pch_pic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = loongarch_pch_pic_reset; + dc->vmsd = &vmstate_loongarch_pch_pic; +} + +static const TypeInfo loongarch_pch_pic_info = { + .name = TYPE_LOONGARCH_PCH_PIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(loongarch_pch_pic), + .instance_init = loongarch_pch_pic_init, + .class_init = loongarch_pch_pic_class_init, +}; + +static void loongarch_pch_pic_register_types(void) +{ + type_register_static(&loongarch_pch_pic_info); +} + +type_init(loongarch_pch_pic_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index a1d00aa48d..c61f171d5c 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -58,3 +58,4 @@ specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'], if_true: files('spapr_xive_kvm.c')) specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c')) specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c')) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 720822f32c..c6d7ebcd5b 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -1,3 +1,4 @@ config LOONGSON_3A5000 bool select PCI_EXPRESS_7A + select LOONGARCH_PCH_PIC diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarch_pch_pic.h new file mode 100644 index 0000000000..f85606de78 --- /dev/null +++ b/include/hw/intc/loongarch_pch_pic.h @@ -0,0 +1,50 @@ +/* + * Loongarch 7A1000 I/O interrupt controller definitions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic" +DECLARE_INSTANCE_CHECKER(struct loongarch_pch_pic, LOONGARCH_PCH_PIC, + TYPE_LOONGARCH_PCH_PIC) + +#define PCH_PIC_ROUTE_ENTRY_OFFSET 0x100 +#define PCH_PIC_INT_ID_OFFSET 0x00 +#define PCH_PIC_INT_ID_VAL 0x7000000UL +#define PCH_PIC_INT_ID_VER 0x1f0001UL +#define PCH_PIC_INT_MASK_OFFSET 0x20 +#define PCH_PIC_INT_EDGE_OFFSET 0x60 +#define PCH_PIC_INT_CLEAR_OFFSET 0x80 +#define PCH_PIC_INT_STATUS_OFFSET 0x3a0 +#define PCH_PIC_INT_POL_OFFSET 0x3e0 +#define PCH_PIC_HTMSI_EN_OFFSET 0x40 +#define PCH_PIC_HTMSI_VEC_OFFSET 0x200 +#define PCH_PIC_AUTO_CTRL0_OFFSET 0xc0 +#define PCH_PIC_AUTO_CTRL1_OFFSET 0xe0 + +typedef struct loongarch_pch_pic { + SysBusDevice parent_obj; + qemu_irq parent_irq[32]; + uint32_t int_id; + uint32_t int_mask; /*0x020 interrupt mask register*/ + uint32_t htmsi_en;/*0x040 1=msi*/ + uint32_t intedge; /*0x060 edge=1 level =0*/ + uint32_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/ + uint32_t auto_crtl0; /*0x0c0*/ + uint32_t auto_crtl1; /*0x0e0*/ + uint8_t route_entry[32]; /*0x100 - 0x120*/ + uint8_t htmsi_vector[32]; /*0x200 - 0x220*/ + uint32_t last_intirr; /* edge detection */ + uint32_t intirr; /* 0x380 interrupt request register */ + uint32_t intisr; /* 0x3a0 interrupt service register */ + /* + * 0x3e0 interrupt level polarity selection + * register 0 for high level trigger + */ + uint32_t int_polarity; + MemoryRegion iomem; +} loongarch_pch_pic; + + From patchwork Tue Oct 19 07:35:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568885 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36F74C433FE for ; Tue, 19 Oct 2021 07:46:47 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 03F6B61374 for ; Tue, 19 Oct 2021 07:46:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 03F6B61374 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:33804 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjpd-0004X8-VK for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:46:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56082) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfH-0001tR-N2 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:05 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35122 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfB-0004bI-SV for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:03 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S20; Tue, 19 Oct 2021 15:35:42 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 18/31] hw/intc: Add loongarch ls7a msi interrupt controller support(PCH-MSI) Date: Tue, 19 Oct 2021 15:35:04 +0800 Message-Id: <1634628917-10031-19-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S20 X-Coremail-Antispam: 1UD129KBjvJXoWxGry5JF1kCryDAr15tF48tFb_yoWrtr43pr sxuw15Kr4kJw47WFZ3J34fAFWrJFs7Wry2vF4a9ryIkr47AFyrZ3Wktry7WFyUK3y8Gryj vFZ5C3W7Xa1UGaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch realize PCH-MSI interrupt controller. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/intc/Kconfig | 5 ++ hw/intc/loongarch_pch_msi.c | 74 +++++++++++++++++++++++++++++ hw/intc/meson.build | 1 + hw/loongarch/Kconfig | 1 + include/hw/intc/loongarch_pch_msi.h | 17 +++++++ 5 files changed, 98 insertions(+) create mode 100644 hw/intc/loongarch_pch_msi.c create mode 100644 include/hw/intc/loongarch_pch_msi.h diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 3b7eca7b03..c0dc12dfa0 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -77,3 +77,8 @@ config M68K_IRQC config LOONGARCH_PCH_PIC bool select UNIMP + +config LOONGARCH_PCH_MSI + select MSI_NONBROKEN + bool + select UNIMP diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c new file mode 100644 index 0000000000..78ccabd468 --- /dev/null +++ b/hw/intc/loongarch_pch_msi.c @@ -0,0 +1,74 @@ +/* + * QEMU Loongson 7A1000 msi interrupt controller. + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/intc/loongarch_pch_msi.h" +#include "hw/pci/msi.h" +#include "hw/misc/unimp.h" +#include "migration/vmstate.h" + +#define DEBUG_LOONGARCH_PCH_MSI 0 + +#define DPRINTF(fmt, ...) \ +do { \ + if (DEBUG_LOONGARCH_PCH_MSI) { \ + fprintf(stderr, "LOONGARCH_PCH_MSI: " fmt , ## __VA_ARGS__); \ + } \ +} while (0) + +static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void loongarch_msi_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + loongarch_pch_msi *s = opaque; + int irq_num = val & 0xff; + + qemu_set_irq(s->pch_msi_irq[irq_num - 32], 1); +} + +static const MemoryRegionOps loongarch_pch_msi_ops = { + .read = loongarch_msi_mem_read, + .write = loongarch_msi_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void loongarch_pch_msi_init(Object *obj) +{ + loongarch_pch_msi *s = LOONGARCH_PCH_MSI(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + int tmp; + + memory_region_init_io(&s->msi_mmio, obj, &loongarch_pch_msi_ops, + s, TYPE_LOONGARCH_PCH_MSI, 0x8); + sysbus_init_mmio(sbd, &s->msi_mmio); + msi_nonbroken = true; + + for (tmp = 0; tmp < 224; tmp++) { + sysbus_init_irq(sbd, &s->pch_msi_irq[tmp]); + } +} + +static const TypeInfo loongarch_pch_msi_info = { + .name = TYPE_LOONGARCH_PCH_MSI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(loongarch_pch_msi), + .instance_init = loongarch_pch_msi_init, +}; + +static void loongarch_pch_msi_register_types(void) +{ + type_register_static(&loongarch_pch_msi_info); +} + +type_init(loongarch_pch_msi_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index c61f171d5c..749c27e072 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -59,3 +59,4 @@ specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'], specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c')) specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c')) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index c6d7ebcd5b..4500fd3a57 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -2,3 +2,4 @@ config LOONGSON_3A5000 bool select PCI_EXPRESS_7A select LOONGARCH_PCH_PIC + select LOONGARCH_PCH_MSI diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h new file mode 100644 index 0000000000..e069663dc8 --- /dev/null +++ b/include/hw/intc/loongarch_pch_msi.h @@ -0,0 +1,17 @@ +/* + * Loongarch 7A1000 I/O interrupt controller definitions + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi" +DECLARE_INSTANCE_CHECKER(struct loongarch_pch_msi, LOONGARCH_PCH_MSI, + TYPE_LOONGARCH_PCH_MSI) + +typedef struct loongarch_pch_msi { + SysBusDevice parent_obj; + qemu_irq pch_msi_irq[224]; + MemoryRegion msi_mmio; +} loongarch_pch_msi; From patchwork Tue Oct 19 07:35:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568901 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28B6CC433F5 for ; Tue, 19 Oct 2021 07:50:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BA7F561374 for ; Tue, 19 Oct 2021 07:49:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org BA7F561374 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:42524 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjsk-00021f-RV for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:49:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56086) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfI-0001tz-D1 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:05 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35160 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfD-0004d0-01 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:04 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S21; Tue, 19 Oct 2021 15:35:42 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC) Date: Tue, 19 Oct 2021 15:35:05 +0800 Message-Id: <1634628917-10031-20-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S21 X-Coremail-Antispam: 1UD129KBjvAXoWfXrW8JFW5Kw4ktF1DJFW7XFb_yoW5Jry8Co WYyr4Yqr4rGrWxCr40vr9rtFyUWr40vFWUZa43Ja17ua13AF15GFZxKw1Ykr4xXFs8Ka45 JrZxuFZrCa4Iq3Z5n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch realize the EIOINTC interrupt controller. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/intc/Kconfig | 3 + hw/intc/loongarch_extioi.c | 571 +++++++++++++++++++++++++++++ hw/intc/meson.build | 1 + hw/loongarch/Kconfig | 1 + include/hw/intc/loongarch_extioi.h | 100 +++++ include/hw/loongarch/loongarch.h | 1 + 6 files changed, 677 insertions(+) create mode 100644 hw/intc/loongarch_extioi.c create mode 100644 include/hw/intc/loongarch_extioi.h diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index c0dc12dfa0..a2d9efd5aa 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -82,3 +82,6 @@ config LOONGARCH_PCH_MSI select MSI_NONBROKEN bool select UNIMP + +config LOONGARCH_EXTIOI + bool diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c new file mode 100644 index 0000000000..f12dec35dd --- /dev/null +++ b/hw/intc/loongarch_extioi.c @@ -0,0 +1,571 @@ +/* + * Loongson 3A5000 ext interrupt controller emulation + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/loongarch/loongarch.h" +#include "hw/qdev-properties.h" +#include "exec/address-spaces.h" +#include "hw/intc/loongarch_extioi.h" +#include "migration/vmstate.h" + +#define DEBUG_APIC 0 + +#define DPRINTF(fmt, ...) \ +do { \ + if (DEBUG_APIC) { \ + fprintf(stderr, "APIC: " fmt , ## __VA_ARGS__); \ + } \ +} while (0) + +static void extioi_update_irq(void *opaque, int irq_num, int level) +{ + loongarch_extioi *s = opaque; + uint8_t ipnum, cpu; + unsigned long found1, found2; + + ipnum = s->sw_ipmap[irq_num]; + cpu = s->sw_coremap[irq_num]; + if (level == 1) { + if (test_bit(irq_num, (void *)s->en_reg8) == false) { + return; + } + bitmap_set((void *)s->coreisr_reg8[cpu], irq_num, 1); + found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]), + EXTIOI_IRQS, 0); + bitmap_set((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1); + + if (found1 >= EXTIOI_IRQS) { + qemu_set_irq(s->parent_irq[cpu][ipnum], level); + } + } else { + bitmap_clear((void *)s->coreisr_reg8[cpu], irq_num, 1); + found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]), + EXTIOI_IRQS, 0); + bitmap_clear((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1); + found2 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]), + EXTIOI_IRQS, 0); + + if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) { + qemu_set_irq(s->parent_irq[cpu][ipnum], level); + } + } +} + +static void extioi_setirq(void *opaque, int irq, int level) +{ + loongarch_extioi *s = opaque; + extioi_update_irq(s, irq, level); +} + +static void extioi_handler(void *opaque, int irq, int level) +{ + loongarch_extioi *extioi = (loongarch_extioi *)opaque; + + qemu_set_irq(extioi->irq[irq], level); +} + +static uint32_t extioi_readb(void *opaque, hwaddr addr) +{ + loongarch_extioi *state = opaque; + unsigned long offset, reg_count; + uint8_t ret; + int cpu; + + offset = addr & 0xffff; + + if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) { + reg_count = (offset - EXTIOI_ENABLE_START); + ret = state->en_reg8[reg_count]; + } else if ((offset >= EXTIOI_BOUNCE_START) && + (offset < EXTIOI_BOUNCE_END)) { + reg_count = (offset - EXTIOI_BOUNCE_START); + ret = state->bounce_reg8[reg_count]; + } else if ((offset >= EXTIOI_COREISR_START) && + (offset < EXTIOI_COREISR_END)) { + reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f); + cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + ret = state->coreisr_reg8[cpu][reg_count]; + } else if ((offset >= EXTIOI_IPMAP_START) && + (offset < EXTIOI_IPMAP_END)) { + reg_count = (offset - EXTIOI_IPMAP_START); + ret = state->ipmap_reg8[reg_count]; + } else if ((offset >= EXTIOI_COREMAP_START) && + (offset < EXTIOI_COREMAP_END)) { + reg_count = (offset - EXTIOI_COREMAP_START); + ret = state->coremap_reg8[reg_count]; + } else if ((offset >= EXTIOI_NODETYPE_START) && + (offset < EXTIOI_NODETYPE_END)) { + reg_count = (offset - EXTIOI_NODETYPE_START); + ret = state->nodetype_reg8[reg_count]; + } + + DPRINTF("readb reg 0x" TARGET_FMT_plx " = %x\n", addr, ret); + return ret; +} + +static uint32_t extioi_readw(void *opaque, hwaddr addr) +{ + loongarch_extioi *state = opaque; + unsigned long offset, reg_count; + uint32_t ret; + int cpu; + + offset = addr & 0xffff; + + if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) { + reg_count = (offset - EXTIOI_ENABLE_START) / 4; + ret = state->en_reg32[reg_count]; + } else if ((offset >= EXTIOI_BOUNCE_START) && + (offset < EXTIOI_BOUNCE_END)) { + reg_count = (offset - EXTIOI_BOUNCE_START) / 4; + ret = state->bounce_reg32[reg_count]; + } else if ((offset >= EXTIOI_COREISR_START) && + (offset < EXTIOI_COREISR_END)) { + reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 4; + cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + ret = state->coreisr_reg32[cpu][reg_count]; + } else if ((offset >= EXTIOI_IPMAP_START) && + (offset < EXTIOI_IPMAP_END)) { + reg_count = (offset - EXTIOI_IPMAP_START) / 4; + ret = state->ipmap_reg32[reg_count]; + } else if ((offset >= EXTIOI_COREMAP_START) && + (offset < EXTIOI_COREMAP_END)) { + reg_count = (offset - EXTIOI_COREMAP_START) / 4; + ret = state->coremap_reg32[reg_count]; + } else if ((offset >= EXTIOI_NODETYPE_START) && + (offset < EXTIOI_NODETYPE_END)) { + reg_count = (offset - EXTIOI_NODETYPE_START) / 4; + ret = state->nodetype_reg32[reg_count]; + } + + DPRINTF("readw reg 0x" TARGET_FMT_plx " = %x\n", addr, ret); + return ret; +} + +static uint64_t extioi_readl(void *opaque, hwaddr addr) +{ + loongarch_extioi *state = opaque; + unsigned long offset, reg_count; + uint64_t ret; + int cpu; + + offset = addr & 0xffff; + + if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) { + reg_count = (offset - EXTIOI_ENABLE_START) / 8; + ret = state->en_reg64[reg_count]; + } else if ((offset >= EXTIOI_BOUNCE_START) && + (offset < EXTIOI_BOUNCE_END)) { + reg_count = (offset - EXTIOI_BOUNCE_START) / 8; + ret = state->bounce_reg64[reg_count]; + } else if ((offset >= EXTIOI_COREISR_START) && + (offset < EXTIOI_COREISR_END)) { + reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 8; + cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + ret = state->coreisr_reg64[cpu][reg_count]; + } else if ((offset >= EXTIOI_IPMAP_START) && + (offset < EXTIOI_IPMAP_END)) { + ret = state->ipmap_reg64; + } else if ((offset >= EXTIOI_COREMAP_START) && + (offset < EXTIOI_COREMAP_END)) { + reg_count = (offset - EXTIOI_COREMAP_START) / 8; + ret = state->coremap_reg64[reg_count]; + } else if ((offset >= EXTIOI_NODETYPE_START) && + (offset < EXTIOI_NODETYPE_END)) { + reg_count = (offset - EXTIOI_NODETYPE_START) / 8; + ret = state->nodetype_reg64[reg_count]; + } + + DPRINTF("readl reg 0x" TARGET_FMT_plx " = %lx\n", addr, ret); + return ret; +} + +static void extioi_writeb(void *opaque, hwaddr addr, uint32_t val) +{ + loongarch_extioi *state = opaque; + unsigned long offset, reg_count; + uint8_t old_data_u8; + int cpu, i, ipnum, level, mask, irqnum; + + offset = addr & 0xffff; + val = val & 0xffUL; + + if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) { + reg_count = (offset - EXTIOI_ENABLE_START); + old_data_u8 = state->en_reg8[reg_count]; + if (old_data_u8 != val) { + state->en_reg8[reg_count] = val; + old_data_u8 = old_data_u8 ^ val; + mask = 0x1; + + for (i = 0; i < 8; i++) { + if (old_data_u8 & mask) { + level = !!(val & (0x1 << i)); + extioi_update_irq(state, i + reg_count * 8, level); + } + mask = mask << 1; + } + } + } else if ((offset >= EXTIOI_BOUNCE_START) && + (offset < EXTIOI_BOUNCE_END)) { + reg_count = (offset - EXTIOI_BOUNCE_START); + state->bounce_reg8[reg_count] = val; + } else if ((offset >= EXTIOI_ISR_START) && (offset < EXTIOI_ISR_END)) { + /* can not be writen */ + reg_count = (offset - EXTIOI_ISR_START) & 0x1f; + old_data_u8 = state->isr_reg8[reg_count]; + state->isr_reg8[reg_count] = old_data_u8 & (~val); + + mask = 0x1; + for (i = 0; i < 8; i++) { + if ((old_data_u8 & mask) && (val & mask)) { + extioi_update_irq(state, i + reg_count * 8, 0); + } + mask = mask << 1; + } + } else if ((offset >= EXTIOI_COREISR_START) && + (offset < EXTIOI_COREISR_END)) { + reg_count = (offset - EXTIOI_COREISR_START) & 0x1f; + cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + + /* ext_isr */ + old_data_u8 = state->isr_reg8[reg_count]; + state->isr_reg8[reg_count] = old_data_u8 & (~val); + + old_data_u8 = state->coreisr_reg8[cpu][reg_count]; + state->coreisr_reg8[cpu][reg_count] = old_data_u8 & (~val); + + if (old_data_u8 != state->coreisr_reg8[cpu][reg_count]) { + mask = 0x1; + for (i = 0; i < 8; i++) { + if ((old_data_u8 & mask) && (val & mask)) { + extioi_update_irq(state, i + reg_count * 8, 0); + } + mask = mask << 1; + } + } + } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) { + /* drop arch.core_ip_mask use state->ipmap */ + reg_count = (offset - EXTIOI_IPMAP_START); + state->ipmap_reg8[reg_count] = val; + + ipnum = 0; + for (i = 0; i < 4; i++) { + if (val & (0x1 << i)) { + ipnum = i; + break; + } + } + + if (val) { + for (i = 0; i < 32; i++) { + irqnum = reg_count * 32 + i; + state->sw_ipmap[irqnum] = ipnum; + } + } else { + for (i = 0; i < 32; i++) { + irqnum = reg_count * 32 + i; + state->sw_ipmap[irqnum] = 0; + } + } + } else if ((offset >= EXTIOI_COREMAP_START) && + (offset < EXTIOI_COREMAP_END)) { + reg_count = (offset - EXTIOI_COREMAP_START); + cpu = val & 0xf; + + /* node map different from kernel */ + if (cpu) { + cpu = ctz32(cpu); + state->coremap_reg8[reg_count] = val; + state->sw_coremap[reg_count] = cpu; + } + } else if ((offset >= EXTIOI_NODETYPE_START) && + (offset < EXTIOI_NODETYPE_END)) { + reg_count = (offset - EXTIOI_NODETYPE_START); + state->nodetype_reg8[reg_count] = val; + } + + DPRINTF("writeb reg 0x" TARGET_FMT_plx " = %x\n", addr, val); +} + +static void extioi_writew(void *opaque, hwaddr addr, uint32_t val) +{ + loongarch_extioi *state = opaque; + int cpu, level; + uint32_t offset, old_data_u32, reg_count, mask, i; + + offset = addr & 0xffff; + + if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) { + reg_count = (offset - EXTIOI_ENABLE_START) / 4; + old_data_u32 = state->en_reg32[reg_count]; + if (old_data_u32 != val) { + state->en_reg32[reg_count] = val; + old_data_u32 = old_data_u32 ^ val; + + mask = 0x1; + for (i = 0; i < 8 * sizeof(old_data_u32); i++) { + if (old_data_u32 & mask) { + level = !!(val & (0x1 << i)); + extioi_update_irq(state, i + reg_count * 32, level); + } + mask = mask << 1; + } + } + } else if ((offset >= EXTIOI_BOUNCE_START) && + (offset < EXTIOI_BOUNCE_END)) { + reg_count = (offset - EXTIOI_BOUNCE_START) / 4; + state->bounce_reg32[reg_count] = val; + } else if ((offset >= EXTIOI_COREISR_START) && + (offset < EXTIOI_COREISR_END)) { + reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 4; + cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + + /* ext_isr */ + old_data_u32 = state->isr_reg32[reg_count]; + state->isr_reg32[reg_count] = old_data_u32 & (~val); + + /* ext_core_ioisr */ + old_data_u32 = state->coreisr_reg32[cpu][reg_count]; + state->coreisr_reg32[cpu][reg_count] = old_data_u32 & (~val); + + if (old_data_u32 != state->coreisr_reg32[cpu][reg_count]) { + mask = 0x1; + for (i = 0; i < 8 * sizeof(old_data_u32); i++) { + if ((old_data_u32 & mask) && (val & mask)) { + extioi_update_irq(state, i + reg_count * 8, 0); + } + mask = mask << 1; + } + } + } else if ((offset >= EXTIOI_IPMAP_START) && + (offset < EXTIOI_IPMAP_END)) { + extioi_writeb(opaque, addr, (val) & 0xff); + extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff); + extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff); + extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff); + } else if ((offset >= EXTIOI_COREMAP_START) && + (offset < EXTIOI_COREMAP_END)) { + extioi_writeb(opaque, addr, (val) & 0xff); + extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff); + extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff); + extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff); + } else if ((offset >= EXTIOI_NODETYPE_START) && + (offset < EXTIOI_NODETYPE_END)) { + reg_count = (offset - EXTIOI_NODETYPE_START) / 4; + state->nodetype_reg32[reg_count] = val; + } + + DPRINTF("writew reg 0x" TARGET_FMT_plx " = %x\n", addr, val); +} + +static void extioi_writel(void *opaque, hwaddr addr, uint64_t val) +{ + loongarch_extioi *state = (loongarch_extioi *)opaque; + int cpu, level; + uint64_t offset, old_data_u64, reg_count, mask, i; + + offset = addr & 0xffff; + + if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) { + reg_count = (offset - EXTIOI_ENABLE_START) / 8; + old_data_u64 = state->en_reg64[reg_count]; + if (old_data_u64 != val) { + state->en_reg64[reg_count] = val; + old_data_u64 = old_data_u64 ^ val; + mask = 0x1; + for (i = 0; i < 8 * sizeof(old_data_u64); i++) { + if (old_data_u64 & mask) { + level = !!(val & (0x1 << i)); + extioi_update_irq(state, i + reg_count * 64, level); + } + mask = mask << 1; + } + } + } else if ((offset >= EXTIOI_BOUNCE_START) && + (offset < EXTIOI_BOUNCE_END)) { + reg_count = (offset - EXTIOI_BOUNCE_START) / 8; + state->bounce_reg64[reg_count] = val; + } else if ((offset >= EXTIOI_COREISR_START) && + (offset < EXTIOI_COREISR_END)) { + reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 8; + cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + + /* core_ext_ioisr */ + old_data_u64 = state->coreisr_reg64[cpu][reg_count]; + state->coreisr_reg64[cpu][reg_count] = old_data_u64 & (~val); + + if (old_data_u64 != state->coreisr_reg64[cpu][reg_count]) { + mask = 0x1; + for (i = 0; i < 8 * sizeof(old_data_u64); i++) { + if ((old_data_u64 & mask) && (val & mask)) { + extioi_update_irq(state, i + reg_count * 64, 0); + } + mask = mask << 1; + } + } + } else if ((offset >= EXTIOI_IPMAP_START) && + (offset < EXTIOI_IPMAP_END)) { + extioi_writeb(opaque, addr, (val) & 0xff); + extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff); + extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff); + extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff); + extioi_writeb(opaque, addr + 4, (val >> 32) & 0xff); + extioi_writeb(opaque, addr + 5, (val >> 40) & 0xff); + extioi_writeb(opaque, addr + 6, (val >> 48) & 0xff); + extioi_writeb(opaque, addr + 7, (val >> 56) & 0xff); + } else if ((offset >= EXTIOI_COREMAP_START) && + (offset < EXTIOI_COREMAP_END)) { + extioi_writeb(opaque, addr, (val) & 0xff); + extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff); + extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff); + extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff); + extioi_writeb(opaque, addr + 4, (val >> 32) & 0xff); + extioi_writeb(opaque, addr + 5, (val >> 40) & 0xff); + extioi_writeb(opaque, addr + 6, (val >> 48) & 0xff); + extioi_writeb(opaque, addr + 7, (val >> 56) & 0xff); + } else if ((offset >= EXTIOI_NODETYPE_START) && + (offset < EXTIOI_NODETYPE_END)) { + reg_count = (offset - EXTIOI_NODETYPE_START) / 8; + state->nodetype_reg64[reg_count] = val; + } + + DPRINTF("writel reg 0x" TARGET_FMT_plx " = %lx\n", addr, val); +} + +static uint64_t extioi_readfn(void *opaque, hwaddr addr, unsigned size) +{ + switch (size) { + case 1: + return extioi_readb(opaque, addr); + case 4: + return extioi_readw(opaque, addr); + case 8: + return extioi_readl(opaque, addr); + default: + g_assert_not_reached(); + } +} + +static void extioi_writefn(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + switch (size) { + case 1: + extioi_writeb(opaque, addr, value); + break; + case 4: + extioi_writew(opaque, addr, value); + break; + case 8: + extioi_writel(opaque, addr, value); + break; + default: + g_assert_not_reached(); + } +} + +static const MemoryRegionOps extioi_ops = { + .read = extioi_readfn, + .write = extioi_writefn, + .impl.min_access_size = 1, + .impl.max_access_size = 8, + .valid.min_access_size = 1, + .valid.max_access_size = 8, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void loongarch_extioi_realize(DeviceState *dev, Error **errp) +{ + LoongarchMachineState *lsms = LOONGARCH_MACHINE(qdev_get_machine()); + MachineState *ms = MACHINE(lsms); + loongarch_extioi *p = LOONGARCH_EXTIOI(dev); + int cpu, pin; + + qdev_init_gpio_in(dev, extioi_setirq, EXTIOI_IRQS); + + for (int i = 0; i < EXTIOI_IRQS; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &p->irq[i]); + } + + memory_region_init_io(&p->mmio, OBJECT(p), &extioi_ops, p, + TYPE_LOONGARCH_EXTIOI, 0x900); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &p->mmio); + + for (cpu = 0; cpu < ms->smp.cpus; cpu++) { + for (pin = 0; pin < LS3A_INTC_IP; pin++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &p->parent_irq[cpu][pin]); + } + } + + /* 0-31 is for non msi device.32-256 for msi/msix device */ + lsms->pch_irq = qemu_allocate_irqs(extioi_handler, p, 256); +} + +static const VMStateDescription vmstate_ext_sw_ipisr = { + .name = "ext_sw_ipisr", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(irq, ext_sw_ipisr, EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_loongarch_extioi = { + .name = TYPE_LOONGARCH_EXTIOI, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(en_reg8, loongarch_extioi, EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_ARRAY(bounce_reg8, loongarch_extioi, + EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_ARRAY(isr_reg8, loongarch_extioi, + EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_2DARRAY(coreisr_reg8, loongarch_extioi, MAX_CORES, + EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_ARRAY(ipmap_reg8, loongarch_extioi, + EXTIOI_IRQS_IPMAP_SIZE), + VMSTATE_UINT8_ARRAY(coremap_reg8, loongarch_extioi, + EXTIOI_IRQS_COREMAP_SIZE), + VMSTATE_UINT16_ARRAY(nodetype_reg16, loongarch_extioi, + EXTIOI_IRQS_NODETYPE_SIZE), + VMSTATE_UINT8_ARRAY(sw_ipmap, loongarch_extioi, EXTIOI_IRQS), + VMSTATE_UINT8_ARRAY(sw_coremap, loongarch_extioi, EXTIOI_IRQS), + VMSTATE_STRUCT_2DARRAY(sw_ipisr, loongarch_extioi, MAX_CORES, + LS3A_INTC_IP, 1, vmstate_ext_sw_ipisr, + ext_sw_ipisr), + VMSTATE_END_OF_LIST() + } +}; + +static void loongarch_extioi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_loongarch_extioi; + dc->realize = loongarch_extioi_realize; +} + +static const TypeInfo loongarch_extioi_info = { + .name = TYPE_LOONGARCH_EXTIOI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(struct loongarch_extioi), + .class_init = loongarch_extioi_class_init, +}; + +static void loongarch_extioi_register_types(void) +{ + type_register_static(&loongarch_extioi_info); +} + +type_init(loongarch_extioi_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 749c27e072..189c73fa9d 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -60,3 +60,4 @@ specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c')) specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c')) +specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c')) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 4500fd3a57..9212127701 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -3,3 +3,4 @@ config LOONGSON_3A5000 select PCI_EXPRESS_7A select LOONGARCH_PCH_PIC select LOONGARCH_PCH_MSI + select LOONGARCH_EXTIOI diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h new file mode 100644 index 0000000000..0096c775c7 --- /dev/null +++ b/include/hw/intc/loongarch_extioi.h @@ -0,0 +1,100 @@ +/* + * Loongarch 3A5000 ext interrupt controller definitions + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "hw/sysbus.h" +#include "hw/loongarch/loongarch.h" + +#ifndef LOONGARCH_EXTIOI_H +#define LOONGARCH_EXTIOI_H + +#define LS3A_INTC_IP 8 +#define MAX_CORES LOONGARCH_MAX_VCPUS +#define EXTIOI_IRQS (256) +#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8) +/* map to ipnum per 32 irqs */ +#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32) +#define EXTIOI_IRQS_COREMAP_SIZE 256 +#define EXTIOI_IRQS_NODETYPE_SIZE 16 + +#define APIC_OFFSET 0x400 +#define APIC_BASE (0x1fe01000ULL + APIC_OFFSET) + +#define EXTIOI_NODETYPE_START (0x4a0 - APIC_OFFSET) +#define EXTIOI_NODETYPE_END (0x4c0 - APIC_OFFSET) +#define EXTIOI_IPMAP_START (0x4c0 - APIC_OFFSET) +#define EXTIOI_IPMAP_END (0x4c8 - APIC_OFFSET) +#define EXTIOI_ENABLE_START (0x600 - APIC_OFFSET) +#define EXTIOI_ENABLE_END (0x620 - APIC_OFFSET) +#define EXTIOI_BOUNCE_START (0x680 - APIC_OFFSET) +#define EXTIOI_BOUNCE_END (0x6a0 - APIC_OFFSET) +#define EXTIOI_ISR_START (0x700 - APIC_OFFSET) +#define EXTIOI_ISR_END (0x720 - APIC_OFFSET) +#define EXTIOI_COREISR_START (0x800 - APIC_OFFSET) +#define EXTIOI_COREISR_END (0xB20 - APIC_OFFSET) +#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET) +#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET) + +#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi" +DECLARE_INSTANCE_CHECKER(struct loongarch_extioi, LOONGARCH_EXTIOI, + TYPE_LOONGARCH_EXTIOI) + +typedef struct ext_sw_ipisr { + uint8_t irq[EXTIOI_IRQS_BITMAP_SIZE]; +} ext_sw_ipisr; + +typedef struct loongarch_extioi { + SysBusDevice parent_obj; + /* hardware state */ + union { + uint64_t en_reg64[EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t en_reg32[EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t en_reg8[EXTIOI_IRQS_BITMAP_SIZE]; + }; + union { + uint64_t bounce_reg64[EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t bounce_reg32[EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t bounce_reg8[EXTIOI_IRQS_BITMAP_SIZE]; + }; + union { + uint64_t isr_reg64[EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t isr_reg32[EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t isr_reg8[EXTIOI_IRQS_BITMAP_SIZE]; + }; + union { + uint64_t coreisr_reg64[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t coreisr_reg32[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t coreisr_reg8[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE]; + }; + union { + uint64_t ipmap_reg64; + uint32_t ipmap_reg32[EXTIOI_IRQS_IPMAP_SIZE / 4]; + uint8_t ipmap_reg8[EXTIOI_IRQS_IPMAP_SIZE]; + }; + union { + uint64_t coremap_reg64[EXTIOI_IRQS_COREMAP_SIZE / 8]; + uint32_t coremap_reg32[EXTIOI_IRQS_COREMAP_SIZE / 4]; + uint8_t coremap_reg8[EXTIOI_IRQS_COREMAP_SIZE]; + }; + union { + uint64_t nodetype_reg64[EXTIOI_IRQS_NODETYPE_SIZE / 4]; + uint32_t nodetype_reg32[EXTIOI_IRQS_NODETYPE_SIZE / 2]; + uint16_t nodetype_reg16[EXTIOI_IRQS_NODETYPE_SIZE]; + uint8_t nodetype_reg8[EXTIOI_IRQS_NODETYPE_SIZE * 2]; + }; + + /*software state */ + uint8_t sw_ipmap[EXTIOI_IRQS]; + uint8_t sw_coremap[EXTIOI_IRQS]; + ext_sw_ipisr sw_ipisr[MAX_CORES][LS3A_INTC_IP]; + + qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP]; + qemu_irq irq[EXTIOI_IRQS]; + MemoryRegion mmio; +} loongarch_extioi; + +#endif /* LOONGARCH_EXTIOI_H */ diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h index 8e98430747..210173471d 100644 --- a/include/hw/loongarch/loongarch.h +++ b/include/hw/loongarch/loongarch.h @@ -41,6 +41,7 @@ typedef struct LoongarchMachineState { MachineState parent_obj; gipiState *gipi; + qemu_irq *pch_irq; } LoongarchMachineState; #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("loongson7a") From patchwork Tue Oct 19 07:35:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojuan Yang X-Patchwork-Id: 12568835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7EB8AC433F5 for ; Tue, 19 Oct 2021 07:37:45 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4A35D61378 for ; Tue, 19 Oct 2021 07:37:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4A35D61378 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:37134 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjgu-0004dw-Cb for qemu-devel@archiver.kernel.org; Tue, 19 Oct 2021 03:37:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56088) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mcjfJ-0001u6-44 for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:05 -0400 Received: from mail.loongson.cn ([114.242.206.163]:35178 helo=loongson.cn) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mcjfD-0004dX-IX for qemu-devel@nongnu.org; Tue, 19 Oct 2021 03:36:04 -0400 Received: from kvm-dev1.localdomain (unknown [10.2.5.134]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxP2s1dW5h3HwcAA--.43474S22; Tue, 19 Oct 2021 15:35:43 +0800 (CST) From: Xiaojuan Yang To: qemu-devel@nongnu.org Subject: [PATCH 20/31] hw/loongarch: Add irq hierarchy for the system Date: Tue, 19 Oct 2021 15:35:06 +0800 Message-Id: <1634628917-10031-21-git-send-email-yangxiaojuan@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> References: <1634628917-10031-1-git-send-email-yangxiaojuan@loongson.cn> X-CM-TRANSID: AQAAf9DxP2s1dW5h3HwcAA--.43474S22 X-Coremail-Antispam: 1UD129KBjvJXoWxGryUGr4rCF1kXFW8Cw1xXwb_yoW5uw4fpF 98Ca9Ygr48Wa17G393Xw1xWr1fJFs7G342vFyS9rWfKF4UJryUXw1vywsrtFWUJaykXrs8 XF9Yka12va18Z3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: p1dqw5xldry3tdq6z05rqj20fqof0/ Received-SPF: pass client-ip=114.242.206.163; envelope-from=yangxiaojuan@loongson.cn; helo=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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, thuth@redhat.com, chenhuacai@loongson.cn, mst@redhat.com, philmd@redhat.com, richard.henderson@linaro.org, laurent@vivier.eu, peterx@redhat.com, f4bug@amsat.org, yangxiaojuan@loongson.cn, alistair.francis@wdc.com, maobibo@loongson.cn, gaosong@loongson.cn, pbonzini@redhat.com, mark.cave-ayland@ilande.co.uk, bmeng.cn@gmail.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch add the irq hierarchy for the virt board. Signed-off-by: Xiaojuan Yang Signed-off-by: Song Gao --- hw/loongarch/ls3a5000_virt.c | 49 ++++++++++++++++++++++++++++++++++++ include/hw/pci-host/ls7a.h | 4 +++ 2 files changed, 53 insertions(+) diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c index 115954033e..89fee1fd9b 100644 --- a/hw/loongarch/ls3a5000_virt.c +++ b/hw/loongarch/ls3a5000_virt.c @@ -16,6 +16,9 @@ #include "sysemu/runstate.h" #include "sysemu/reset.h" #include "hw/loongarch/loongarch.h" +#include "hw/intc/loongarch_extioi.h" +#include "hw/intc/loongarch_pch_pic.h" +#include "hw/intc/loongarch_pch_msi.h" #include "hw/pci-host/ls7a.h" CPULoongArchState *cpu_states[LOONGARCH_MAX_VCPUS]; @@ -103,6 +106,49 @@ static const MemoryRegionOps loongarch_qemu_ops = { }, }; +static void ls3a5000_irq_init(MachineState *machine, CPULoongArchState *env[]) +{ + LoongarchMachineState *lsms = LOONGARCH_MACHINE(machine); + DeviceState *extioi, *pch_pic, *pch_msi; + SysBusDevice *d; + int cpu, pin, i; + + extioi = qdev_new(TYPE_LOONGARCH_EXTIOI); + d = SYS_BUS_DEVICE(extioi); + sysbus_realize_and_unref(d, &error_fatal); + sysbus_mmio_map(d, 0, APIC_BASE); + + for (i = 0; i < EXTIOI_IRQS; i++) { + sysbus_connect_irq(d, i, qdev_get_gpio_in(extioi, i)); + } + + for (cpu = 0; cpu < machine->smp.cpus; cpu++) { + /* cpu_pin[9:2] <= intc_pin[7:0] */ + for (pin = 0; pin < LS3A_INTC_IP; pin++) { + sysbus_connect_irq(d, (EXTIOI_IRQS + cpu * 8 + pin), + env[cpu]->irq[pin + 2]); + } + } + + pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC); + d = SYS_BUS_DEVICE(pch_pic); + sysbus_realize_and_unref(d, &error_fatal); + sysbus_mmio_map(d, 0, LS7A_IOAPIC_REG_BASE); + + for (int i = 0; i < 32; i++) { + sysbus_connect_irq(d, i, lsms->pch_irq[i]); + } + + pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI); + d = SYS_BUS_DEVICE(pch_msi); + sysbus_realize_and_unref(d, &error_fatal); + sysbus_mmio_map(d, 0, LS7A_PCH_MSI_ADDR_LOW); + for (i = 0; i < 224; i++) { + sysbus_connect_irq(d, i, lsms->pch_irq[i + 32]); + } + +} + static void ls3a5000_virt_init(MachineState *machine) { const char *cpu_model = machine->cpu_type; @@ -175,6 +221,9 @@ static void ls3a5000_virt_init(MachineState *machine) memory_region_add_subregion(address_space_mem, PM_MMIO_ADDR, iomem); + /*Initialize the IO interrupt subsystem*/ + ls3a5000_irq_init(machine, cpu_states); + LOONGARCH_SIMPLE_MMIO_OPS(FEATURE_REG, "loongarch_feature", 0x8); LOONGARCH_SIMPLE_MMIO_OPS(VENDOR_REG, "loongarch_vendor", 0x8); LOONGARCH_SIMPLE_MMIO_OPS(CPUNAME_REG, "loongarch_cpuname", 0x8); diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index 4c95a11ab8..e957c8c855 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -24,6 +24,10 @@ #define LS7A_PCI_IO_BASE 0x18000000UL #define LS7A_PCI_IO_SIZE 0x00010000 +#define LS7A_PCH_REG_BASE 0x10000000UL +#define LS7A_IOAPIC_REG_BASE (LS7A_PCH_REG_BASE) +#define LS7A_PCH_MSI_ADDR_LOW 0x2FF00000UL + typedef struct LS7APCIState LS7APCIState; typedef struct LS7APCIEHost { PCIExpressHost parent_obj;