From nobody Sat Apr 20 01:34:06 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617982841; cv=none; d=zohomail.com; s=zohoarc; b=eUod4nUMYvETBssujeLo1eOQ9NLTZN2VZplXM3twglc6yMbSScRIT4o/9ogCkZfp1S6GN6UdscEuiJJ911CjPwkTYt1UaosRO60c7wL9LIhHPoODc77JyHvW3dWo/UK99TOnF6fmambXt0YaHoqP2oh+MudeKbwGopJCpcJ1Z/M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617982841; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=w7IbVW6cZG+YWIaArfAYDU+av8coOY+awwid3Uq+SNA=; b=Pq2w8G8n3IEynE28viZFFZq49kG5utBb5xViCYPqvhY50lskdgXNEnG00gZ5TfWyadE8vgtDxvMPYUD/Rp/n1wuPteym+mhft4w/dU5pOWE7FM7/oW1D1uLESFTO4Ak5UQVYnyDftu4RDBMxTij9M70vazvEZYXNA7ab+oTNBi0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617982841237650.1339199414008; Fri, 9 Apr 2021 08:40:41 -0700 (PDT) Received: from localhost ([::1]:46370 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtFP-0003nr-Kd for importer@patchew.org; Fri, 09 Apr 2021 11:40:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39798) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lUtBV-0001QU-Uo; Fri, 09 Apr 2021 11:36:37 -0400 Received: from [201.28.113.2] (port=55645 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtBR-00025X-D4; Fri, 09 Apr 2021 11:36:37 -0400 Received: from power9a ([10.10.71.235]) by outlook.eldorado.org.br with Microsoft SMTPSVC(8.5.9600.16384); Fri, 9 Apr 2021 12:19:21 -0300 Received: from eldorado.org.br (unknown [10.10.71.235]) by power9a (Postfix) with ESMTP id 4E52C801350; Fri, 9 Apr 2021 12:19:21 -0300 (-03) From: "Bruno Larsen (billionai)" To: qemu-devel@nongnu.org Subject: [PATCH 1/4] target/ppc: Code motion required to build disabling tcg Date: Fri, 9 Apr 2021 12:19:13 -0300 Message-Id: <20210409151916.97326-2-bruno.larsen@eldorado.org.br> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> References: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> X-OriginalArrivalTime: 09 Apr 2021 15:19:21.0516 (UTC) FILETIME=[B7845EC0:01D72D53] X-Host-Lookup-Failed: Reverse DNS lookup failed for 201.28.113.2 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=201.28.113.2; envelope-from=bruno.larsen@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: lucas.araujo@eldorado.org.br, lagarcia@br.ibm.com, luis.pires@eldorado.org.br, fernando.valle@eldorado.org.br, qemu-ppc@nongnu.org, andre.silva@eldorado.org.br, "Bruno Larsen \(billionai\)" , matheus.ferst@eldorado.org.br Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This commit does the necessary code motion from translate_init.c.inc This moves all functions that start with gdb_* into target/ppc/gdbstub.c and creates a new function that calls those and is called by ppc_cpu_realize All functions related to realizing the cpu have been moved to cpu.c, which may call functions from gdbstub or translate_init Signed-off-by: Bruno Larsen (billionai) --- target/ppc/cpu.c | 859 +++++++++++++++++++++++ target/ppc/cpu.h | 15 + target/ppc/gdbstub.c | 253 +++++++ target/ppc/translate_init.c.inc | 1148 +------------------------------ 4 files changed, 1163 insertions(+), 1112 deletions(-) diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c index e501a7ff6f..b77ea1c943 100644 --- a/target/ppc/cpu.c +++ b/target/ppc/cpu.c @@ -20,6 +20,21 @@ #include "qemu/osdep.h" #include "cpu.h" #include "cpu-models.h" +#include "kvm_ppc.h" +#include "qemu/qemu-print.h" +#include "qemu/cutils.h" +#include "qapi/qapi-commands-machine-target.h" + +#include "qapi/error.h" +#include "sysemu/tcg.h" +#include "helper_regs.h" +#include "hw/ppc/ppc.h" +#include "fpu/softfloat-helpers.h" +#include "sysemu/hw_accel.h" +#include "disas/capstone.h" +#include "hw/qdev-properties.h" +#include "internal.h" +#include "mmu-hash64.h" =20 target_ulong cpu_read_xer(CPUPPCState *env) { @@ -45,3 +60,847 @@ void cpu_write_xer(CPUPPCState *env, target_ulong xer) (1ul << XER_OV) | (1ul << XER_CA) | (1ul << XER_OV32) | (1ul << XER_CA32)); } + + +static const char *ppc_cpu_lookup_alias(const char *alias) +{ + int ai; + + for (ai =3D 0; ppc_cpu_aliases[ai].alias !=3D NULL; ai++) { + if (strcmp(ppc_cpu_aliases[ai].alias, alias) =3D=3D 0) { + return ppc_cpu_aliases[ai].model; + } + } + + return NULL; +} + +static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b) +{ + ObjectClass *oc =3D (ObjectClass *)a; + uint32_t pvr =3D *(uint32_t *)b; + PowerPCCPUClass *pcc =3D (PowerPCCPUClass *)a; + + /* -cpu host does a PVR lookup during construction */ + if (unlikely(strcmp(object_class_get_name(oc), + TYPE_HOST_POWERPC_CPU) =3D=3D 0)) { + return -1; + } + + return pcc->pvr =3D=3D pvr ? 0 : -1; +} + +static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer = b) +{ + ObjectClass *oc =3D (ObjectClass *)a; + uint32_t pvr =3D *(uint32_t *)b; + PowerPCCPUClass *pcc =3D (PowerPCCPUClass *)a; + + /* -cpu host does a PVR lookup during construction */ + if (unlikely(strcmp(object_class_get_name(oc), + TYPE_HOST_POWERPC_CPU) =3D=3D 0)) { + return -1; + } + + if (pcc->pvr_match(pcc, pvr)) { + return 0; + } + + return -1; +} + +PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr) +{ + GSList *list, *item; + PowerPCCPUClass *pcc =3D NULL; + + list =3D object_class_get_list(TYPE_POWERPC_CPU, false); + item =3D g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr); + if (item !=3D NULL) { + pcc =3D POWERPC_CPU_CLASS(item->data); + } + g_slist_free(list); + + return pcc; +} + +PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr) +{ + GSList *list, *item; + PowerPCCPUClass *pcc =3D NULL; + + list =3D object_class_get_list(TYPE_POWERPC_CPU, true); + item =3D g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr_mas= k); + if (item !=3D NULL) { + pcc =3D POWERPC_CPU_CLASS(item->data); + } + g_slist_free(list); + + return pcc; +} + +PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) +{ + ObjectClass *oc =3D OBJECT_CLASS(pcc); + + while (oc && !object_class_is_abstract(oc)) { + oc =3D object_class_get_parent(oc); + } + assert(oc); + + return POWERPC_CPU_CLASS(oc); +} + +/* Sort by PVR, ordering special case "host" last. */ +static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b) +{ + ObjectClass *oc_a =3D (ObjectClass *)a; + ObjectClass *oc_b =3D (ObjectClass *)b; + PowerPCCPUClass *pcc_a =3D POWERPC_CPU_CLASS(oc_a); + PowerPCCPUClass *pcc_b =3D POWERPC_CPU_CLASS(oc_b); + const char *name_a =3D object_class_get_name(oc_a); + const char *name_b =3D object_class_get_name(oc_b); + + if (strcmp(name_a, TYPE_HOST_POWERPC_CPU) =3D=3D 0) { + return 1; + } else if (strcmp(name_b, TYPE_HOST_POWERPC_CPU) =3D=3D 0) { + return -1; + } else { + /* Avoid an integer overflow during subtraction */ + if (pcc_a->pvr < pcc_b->pvr) { + return -1; + } else if (pcc_a->pvr > pcc_b->pvr) { + return 1; + } else { + return 0; + } + } +} +#ifndef CONFIG_USER_ONLY +static const TypeInfo ppc_vhyp_type_info =3D { + .name =3D TYPE_PPC_VIRTUAL_HYPERVISOR, + .parent =3D TYPE_INTERFACE, + .class_size =3D sizeof(PPCVirtualHypervisorClass), +}; +#endif + +static ObjectClass *ppc_cpu_class_by_name(const char *name) +{ + char *cpu_model, *typename; + ObjectClass *oc; + const char *p; + unsigned long pvr; + + /* + * Lookup by PVR if cpu_model is valid 8 digit hex number (excl: + * 0x prefix if present) + */ + if (!qemu_strtoul(name, &p, 16, &pvr)) { + int len =3D p - name; + len =3D (len =3D=3D 10) && (name[1] =3D=3D 'x') ? len - 2 : len; + if ((len =3D=3D 8) && (*p =3D=3D '\0')) { + return OBJECT_CLASS(ppc_cpu_class_by_pvr(pvr)); + } + } + + cpu_model =3D g_ascii_strdown(name, -1); + p =3D ppc_cpu_lookup_alias(cpu_model); + if (p) { + g_free(cpu_model); + cpu_model =3D g_strdup(p); + } + + typename =3D g_strdup_printf("%s" POWERPC_CPU_TYPE_SUFFIX, cpu_model); + oc =3D object_class_by_name(typename); + g_free(typename); + g_free(cpu_model); + + return oc; +} + +static bool ppc_cpu_interrupts_big_endian_always(PowerPCCPU *cpu) +{ + return true; +} + +static int ppc_fixup_cpu(PowerPCCPU *cpu) +{ + CPUPPCState *env =3D &cpu->env; + + /* + * TCG doesn't (yet) emulate some groups of instructions that are + * implemented on some otherwise supported CPUs (e.g. VSX and + * decimal floating point instructions on POWER7). We remove + * unsupported instruction groups from the cpu state's instruction + * masks and hope the guest can cope. For at least the pseries + * machine, the unavailability of these instructions can be + * advertised to the guest via the device tree. + */ + if ((env->insns_flags & ~PPC_TCG_INSNS) + || (env->insns_flags2 & ~PPC_TCG_INSNS2)) { + warn_report("Disabling some instructions which are not " + "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")", + env->insns_flags & ~PPC_TCG_INSNS, + env->insns_flags2 & ~PPC_TCG_INSNS2); + } + env->insns_flags &=3D PPC_TCG_INSNS; + env->insns_flags2 &=3D PPC_TCG_INSNS2; + return 0; +} + +static void ppc_cpu_realize(DeviceState *dev, Error **errp) +{ + CPUState *cs =3D CPU(dev); + PowerPCCPU *cpu =3D POWERPC_CPU(dev); + PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); + Error *local_err =3D NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err !=3D NULL) { + error_propagate(errp, local_err); + return; + } + if (cpu->vcpu_id =3D=3D UNASSIGNED_CPU_INDEX) { + cpu->vcpu_id =3D cs->cpu_index; + } + + if (tcg_enabled()) { + if (ppc_fixup_cpu(cpu) !=3D 0) { + error_setg(errp, "Unable to emulate selected CPU with TCG"); + goto unrealize; + } + } + + create_ppc_opcodes(cpu, &local_err); + if (local_err !=3D NULL) { + error_propagate(errp, local_err); + goto unrealize; + } + init_ppc_proc(cpu); + + ppc_cpu_gdb_init(cs, pcc); + + qemu_init_vcpu(cs); + + pcc->parent_realize(dev, errp); + +#if defined(PPC_DUMP_CPU) + { + CPUPPCState *env =3D &cpu->env; + const char *mmu_model, *excp_model, *bus_model; + switch (env->mmu_model) { + case POWERPC_MMU_32B: + mmu_model =3D "PowerPC 32"; + break; + case POWERPC_MMU_SOFT_6xx: + mmu_model =3D "PowerPC 6xx/7xx with software driven TLBs"; + break; + case POWERPC_MMU_SOFT_74xx: + mmu_model =3D "PowerPC 74xx with software driven TLBs"; + break; + case POWERPC_MMU_SOFT_4xx: + mmu_model =3D "PowerPC 4xx with software driven TLBs"; + break; + case POWERPC_MMU_SOFT_4xx_Z: + mmu_model =3D "PowerPC 4xx with software driven TLBs " + "and zones protections"; + break; + case POWERPC_MMU_REAL: + mmu_model =3D "PowerPC real mode only"; + break; + case POWERPC_MMU_MPC8xx: + mmu_model =3D "PowerPC MPC8xx"; + break; + case POWERPC_MMU_BOOKE: + mmu_model =3D "PowerPC BookE"; + break; + case POWERPC_MMU_BOOKE206: + mmu_model =3D "PowerPC BookE 2.06"; + break; + case POWERPC_MMU_601: + mmu_model =3D "PowerPC 601"; + break; +#if defined(TARGET_PPC64) + case POWERPC_MMU_64B: + mmu_model =3D "PowerPC 64"; + break; +#endif + default: + mmu_model =3D "Unknown or invalid"; + break; + } + switch (env->excp_model) { + case POWERPC_EXCP_STD: + excp_model =3D "PowerPC"; + break; + case POWERPC_EXCP_40x: + excp_model =3D "PowerPC 40x"; + break; + case POWERPC_EXCP_601: + excp_model =3D "PowerPC 601"; + break; + case POWERPC_EXCP_602: + excp_model =3D "PowerPC 602"; + break; + case POWERPC_EXCP_603: + excp_model =3D "PowerPC 603"; + break; + case POWERPC_EXCP_603E: + excp_model =3D "PowerPC 603e"; + break; + case POWERPC_EXCP_604: + excp_model =3D "PowerPC 604"; + break; + case POWERPC_EXCP_7x0: + excp_model =3D "PowerPC 740/750"; + break; + case POWERPC_EXCP_7x5: + excp_model =3D "PowerPC 745/755"; + break; + case POWERPC_EXCP_74xx: + excp_model =3D "PowerPC 74xx"; + break; + case POWERPC_EXCP_BOOKE: + excp_model =3D "PowerPC BookE"; + break; +#if defined(TARGET_PPC64) + case POWERPC_EXCP_970: + excp_model =3D "PowerPC 970"; + break; +#endif + default: + excp_model =3D "Unknown or invalid"; + break; + } + switch (env->bus_model) { + case PPC_FLAGS_INPUT_6xx: + bus_model =3D "PowerPC 6xx"; + break; + case PPC_FLAGS_INPUT_BookE: + bus_model =3D "PowerPC BookE"; + break; + case PPC_FLAGS_INPUT_405: + bus_model =3D "PowerPC 405"; + break; + case PPC_FLAGS_INPUT_401: + bus_model =3D "PowerPC 401/403"; + break; + case PPC_FLAGS_INPUT_RCPU: + bus_model =3D "RCPU / MPC8xx"; + break; +#if defined(TARGET_PPC64) + case PPC_FLAGS_INPUT_970: + bus_model =3D "PowerPC 970"; + break; +#endif + default: + bus_model =3D "Unknown or invalid"; + break; + } + printf("PowerPC %-12s : PVR %08x MSR %016" PRIx64 "\n" + " MMU model : %s\n", + object_class_get_name(OBJECT_CLASS(pcc)), + pcc->pvr, pcc->msr_mask, mmu_model); +#if !defined(CONFIG_USER_ONLY) + if (env->tlb.tlb6) { + printf(" %d %s TLB in %d ways\n", + env->nb_tlb, env->id_tlbs ? "splitted" : "merged", + env->nb_ways); + } +#endif + printf(" Exceptions model : %s\n" + " Bus model : %s\n", + excp_model, bus_model); + printf(" MSR features :\n"); + if (env->flags & POWERPC_FLAG_SPE) { + printf(" signal processing engine enabl= e" + "\n"); + } else if (env->flags & POWERPC_FLAG_VRE) { + printf(" vector processor enable\n"); + } + if (env->flags & POWERPC_FLAG_TGPR) { + printf(" temporary GPRs\n"); + } else if (env->flags & POWERPC_FLAG_CE) { + printf(" critical input enable\n"); + } + if (env->flags & POWERPC_FLAG_SE) { + printf(" single-step trace mode\n"); + } else if (env->flags & POWERPC_FLAG_DWE) { + printf(" debug wait enable\n"); + } else if (env->flags & POWERPC_FLAG_UBLE) { + printf(" user BTB lock enable\n"); + } + if (env->flags & POWERPC_FLAG_BE) { + printf(" branch-step trace mode\n"); + } else if (env->flags & POWERPC_FLAG_DE) { + printf(" debug interrupt enable\n"); + } + if (env->flags & POWERPC_FLAG_PX) { + printf(" inclusive protection\n"); + } else if (env->flags & POWERPC_FLAG_PMM) { + printf(" performance monitor mark\n"); + } + if (env->flags =3D=3D POWERPC_FLAG_NONE) { + printf(" none\n"); + } + printf(" Time-base/decrementer clock source: %s\n", + env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus cloc= k"); + dump_ppc_insns(env); + dump_ppc_sprs(env); + fflush(stdout); + } +#endif + return; + +unrealize: + cpu_exec_unrealizefn(cs); +} + +static void ppc_cpu_unrealize(DeviceState *dev) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(dev); + PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); + + pcc->parent_unrealize(dev); + + cpu_remove_sync(CPU(cpu)); + + destroy_ppc_opcodes(cpu); +} + +static void ppc_cpu_set_pc(CPUState *cs, vaddr value) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + + cpu->env.nip =3D value; +} + +static bool ppc_cpu_has_work(CPUState *cs) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + CPUPPCState *env =3D &cpu->env; + + return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD); +} + +static void ppc_cpu_reset(DeviceState *dev) +{ + CPUState *s =3D CPU(dev); + PowerPCCPU *cpu =3D POWERPC_CPU(s); + PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); + CPUPPCState *env =3D &cpu->env; + target_ulong msr; + int i; + + pcc->parent_reset(dev); + + msr =3D (target_ulong)0; + msr |=3D (target_ulong)MSR_HVB; + msr |=3D (target_ulong)0 << MSR_AP; /* TO BE CHECKED */ + msr |=3D (target_ulong)0 << MSR_SA; /* TO BE CHECKED */ + msr |=3D (target_ulong)1 << MSR_EP; +#if defined(DO_SINGLE_STEP) && 0 + /* Single step trace mode */ + msr |=3D (target_ulong)1 << MSR_SE; + msr |=3D (target_ulong)1 << MSR_BE; +#endif +#if defined(CONFIG_USER_ONLY) + msr |=3D (target_ulong)1 << MSR_FP; /* Allow floating point usage */ + msr |=3D (target_ulong)1 << MSR_FE0; /* Allow floating point exception= s */ + msr |=3D (target_ulong)1 << MSR_FE1; + msr |=3D (target_ulong)1 << MSR_VR; /* Allow altivec usage */ + msr |=3D (target_ulong)1 << MSR_VSX; /* Allow VSX usage */ + msr |=3D (target_ulong)1 << MSR_SPE; /* Allow SPE usage */ + msr |=3D (target_ulong)1 << MSR_PR; +#if defined(TARGET_PPC64) + msr |=3D (target_ulong)1 << MSR_TM; /* Transactional memory */ +#endif +#if !defined(TARGET_WORDS_BIGENDIAN) + msr |=3D (target_ulong)1 << MSR_LE; /* Little-endian user mode */ + if (!((env->msr_mask >> MSR_LE) & 1)) { + fprintf(stderr, "Selected CPU does not support little-endian.\n"); + exit(1); + } +#endif +#endif + +#if defined(TARGET_PPC64) + if (mmu_is_64bit(env->mmu_model)) { + msr |=3D (1ULL << MSR_SF); + } +#endif + + hreg_store_msr(env, msr, 1); + +#if !defined(CONFIG_USER_ONLY) + env->nip =3D env->hreset_vector | env->excp_prefix; + if (env->mmu_model !=3D POWERPC_MMU_REAL) { + ppc_tlb_invalidate_all(env); + } +#endif + + hreg_compute_hflags(env); + env->reserve_addr =3D (target_ulong)-1ULL; + /* Be sure no exception or interrupt is pending */ + env->pending_interrupts =3D 0; + s->exception_index =3D POWERPC_EXCP_NONE; + env->error_code =3D 0; + ppc_irq_reset(cpu); + + /* tininess for underflow is detected before rounding */ + set_float_detect_tininess(float_tininess_before_rounding, + &env->fp_status); + + for (i =3D 0; i < ARRAY_SIZE(env->spr_cb); i++) { + ppc_spr_t *spr =3D &env->spr_cb[i]; + + if (!spr->name) { + continue; + } + env->spr[i] =3D spr->default_value; + } +} + +#ifndef CONFIG_USER_ONLY + +static bool ppc_cpu_is_big_endian(CPUState *cs) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + CPUPPCState *env =3D &cpu->env; + + cpu_synchronize_state(cs); + + return !msr_le; +} + +#ifdef CONFIG_TCG +static void ppc_cpu_exec_enter(CPUState *cs) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + + if (cpu->vhyp) { + PPCVirtualHypervisorClass *vhc =3D + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->cpu_exec_enter(cpu->vhyp, cpu); + } +} + +static void ppc_cpu_exec_exit(CPUState *cs) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + + if (cpu->vhyp) { + PPCVirtualHypervisorClass *vhc =3D + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->cpu_exec_exit(cpu->vhyp, cpu); + } +} +#endif /* CONFIG_TCG */ + +#endif /* !CONFIG_USER_ONLY */ + +static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr) +{ + return pcc->pvr =3D=3D pvr; +} + +static gchar *ppc_gdb_arch_name(CPUState *cs) +{ +#if defined(TARGET_PPC64) + return g_strdup("powerpc:common64"); +#else + return g_strdup("powerpc:common"); +#endif +} + +static void ppc_disas_set_info(CPUState *cs, disassemble_info *info) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + CPUPPCState *env =3D &cpu->env; + + if ((env->hflags >> MSR_LE) & 1) { + info->endian =3D BFD_ENDIAN_LITTLE; + } + info->mach =3D env->bfd_mach; + if (!env->bfd_mach) { +#ifdef TARGET_PPC64 + info->mach =3D bfd_mach_ppc64; +#else + info->mach =3D bfd_mach_ppc; +#endif + } + info->disassembler_options =3D (char *)"any"; + info->print_insn =3D print_insn_ppc; + + info->cap_arch =3D CS_ARCH_PPC; +#ifdef TARGET_PPC64 + info->cap_mode =3D CS_MODE_64; +#endif +} + +static Property ppc_cpu_properties[] =3D { + DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, f= alse), + DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, + false), + DEFINE_PROP_BOOL("pre-3.0-migration", PowerPCCPU, pre_3_0_migration, + false), + DEFINE_PROP_END_OF_LIST(), +}; + +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" + +static struct TCGCPUOps ppc_tcg_ops =3D { + .initialize =3D ppc_translate_init, + .cpu_exec_interrupt =3D ppc_cpu_exec_interrupt, + .tlb_fill =3D ppc_cpu_tlb_fill, + +#ifndef CONFIG_USER_ONLY + .do_interrupt =3D ppc_cpu_do_interrupt, + .cpu_exec_enter =3D ppc_cpu_exec_enter, + .cpu_exec_exit =3D ppc_cpu_exec_exit, + .do_unaligned_access =3D ppc_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + +static void ppc_cpu_class_init(ObjectClass *oc, void *data) +{ + PowerPCCPUClass *pcc =3D POWERPC_CPU_CLASS(oc); + CPUClass *cc =3D CPU_CLASS(oc); + DeviceClass *dc =3D DEVICE_CLASS(oc); + + device_class_set_parent_realize(dc, ppc_cpu_realize, + &pcc->parent_realize); + device_class_set_parent_unrealize(dc, ppc_cpu_unrealize, + &pcc->parent_unrealize); + pcc->pvr_match =3D ppc_pvr_match_default; + pcc->interrupts_big_endian =3D ppc_cpu_interrupts_big_endian_always; + device_class_set_props(dc, ppc_cpu_properties); + + device_class_set_parent_reset(dc, ppc_cpu_reset, &pcc->parent_reset); + + cc->class_by_name =3D ppc_cpu_class_by_name; + cc->has_work =3D ppc_cpu_has_work; + cc->dump_state =3D ppc_cpu_dump_state; + cc->dump_statistics =3D ppc_cpu_dump_statistics; + cc->set_pc =3D ppc_cpu_set_pc; + cc->gdb_read_register =3D ppc_cpu_gdb_read_register; + cc->gdb_write_register =3D ppc_cpu_gdb_write_register; +#ifndef CONFIG_USER_ONLY + cc->get_phys_page_debug =3D ppc_cpu_get_phys_page_debug; + cc->vmsd =3D &vmstate_ppc_cpu; +#endif +#if defined(CONFIG_SOFTMMU) + cc->write_elf64_note =3D ppc64_cpu_write_elf64_note; + cc->write_elf32_note =3D ppc32_cpu_write_elf32_note; +#endif + + cc->gdb_num_core_regs =3D 71; +#ifndef CONFIG_USER_ONLY + cc->gdb_get_dynamic_xml =3D ppc_gdb_get_dynamic_xml; +#endif +#ifdef USE_APPLE_GDB + cc->gdb_read_register =3D ppc_cpu_gdb_read_register_apple; + cc->gdb_write_register =3D ppc_cpu_gdb_write_register_apple; + cc->gdb_num_core_regs =3D 71 + 32; +#endif + + cc->gdb_arch_name =3D ppc_gdb_arch_name; +#if defined(TARGET_PPC64) + cc->gdb_core_xml_file =3D "power64-core.xml"; +#else + cc->gdb_core_xml_file =3D "power-core.xml"; +#endif +#ifndef CONFIG_USER_ONLY + cc->virtio_is_big_endian =3D ppc_cpu_is_big_endian; +#endif + cc->disas_set_info =3D ppc_disas_set_info; + + dc->fw_name =3D "PowerPC,UNKNOWN"; + +#ifdef CONFIG_TCG + cc->tcg_ops =3D &ppc_tcg_ops; +#endif /* CONFIG_TCG */ +} + +static void ppc_cpu_instance_init(Object *obj) +{ + PowerPCCPU *cpu =3D POWERPC_CPU(obj); + PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); + CPUPPCState *env =3D &cpu->env; + + cpu_set_cpustate_pointers(cpu); + cpu->vcpu_id =3D UNASSIGNED_CPU_INDEX; + + env->msr_mask =3D pcc->msr_mask; + env->mmu_model =3D pcc->mmu_model; + env->excp_model =3D pcc->excp_model; + env->bus_model =3D pcc->bus_model; + env->insns_flags =3D pcc->insns_flags; + env->insns_flags2 =3D pcc->insns_flags2; + env->flags =3D pcc->flags; + env->bfd_mach =3D pcc->bfd_mach; + env->check_pow =3D pcc->check_pow; + + /* + * Mark HV mode as supported if the CPU has an MSR_HV bit in the + * msr_mask. The mask can later be cleared by PAPR mode but the hv + * mode support will remain, thus enforcing that we cannot use + * priv. instructions in guest in PAPR mode. For 970 we currently + * simply don't set HV in msr_mask thus simulating an "Apple mode" + * 970. If we ever want to support 970 HV mode, we'll have to add + * a processor attribute of some sort. + */ +#if !defined(CONFIG_USER_ONLY) + env->has_hv_mode =3D !!(env->msr_mask & MSR_HVB); +#endif + +#ifdef CONFIG_TCG + ppc_hash64_init(cpu); +#endif +} + +static void ppc_cpu_instance_finalize(Object *obj) +{ +#ifdef CONFIG_TCG + PowerPCCPU *cpu =3D POWERPC_CPU(obj); + + ppc_hash64_finalize(cpu); +#endif +} + +static const TypeInfo ppc_cpu_type_info =3D { + .name =3D TYPE_POWERPC_CPU, + .parent =3D TYPE_CPU, + .instance_size =3D sizeof(PowerPCCPU), + .instance_align =3D __alignof__(PowerPCCPU), + .instance_init =3D ppc_cpu_instance_init, + .instance_finalize =3D ppc_cpu_instance_finalize, + .abstract =3D true, + .class_size =3D sizeof(PowerPCCPUClass), + .class_init =3D ppc_cpu_class_init, +}; + +static void ppc_cpu_register_types(void) +{ + type_register_static(&ppc_cpu_type_info); +#ifndef CONFIG_USER_ONLY + type_register_static(&ppc_vhyp_type_info); +#endif +} + +type_init(ppc_cpu_register_types) + +static void ppc_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc =3D data; + PowerPCCPUClass *pcc =3D POWERPC_CPU_CLASS(oc); + DeviceClass *family =3D DEVICE_CLASS(ppc_cpu_get_family_class(pcc)); + const char *typename =3D object_class_get_name(oc); + char *name; + int i; + + if (unlikely(strcmp(typename, TYPE_HOST_POWERPC_CPU) =3D=3D 0)) { + return; + } + + name =3D g_strndup(typename, + strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX)); + qemu_printf("PowerPC %-16s PVR %08x\n", name, pcc->pvr); + for (i =3D 0; ppc_cpu_aliases[i].alias !=3D NULL; i++) { + PowerPCCPUAlias *alias =3D &ppc_cpu_aliases[i]; + ObjectClass *alias_oc =3D ppc_cpu_class_by_name(alias->model); + + if (alias_oc !=3D oc) { + continue; + } + /* + * If running with KVM, we might update the family alias later, so + * avoid printing the wrong alias here and use "preferred" instead + */ + if (strcmp(alias->alias, family->desc) =3D=3D 0) { + qemu_printf("PowerPC %-16s (alias for preferred %s CPU)\n", + alias->alias, family->desc); + } else { + qemu_printf("PowerPC %-16s (alias for %s)\n", + alias->alias, name); + } + } + g_free(name); +} + +void ppc_cpu_list(void) +{ + GSList *list; + + list =3D object_class_get_list(TYPE_POWERPC_CPU, false); + list =3D g_slist_sort(list, ppc_cpu_list_compare); + g_slist_foreach(list, ppc_cpu_list_entry, NULL); + g_slist_free(list); + +#ifdef CONFIG_KVM + qemu_printf("\n"); + qemu_printf("PowerPC %-16s\n", "host"); +#endif +} + +static void ppc_cpu_defs_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc =3D data; + CpuDefinitionInfoList **first =3D user_data; + const char *typename; + CpuDefinitionInfo *info; + + typename =3D object_class_get_name(oc); + info =3D g_malloc0(sizeof(*info)); + info->name =3D g_strndup(typename, + strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFF= IX)); + + QAPI_LIST_PREPEND(*first, info); +} + +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + CpuDefinitionInfoList *cpu_list =3D NULL; + GSList *list; + int i; + + list =3D object_class_get_list(TYPE_POWERPC_CPU, false); + g_slist_foreach(list, ppc_cpu_defs_entry, &cpu_list); + g_slist_free(list); + + for (i =3D 0; ppc_cpu_aliases[i].alias !=3D NULL; i++) { + PowerPCCPUAlias *alias =3D &ppc_cpu_aliases[i]; + ObjectClass *oc; + CpuDefinitionInfo *info; + + oc =3D ppc_cpu_class_by_name(alias->model); + if (oc =3D=3D NULL) { + continue; + } + + info =3D g_malloc0(sizeof(*info)); + info->name =3D g_strdup(alias->alias); + info->q_typename =3D g_strdup(object_class_get_name(oc)); + + QAPI_LIST_PREPEND(cpu_list, info); + } + + return cpu_list; +} +#if !defined(CONFIG_USER_ONLY) +void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) +{ + CPUPPCState *env =3D &cpu->env; + + cpu->vhyp =3D vhyp; + + /* + * With a virtual hypervisor mode we never allow the CPU to go + * hypervisor mode itself + */ + env->msr_mask &=3D ~MSR_HVB; +} + +#endif /* !defined(CONFIG_USER_ONLY) */ diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index e73416da68..031b04ee40 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2612,4 +2612,19 @@ static inline ppc_avr_t *cpu_avr_ptr(CPUPPCState *en= v, int i) void dump_mmu(CPUPPCState *env); =20 void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len); + +/* + * functions used by cpu_ppc_realize, but that dont necessarily make sense + * to be added to cpu.c, because they seem very related to TCG or gdb + */ + +/* gdbstub.c */ +void ppc_cpu_gdb_init(CPUState *cs, PowerPCCPUClass *ppc); + +/* translate_init.c.inc */ +void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp); +void destroy_ppc_opcodes(PowerPCCPU *cpu); +void gen_spr_generic(CPUPPCState *env); +void init_ppc_proc(PowerPCCPU *cpu); + #endif /* PPC_CPU_H */ diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c index c28319fb97..e6a6c0a6a0 100644 --- a/target/ppc/gdbstub.c +++ b/target/ppc/gdbstub.c @@ -20,6 +20,10 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/gdbstub.h" +#ifdef CONFIG_TCG +#include "exec/helper-proto.h" +#endif +#include "kvm_ppc.h" =20 static int ppc_gdb_register_len_apple(int n) { @@ -387,3 +391,252 @@ const char *ppc_gdb_get_dynamic_xml(CPUState *cs, con= st char *xml_name) return NULL; } #endif + +static bool avr_need_swap(CPUPPCState *env) +{ +#ifdef HOST_WORDS_BIGENDIAN + return msr_le; +#else + return !msr_le; +#endif +} + +#if !defined(CONFIG_USER_ONLY) +static int gdb_find_spr_idx(CPUPPCState *env, int n) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(env->spr_cb); i++) { + ppc_spr_t *spr =3D &env->spr_cb[i]; + + if (spr->name && spr->gdb_id =3D=3D n) { + return i; + } + } + return -1; +} + +static int gdb_get_spr_reg(CPUPPCState *env, GByteArray *buf, int n) +{ + int reg; + int len; + + reg =3D gdb_find_spr_idx(env, n); + if (reg < 0) { + return 0; + } + + len =3D TARGET_LONG_SIZE; + gdb_get_regl(buf, env->spr[reg]); + ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, len), len); + return len; +} + +static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n) +{ + int reg; + int len; + + reg =3D gdb_find_spr_idx(env, n); + if (reg < 0) { + return 0; + } + + len =3D TARGET_LONG_SIZE; + ppc_maybe_bswap_register(env, mem_buf, len); + env->spr[reg] =3D ldn_p(mem_buf, len); + + return len; +} +#endif + +static int gdb_get_float_reg(CPUPPCState *env, GByteArray *buf, int n) +{ + uint8_t *mem_buf; + if (n < 32) { + gdb_get_reg64(buf, *cpu_fpr_ptr(env, n)); + mem_buf =3D gdb_get_reg_ptr(buf, 8); + ppc_maybe_bswap_register(env, mem_buf, 8); + return 8; + } + if (n =3D=3D 32) { + gdb_get_reg32(buf, env->fpscr); + mem_buf =3D gdb_get_reg_ptr(buf, 4); + ppc_maybe_bswap_register(env, mem_buf, 4); + return 4; + } + return 0; +} + +static int gdb_set_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n) +{ + if (n < 32) { + ppc_maybe_bswap_register(env, mem_buf, 8); + *cpu_fpr_ptr(env, n) =3D ldq_p(mem_buf); + return 8; + } + if (n =3D=3D 32) { + ppc_maybe_bswap_register(env, mem_buf, 4); + store_fpscr(env, ldl_p(mem_buf), 0xffffffff); + return 4; + } + return 0; +} + +static int gdb_get_avr_reg(CPUPPCState *env, GByteArray *buf, int n) +{ + uint8_t *mem_buf; + + if (n < 32) { + ppc_avr_t *avr =3D cpu_avr_ptr(env, n); + if (!avr_need_swap(env)) { + gdb_get_reg128(buf, avr->u64[0] , avr->u64[1]); + } else { + gdb_get_reg128(buf, avr->u64[1] , avr->u64[0]); + } + mem_buf =3D gdb_get_reg_ptr(buf, 16); + ppc_maybe_bswap_register(env, mem_buf, 8); + ppc_maybe_bswap_register(env, mem_buf + 8, 8); + return 16; + } + if (n =3D=3D 32) { + gdb_get_reg32(buf, helper_mfvscr(env)); + mem_buf =3D gdb_get_reg_ptr(buf, 4); + ppc_maybe_bswap_register(env, mem_buf, 4); + return 4; + } + if (n =3D=3D 33) { + gdb_get_reg32(buf, (uint32_t)env->spr[SPR_VRSAVE]); + mem_buf =3D gdb_get_reg_ptr(buf, 4); + ppc_maybe_bswap_register(env, mem_buf, 4); + return 4; + } + return 0; +} + +static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n) +{ + if (n < 32) { + ppc_avr_t *avr =3D cpu_avr_ptr(env, n); + ppc_maybe_bswap_register(env, mem_buf, 8); + ppc_maybe_bswap_register(env, mem_buf + 8, 8); + if (!avr_need_swap(env)) { + avr->u64[0] =3D ldq_p(mem_buf); + avr->u64[1] =3D ldq_p(mem_buf + 8); + } else { + avr->u64[1] =3D ldq_p(mem_buf); + avr->u64[0] =3D ldq_p(mem_buf + 8); + } + return 16; + } + if (n =3D=3D 32) { + ppc_maybe_bswap_register(env, mem_buf, 4); + helper_mtvscr(env, ldl_p(mem_buf)); + return 4; + } + if (n =3D=3D 33) { + ppc_maybe_bswap_register(env, mem_buf, 4); + env->spr[SPR_VRSAVE] =3D (target_ulong)ldl_p(mem_buf); + return 4; + } + return 0; +} + +static int gdb_get_spe_reg(CPUPPCState *env, GByteArray *buf, int n) +{ + if (n < 32) { +#if defined(TARGET_PPC64) + gdb_get_reg32(buf, env->gpr[n] >> 32); + ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4); +#else + gdb_get_reg32(buf, env->gprh[n]); +#endif + return 4; + } + if (n =3D=3D 32) { + gdb_get_reg64(buf, env->spe_acc); + ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8); + return 8; + } + if (n =3D=3D 33) { + gdb_get_reg32(buf, env->spe_fscr); + ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4); + return 4; + } + return 0; +} + +static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n) +{ + if (n < 32) { +#if defined(TARGET_PPC64) + target_ulong lo =3D (uint32_t)env->gpr[n]; + target_ulong hi; + + ppc_maybe_bswap_register(env, mem_buf, 4); + + hi =3D (target_ulong)ldl_p(mem_buf) << 32; + env->gpr[n] =3D lo | hi; +#else + env->gprh[n] =3D ldl_p(mem_buf); +#endif + return 4; + } + if (n =3D=3D 32) { + ppc_maybe_bswap_register(env, mem_buf, 8); + env->spe_acc =3D ldq_p(mem_buf); + return 8; + } + if (n =3D=3D 33) { + ppc_maybe_bswap_register(env, mem_buf, 4); + env->spe_fscr =3D ldl_p(mem_buf); + return 4; + } + return 0; +} + +static int gdb_get_vsx_reg(CPUPPCState *env, GByteArray *buf, int n) +{ + if (n < 32) { + gdb_get_reg64(buf, *cpu_vsrl_ptr(env, n)); + ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8); + return 8; + } + return 0; +} + +static int gdb_set_vsx_reg(CPUPPCState *env, uint8_t *mem_buf, int n) +{ + if (n < 32) { + ppc_maybe_bswap_register(env, mem_buf, 8); + *cpu_vsrl_ptr(env, n) =3D ldq_p(mem_buf); + return 8; + } + return 0; +} + + +void ppc_cpu_gdb_init(CPUState *cs, PowerPCCPUClass *pcc) +{ + + if (pcc->insns_flags & PPC_FLOAT) { + gdb_register_coprocessor(cs, gdb_get_float_reg, gdb_set_float_reg, + 33, "power-fpu.xml", 0); + } + if (pcc->insns_flags & PPC_ALTIVEC) { + gdb_register_coprocessor(cs, gdb_get_avr_reg, gdb_set_avr_reg, + 34, "power-altivec.xml", 0); + } + if (pcc->insns_flags & PPC_SPE) { + gdb_register_coprocessor(cs, gdb_get_spe_reg, gdb_set_spe_reg, + 34, "power-spe.xml", 0); + } + if (pcc->insns_flags2 & PPC2_VSX) { + gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg, + 32, "power-vsx.xml", 0); + } +#ifndef CONFIG_USER_ONLY + gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg, + pcc->gdb_num_sprs, "power-spr.xml", 0); +#endif +} diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.= inc index c03a7c4f52..e1228a4b92 100644 --- a/target/ppc/translate_init.c.inc +++ b/target/ppc/translate_init.c.inc @@ -820,7 +820,7 @@ static inline void _spr_register(CPUPPCState *env, int = num, } =20 /* Generic PowerPC SPRs */ -static void gen_spr_generic(CPUPPCState *env) +void gen_spr_generic(CPUPPCState *env) { /* Integer processing */ spr_register(env, SPR_XER, "XER", @@ -3498,11 +3498,6 @@ static int check_pow_hid0_74xx(CPUPPCState *env) return 0; } =20 -static bool ppc_cpu_interrupts_big_endian_always(PowerPCCPU *cpu) -{ - return true; -} - #ifdef TARGET_PPC64 static bool ppc_cpu_interrupts_big_endian_lpcr(PowerPCCPU *cpu) { @@ -9329,27 +9324,12 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) pcc->interrupts_big_endian =3D ppc_cpu_interrupts_big_endian_lpcr; } =20 -#if !defined(CONFIG_USER_ONLY) -void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) -{ - CPUPPCState *env =3D &cpu->env; - - cpu->vhyp =3D vhyp; - - /* - * With a virtual hypervisor mode we never allow the CPU to go - * hypervisor mode itself - */ - env->msr_mask &=3D ~MSR_HVB; -} - -#endif /* !defined(CONFIG_USER_ONLY) */ =20 #endif /* defined(TARGET_PPC64) */ =20 /*************************************************************************= ****/ /* Generic CPU instantiation routine = */ -static void init_ppc_proc(PowerPCCPU *cpu) +void init_ppc_proc(PowerPCCPU *cpu) { PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); CPUPPCState *env =3D &cpu->env; @@ -9783,7 +9763,7 @@ static void fix_opcode_tables(opc_handler_t **ppc_opc= odes) } =20 /*************************************************************************= ****/ -static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp) +void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp) { PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); opcode_t *opc; @@ -9805,6 +9785,39 @@ static void create_ppc_opcodes(PowerPCCPU *cpu, Erro= r **errp) fflush(stderr); } =20 +void destroy_ppc_opcodes(PowerPCCPU *cpu) { + opc_handler_t **table, **table_2; + int i, j, k; + + for (i =3D 0; i < PPC_CPU_OPCODES_LEN; i++) { + if (cpu->opcodes[i] =3D=3D &invalid_handler) { + continue; + } + if (is_indirect_opcode(cpu->opcodes[i])) { + table =3D ind_table(cpu->opcodes[i]); + for (j =3D 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) { + if (table[j] =3D=3D &invalid_handler) { + continue; + } + if (is_indirect_opcode(table[j])) { + table_2 =3D ind_table(table[j]); + for (k =3D 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) { + if (table_2[k] !=3D &invalid_handler && + is_indirect_opcode(table_2[k])) { + g_free((opc_handler_t *)((uintptr_t)table_2[k]= & + ~PPC_INDIRECT)); + } + } + g_free((opc_handler_t *)((uintptr_t)table[j] & + ~PPC_INDIRECT)); + } + } + g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] & + ~PPC_INDIRECT)); + } + } +} + #if defined(PPC_DUMP_CPU) static void dump_ppc_insns(CPUPPCState *env) { @@ -9895,1092 +9908,3 @@ static void dump_ppc_insns(CPUPPCState *env) } } #endif - -static bool avr_need_swap(CPUPPCState *env) -{ -#ifdef HOST_WORDS_BIGENDIAN - return msr_le; -#else - return !msr_le; -#endif -} - -#if !defined(CONFIG_USER_ONLY) -static int gdb_find_spr_idx(CPUPPCState *env, int n) -{ - int i; - - for (i =3D 0; i < ARRAY_SIZE(env->spr_cb); i++) { - ppc_spr_t *spr =3D &env->spr_cb[i]; - - if (spr->name && spr->gdb_id =3D=3D n) { - return i; - } - } - return -1; -} - -static int gdb_get_spr_reg(CPUPPCState *env, GByteArray *buf, int n) -{ - int reg; - int len; - - reg =3D gdb_find_spr_idx(env, n); - if (reg < 0) { - return 0; - } - - len =3D TARGET_LONG_SIZE; - gdb_get_regl(buf, env->spr[reg]); - ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, len), len); - return len; -} - -static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n) -{ - int reg; - int len; - - reg =3D gdb_find_spr_idx(env, n); - if (reg < 0) { - return 0; - } - - len =3D TARGET_LONG_SIZE; - ppc_maybe_bswap_register(env, mem_buf, len); - env->spr[reg] =3D ldn_p(mem_buf, len); - - return len; -} -#endif - -static int gdb_get_float_reg(CPUPPCState *env, GByteArray *buf, int n) -{ - uint8_t *mem_buf; - if (n < 32) { - gdb_get_reg64(buf, *cpu_fpr_ptr(env, n)); - mem_buf =3D gdb_get_reg_ptr(buf, 8); - ppc_maybe_bswap_register(env, mem_buf, 8); - return 8; - } - if (n =3D=3D 32) { - gdb_get_reg32(buf, env->fpscr); - mem_buf =3D gdb_get_reg_ptr(buf, 4); - ppc_maybe_bswap_register(env, mem_buf, 4); - return 4; - } - return 0; -} - -static int gdb_set_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n) -{ - if (n < 32) { - ppc_maybe_bswap_register(env, mem_buf, 8); - *cpu_fpr_ptr(env, n) =3D ldq_p(mem_buf); - return 8; - } - if (n =3D=3D 32) { - ppc_maybe_bswap_register(env, mem_buf, 4); - helper_store_fpscr(env, ldl_p(mem_buf), 0xffffffff); - return 4; - } - return 0; -} - -static int gdb_get_avr_reg(CPUPPCState *env, GByteArray *buf, int n) -{ - uint8_t *mem_buf; - - if (n < 32) { - ppc_avr_t *avr =3D cpu_avr_ptr(env, n); - if (!avr_need_swap(env)) { - gdb_get_reg128(buf, avr->u64[0] , avr->u64[1]); - } else { - gdb_get_reg128(buf, avr->u64[1] , avr->u64[0]); - } - mem_buf =3D gdb_get_reg_ptr(buf, 16); - ppc_maybe_bswap_register(env, mem_buf, 8); - ppc_maybe_bswap_register(env, mem_buf + 8, 8); - return 16; - } - if (n =3D=3D 32) { - gdb_get_reg32(buf, helper_mfvscr(env)); - mem_buf =3D gdb_get_reg_ptr(buf, 4); - ppc_maybe_bswap_register(env, mem_buf, 4); - return 4; - } - if (n =3D=3D 33) { - gdb_get_reg32(buf, (uint32_t)env->spr[SPR_VRSAVE]); - mem_buf =3D gdb_get_reg_ptr(buf, 4); - ppc_maybe_bswap_register(env, mem_buf, 4); - return 4; - } - return 0; -} - -static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n) -{ - if (n < 32) { - ppc_avr_t *avr =3D cpu_avr_ptr(env, n); - ppc_maybe_bswap_register(env, mem_buf, 8); - ppc_maybe_bswap_register(env, mem_buf + 8, 8); - if (!avr_need_swap(env)) { - avr->u64[0] =3D ldq_p(mem_buf); - avr->u64[1] =3D ldq_p(mem_buf + 8); - } else { - avr->u64[1] =3D ldq_p(mem_buf); - avr->u64[0] =3D ldq_p(mem_buf + 8); - } - return 16; - } - if (n =3D=3D 32) { - ppc_maybe_bswap_register(env, mem_buf, 4); - helper_mtvscr(env, ldl_p(mem_buf)); - return 4; - } - if (n =3D=3D 33) { - ppc_maybe_bswap_register(env, mem_buf, 4); - env->spr[SPR_VRSAVE] =3D (target_ulong)ldl_p(mem_buf); - return 4; - } - return 0; -} - -static int gdb_get_spe_reg(CPUPPCState *env, GByteArray *buf, int n) -{ - if (n < 32) { -#if defined(TARGET_PPC64) - gdb_get_reg32(buf, env->gpr[n] >> 32); - ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4); -#else - gdb_get_reg32(buf, env->gprh[n]); -#endif - return 4; - } - if (n =3D=3D 32) { - gdb_get_reg64(buf, env->spe_acc); - ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8); - return 8; - } - if (n =3D=3D 33) { - gdb_get_reg32(buf, env->spe_fscr); - ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4); - return 4; - } - return 0; -} - -static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n) -{ - if (n < 32) { -#if defined(TARGET_PPC64) - target_ulong lo =3D (uint32_t)env->gpr[n]; - target_ulong hi; - - ppc_maybe_bswap_register(env, mem_buf, 4); - - hi =3D (target_ulong)ldl_p(mem_buf) << 32; - env->gpr[n] =3D lo | hi; -#else - env->gprh[n] =3D ldl_p(mem_buf); -#endif - return 4; - } - if (n =3D=3D 32) { - ppc_maybe_bswap_register(env, mem_buf, 8); - env->spe_acc =3D ldq_p(mem_buf); - return 8; - } - if (n =3D=3D 33) { - ppc_maybe_bswap_register(env, mem_buf, 4); - env->spe_fscr =3D ldl_p(mem_buf); - return 4; - } - return 0; -} - -static int gdb_get_vsx_reg(CPUPPCState *env, GByteArray *buf, int n) -{ - if (n < 32) { - gdb_get_reg64(buf, *cpu_vsrl_ptr(env, n)); - ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8); - return 8; - } - return 0; -} - -static int gdb_set_vsx_reg(CPUPPCState *env, uint8_t *mem_buf, int n) -{ - if (n < 32) { - ppc_maybe_bswap_register(env, mem_buf, 8); - *cpu_vsrl_ptr(env, n) =3D ldq_p(mem_buf); - return 8; - } - return 0; -} - -static int ppc_fixup_cpu(PowerPCCPU *cpu) -{ - CPUPPCState *env =3D &cpu->env; - - /* - * TCG doesn't (yet) emulate some groups of instructions that are - * implemented on some otherwise supported CPUs (e.g. VSX and - * decimal floating point instructions on POWER7). We remove - * unsupported instruction groups from the cpu state's instruction - * masks and hope the guest can cope. For at least the pseries - * machine, the unavailability of these instructions can be - * advertised to the guest via the device tree. - */ - if ((env->insns_flags & ~PPC_TCG_INSNS) - || (env->insns_flags2 & ~PPC_TCG_INSNS2)) { - warn_report("Disabling some instructions which are not " - "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")", - env->insns_flags & ~PPC_TCG_INSNS, - env->insns_flags2 & ~PPC_TCG_INSNS2); - } - env->insns_flags &=3D PPC_TCG_INSNS; - env->insns_flags2 &=3D PPC_TCG_INSNS2; - return 0; -} - -static void ppc_cpu_realize(DeviceState *dev, Error **errp) -{ - CPUState *cs =3D CPU(dev); - PowerPCCPU *cpu =3D POWERPC_CPU(dev); - PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - Error *local_err =3D NULL; - - cpu_exec_realizefn(cs, &local_err); - if (local_err !=3D NULL) { - error_propagate(errp, local_err); - return; - } - if (cpu->vcpu_id =3D=3D UNASSIGNED_CPU_INDEX) { - cpu->vcpu_id =3D cs->cpu_index; - } - - if (tcg_enabled()) { - if (ppc_fixup_cpu(cpu) !=3D 0) { - error_setg(errp, "Unable to emulate selected CPU with TCG"); - goto unrealize; - } - } - - create_ppc_opcodes(cpu, &local_err); - if (local_err !=3D NULL) { - error_propagate(errp, local_err); - goto unrealize; - } - init_ppc_proc(cpu); - - if (pcc->insns_flags & PPC_FLOAT) { - gdb_register_coprocessor(cs, gdb_get_float_reg, gdb_set_float_reg, - 33, "power-fpu.xml", 0); - } - if (pcc->insns_flags & PPC_ALTIVEC) { - gdb_register_coprocessor(cs, gdb_get_avr_reg, gdb_set_avr_reg, - 34, "power-altivec.xml", 0); - } - if (pcc->insns_flags & PPC_SPE) { - gdb_register_coprocessor(cs, gdb_get_spe_reg, gdb_set_spe_reg, - 34, "power-spe.xml", 0); - } - if (pcc->insns_flags2 & PPC2_VSX) { - gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg, - 32, "power-vsx.xml", 0); - } -#ifndef CONFIG_USER_ONLY - gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg, - pcc->gdb_num_sprs, "power-spr.xml", 0); -#endif - qemu_init_vcpu(cs); - - pcc->parent_realize(dev, errp); - -#if defined(PPC_DUMP_CPU) - { - CPUPPCState *env =3D &cpu->env; - const char *mmu_model, *excp_model, *bus_model; - switch (env->mmu_model) { - case POWERPC_MMU_32B: - mmu_model =3D "PowerPC 32"; - break; - case POWERPC_MMU_SOFT_6xx: - mmu_model =3D "PowerPC 6xx/7xx with software driven TLBs"; - break; - case POWERPC_MMU_SOFT_74xx: - mmu_model =3D "PowerPC 74xx with software driven TLBs"; - break; - case POWERPC_MMU_SOFT_4xx: - mmu_model =3D "PowerPC 4xx with software driven TLBs"; - break; - case POWERPC_MMU_SOFT_4xx_Z: - mmu_model =3D "PowerPC 4xx with software driven TLBs " - "and zones protections"; - break; - case POWERPC_MMU_REAL: - mmu_model =3D "PowerPC real mode only"; - break; - case POWERPC_MMU_MPC8xx: - mmu_model =3D "PowerPC MPC8xx"; - break; - case POWERPC_MMU_BOOKE: - mmu_model =3D "PowerPC BookE"; - break; - case POWERPC_MMU_BOOKE206: - mmu_model =3D "PowerPC BookE 2.06"; - break; - case POWERPC_MMU_601: - mmu_model =3D "PowerPC 601"; - break; -#if defined(TARGET_PPC64) - case POWERPC_MMU_64B: - mmu_model =3D "PowerPC 64"; - break; -#endif - default: - mmu_model =3D "Unknown or invalid"; - break; - } - switch (env->excp_model) { - case POWERPC_EXCP_STD: - excp_model =3D "PowerPC"; - break; - case POWERPC_EXCP_40x: - excp_model =3D "PowerPC 40x"; - break; - case POWERPC_EXCP_601: - excp_model =3D "PowerPC 601"; - break; - case POWERPC_EXCP_602: - excp_model =3D "PowerPC 602"; - break; - case POWERPC_EXCP_603: - excp_model =3D "PowerPC 603"; - break; - case POWERPC_EXCP_603E: - excp_model =3D "PowerPC 603e"; - break; - case POWERPC_EXCP_604: - excp_model =3D "PowerPC 604"; - break; - case POWERPC_EXCP_7x0: - excp_model =3D "PowerPC 740/750"; - break; - case POWERPC_EXCP_7x5: - excp_model =3D "PowerPC 745/755"; - break; - case POWERPC_EXCP_74xx: - excp_model =3D "PowerPC 74xx"; - break; - case POWERPC_EXCP_BOOKE: - excp_model =3D "PowerPC BookE"; - break; -#if defined(TARGET_PPC64) - case POWERPC_EXCP_970: - excp_model =3D "PowerPC 970"; - break; -#endif - default: - excp_model =3D "Unknown or invalid"; - break; - } - switch (env->bus_model) { - case PPC_FLAGS_INPUT_6xx: - bus_model =3D "PowerPC 6xx"; - break; - case PPC_FLAGS_INPUT_BookE: - bus_model =3D "PowerPC BookE"; - break; - case PPC_FLAGS_INPUT_405: - bus_model =3D "PowerPC 405"; - break; - case PPC_FLAGS_INPUT_401: - bus_model =3D "PowerPC 401/403"; - break; - case PPC_FLAGS_INPUT_RCPU: - bus_model =3D "RCPU / MPC8xx"; - break; -#if defined(TARGET_PPC64) - case PPC_FLAGS_INPUT_970: - bus_model =3D "PowerPC 970"; - break; -#endif - default: - bus_model =3D "Unknown or invalid"; - break; - } - printf("PowerPC %-12s : PVR %08x MSR %016" PRIx64 "\n" - " MMU model : %s\n", - object_class_get_name(OBJECT_CLASS(pcc)), - pcc->pvr, pcc->msr_mask, mmu_model); -#if !defined(CONFIG_USER_ONLY) - if (env->tlb.tlb6) { - printf(" %d %s TLB in %d ways\n", - env->nb_tlb, env->id_tlbs ? "splitted" : "merged", - env->nb_ways); - } -#endif - printf(" Exceptions model : %s\n" - " Bus model : %s\n", - excp_model, bus_model); - printf(" MSR features :\n"); - if (env->flags & POWERPC_FLAG_SPE) { - printf(" signal processing engine enabl= e" - "\n"); - } else if (env->flags & POWERPC_FLAG_VRE) { - printf(" vector processor enable\n"); - } - if (env->flags & POWERPC_FLAG_TGPR) { - printf(" temporary GPRs\n"); - } else if (env->flags & POWERPC_FLAG_CE) { - printf(" critical input enable\n"); - } - if (env->flags & POWERPC_FLAG_SE) { - printf(" single-step trace mode\n"); - } else if (env->flags & POWERPC_FLAG_DWE) { - printf(" debug wait enable\n"); - } else if (env->flags & POWERPC_FLAG_UBLE) { - printf(" user BTB lock enable\n"); - } - if (env->flags & POWERPC_FLAG_BE) { - printf(" branch-step trace mode\n"); - } else if (env->flags & POWERPC_FLAG_DE) { - printf(" debug interrupt enable\n"); - } - if (env->flags & POWERPC_FLAG_PX) { - printf(" inclusive protection\n"); - } else if (env->flags & POWERPC_FLAG_PMM) { - printf(" performance monitor mark\n"); - } - if (env->flags =3D=3D POWERPC_FLAG_NONE) { - printf(" none\n"); - } - printf(" Time-base/decrementer clock source: %s\n", - env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus cloc= k"); - dump_ppc_insns(env); - dump_ppc_sprs(env); - fflush(stdout); - } -#endif - return; - -unrealize: - cpu_exec_unrealizefn(cs); -} - -static void ppc_cpu_unrealize(DeviceState *dev) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(dev); - PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - opc_handler_t **table, **table_2; - int i, j, k; - - pcc->parent_unrealize(dev); - - cpu_remove_sync(CPU(cpu)); - - for (i =3D 0; i < PPC_CPU_OPCODES_LEN; i++) { - if (cpu->opcodes[i] =3D=3D &invalid_handler) { - continue; - } - if (is_indirect_opcode(cpu->opcodes[i])) { - table =3D ind_table(cpu->opcodes[i]); - for (j =3D 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) { - if (table[j] =3D=3D &invalid_handler) { - continue; - } - if (is_indirect_opcode(table[j])) { - table_2 =3D ind_table(table[j]); - for (k =3D 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) { - if (table_2[k] !=3D &invalid_handler && - is_indirect_opcode(table_2[k])) { - g_free((opc_handler_t *)((uintptr_t)table_2[k]= & - ~PPC_INDIRECT)); - } - } - g_free((opc_handler_t *)((uintptr_t)table[j] & - ~PPC_INDIRECT)); - } - } - g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] & - ~PPC_INDIRECT)); - } - } -} - -static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b) -{ - ObjectClass *oc =3D (ObjectClass *)a; - uint32_t pvr =3D *(uint32_t *)b; - PowerPCCPUClass *pcc =3D (PowerPCCPUClass *)a; - - /* -cpu host does a PVR lookup during construction */ - if (unlikely(strcmp(object_class_get_name(oc), - TYPE_HOST_POWERPC_CPU) =3D=3D 0)) { - return -1; - } - - return pcc->pvr =3D=3D pvr ? 0 : -1; -} - -PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr) -{ - GSList *list, *item; - PowerPCCPUClass *pcc =3D NULL; - - list =3D object_class_get_list(TYPE_POWERPC_CPU, false); - item =3D g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr); - if (item !=3D NULL) { - pcc =3D POWERPC_CPU_CLASS(item->data); - } - g_slist_free(list); - - return pcc; -} - -static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer = b) -{ - ObjectClass *oc =3D (ObjectClass *)a; - uint32_t pvr =3D *(uint32_t *)b; - PowerPCCPUClass *pcc =3D (PowerPCCPUClass *)a; - - /* -cpu host does a PVR lookup during construction */ - if (unlikely(strcmp(object_class_get_name(oc), - TYPE_HOST_POWERPC_CPU) =3D=3D 0)) { - return -1; - } - - if (pcc->pvr_match(pcc, pvr)) { - return 0; - } - - return -1; -} - -PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr) -{ - GSList *list, *item; - PowerPCCPUClass *pcc =3D NULL; - - list =3D object_class_get_list(TYPE_POWERPC_CPU, true); - item =3D g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr_mas= k); - if (item !=3D NULL) { - pcc =3D POWERPC_CPU_CLASS(item->data); - } - g_slist_free(list); - - return pcc; -} - -static const char *ppc_cpu_lookup_alias(const char *alias) -{ - int ai; - - for (ai =3D 0; ppc_cpu_aliases[ai].alias !=3D NULL; ai++) { - if (strcmp(ppc_cpu_aliases[ai].alias, alias) =3D=3D 0) { - return ppc_cpu_aliases[ai].model; - } - } - - return NULL; -} - -static ObjectClass *ppc_cpu_class_by_name(const char *name) -{ - char *cpu_model, *typename; - ObjectClass *oc; - const char *p; - unsigned long pvr; - - /* - * Lookup by PVR if cpu_model is valid 8 digit hex number (excl: - * 0x prefix if present) - */ - if (!qemu_strtoul(name, &p, 16, &pvr)) { - int len =3D p - name; - len =3D (len =3D=3D 10) && (name[1] =3D=3D 'x') ? len - 2 : len; - if ((len =3D=3D 8) && (*p =3D=3D '\0')) { - return OBJECT_CLASS(ppc_cpu_class_by_pvr(pvr)); - } - } - - cpu_model =3D g_ascii_strdown(name, -1); - p =3D ppc_cpu_lookup_alias(cpu_model); - if (p) { - g_free(cpu_model); - cpu_model =3D g_strdup(p); - } - - typename =3D g_strdup_printf("%s" POWERPC_CPU_TYPE_SUFFIX, cpu_model); - oc =3D object_class_by_name(typename); - g_free(typename); - g_free(cpu_model); - - return oc; -} - -PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) -{ - ObjectClass *oc =3D OBJECT_CLASS(pcc); - - while (oc && !object_class_is_abstract(oc)) { - oc =3D object_class_get_parent(oc); - } - assert(oc); - - return POWERPC_CPU_CLASS(oc); -} - -/* Sort by PVR, ordering special case "host" last. */ -static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b) -{ - ObjectClass *oc_a =3D (ObjectClass *)a; - ObjectClass *oc_b =3D (ObjectClass *)b; - PowerPCCPUClass *pcc_a =3D POWERPC_CPU_CLASS(oc_a); - PowerPCCPUClass *pcc_b =3D POWERPC_CPU_CLASS(oc_b); - const char *name_a =3D object_class_get_name(oc_a); - const char *name_b =3D object_class_get_name(oc_b); - - if (strcmp(name_a, TYPE_HOST_POWERPC_CPU) =3D=3D 0) { - return 1; - } else if (strcmp(name_b, TYPE_HOST_POWERPC_CPU) =3D=3D 0) { - return -1; - } else { - /* Avoid an integer overflow during subtraction */ - if (pcc_a->pvr < pcc_b->pvr) { - return -1; - } else if (pcc_a->pvr > pcc_b->pvr) { - return 1; - } else { - return 0; - } - } -} - -static void ppc_cpu_list_entry(gpointer data, gpointer user_data) -{ - ObjectClass *oc =3D data; - PowerPCCPUClass *pcc =3D POWERPC_CPU_CLASS(oc); - DeviceClass *family =3D DEVICE_CLASS(ppc_cpu_get_family_class(pcc)); - const char *typename =3D object_class_get_name(oc); - char *name; - int i; - - if (unlikely(strcmp(typename, TYPE_HOST_POWERPC_CPU) =3D=3D 0)) { - return; - } - - name =3D g_strndup(typename, - strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX)); - qemu_printf("PowerPC %-16s PVR %08x\n", name, pcc->pvr); - for (i =3D 0; ppc_cpu_aliases[i].alias !=3D NULL; i++) { - PowerPCCPUAlias *alias =3D &ppc_cpu_aliases[i]; - ObjectClass *alias_oc =3D ppc_cpu_class_by_name(alias->model); - - if (alias_oc !=3D oc) { - continue; - } - /* - * If running with KVM, we might update the family alias later, so - * avoid printing the wrong alias here and use "preferred" instead - */ - if (strcmp(alias->alias, family->desc) =3D=3D 0) { - qemu_printf("PowerPC %-16s (alias for preferred %s CPU)\n", - alias->alias, family->desc); - } else { - qemu_printf("PowerPC %-16s (alias for %s)\n", - alias->alias, name); - } - } - g_free(name); -} - -void ppc_cpu_list(void) -{ - GSList *list; - - list =3D object_class_get_list(TYPE_POWERPC_CPU, false); - list =3D g_slist_sort(list, ppc_cpu_list_compare); - g_slist_foreach(list, ppc_cpu_list_entry, NULL); - g_slist_free(list); - -#ifdef CONFIG_KVM - qemu_printf("\n"); - qemu_printf("PowerPC %-16s\n", "host"); -#endif -} - -static void ppc_cpu_defs_entry(gpointer data, gpointer user_data) -{ - ObjectClass *oc =3D data; - CpuDefinitionInfoList **first =3D user_data; - const char *typename; - CpuDefinitionInfo *info; - - typename =3D object_class_get_name(oc); - info =3D g_malloc0(sizeof(*info)); - info->name =3D g_strndup(typename, - strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFF= IX)); - - QAPI_LIST_PREPEND(*first, info); -} - -CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) -{ - CpuDefinitionInfoList *cpu_list =3D NULL; - GSList *list; - int i; - - list =3D object_class_get_list(TYPE_POWERPC_CPU, false); - g_slist_foreach(list, ppc_cpu_defs_entry, &cpu_list); - g_slist_free(list); - - for (i =3D 0; ppc_cpu_aliases[i].alias !=3D NULL; i++) { - PowerPCCPUAlias *alias =3D &ppc_cpu_aliases[i]; - ObjectClass *oc; - CpuDefinitionInfo *info; - - oc =3D ppc_cpu_class_by_name(alias->model); - if (oc =3D=3D NULL) { - continue; - } - - info =3D g_malloc0(sizeof(*info)); - info->name =3D g_strdup(alias->alias); - info->q_typename =3D g_strdup(object_class_get_name(oc)); - - QAPI_LIST_PREPEND(cpu_list, info); - } - - return cpu_list; -} - -static void ppc_cpu_set_pc(CPUState *cs, vaddr value) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - - cpu->env.nip =3D value; -} - -static bool ppc_cpu_has_work(CPUState *cs) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - CPUPPCState *env =3D &cpu->env; - - return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD); -} - -static void ppc_cpu_reset(DeviceState *dev) -{ - CPUState *s =3D CPU(dev); - PowerPCCPU *cpu =3D POWERPC_CPU(s); - PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - CPUPPCState *env =3D &cpu->env; - target_ulong msr; - int i; - - pcc->parent_reset(dev); - - msr =3D (target_ulong)0; - msr |=3D (target_ulong)MSR_HVB; - msr |=3D (target_ulong)0 << MSR_AP; /* TO BE CHECKED */ - msr |=3D (target_ulong)0 << MSR_SA; /* TO BE CHECKED */ - msr |=3D (target_ulong)1 << MSR_EP; -#if defined(DO_SINGLE_STEP) && 0 - /* Single step trace mode */ - msr |=3D (target_ulong)1 << MSR_SE; - msr |=3D (target_ulong)1 << MSR_BE; -#endif -#if defined(CONFIG_USER_ONLY) - msr |=3D (target_ulong)1 << MSR_FP; /* Allow floating point usage */ - msr |=3D (target_ulong)1 << MSR_FE0; /* Allow floating point exception= s */ - msr |=3D (target_ulong)1 << MSR_FE1; - msr |=3D (target_ulong)1 << MSR_VR; /* Allow altivec usage */ - msr |=3D (target_ulong)1 << MSR_VSX; /* Allow VSX usage */ - msr |=3D (target_ulong)1 << MSR_SPE; /* Allow SPE usage */ - msr |=3D (target_ulong)1 << MSR_PR; -#if defined(TARGET_PPC64) - msr |=3D (target_ulong)1 << MSR_TM; /* Transactional memory */ -#endif -#if !defined(TARGET_WORDS_BIGENDIAN) - msr |=3D (target_ulong)1 << MSR_LE; /* Little-endian user mode */ - if (!((env->msr_mask >> MSR_LE) & 1)) { - fprintf(stderr, "Selected CPU does not support little-endian.\n"); - exit(1); - } -#endif -#endif - -#if defined(TARGET_PPC64) - if (mmu_is_64bit(env->mmu_model)) { - msr |=3D (1ULL << MSR_SF); - } -#endif - - hreg_store_msr(env, msr, 1); - -#if !defined(CONFIG_USER_ONLY) - env->nip =3D env->hreset_vector | env->excp_prefix; - if (env->mmu_model !=3D POWERPC_MMU_REAL) { - ppc_tlb_invalidate_all(env); - } -#endif - - hreg_compute_hflags(env); - env->reserve_addr =3D (target_ulong)-1ULL; - /* Be sure no exception or interrupt is pending */ - env->pending_interrupts =3D 0; - s->exception_index =3D POWERPC_EXCP_NONE; - env->error_code =3D 0; - ppc_irq_reset(cpu); - - /* tininess for underflow is detected before rounding */ - set_float_detect_tininess(float_tininess_before_rounding, - &env->fp_status); - - for (i =3D 0; i < ARRAY_SIZE(env->spr_cb); i++) { - ppc_spr_t *spr =3D &env->spr_cb[i]; - - if (!spr->name) { - continue; - } - env->spr[i] =3D spr->default_value; - } -} - -#ifndef CONFIG_USER_ONLY - -static bool ppc_cpu_is_big_endian(CPUState *cs) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - CPUPPCState *env =3D &cpu->env; - - cpu_synchronize_state(cs); - - return !msr_le; -} - -#ifdef CONFIG_TCG -static void ppc_cpu_exec_enter(CPUState *cs) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - - if (cpu->vhyp) { - PPCVirtualHypervisorClass *vhc =3D - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); - vhc->cpu_exec_enter(cpu->vhyp, cpu); - } -} - -static void ppc_cpu_exec_exit(CPUState *cs) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - - if (cpu->vhyp) { - PPCVirtualHypervisorClass *vhc =3D - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); - vhc->cpu_exec_exit(cpu->vhyp, cpu); - } -} -#endif /* CONFIG_TCG */ - -#endif /* !CONFIG_USER_ONLY */ - -static void ppc_cpu_instance_init(Object *obj) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(obj); - PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cpu); - CPUPPCState *env =3D &cpu->env; - - cpu_set_cpustate_pointers(cpu); - cpu->vcpu_id =3D UNASSIGNED_CPU_INDEX; - - env->msr_mask =3D pcc->msr_mask; - env->mmu_model =3D pcc->mmu_model; - env->excp_model =3D pcc->excp_model; - env->bus_model =3D pcc->bus_model; - env->insns_flags =3D pcc->insns_flags; - env->insns_flags2 =3D pcc->insns_flags2; - env->flags =3D pcc->flags; - env->bfd_mach =3D pcc->bfd_mach; - env->check_pow =3D pcc->check_pow; - - /* - * Mark HV mode as supported if the CPU has an MSR_HV bit in the - * msr_mask. The mask can later be cleared by PAPR mode but the hv - * mode support will remain, thus enforcing that we cannot use - * priv. instructions in guest in PAPR mode. For 970 we currently - * simply don't set HV in msr_mask thus simulating an "Apple mode" - * 970. If we ever want to support 970 HV mode, we'll have to add - * a processor attribute of some sort. - */ -#if !defined(CONFIG_USER_ONLY) - env->has_hv_mode =3D !!(env->msr_mask & MSR_HVB); -#endif - - ppc_hash64_init(cpu); -} - -static void ppc_cpu_instance_finalize(Object *obj) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(obj); - - ppc_hash64_finalize(cpu); -} - -static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr) -{ - return pcc->pvr =3D=3D pvr; -} - -static gchar *ppc_gdb_arch_name(CPUState *cs) -{ -#if defined(TARGET_PPC64) - return g_strdup("powerpc:common64"); -#else - return g_strdup("powerpc:common"); -#endif -} - -static void ppc_disas_set_info(CPUState *cs, disassemble_info *info) -{ - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - CPUPPCState *env =3D &cpu->env; - - if ((env->hflags >> MSR_LE) & 1) { - info->endian =3D BFD_ENDIAN_LITTLE; - } - info->mach =3D env->bfd_mach; - if (!env->bfd_mach) { -#ifdef TARGET_PPC64 - info->mach =3D bfd_mach_ppc64; -#else - info->mach =3D bfd_mach_ppc; -#endif - } - info->disassembler_options =3D (char *)"any"; - info->print_insn =3D print_insn_ppc; - - info->cap_arch =3D CS_ARCH_PPC; -#ifdef TARGET_PPC64 - info->cap_mode =3D CS_MODE_64; -#endif -} - -static Property ppc_cpu_properties[] =3D { - DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, f= alse), - DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, - false), - DEFINE_PROP_BOOL("pre-3.0-migration", PowerPCCPU, pre_3_0_migration, - false), - DEFINE_PROP_END_OF_LIST(), -}; - -#ifdef CONFIG_TCG -#include "hw/core/tcg-cpu-ops.h" - -static struct TCGCPUOps ppc_tcg_ops =3D { - .initialize =3D ppc_translate_init, - .cpu_exec_interrupt =3D ppc_cpu_exec_interrupt, - .tlb_fill =3D ppc_cpu_tlb_fill, - -#ifndef CONFIG_USER_ONLY - .do_interrupt =3D ppc_cpu_do_interrupt, - .cpu_exec_enter =3D ppc_cpu_exec_enter, - .cpu_exec_exit =3D ppc_cpu_exec_exit, - .do_unaligned_access =3D ppc_cpu_do_unaligned_access, -#endif /* !CONFIG_USER_ONLY */ -}; -#endif /* CONFIG_TCG */ - -static void ppc_cpu_class_init(ObjectClass *oc, void *data) -{ - PowerPCCPUClass *pcc =3D POWERPC_CPU_CLASS(oc); - CPUClass *cc =3D CPU_CLASS(oc); - DeviceClass *dc =3D DEVICE_CLASS(oc); - - device_class_set_parent_realize(dc, ppc_cpu_realize, - &pcc->parent_realize); - device_class_set_parent_unrealize(dc, ppc_cpu_unrealize, - &pcc->parent_unrealize); - pcc->pvr_match =3D ppc_pvr_match_default; - pcc->interrupts_big_endian =3D ppc_cpu_interrupts_big_endian_always; - device_class_set_props(dc, ppc_cpu_properties); - - device_class_set_parent_reset(dc, ppc_cpu_reset, &pcc->parent_reset); - - cc->class_by_name =3D ppc_cpu_class_by_name; - cc->has_work =3D ppc_cpu_has_work; - cc->dump_state =3D ppc_cpu_dump_state; - cc->dump_statistics =3D ppc_cpu_dump_statistics; - cc->set_pc =3D ppc_cpu_set_pc; - cc->gdb_read_register =3D ppc_cpu_gdb_read_register; - cc->gdb_write_register =3D ppc_cpu_gdb_write_register; -#ifndef CONFIG_USER_ONLY - cc->get_phys_page_debug =3D ppc_cpu_get_phys_page_debug; - cc->vmsd =3D &vmstate_ppc_cpu; -#endif -#if defined(CONFIG_SOFTMMU) - cc->write_elf64_note =3D ppc64_cpu_write_elf64_note; - cc->write_elf32_note =3D ppc32_cpu_write_elf32_note; -#endif - - cc->gdb_num_core_regs =3D 71; -#ifndef CONFIG_USER_ONLY - cc->gdb_get_dynamic_xml =3D ppc_gdb_get_dynamic_xml; -#endif -#ifdef USE_APPLE_GDB - cc->gdb_read_register =3D ppc_cpu_gdb_read_register_apple; - cc->gdb_write_register =3D ppc_cpu_gdb_write_register_apple; - cc->gdb_num_core_regs =3D 71 + 32; -#endif - - cc->gdb_arch_name =3D ppc_gdb_arch_name; -#if defined(TARGET_PPC64) - cc->gdb_core_xml_file =3D "power64-core.xml"; -#else - cc->gdb_core_xml_file =3D "power-core.xml"; -#endif -#ifndef CONFIG_USER_ONLY - cc->virtio_is_big_endian =3D ppc_cpu_is_big_endian; -#endif - cc->disas_set_info =3D ppc_disas_set_info; - - dc->fw_name =3D "PowerPC,UNKNOWN"; - -#ifdef CONFIG_TCG - cc->tcg_ops =3D &ppc_tcg_ops; -#endif /* CONFIG_TCG */ -} - -static const TypeInfo ppc_cpu_type_info =3D { - .name =3D TYPE_POWERPC_CPU, - .parent =3D TYPE_CPU, - .instance_size =3D sizeof(PowerPCCPU), - .instance_align =3D __alignof__(PowerPCCPU), - .instance_init =3D ppc_cpu_instance_init, - .instance_finalize =3D ppc_cpu_instance_finalize, - .abstract =3D true, - .class_size =3D sizeof(PowerPCCPUClass), - .class_init =3D ppc_cpu_class_init, -}; - -#ifndef CONFIG_USER_ONLY -static const TypeInfo ppc_vhyp_type_info =3D { - .name =3D TYPE_PPC_VIRTUAL_HYPERVISOR, - .parent =3D TYPE_INTERFACE, - .class_size =3D sizeof(PPCVirtualHypervisorClass), -}; -#endif - -static void ppc_cpu_register_types(void) -{ - type_register_static(&ppc_cpu_type_info); -#ifndef CONFIG_USER_ONLY - type_register_static(&ppc_vhyp_type_info); -#endif -} - -type_init(ppc_cpu_register_types) --=20 2.17.1 From nobody Sat Apr 20 01:34:06 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617983031; cv=none; d=zohomail.com; s=zohoarc; b=lU82OXL/UKWV02sTO1dkFHO5ixc8fL7qgH8c2Erja4GFD2bZzVnPkMTSptGrtuyQbv0MudZAmAqUJMAuATvBaPpHe0TcQw3UkhunduUHaXLAsj8J1BTBfO/k8YlwmQP0rzqsUFvxG8AtUEsY7M89DHPQyyJ2L5wuz8e+1I23rcM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617983031; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=RC6RrmHQ0i7XdfK5zWQLyWpbERw2xvAAF2qXyF4QwuM=; b=KbQ+2ndSADvS4mX5mJ4O/0W/LKheERguy8rHtxm7ULQRVpmiJbkSAP3zs13UEZHyUgXOeJFZC8u6QjV7xWDGHsRZGtpGS/hEymBYz2a0/8QRHIIb68sbOdPl04NPat27PKWP4DjI32GJ2hdo2aQFcWsxwC4VCVny0us8xZgV4HQ= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617983031564943.3100684000455; Fri, 9 Apr 2021 08:43:51 -0700 (PDT) Received: from localhost ([::1]:53712 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtIT-00075s-KN for importer@patchew.org; Fri, 09 Apr 2021 11:43:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40022) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lUtCb-0002S8-LT; Fri, 09 Apr 2021 11:37:45 -0400 Received: from [201.28.113.2] (port=41884 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtCY-0002YS-3q; Fri, 09 Apr 2021 11:37:45 -0400 Received: from power9a ([10.10.71.235]) by outlook.eldorado.org.br with Microsoft SMTPSVC(8.5.9600.16384); Fri, 9 Apr 2021 12:19:21 -0300 Received: from eldorado.org.br (unknown [10.10.71.235]) by power9a (Postfix) with ESMTP id 6B82A800172; Fri, 9 Apr 2021 12:19:21 -0300 (-03) From: "Bruno Larsen (billionai)" To: qemu-devel@nongnu.org Subject: [PATCH 2/4] target/ppc: added solutions for building with disable-tcg Date: Fri, 9 Apr 2021 12:19:14 -0300 Message-Id: <20210409151916.97326-3-bruno.larsen@eldorado.org.br> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> References: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> X-OriginalArrivalTime: 09 Apr 2021 15:19:21.0594 (UTC) FILETIME=[B79045A0:01D72D53] X-Host-Lookup-Failed: Reverse DNS lookup failed for 201.28.113.2 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=201.28.113.2; envelope-from=bruno.larsen@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: lucas.araujo@eldorado.org.br, lagarcia@br.ibm.com, luis.pires@eldorado.org.br, fernando.valle@eldorado.org.br, qemu-ppc@nongnu.org, andre.silva@eldorado.org.br, "Bruno Larsen \(billionai\)" , matheus.ferst@eldorado.org.br Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" this commit presents 2 possible solutions for substituting TCG emulation with KVM calls. One - used in machine.c and arch_dump.c - explicitly adds the KVM function and has the possibility of adding the TCG one for more generic compilation, prioritizing te KVM option. The second option, implemented in kvm_ppc.h, transparently changes the helper into the KVM call, if TCG is not enabled. I believe the first solution is better, but it is less readable, so I wanted to have some feedback Signed-off-by: Bruno Larsen (billionai) --- target/ppc/arch_dump.c | 17 +++++++++++++++++ target/ppc/kvm.c | 30 ++++++++++++++++++++++++++++++ target/ppc/kvm_ppc.h | 11 +++++++++++ target/ppc/machine.c | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index 9ab04b2c38..c53e01011a 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -17,7 +17,10 @@ #include "elf.h" #include "sysemu/dump.h" #include "sysemu/kvm.h" +#include "kvm_ppc.h" +#if defined(CONFIG_TCG) #include "exec/helper-proto.h" +#endif /* CONFIG_TCG */ =20 #ifdef TARGET_PPC64 #define ELFCLASS ELFCLASS64 @@ -176,7 +179,21 @@ static void ppc_write_elf_vmxregset(NoteFuncArg *arg, = PowerPCCPU *cpu) vmxregset->avr[i].u64[1] =3D avr->u64[1]; } } + /* This is the first solution implemented. My personal favorite as it + * allows for explicit error handling, however it is much less readabl= e */ +#if defined(CONFIG_KVM) + if(kvm_enabled()){ + vmxregset->vscr.u32[3] =3D cpu_to_dump32(s, kvmppc_mfvscr(cpu)); + }else +#endif + +#if defined(CONFIG_TCG) vmxregset->vscr.u32[3] =3D cpu_to_dump32(s, helper_mfvscr(&cpu->env)); +#else + { + /* TODO: add proper error handling, even tough this should never b= e reached */ + } +#endif } =20 static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 104a308abb..8ed54d12d8 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -51,6 +51,7 @@ #include "elf.h" #include "sysemu/kvm_int.h" =20 + #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" =20 #define DEBUG_RETURN_GUEST 0 @@ -2947,3 +2948,32 @@ bool kvm_arch_cpu_check_are_resettable(void) { return true; } + +/* Functions added to replace helper_m(t|f)vscr from int_helper.c */ +int kvmppc_mtvscr(PowerPCCPU *cpu, uint32_t val){ + CPUState *cs =3D CPU(cpu); + CPUPPCState *env =3D &cpu->env; + struct kvm_one_reg reg; + int ret; + reg.id =3D KVM_REG_PPC_VSCR; + reg.addr =3D (uintptr_t) &env->vscr; + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if(ret < 0){ + fprintf(stderr, "Unable to set VSCR to KVM: %s", strerror(errno)); + } + return ret; +} + +int kvmppc_mfvscr(PowerPCCPU *cpu){ + CPUState *cs =3D CPU(cpu); + CPUPPCState *env =3D &cpu->env; + struct kvm_one_reg reg; + int ret; + reg.id =3D KVM_REG_PPC_VSCR; + reg.addr =3D (uintptr_t) &env->vscr; + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if(ret < 0){ + fprintf(stderr, "Unable to get VSCR to KVM: %s", strerror(errno)); + } + return ret; +} diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 989f61ace0..f618cb28b1 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -86,6 +86,17 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t t= b_offset); =20 int kvm_handle_nmi(PowerPCCPU *cpu, struct kvm_run *run); =20 +int kvmppc_mtvscr(PowerPCCPU*, uint32_t); +int kvmppc_mfvscr(PowerPCCPU*); + +/* This is the second (quick and dirty) solution. Not my personal favorite + * as it hides what is actually happening from the user and doesn't allow + * for error checking. but it requires less change in other files */ +#ifndef CONFIG_TCG +#define helper_mtvscr(env, val) kvmppc_mtvscr(env_archcpu(env),val) +#define helper_mfvscr(env) kvmppc_mfvscr(env_archcpu(env)) +#endif + #else =20 static inline uint32_t kvmppc_get_tbfreq(void) diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 283db1d28a..d92bc18859 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -8,7 +8,9 @@ #include "qapi/error.h" #include "qemu/main-loop.h" #include "kvm_ppc.h" +#ifdef CONFIG_TCG #include "exec/helper-proto.h" +#endif /*CONFIG_TCG*/ =20 static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) { @@ -95,7 +97,18 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int v= ersion_id) ppc_store_sdr1(env, sdr1); } qemu_get_be32s(f, &vscr); - helper_mtvscr(env, vscr); +#if defined(CONFIG_KVM) + if(kvm_enabled()){ + kvmppc_mtvscr(cpu, vscr); + }else +#endif +#if defined(CONFIG_TCG) + helper_mtvscr(env, vscr); +#else + { + /* TODO: Add correct error handling, even though this should never= be reached */ + } +#endif qemu_get_be64s(f, &env->spe_acc); qemu_get_be32s(f, &env->spe_fscr); qemu_get_betls(f, &env->msr_mask); @@ -450,7 +463,16 @@ static int get_vscr(QEMUFile *f, void *opaque, size_t = size, const VMStateField *field) { PowerPCCPU *cpu =3D opaque; +#if defined(CONFIG_KVM) + if(kvm_enabled()){ + kvmppc_mtvscr(cpu, qemu_get_be32(f)); + return 0; + } +#endif /*CONFIG_KVM*/ + +#if defined(CONFIG_TCG) helper_mtvscr(&cpu->env, qemu_get_be32(f)); +#endif /*CONFIG_TCG*/ return 0; } =20 @@ -458,7 +480,16 @@ static int put_vscr(QEMUFile *f, void *opaque, size_t = size, const VMStateField *field, JSONWriter *vmdesc) { PowerPCCPU *cpu =3D opaque; +#if defined(CONFIG_KVM) + if(kvm_enabled()){ + qemu_put_be32(f, kvmppc_mfvscr(cpu)); + return 0; + } +#endif /*CONFIG_KVM*/ + +#if defined(CONFIG_TCG) qemu_put_be32(f, helper_mfvscr(&cpu->env)); +#endif /*CONFIG_TCG*/ return 0; } =20 --=20 2.17.1 From nobody Sat Apr 20 01:34:06 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617983236; cv=none; d=zohomail.com; s=zohoarc; b=MGowlFc/GUg0+DNQYSHVZz/70nco8PkhB3hFF23E23J5Qrxq4dGie7EC5DlHNk+rg/1TsZLiFa/jyPJmWKLK3SwlBbnxMKIncKHLPYfgwfs4gbmmTETHY89cJQpWI529J19H7mEEu0Uvlpfk4++gqANkx0YLwUjKTz6WOivlHwk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617983236; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=c2bHn/OFdYq5SIcCSiO3qIsvUhI5ZpltpA8Wq8lld48=; b=Mze+lO7XobT6Qy9ZmrvwuceL6p+cwPShfHK6x8Mqz8n7oSbo+7ZdogA1xVlLM7bOJFg65XX7sHEshe6LagGX3I8+QzDhNK5r+xp0JG2tQ3JtyxRbw+TvTS0Bt77VBN0hb8PptGceVkAtCzwbQs+2z4A4ReeEK4z9vnRuiWnU/U4= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617983236417984.8180021453467; Fri, 9 Apr 2021 08:47:16 -0700 (PDT) Received: from localhost ([::1]:57700 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtLn-0000SV-75 for importer@patchew.org; Fri, 09 Apr 2021 11:47:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40044) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lUtCe-0002Tw-8B; Fri, 09 Apr 2021 11:37:48 -0400 Received: from [201.28.113.2] (port=41884 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtCc-0002YS-Mg; Fri, 09 Apr 2021 11:37:48 -0400 Received: from power9a ([10.10.71.235]) by outlook.eldorado.org.br with Microsoft SMTPSVC(8.5.9600.16384); Fri, 9 Apr 2021 12:19:21 -0300 Received: from eldorado.org.br (unknown [10.10.71.235]) by power9a (Postfix) with ESMTP id 7FE06801350; Fri, 9 Apr 2021 12:19:21 -0300 (-03) From: "Bruno Larsen (billionai)" To: qemu-devel@nongnu.org Subject: [PATCH 3/4] target/ppc: Add stubs for tcg functions, so it builds Date: Fri, 9 Apr 2021 12:19:15 -0300 Message-Id: <20210409151916.97326-4-bruno.larsen@eldorado.org.br> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> References: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> X-OriginalArrivalTime: 09 Apr 2021 15:19:21.0673 (UTC) FILETIME=[B79C5390:01D72D53] X-Host-Lookup-Failed: Reverse DNS lookup failed for 201.28.113.2 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=201.28.113.2; envelope-from=bruno.larsen@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: lucas.araujo@eldorado.org.br, lagarcia@br.ibm.com, luis.pires@eldorado.org.br, fernando.valle@eldorado.org.br, qemu-ppc@nongnu.org, andre.silva@eldorado.org.br, "Bruno Larsen \(billionai\)" , matheus.ferst@eldorado.org.br Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This file basically adds all stubs required to build the project with disable-tcg. most of these are not going to remain stubs by the end, but this part is where it got complicated, and I wanted to get an RFC ASAP. Most of these have to do with mmu emulation, so they'll probably be replaced by a KVM implementation in the final product, but I'm not sure which ones have to be replace, which can remain stubs, and which should not be called at all. Input in general is very much welcome. Signed-off-by: Bruno Larsen (billionai) --- target/ppc/tcg-stub.c | 139 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 target/ppc/tcg-stub.c diff --git a/target/ppc/tcg-stub.c b/target/ppc/tcg-stub.c new file mode 100644 index 0000000000..5dc8cf8911 --- /dev/null +++ b/target/ppc/tcg-stub.c @@ -0,0 +1,139 @@ +#include "qemu/osdep.h" +#include "cpu.h" +#include "mmu-hash64.h" + +/* STUFF FOR FIRST LINKER ERROR */ +/* This stuff happens in target/ppc files */ + +#if !defined(CONFIG_USER_ONLY) + +void ppc_store_sdr1(CPUPPCState *env, target_ulong value) { + /* stub to make things compile */ + return; +} + +void ppc_store_ptcr(CPUPPCState *env, target_ulong value) { + /* stub to make things compile */ + return; +} + +#endif /* !defined(CONFIG_USER_ONLY) */ +void ppc_store_msr(CPUPPCState *env, target_ulong value) { + /* stub to make things compile */ + return; +} + +void dump_mmu(CPUPPCState *env){ + /* stub to make things compile */ + return; +} + +void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask) { + /* stub to make things compile */ + return; +} + +void ppc_cpu_do_interrupt(CPUState *cpu) { + /* stub to make things compile */ + return; +} + +/* STUFF FOR SECOND LINKER ERROR*/ +/* these errors happen mostly in hw/ppc */ + +#ifdef TARGET_PPC64 +int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, + target_ulong esid, target_ulong vsid) { + /* rquired by kvm.c and machine.c */ + return 0; +} + +void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu, + bool (*cb)(void *, uint32_t, uint32_t), + void *opaque) { + /* required by spapr_caps.c */ + return;=20 +} + +void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val) { + /* required by spapr_* */ + return; +} + +const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu, + hwaddr ptex, int n) { + /* used by spapr_hcall a bunch */ + return NULL; +} + +void ppc_hash64_unmap_hptes(PowerPCCPU *cpu, const ppc_hash_pte64_t *hptes, + hwaddr ptex, int n) { + /* used a bunch by spapr_hcall */ + return;=20 +} + +void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, + target_ulong pte_index, + target_ulong pte0, target_ulong pte1){ + return;=20 +} + +unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, + uint64_t pte0, uint64_t pte1) { + return 0; +} +#endif + +void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) { + /* required by spapr_events spapr_mce_dispatch_elog */ + return; +} +#ifndef CONFIG_USER_ONLY +void ppc_cpu_do_system_reset(CPUState *cs){ + /* required by pnv and spapr */ + return; +} +#endif + +bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, + ppc_v3_pate_t *entry); + +bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, + ppc_v3_pate_t *entry) { + /* used by spapr_hcall: ppc_hash64_hpt_mask */ + return true; +} + +/* THIRD BATCH OF ERRORS, AFTER MOVING STUFF FROM TRANSLATE TO CPU.C */ + +/* they are all coming from cpu.c, probably */ + +void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp) { + return; +} + +void init_ppc_proc(PowerPCCPU *cpu) { + return; +} + +void destroy_ppc_opcodes(PowerPCCPU *cpu) { + return; +} + +void ppc_tlb_invalidate_all(CPUPPCState *env) { + return; +} + +void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags) { + return; +} + +void ppc_cpu_dump_statistics(CPUState *cpu, int flags) { + return; +} + +#include "exec/hwaddr.h" + +hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr) { + return 0; +} --=20 2.17.1 From nobody Sat Apr 20 01:34:06 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617982843; cv=none; d=zohomail.com; s=zohoarc; b=gK4evW9hGPRYu5YhwDVJD4fpl4yLLhiQucZRt7L89bZvU4MFrUW0wxfUzm1ZtG9HlrkTgTQq5tD9642n6RDe+gpCnwLJAUHGP9oYf4LGmyQ0pA/9D6+NibZ77vJYevGp3223e80wcSlZ4oCwAEpi1TNrnwJkm1MH7v67Di6gVHk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617982843; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=0QKDwAwI4ItVkUGW6VmqzJSH2QSVRjhvjlxnDqXeeoE=; b=BgEu7Ms9bwCSmCiqnRWeSdcfQAzb2qG8pGgkYMq+MU9lZxUTsxnI1sCJXZBEmc8GXwklwrHm//bEtX/MKAX773xR4ps6J2rpGyshDBDEZYuKXJOCb8ZYvNMzCouFXphNHTfjq27eR3DPkma9X4PU6RV/ceyu7NuqTFApOjAfSvo= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617982843411695.4354940807248; Fri, 9 Apr 2021 08:40:43 -0700 (PDT) Received: from localhost ([::1]:46532 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtFS-0003sD-7p for importer@patchew.org; Fri, 09 Apr 2021 11:40:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40062) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lUtCg-0002Xa-M1; Fri, 09 Apr 2021 11:37:50 -0400 Received: from [201.28.113.2] (port=41884 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lUtCf-0002YS-Bx; Fri, 09 Apr 2021 11:37:50 -0400 Received: from power9a ([10.10.71.235]) by outlook.eldorado.org.br with Microsoft SMTPSVC(8.5.9600.16384); Fri, 9 Apr 2021 12:19:21 -0300 Received: from eldorado.org.br (unknown [10.10.71.235]) by power9a (Postfix) with ESMTP id 94227800172; Fri, 9 Apr 2021 12:19:21 -0300 (-03) From: "Bruno Larsen (billionai)" To: qemu-devel@nongnu.org Subject: [PATCH 4/4] target/ppc: updated build rules for disable-tcg option Date: Fri, 9 Apr 2021 12:19:16 -0300 Message-Id: <20210409151916.97326-5-bruno.larsen@eldorado.org.br> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> References: <20210409151916.97326-1-bruno.larsen@eldorado.org.br> X-OriginalArrivalTime: 09 Apr 2021 15:19:21.0767 (UTC) FILETIME=[B7AAAB70:01D72D53] X-Host-Lookup-Failed: Reverse DNS lookup failed for 201.28.113.2 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=201.28.113.2; envelope-from=bruno.larsen@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: lucas.araujo@eldorado.org.br, lagarcia@br.ibm.com, luis.pires@eldorado.org.br, fernando.valle@eldorado.org.br, qemu-ppc@nongnu.org, andre.silva@eldorado.org.br, "Bruno Larsen \(billionai\)" , matheus.ferst@eldorado.org.br Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" updated the meson file to respect the disable-tcg option and only add relevant files to the build process Signed-off-by: Bruno Larsen (billionai) --- target/ppc/meson.build | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/target/ppc/meson.build b/target/ppc/meson.build index bbfef90e08..23f9346a6e 100644 --- a/target/ppc/meson.build +++ b/target/ppc/meson.build @@ -2,32 +2,40 @@ ppc_ss =3D ss.source_set() ppc_ss.add(files( 'cpu-models.c', 'cpu.c', + 'gdbstub.c', +)) + +ppc_ss.add(libdecnumber) + +ppc_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('k= vm-stub.c')) +ppc_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user_only_helper.c')) +ppc_ss.add(when: 'CONFIG_TCG', if_true: files( 'dfp_helper.c', 'excp_helper.c', 'fpu_helper.c', - 'gdbstub.c', 'int_helper.c', 'mem_helper.c', 'misc_helper.c', 'timebase_helper.c', 'translate.c', -)) +), if_false: files('tcg-stub.c')) =20 -ppc_ss.add(libdecnumber) - -ppc_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('k= vm-stub.c')) -ppc_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user_only_helper.c')) =20 ppc_softmmu_ss =3D ss.source_set() ppc_softmmu_ss.add(files( 'arch_dump.c', 'machine.c', + 'monitor.c', +)) +ppc_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files( 'mmu-hash32.c', 'mmu_helper.c', - 'monitor.c', )) + ppc_softmmu_ss.add(when: 'TARGET_PPC64', if_true: files( 'compat.c', +)) +ppc_softmmu_ss.add(when: ['TARGET_PPC64', 'CONFIG_TCG'], if_true: files( 'mmu-book3s-v3.c', 'mmu-hash64.c', 'mmu-radix64.c', --=20 2.17.1