From patchwork Fri Jan 13 06:28:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suraj Jitindar Singh X-Patchwork-Id: 9514679 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5EFD260762 for ; Fri, 13 Jan 2017 06:47:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 553302040D for ; Fri, 13 Jan 2017 06:47:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 47DD12860A; Fri, 13 Jan 2017 06:47:44 +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=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5E1AD2040D for ; Fri, 13 Jan 2017 06:47:42 +0000 (UTC) Received: from localhost ([::1]:39388 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cRveH-0007u4-8z for patchwork-qemu-devel@patchwork.kernel.org; Fri, 13 Jan 2017 01:47:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53290) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cRvMO-0006NA-Pn for qemu-devel@nongnu.org; Fri, 13 Jan 2017 01:29:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cRvMN-00022K-79 for qemu-devel@nongnu.org; Fri, 13 Jan 2017 01:29:12 -0500 Received: from mail-pf0-x244.google.com ([2607:f8b0:400e:c00::244]:35562) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cRvMH-00020z-Ty; Fri, 13 Jan 2017 01:29:06 -0500 Received: by mail-pf0-x244.google.com with SMTP id f144so6905247pfa.2; Thu, 12 Jan 2017 22:29:05 -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; bh=U4WynXmLahVUif5TYD3SUnWE7H+3OLn1loNOBYDsQO4=; b=HneNLXP7AYErNgt0GkEo++s9ell/IJqT0ioZXMAz5NMBftdwDQwtcoEfAYs+MAeYpR BGIIxTYCp18yS0s2Z4p0WQV0WLUXiFlICo+lYBw8T4OKG1dogcZNbpItawuTmNyLRx2v MfaagHuQw3G/LbSPT48HiX2SbYZq5GXrfoJOL/leO34ct2ZN4t5ife3lMAzdcNjNN8f6 3M8HQ5LSNh1963mN5n6Oo0uNk6xwX/0t15BggZVPOMh1KWR+DnqAB/QQrYKlYcUZoZW+ HBYDlmbWpdfUm+bXc29vbvq5pFRhVjhHb6ksf1mhDMvaEa19z/j73MSwg8EHF25/4k4Z ebAA== 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; bh=U4WynXmLahVUif5TYD3SUnWE7H+3OLn1loNOBYDsQO4=; b=sFmFLsl/eW5lg2owKPODNUUkevsxDW/SZXbCu9TPMvPabQgm+Gwzv1/9tbEPIy8WKc 5YhR/NWGDwPQP9HbAppCZ6fbbsEoWcFXW9ndBZuNnYy8JfcyDgj+Szujy4MWAXximdSm ZmDhGlnxa5l8FUNaroa4yhfI3HAm+39hGi1ad8FeFXjZ2DAiSaGgcgsbA2NrD1IhuEL/ JaHZyyiDsSasfn/PiTVTMDOLx32hg2hpAzRmYZIEzSDKxwmV7WFqJerqtNj+1f5do0cW 3arJoLI91SDy5L2SOOFv+QQl1n/AGGSxxa0BKq0PrEADf9BA7hjDyQEIzii8a+wtHu5n X6RQ== X-Gm-Message-State: AIkVDXIxcHs2Iwy2tc2lWs34yUkbIa/2K4zkjd5BW3vsx9lTv0HqHYqbj1V+HO+VedCHEg== X-Received: by 10.84.210.8 with SMTP id z8mr26851012plh.94.1484288945046; Thu, 12 Jan 2017 22:29:05 -0800 (PST) Received: from dyn253.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id r2sm26004999pfi.67.2017.01.12.22.29.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Jan 2017 22:29:04 -0800 (PST) From: Suraj Jitindar Singh To: qemu-ppc@nongnu.org Date: Fri, 13 Jan 2017 17:28:17 +1100 Message-Id: <1484288903-18807-12-git-send-email-sjitindarsingh@gmail.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1484288903-18807-1-git-send-email-sjitindarsingh@gmail.com> References: <1484288903-18807-1-git-send-email-sjitindarsingh@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::244 Subject: [Qemu-devel] [RFC PATCH 11/17] target/ppc/POWER9: Update to new pte format for POWER9 accesses 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, agraf@suse.de, 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 The page table entry format was updated for the POWER9 processor. It was decided that kernels would used the old format irrespective with the translation occuring at the hypervisor level. Thus we convert between the old and new format when accessing the ptes. Since we need the whole pte to perform this conversion, we remove the old functions which accessed either the first or second doubleword and introduce a new functions which access the entire pte, returning the entry converted back to the old format (if required). Update call sites accordingly. Signed-off-by: Suraj Jitindar Singh --- hw/ppc/spapr_hcall.c | 51 ++++++++++++++++++----------------- target/ppc/mmu-hash64.c | 13 +++++---- target/ppc/mmu-hash64.h | 71 ++++++++++++++++++++++++++++++++++++------------- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 9a9bedf..9f0c20d 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -125,7 +125,8 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr, pte_index &= ~7ULL; token = ppc_hash64_start_access(cpu, pte_index); for (; index < 8; index++) { - if (!(ppc_hash64_load_hpte0(cpu, token, index) & HPTE64_V_VALID)) { + ppc_hash_pte64_t pte = ppc_hash64_load_hpte(cpu, token, index); + if (!(pte.pte0 & HPTE64_V_VALID)) { break; } } @@ -134,8 +135,10 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr, return H_PTEG_FULL; } } else { + ppc_hash_pte64_t pte; token = ppc_hash64_start_access(cpu, pte_index); - if (ppc_hash64_load_hpte0(cpu, token, 0) & HPTE64_V_VALID) { + pte = ppc_hash64_load_hpte(cpu, token, 0); + if (pte.pte0 & HPTE64_V_VALID) { ppc_hash64_stop_access(cpu, token); return H_PTEG_FULL; } @@ -163,26 +166,25 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex, { CPUPPCState *env = &cpu->env; uint64_t token; - target_ulong v, r; + ppc_hash_pte64_t pte; if (!valid_pte_index(env, ptex)) { return REMOVE_PARM; } token = ppc_hash64_start_access(cpu, ptex); - v = ppc_hash64_load_hpte0(cpu, token, 0); - r = ppc_hash64_load_hpte1(cpu, token, 0); + pte = ppc_hash64_load_hpte(cpu, token, 0); ppc_hash64_stop_access(cpu, token); - if ((v & HPTE64_V_VALID) == 0 || - ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) || - ((flags & H_ANDCOND) && (v & avpn) != 0)) { + if ((pte.pte0 & HPTE64_V_VALID) == 0 || + ((flags & H_AVPN) && (pte.pte0 & ~0x7fULL) != avpn) || + ((flags & H_ANDCOND) && (pte.pte0 & avpn) != 0)) { return REMOVE_NOT_FOUND; } - *vp = v; - *rp = r; + *vp = pte.pte0; + *rp = pte.pte1; ppc_hash64_store_hpte(cpu, ptex, HPTE64_V_HPTE_DIRTY, 0); - ppc_hash64_tlb_flush_hpte(cpu, ptex, v, r); + ppc_hash64_tlb_flush_hpte(cpu, ptex, pte.pte0, pte.pte1); return REMOVE_SUCCESS; } @@ -293,35 +295,36 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; + ppc_hash_pte64_t pte; uint64_t token; - target_ulong v, r; if (!valid_pte_index(env, pte_index)) { return H_PARAMETER; } token = ppc_hash64_start_access(cpu, pte_index); - v = ppc_hash64_load_hpte0(cpu, token, 0); - r = ppc_hash64_load_hpte1(cpu, token, 0); + pte = ppc_hash64_load_hpte(cpu, token, 0); ppc_hash64_stop_access(cpu, token); - if ((v & HPTE64_V_VALID) == 0 || - ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) { + if ((pte.pte0 & HPTE64_V_VALID) == 0 || + ((flags & H_AVPN) && (pte.pte0 & ~0x7fULL) != avpn)) { return H_NOT_FOUND; } - r &= ~(HPTE64_R_PP0 | HPTE64_R_PP | HPTE64_R_N | - HPTE64_R_KEY_HI | HPTE64_R_KEY_LO); - r |= (flags << 55) & HPTE64_R_PP0; - r |= (flags << 48) & HPTE64_R_KEY_HI; - r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO); + pte.pte1 &= ~(HPTE64_R_PP0 | HPTE64_R_PP | HPTE64_R_N | + HPTE64_R_KEY_HI | HPTE64_R_KEY_LO); + pte.pte1 |= (flags << 55) & HPTE64_R_PP0; + pte.pte1 |= (flags << 48) & HPTE64_R_KEY_HI; + pte.pte1 |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO); ppc_hash64_store_hpte(cpu, pte_index, - (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0); - ppc_hash64_tlb_flush_hpte(cpu, pte_index, v, r); + (pte.pte0 & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, + 0); + ppc_hash64_tlb_flush_hpte(cpu, pte_index, pte.pte0, pte.pte1); /* Flush the tlb */ check_tlb_flush(env, true); /* Don't need a memory barrier, due to qemu's global lock */ - ppc_hash64_store_hpte(cpu, pte_index, v | HPTE64_V_HPTE_DIRTY, r); + ppc_hash64_store_hpte(cpu, pte_index, pte.pte0 | HPTE64_V_HPTE_DIRTY, + pte.pte1); return H_SUCCESS; } diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index b476b3f..03607d5 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -515,7 +515,6 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, CPUPPCState *env = &cpu->env; int i; uint64_t token; - target_ulong pte0, pte1; target_ulong pte_index; pte_index = (hash & env->htab_mask) * HPTES_PER_GROUP; @@ -524,12 +523,11 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, return -1; } for (i = 0; i < HPTES_PER_GROUP; i++) { - pte0 = ppc_hash64_load_hpte0(cpu, token, i); - pte1 = ppc_hash64_load_hpte1(cpu, token, i); + ppc_hash_pte64_t entry = ppc_hash64_load_hpte(cpu, token, i); /* This compares V, B, H (secondary) and the AVPN */ - if (HPTE64_V_COMPARE(pte0, ptem)) { - *pshift = hpte_page_shift(sps, pte0, pte1); + if (HPTE64_V_COMPARE(entry.pte0, ptem)) { + *pshift = hpte_page_shift(sps, entry.pte0, entry.pte1); /* * If there is no match, ignore the PTE, it could simply * be for a different segment size encoding and the @@ -543,8 +541,7 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, /* We don't do anything with pshift yet as qemu TLB only deals * with 4K pages anyway */ - pte->pte0 = pte0; - pte->pte1 = pte1; + *pte = entry; ppc_hash64_stop_access(cpu, token); return (pte_index + i) * HASH_PTE_SIZE_64; } @@ -924,6 +921,8 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, { CPUPPCState *env = &cpu->env; + ppc_hash64_hpte_old_to_new(env, &pte0, &pte1); + if (env->external_htab == MMU_HASH64_KVM_MANAGED_HPT) { kvmppc_hash64_write_pte(env, pte_index, pte0, pte1); return; diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index ab5d347..73d7ce4 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -60,6 +60,7 @@ void ppc_hash64_update_rmls(CPUPPCState *env); #define HASH_PTE_SIZE_64 16 #define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP) +#define HPTE64_V_3_00_COMMON 0x000fffffffffffffULL #define HPTE64_V_SSIZE_SHIFT 62 #define HPTE64_V_AVPN_SHIFT 7 #define HPTE64_V_AVPN 0x3fffffffffffff80ULL @@ -69,9 +70,12 @@ void ppc_hash64_update_rmls(CPUPPCState *env); #define HPTE64_V_SECONDARY 0x0000000000000002ULL #define HPTE64_V_VALID 0x0000000000000001ULL +#define HPTE64_R_3_00_COMMON 0xf1ffffffffffffffULL #define HPTE64_R_PP0 0x8000000000000000ULL #define HPTE64_R_TS 0x4000000000000000ULL #define HPTE64_R_KEY_HI 0x3000000000000000ULL +#define HPTE64_R_SSIZE_SHIFT 58 +#define HPTE64_R_SSIZE_MASK (3ULL << HPTE64_R_SSIZE_SHIFT) #define HPTE64_R_RPN_SHIFT 12 #define HPTE64_R_RPN 0x0ffffffffffff000ULL #define HPTE64_R_FLAGS 0x00000000000003ffULL @@ -91,6 +95,10 @@ void ppc_hash64_update_rmls(CPUPPCState *env); #define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL +typedef struct { + uint64_t pte0, pte1; +} ppc_hash_pte64_t; + void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value, Error **errp); void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, @@ -99,37 +107,64 @@ void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, uint64_t ppc_hash64_start_access(PowerPCCPU *cpu, target_ulong pte_index); void ppc_hash64_stop_access(PowerPCCPU *cpu, uint64_t token); -static inline target_ulong ppc_hash64_load_hpte0(PowerPCCPU *cpu, - uint64_t token, int index) +static inline void ppc_hash64_hpte_old_to_new(CPUPPCState *env, + target_ulong *pte0, + target_ulong *pte1) { - CPUPPCState *env = &cpu->env; - uint64_t addr; + switch (env->mmu_model) { + case POWERPC_MMU_3_00: + /* + * v3.00 of the ISA moved the B field to the second doubleword and + * shortened the abbreviated virtual address and abbreviated real page + * number fields + */ + *pte1 = (*pte1 & HPTE64_R_3_00_COMMON) | + ((*pte0 >> HPTE64_V_SSIZE_SHIFT) << HPTE64_R_SSIZE_SHIFT); + *pte0 = *pte0 & HPTE64_V_3_00_COMMON; + default: + ; + } +} - addr = token + (index * HASH_PTE_SIZE_64); - if (env->external_htab) { - return ldq_p((const void *)(uintptr_t)addr); - } else { - return ldq_phys(CPU(cpu)->as, addr); +static inline void ppc_hash64_hpte_new_to_old(CPUPPCState *env, + target_ulong *pte0, + target_ulong *pte1) +{ + switch (env->mmu_model) { + case POWERPC_MMU_3_00: + /* + * v3.00 of the ISA moved the B field to the second doubleword and + * shortened the abbreviated virtual address and abbreviated real page + * number fields + */ + *pte0 = (*pte0 & HPTE64_V_3_00_COMMON) | ((*pte1 & HPTE64_R_SSIZE_MASK) + << (HPTE64_V_SSIZE_SHIFT - HPTE64_R_SSIZE_SHIFT)); + *pte1 = *pte1 & HPTE64_R_3_00_COMMON; + default: + ; } } -static inline target_ulong ppc_hash64_load_hpte1(PowerPCCPU *cpu, - uint64_t token, int index) +static inline ppc_hash_pte64_t ppc_hash64_load_hpte(PowerPCCPU *cpu, + uint64_t token, + int index) { CPUPPCState *env = &cpu->env; + ppc_hash_pte64_t pte; uint64_t addr; - addr = token + (index * HASH_PTE_SIZE_64) + HASH_PTE_SIZE_64/2; + addr = token + (index * HASH_PTE_SIZE_64); if (env->external_htab) { - return ldq_p((const void *)(uintptr_t)addr); + pte.pte0 = ldq_p((const void *)(uintptr_t)addr); + pte.pte1 = ldq_p((const void *)(uintptr_t)addr + HASH_PTE_SIZE_64/2); } else { - return ldq_phys(CPU(cpu)->as, addr); + pte.pte0 = ldq_phys(CPU(cpu)->as, addr); + pte.pte1 = ldq_phys(CPU(cpu)->as, addr + HASH_PTE_SIZE_64/2); } -} -typedef struct { - uint64_t pte0, pte1; -} ppc_hash_pte64_t; + ppc_hash64_hpte_new_to_old(env, &pte.pte0, &pte.pte1); + return pte; +} #endif /* CONFIG_USER_ONLY */