From patchwork Tue Feb 26 03:05:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Suraj Jitindar Singh X-Patchwork-Id: 10829361 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A2B5E15AC for ; Tue, 26 Feb 2019 03:10:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 883DF2B338 for ; Tue, 26 Feb 2019 03:10:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7620C2AA4E; Tue, 26 Feb 2019 03:10:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 81FD82AA4E for ; Tue, 26 Feb 2019 03:10:09 +0000 (UTC) Received: from localhost ([127.0.0.1]:47503 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gyT8C-0006CU-Su for patchwork-qemu-devel@patchwork.kernel.org; Mon, 25 Feb 2019 22:10:08 -0500 Received: from eggs.gnu.org ([209.51.188.92]:39723) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gyT4H-0003tE-T2 for qemu-devel@nongnu.org; Mon, 25 Feb 2019 22:06:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gyT4F-0007iA-EM for qemu-devel@nongnu.org; Mon, 25 Feb 2019 22:06:05 -0500 Received: from mail-pf1-x441.google.com ([2607:f8b0:4864:20::441]:44483) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gyT49-0007bX-IJ; Mon, 25 Feb 2019 22:05:59 -0500 Received: by mail-pf1-x441.google.com with SMTP id a3so5465363pff.11; Mon, 25 Feb 2019 19:05:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Jj6lZWiiSlrOt4vVog8SmooRLMbEyS7xw1jh6oSDAjQ=; b=ucKrV6Dm7LcsRyu4hnARFiTV6jxJryOKd6e4YYRhIKqs/PfNN6awDNHozMQveZTdu1 imHG2Uz72antJfNf5yFTSHEsgkzR9Gd6ZbCCzcHbKIMbBrqQqRANyUxhUILmQyw1awCN tPgQlLZ+0o+fwszNS8mYyjXVsM1l5n3A75ucap7So9xbRAgjqvpq0N/0gqzEj6ZdIeNP zcEwriDgPRY5jb2J6tNmqSq3Tz+7u5t7If7Q4jCdEWz998TkNSXCquYMcjdmsqFaKb41 pPi3K3QYc446oin1v6zxcSFWPYF30kO3rwYmANShLQcIK67nkFRuU3xMYXeJC9tZp4W7 c7gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Jj6lZWiiSlrOt4vVog8SmooRLMbEyS7xw1jh6oSDAjQ=; b=Ite3v/RE1Vmipp8xIuZikE42+z/TkBjuw3CqocI7si2p4C3abX33eNuIjRtVVbZmL6 Ohqn6lyf6soZT2k9EbcD6NCxAQ85qS0pHyoKYwxmr+7EntEfOL75Cbfq2Goi8ja654IE IIffXqsmhN0BcGCxHuC22poD4vcB+9wux0eSfwHm3OM48BWlzbRteBZzq/x/WswcrkLX mlGGuD7C6jRWazwN4UErvzck16EtPUiqtuXXBW+LvsMOynBkRnfNkvlv+3hculObSmKa v1VyIcMNJefyAcYy0ew9BtS0i9FUCqDFORRl/94cY9/2Fhgo/ik5Au4VhRHbK8VjiNpR BkXA== X-Gm-Message-State: AHQUAuYjypjI+92/dGWg6gWRxWdRSoQHRkSNrA+fxAO2U3RJlWrNGZe5 QCXLA8GXPkIvFty+w5ssCNVDP9+S X-Google-Smtp-Source: AHgI3IYL/ZziYvUVmwUjB4Yd5zex+aaKUxTnPHd4cpB7O8G+JnWR5/U+WjkXtyrRuVfGz4w3DmAJOw== X-Received: by 2002:a62:449b:: with SMTP id m27mr23963491pfi.79.1551150353248; Mon, 25 Feb 2019 19:05:53 -0800 (PST) Received: from surajjs2.ozlabs.ibm.com.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id j1sm4427825pgp.84.2019.02.25.19.05.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 25 Feb 2019 19:05:52 -0800 (PST) From: Suraj Jitindar Singh To: qemu-ppc@nongnu.org Date: Tue, 26 Feb 2019 14:05:29 +1100 Message-Id: <20190226030531.9932-2-sjitindarsingh@gmail.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190226030531.9932-1-sjitindarsingh@gmail.com> References: <20190226030531.9932-1-sjitindarsingh@gmail.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::441 Subject: [Qemu-devel] [QEMU-PPC] [PATCH 2/4] target/ppc: Implement large decrementer support for TCG X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org, clg@kaod.org, Suraj Jitindar Singh , david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Prior to POWER9 the decrementer was a 32-bit register which decremented with each tick of the timebase. From POWER9 onwards the decrementer can be set to operate in a mode called large decrementer where it acts as a n-bit decrementing register which is visible as a 64-bit register, that is the value of the decrementer is sign extended to 64 bits (where n is implementation dependant). The mode in which the decrementer operates is controlled by the LPCR_LD bit in the logical paritition control register (LPCR). From POWER9 onwards the HDEC (hypervisor decrementer) was enlarged to h-bits, also sign extended to 64 bits (where h is implementation dependant). Note this isn't configurable and is always enabled. For TCG we allow the user to configure a custom large decrementer size, so long as it's at least 32 and less than the size of the HDEC (the restrictions imposed by the ISA). Signed-off-by: Suraj Jitindar Singh Signed-off-by: Cédric Le Goater --- hw/ppc/ppc.c | 78 ++++++++++++++++++++++++++++------------- hw/ppc/spapr.c | 8 +++++ hw/ppc/spapr_caps.c | 38 +++++++++++++++++++- target/ppc/cpu-qom.h | 1 + target/ppc/cpu.h | 11 +++--- target/ppc/mmu-hash64.c | 2 +- target/ppc/translate.c | 2 +- target/ppc/translate_init.inc.c | 1 + 8 files changed, 109 insertions(+), 32 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index d1e3d4cd20..853afeed6a 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -744,10 +744,10 @@ bool ppc_decr_clear_on_delivery(CPUPPCState *env) return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED); } -static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next) +static inline uint64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next) { ppc_tb_t *tb_env = env->tb_env; - uint32_t decr; + uint64_t decr; int64_t diff; diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -758,27 +758,42 @@ static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next) } else { decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND); } - LOG_TB("%s: %08" PRIx32 "\n", __func__, decr); + LOG_TB("%s: %016" PRIx64 "\n", __func__, decr); return decr; } -uint32_t cpu_ppc_load_decr (CPUPPCState *env) +target_ulong cpu_ppc_load_decr (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; + uint64_t decr; if (kvm_enabled()) { return env->spr[SPR_DECR]; } - return _cpu_ppc_load_decr(env, tb_env->decr_next); + decr = _cpu_ppc_load_decr(env, tb_env->decr_next); + + /* + * If large decrementer is enabled then the decrementer is signed extened + * to 64 bits, otherwise it is a 32 bit value. + */ + if (env->spr[SPR_LPCR] & LPCR_LD) + return decr; + return (uint32_t) decr; } -uint32_t cpu_ppc_load_hdecr (CPUPPCState *env) +target_ulong cpu_ppc_load_hdecr (CPUPPCState *env) { ppc_tb_t *tb_env = env->tb_env; + uint64_t decr; - return _cpu_ppc_load_decr(env, tb_env->hdecr_next); + decr = _cpu_ppc_load_decr(env, tb_env->hdecr_next); + + /* If POWER9 or later then hdecr is sign extended to 64 bits otherwise 32 */ + if (env->mmu_model & POWERPC_MMU_3_00) + return decr; + return (uint32_t) decr; } uint64_t cpu_ppc_load_purr (CPUPPCState *env) @@ -832,13 +847,21 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, QEMUTimer *timer, void (*raise_excp)(void *), void (*lower_excp)(PowerPCCPU *), - uint32_t decr, uint32_t value) + target_ulong decr, target_ulong value, + int nr_bits) { CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env = env->tb_env; uint64_t now, next; + bool negative; + + /* Truncate value to decr_width and sign extend for simplicity */ + value &= ((1ULL << nr_bits) - 1); + negative = !!(value & (1ULL << (nr_bits - 1))); + if (negative) + value |= (0xFFFFFFFFULL << nr_bits); - LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__, + LOG_TB("%s: " TARGET_FMT_lx " => " TARGET_FMT_lx "\n", __func__, decr, value); if (kvm_enabled()) { @@ -860,15 +883,15 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, * an edge interrupt, so raise it here too. */ if ((value < 3) || - ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) || - ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000) - && !(decr & 0x80000000))) { + ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && negative) || + ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && negative + && !(decr & (1ULL << (nr_bits - 1))))) { (*raise_excp)(cpu); return; } /* On MSB level based systems a 0 for the MSB stops interrupt delivery */ - if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) { + if (!negative && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) { (*lower_excp)(cpu); } @@ -881,21 +904,24 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, timer_mod(timer, next); } -static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr, - uint32_t value) +static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr, + target_ulong value, int nr_bits) { ppc_tb_t *tb_env = cpu->env.tb_env; __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer, tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr, - value); + value, nr_bits); } -void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value) +void cpu_ppc_store_decr (CPUPPCState *env, target_ulong value) { PowerPCCPU *cpu = ppc_env_get_cpu(env); + int nr_bits = 32; + if ((env->spr[SPR_LPCR] & LPCR_LD) && (env->large_decr_bits > 32)) + nr_bits = env->large_decr_bits; - _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value); + _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, nr_bits); } static void cpu_ppc_decr_cb(void *opaque) @@ -905,23 +931,25 @@ static void cpu_ppc_decr_cb(void *opaque) cpu_ppc_decr_excp(cpu); } -static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr, - uint32_t value) +static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr, + target_ulong value, int nr_bits) { ppc_tb_t *tb_env = cpu->env.tb_env; if (tb_env->hdecr_timer != NULL) { __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer, tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower, - hdecr, value); + hdecr, value, nr_bits); } } -void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value) +void cpu_ppc_store_hdecr (CPUPPCState *env, target_ulong value) { PowerPCCPU *cpu = ppc_env_get_cpu(env); + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); + int nr_bits = (pcc->hdecr_bits > 32) ? pcc->hdecr_bits : 32; - _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value); + _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, nr_bits); } static void cpu_ppc_hdecr_cb(void *opaque) @@ -951,8 +979,8 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) * if a decrementer exception is pending when it enables msr_ee at startup, * it's not ready to handle it... */ - _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF); - _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF); + _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32); + _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32); cpu_ppc_store_purr(cpu, 0x0000000000000000ULL); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index acf62a2b9f..966bc74e68 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -557,6 +557,14 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, pcc->radix_page_info->count * sizeof(radix_AP_encodings[0])))); } + + /* + * We set this property to let the guest know that it can use the large + * decrementer and its width in bits. + */ + if (env->large_decr_bits) + _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", + env->large_decr_bits))); } static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index 1545a02729..44542fdbb2 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -421,8 +421,43 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr, static void cap_large_decr_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) { - if (val) + PowerPCCPU *cpu = POWERPC_CPU(first_cpu); + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); + + if (!val) + return; /* Disabled by default */ + + if (tcg_enabled()) { + if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, + spapr->max_compat_pvr)) { + error_setg(errp, + "Large decrementer only supported on POWER9, try -cpu POWER9"); + return; + } + if ((val < 32) || (val > pcc->hdecr_bits)) { + error_setg(errp, + "Large decrementer size unsupported, try -cap-large-decr=%d", + pcc->hdecr_bits); + return; + } + } else { error_setg(errp, "No large decrementer support, try cap-large-decr=0"); + } +} + +static void cap_large_decr_cpu_apply(sPAPRMachineState *spapr, + PowerPCCPU *cpu, + uint8_t val, Error **errp) +{ + CPUPPCState *env = &cpu->env; + target_ulong lpcr = env->spr[SPR_LPCR]; + + if (val) + lpcr |= LPCR_LD; + else + lpcr &= ~LPCR_LD; + ppc_store_lpcr(cpu, lpcr); + env->large_decr_bits = val; } sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { @@ -511,6 +546,7 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { .set = spapr_cap_set_uint8, .type = "int", .apply = cap_large_decr_apply, + .cpu_apply = cap_large_decr_cpu_apply, }, }; diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index ae51fe754e..cced705e30 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -190,6 +190,7 @@ typedef struct PowerPCCPUClass { #endif const PPCHash64Options *hash64_opts; struct ppc_radix_page_info *radix_page_info; + uint32_t hdecr_bits; void (*init_proc)(CPUPPCState *env); int (*check_pow)(CPUPPCState *env); int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 26604ddf98..8da333e9da 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1171,6 +1171,9 @@ struct CPUPPCState { uint32_t tm_vscr; uint64_t tm_dscr; uint64_t tm_tar; + + /* Large Decrementer */ + int large_decr_bits; }; #define SET_FIT_PERIOD(a_, b_, c_, d_) \ @@ -1321,10 +1324,10 @@ uint32_t cpu_ppc_load_atbu (CPUPPCState *env); void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value); void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value); bool ppc_decr_clear_on_delivery(CPUPPCState *env); -uint32_t cpu_ppc_load_decr (CPUPPCState *env); -void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value); -uint32_t cpu_ppc_load_hdecr (CPUPPCState *env); -void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value); +target_ulong cpu_ppc_load_decr (CPUPPCState *env); +void cpu_ppc_store_decr (CPUPPCState *env, target_ulong value); +target_ulong cpu_ppc_load_hdecr (CPUPPCState *env); +void cpu_ppc_store_hdecr (CPUPPCState *env, target_ulong value); uint64_t cpu_ppc_load_purr (CPUPPCState *env); uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env); uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env); diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index c431303eff..a2b1ec5040 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -1109,7 +1109,7 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val) case POWERPC_MMU_3_00: /* P9 */ lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | - LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | + LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC | LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 819221f246..b156be4d98 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -7417,7 +7417,7 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, #if !defined(NO_TIMER_DUMP) cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64 #if !defined(CONFIG_USER_ONLY) - " DECR %08" PRIu32 + " DECR " TARGET_FMT_lu #endif "\n", cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env) diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 58542c0fe0..4e0bf1f47a 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -8926,6 +8926,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) /* segment page size remain the same */ pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->radix_page_info = &POWER9_radix_page_info; + pcc->hdecr_bits = 56; #endif pcc->excp_model = POWERPC_EXCP_POWER9; pcc->bus_model = PPC_FLAGS_INPUT_POWER9;