3f9f76d5bb
This commit attempts to fix a technical hiccup first mentioned by Richard Henderson in https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06247.html To sumarize the hiccup here, when radix-style mmus are translating an address, they might need to call a second level of translation, with hypervisor privileges. However, the way it was being done up until this point meant that the second level translation had the same privileges as the first level. It could lead to a bug in address translation when running KVM inside a TCG guest, but this bug was never experienced by users, so this isn't as much a bug fix as it is a correctness cleanup. This patch attempts that cleanup by making radix64_*_xlate functions receive the mmu_idx, and passing one with the correct permission for the second level translation. The mmuidx macros added by this patch are only correct for non-bookE mmus, because BookE style set the IS and DS bits inverted and there might be other subtle differences. However, there doesn't seem to be BookE cpus that have radix-style mmus, so we left a comment there to document the issue, in case a machine does have that and was missed. As part of this cleanup, we now need to send the correct mmmu_idx when calling get_phys_page_debug, otherwise we might not be able to see the memory that the CPU could Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Bruno Larsen (billionai) <bruno.larsen@eldorado.org.br> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Cédric Le Goater <clg@kaod.org> Tested-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20210628133610.1143-2-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
130 lines
3.7 KiB
C
130 lines
3.7 KiB
C
/*
|
|
* PowerPC ISAV3 BookS emulation generic mmu definitions for qemu.
|
|
*
|
|
* Copyright (c) 2017 Suraj Jitindar Singh, IBM Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef PPC_MMU_BOOK3S_V3_H
|
|
#define PPC_MMU_BOOK3S_V3_H
|
|
|
|
#include "mmu-hash64.h"
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
/*
|
|
* Partition table definitions
|
|
*/
|
|
#define PTCR_PATB 0x0FFFFFFFFFFFF000ULL /* Partition Table Base */
|
|
#define PTCR_PATS 0x000000000000001FULL /* Partition Table Size */
|
|
|
|
/* Partition Table Entry Fields */
|
|
#define PATE0_HR 0x8000000000000000
|
|
|
|
/*
|
|
* WARNING: This field doesn't actually exist in the final version of
|
|
* the architecture and is unused by hardware. However, qemu uses it
|
|
* as an indication of a radix guest in the pseudo-PATB entry that it
|
|
* maintains for SPAPR guests and in the migration stream, so we need
|
|
* to keep it around
|
|
*/
|
|
#define PATE1_GR 0x8000000000000000
|
|
|
|
/* Process Table Entry */
|
|
struct prtb_entry {
|
|
uint64_t prtbe0, prtbe1;
|
|
};
|
|
|
|
/*
|
|
* These correspond to the mmu_idx values computed in
|
|
* hreg_compute_hflags_value. See the tables therein
|
|
*
|
|
* They are here because some bits are inverted for BookE MMUs
|
|
* not necessarily because they only work for BookS. However,
|
|
* we only needed to change BookS MMUs, we left the functions
|
|
* here to avoid other possible bugs for untested MMUs
|
|
*/
|
|
static inline bool mmuidx_pr(int idx) { return !(idx & 1); }
|
|
static inline bool mmuidx_real(int idx) { return idx & 2; }
|
|
static inline bool mmuidx_hv(int idx) { return idx & 4; }
|
|
|
|
#ifdef TARGET_PPC64
|
|
|
|
static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu)
|
|
{
|
|
return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT);
|
|
}
|
|
|
|
bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid,
|
|
ppc_v3_pate_t *entry);
|
|
|
|
/*
|
|
* The LPCR:HR bit is a shortcut that avoids having to
|
|
* dig out the partition table in the fast path. This is
|
|
* also how the HW uses it.
|
|
*/
|
|
static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
|
|
{
|
|
return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
|
|
}
|
|
|
|
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
|
|
{
|
|
uint64_t base;
|
|
|
|
if (cpu->vhyp) {
|
|
return 0;
|
|
}
|
|
if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
|
|
ppc_v3_pate_t pate;
|
|
|
|
if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
|
|
return 0;
|
|
}
|
|
base = pate.dw0;
|
|
} else {
|
|
base = cpu->env.spr[SPR_SDR1];
|
|
}
|
|
return base & SDR_64_HTABORG;
|
|
}
|
|
|
|
static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
|
|
{
|
|
uint64_t base;
|
|
|
|
if (cpu->vhyp) {
|
|
PPCVirtualHypervisorClass *vhc =
|
|
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
|
|
return vhc->hpt_mask(cpu->vhyp);
|
|
}
|
|
if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
|
|
ppc_v3_pate_t pate;
|
|
|
|
if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
|
|
return 0;
|
|
}
|
|
base = pate.dw0;
|
|
} else {
|
|
base = cpu->env.spr[SPR_SDR1];
|
|
}
|
|
return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1;
|
|
}
|
|
|
|
#endif /* TARGET_PPC64 */
|
|
|
|
#endif /* CONFIG_USER_ONLY */
|
|
|
|
#endif /* PPC_MMU_BOOK3S_V3_H */
|