1d76d1650Saurel32 /* 2d76d1650Saurel32 * PowerPC implementation of KVM hooks 3d76d1650Saurel32 * 4d76d1650Saurel32 * Copyright IBM Corp. 2007 590dc8812SScott Wood * Copyright (C) 2011 Freescale Semiconductor, Inc. 6d76d1650Saurel32 * 7d76d1650Saurel32 * Authors: 8d76d1650Saurel32 * Jerone Young <jyoung5@us.ibm.com> 9d76d1650Saurel32 * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> 10d76d1650Saurel32 * Hollis Blanchard <hollisb@us.ibm.com> 11d76d1650Saurel32 * 12d76d1650Saurel32 * This work is licensed under the terms of the GNU GPL, version 2 or later. 13d76d1650Saurel32 * See the COPYING file in the top-level directory. 14d76d1650Saurel32 * 15d76d1650Saurel32 */ 16d76d1650Saurel32 170d75590dSPeter Maydell #include "qemu/osdep.h" 18eadaada1SAlexander Graf #include <dirent.h> 19d76d1650Saurel32 #include <sys/ioctl.h> 204656e1f0SBenjamin Herrenschmidt #include <sys/vfs.h> 21d76d1650Saurel32 22d76d1650Saurel32 #include <linux/kvm.h> 23d76d1650Saurel32 24d76d1650Saurel32 #include "qemu-common.h" 25072ed5f2SThomas Huth #include "qemu/error-report.h" 2633c11879SPaolo Bonzini #include "cpu.h" 27*715d4b96SThomas Huth #include "cpu-models.h" 281de7afc9SPaolo Bonzini #include "qemu/timer.h" 299c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 30b3946626SVincent Palatin #include "sysemu/hw_accel.h" 3186b50f2eSThomas Huth #include "sysemu/numa.h" 32d76d1650Saurel32 #include "kvm_ppc.h" 339c17d615SPaolo Bonzini #include "sysemu/cpus.h" 349c17d615SPaolo Bonzini #include "sysemu/device_tree.h" 35d5aea6f3SDavid Gibson #include "mmu-hash64.h" 36d76d1650Saurel32 37f61b4bedSAlexander Graf #include "hw/sysbus.h" 380d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 390d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 407ebaf795SBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 4198a8b524SAlexey Kardashevskiy #include "hw/ppc/ppc.h" 4231f2cb8fSBharat Bhushan #include "sysemu/watchdog.h" 43b36f100eSAlexey Kardashevskiy #include "trace.h" 4488365d17SBharat Bhushan #include "exec/gdbstub.h" 454c663752SPaolo Bonzini #include "exec/memattrs.h" 462d103aaeSMichael Roth #include "sysemu/hostmem.h" 47f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 483b542549SBharata B Rao #if defined(TARGET_PPC64) 493b542549SBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 503b542549SBharata B Rao #endif 51f61b4bedSAlexander Graf 52d76d1650Saurel32 //#define DEBUG_KVM 53d76d1650Saurel32 54d76d1650Saurel32 #ifdef DEBUG_KVM 55da56ff91SPeter Maydell #define DPRINTF(fmt, ...) \ 56d76d1650Saurel32 do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 57d76d1650Saurel32 #else 58da56ff91SPeter Maydell #define DPRINTF(fmt, ...) \ 59d76d1650Saurel32 do { } while (0) 60d76d1650Saurel32 #endif 61d76d1650Saurel32 62eadaada1SAlexander Graf #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" 63eadaada1SAlexander Graf 6494a8d39aSJan Kiszka const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 6594a8d39aSJan Kiszka KVM_CAP_LAST_INFO 6694a8d39aSJan Kiszka }; 6794a8d39aSJan Kiszka 68fc87e185SAlexander Graf static int cap_interrupt_unset = false; 69fc87e185SAlexander Graf static int cap_interrupt_level = false; 7090dc8812SScott Wood static int cap_segstate; 7190dc8812SScott Wood static int cap_booke_sregs; 72e97c3636SDavid Gibson static int cap_ppc_smt; 73354ac20aSDavid Gibson static int cap_ppc_rma; 740f5cb298SDavid Gibson static int cap_spapr_tce; 75da95324eSAlexey Kardashevskiy static int cap_spapr_multitce; 769bb62a07SAlexey Kardashevskiy static int cap_spapr_vfio; 77f1af19d7SDavid Gibson static int cap_hior; 78d67d40eaSDavid Gibson static int cap_one_reg; 793b961124SStuart Yoder static int cap_epr; 8031f2cb8fSBharat Bhushan static int cap_ppc_watchdog; 819b00ea49SDavid Gibson static int cap_papr; 82e68cb8b4SAlexey Kardashevskiy static int cap_htab_fd; 8387a91de6SAlexander Graf static int cap_fixup_hcalls; 84bac3bf28SThomas Huth static int cap_htm; /* Hardware transactional memory support */ 85fc87e185SAlexander Graf 863c902d44SBharat Bhushan static uint32_t debug_inst_opcode; 873c902d44SBharat Bhushan 88c821c2bdSAlexander Graf /* XXX We have a race condition where we actually have a level triggered 89c821c2bdSAlexander Graf * interrupt, but the infrastructure can't expose that yet, so the guest 90c821c2bdSAlexander Graf * takes but ignores it, goes to sleep and never gets notified that there's 91c821c2bdSAlexander Graf * still an interrupt pending. 92c6a94ba5SAlexander Graf * 93c821c2bdSAlexander Graf * As a quick workaround, let's just wake up again 20 ms after we injected 94c821c2bdSAlexander Graf * an interrupt. That way we can assure that we're always reinjecting 95c821c2bdSAlexander Graf * interrupts in case the guest swallowed them. 96c6a94ba5SAlexander Graf */ 97c6a94ba5SAlexander Graf static QEMUTimer *idle_timer; 98c6a94ba5SAlexander Graf 99d5a68146SAndreas Färber static void kvm_kick_cpu(void *opaque) 100c6a94ba5SAlexander Graf { 101d5a68146SAndreas Färber PowerPCCPU *cpu = opaque; 102d5a68146SAndreas Färber 103c08d7424SAndreas Färber qemu_cpu_kick(CPU(cpu)); 104c6a94ba5SAlexander Graf } 105c6a94ba5SAlexander Graf 10696c9cff0SThomas Huth /* Check whether we are running with KVM-PR (instead of KVM-HV). This 10796c9cff0SThomas Huth * should only be used for fallback tests - generally we should use 10896c9cff0SThomas Huth * explicit capabilities for the features we want, rather than 10996c9cff0SThomas Huth * assuming what is/isn't available depending on the KVM variant. */ 11096c9cff0SThomas Huth static bool kvmppc_is_pr(KVMState *ks) 11196c9cff0SThomas Huth { 11296c9cff0SThomas Huth /* Assume KVM-PR if the GET_PVINFO capability is available */ 11396c9cff0SThomas Huth return kvm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; 11496c9cff0SThomas Huth } 11596c9cff0SThomas Huth 1165ba4576bSAndreas Färber static int kvm_ppc_register_host_cpu_type(void); 1175ba4576bSAndreas Färber 118b16565b3SMarcel Apfelbaum int kvm_arch_init(MachineState *ms, KVMState *s) 119d76d1650Saurel32 { 120fc87e185SAlexander Graf cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ); 121fc87e185SAlexander Graf cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL); 12290dc8812SScott Wood cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE); 12390dc8812SScott Wood cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS); 124e97c3636SDavid Gibson cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT); 125354ac20aSDavid Gibson cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA); 1260f5cb298SDavid Gibson cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); 127da95324eSAlexey Kardashevskiy cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE); 1289bb62a07SAlexey Kardashevskiy cap_spapr_vfio = false; 129d67d40eaSDavid Gibson cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG); 130f1af19d7SDavid Gibson cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR); 1313b961124SStuart Yoder cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR); 13231f2cb8fSBharat Bhushan cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG); 1339b00ea49SDavid Gibson /* Note: we don't set cap_papr here, because this capability is 1349b00ea49SDavid Gibson * only activated after this by kvmppc_set_papr() */ 135e68cb8b4SAlexey Kardashevskiy cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD); 13687a91de6SAlexander Graf cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL); 137bac3bf28SThomas Huth cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM); 138fc87e185SAlexander Graf 139fc87e185SAlexander Graf if (!cap_interrupt_level) { 140fc87e185SAlexander Graf fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the " 141fc87e185SAlexander Graf "VM to stall at times!\n"); 142fc87e185SAlexander Graf } 143fc87e185SAlexander Graf 1445ba4576bSAndreas Färber kvm_ppc_register_host_cpu_type(); 1455ba4576bSAndreas Färber 146d76d1650Saurel32 return 0; 147d76d1650Saurel32 } 148d76d1650Saurel32 149d525ffabSPaolo Bonzini int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) 150d525ffabSPaolo Bonzini { 151d525ffabSPaolo Bonzini return 0; 152d525ffabSPaolo Bonzini } 153d525ffabSPaolo Bonzini 1541bc22652SAndreas Färber static int kvm_arch_sync_sregs(PowerPCCPU *cpu) 155d76d1650Saurel32 { 1561bc22652SAndreas Färber CPUPPCState *cenv = &cpu->env; 1571bc22652SAndreas Färber CPUState *cs = CPU(cpu); 158861bbc80SAlexander Graf struct kvm_sregs sregs; 1595666ca4aSScott Wood int ret; 1605666ca4aSScott Wood 1615666ca4aSScott Wood if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 16264e07be5SAlexander Graf /* What we're really trying to say is "if we're on BookE, we use 16364e07be5SAlexander Graf the native PVR for now". This is the only sane way to check 16464e07be5SAlexander Graf it though, so we potentially confuse users that they can run 16564e07be5SAlexander Graf BookE guests on BookS. Let's hope nobody dares enough :) */ 1665666ca4aSScott Wood return 0; 1675666ca4aSScott Wood } else { 16890dc8812SScott Wood if (!cap_segstate) { 16964e07be5SAlexander Graf fprintf(stderr, "kvm error: missing PVR setting capability\n"); 17064e07be5SAlexander Graf return -ENOSYS; 1715666ca4aSScott Wood } 1725666ca4aSScott Wood } 1735666ca4aSScott Wood 1741bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); 1755666ca4aSScott Wood if (ret) { 1765666ca4aSScott Wood return ret; 1775666ca4aSScott Wood } 178861bbc80SAlexander Graf 179861bbc80SAlexander Graf sregs.pvr = cenv->spr[SPR_PVR]; 1801bc22652SAndreas Färber return kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); 1815666ca4aSScott Wood } 1825666ca4aSScott Wood 18393dd5e85SScott Wood /* Set up a shared TLB array with KVM */ 1841bc22652SAndreas Färber static int kvm_booke206_tlb_init(PowerPCCPU *cpu) 18593dd5e85SScott Wood { 1861bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 1871bc22652SAndreas Färber CPUState *cs = CPU(cpu); 18893dd5e85SScott Wood struct kvm_book3e_206_tlb_params params = {}; 18993dd5e85SScott Wood struct kvm_config_tlb cfg = {}; 19093dd5e85SScott Wood unsigned int entries = 0; 19193dd5e85SScott Wood int ret, i; 19293dd5e85SScott Wood 19393dd5e85SScott Wood if (!kvm_enabled() || 194a60f24b5SAndreas Färber !kvm_check_extension(cs->kvm_state, KVM_CAP_SW_TLB)) { 19593dd5e85SScott Wood return 0; 19693dd5e85SScott Wood } 19793dd5e85SScott Wood 19893dd5e85SScott Wood assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN); 19993dd5e85SScott Wood 20093dd5e85SScott Wood for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 20193dd5e85SScott Wood params.tlb_sizes[i] = booke206_tlb_size(env, i); 20293dd5e85SScott Wood params.tlb_ways[i] = booke206_tlb_ways(env, i); 20393dd5e85SScott Wood entries += params.tlb_sizes[i]; 20493dd5e85SScott Wood } 20593dd5e85SScott Wood 20693dd5e85SScott Wood assert(entries == env->nb_tlb); 20793dd5e85SScott Wood assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t)); 20893dd5e85SScott Wood 20993dd5e85SScott Wood env->tlb_dirty = true; 21093dd5e85SScott Wood 21193dd5e85SScott Wood cfg.array = (uintptr_t)env->tlb.tlbm; 21293dd5e85SScott Wood cfg.array_len = sizeof(ppcmas_tlb_t) * entries; 21393dd5e85SScott Wood cfg.params = (uintptr_t)¶ms; 21493dd5e85SScott Wood cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV; 21593dd5e85SScott Wood 21648add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_SW_TLB, 0, (uintptr_t)&cfg); 21793dd5e85SScott Wood if (ret < 0) { 21893dd5e85SScott Wood fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n", 21993dd5e85SScott Wood __func__, strerror(-ret)); 22093dd5e85SScott Wood return ret; 22193dd5e85SScott Wood } 22293dd5e85SScott Wood 22393dd5e85SScott Wood env->kvm_sw_tlb = true; 22493dd5e85SScott Wood return 0; 22593dd5e85SScott Wood } 22693dd5e85SScott Wood 2274656e1f0SBenjamin Herrenschmidt 2284656e1f0SBenjamin Herrenschmidt #if defined(TARGET_PPC64) 229a60f24b5SAndreas Färber static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu, 2304656e1f0SBenjamin Herrenschmidt struct kvm_ppc_smmu_info *info) 2314656e1f0SBenjamin Herrenschmidt { 232a60f24b5SAndreas Färber CPUPPCState *env = &cpu->env; 233a60f24b5SAndreas Färber CPUState *cs = CPU(cpu); 234a60f24b5SAndreas Färber 2354656e1f0SBenjamin Herrenschmidt memset(info, 0, sizeof(*info)); 2364656e1f0SBenjamin Herrenschmidt 2374656e1f0SBenjamin Herrenschmidt /* We don't have the new KVM_PPC_GET_SMMU_INFO ioctl, so 2384656e1f0SBenjamin Herrenschmidt * need to "guess" what the supported page sizes are. 2394656e1f0SBenjamin Herrenschmidt * 2404656e1f0SBenjamin Herrenschmidt * For that to work we make a few assumptions: 2414656e1f0SBenjamin Herrenschmidt * 24296c9cff0SThomas Huth * - Check whether we are running "PR" KVM which only supports 4K 24396c9cff0SThomas Huth * and 16M pages, but supports them regardless of the backing 24496c9cff0SThomas Huth * store characteritics. We also don't support 1T segments. 2454656e1f0SBenjamin Herrenschmidt * 2464656e1f0SBenjamin Herrenschmidt * This is safe as if HV KVM ever supports that capability or PR 2474656e1f0SBenjamin Herrenschmidt * KVM grows supports for more page/segment sizes, those versions 2484656e1f0SBenjamin Herrenschmidt * will have implemented KVM_CAP_PPC_GET_SMMU_INFO and thus we 2494656e1f0SBenjamin Herrenschmidt * will not hit this fallback 2504656e1f0SBenjamin Herrenschmidt * 2514656e1f0SBenjamin Herrenschmidt * - Else we are running HV KVM. This means we only support page 2524656e1f0SBenjamin Herrenschmidt * sizes that fit in the backing store. Additionally we only 2534656e1f0SBenjamin Herrenschmidt * advertize 64K pages if the processor is ARCH 2.06 and we assume 2544656e1f0SBenjamin Herrenschmidt * P7 encodings for the SLB and hash table. Here too, we assume 2554656e1f0SBenjamin Herrenschmidt * support for any newer processor will mean a kernel that 2564656e1f0SBenjamin Herrenschmidt * implements KVM_CAP_PPC_GET_SMMU_INFO and thus doesn't hit 2574656e1f0SBenjamin Herrenschmidt * this fallback. 2584656e1f0SBenjamin Herrenschmidt */ 25996c9cff0SThomas Huth if (kvmppc_is_pr(cs->kvm_state)) { 2604656e1f0SBenjamin Herrenschmidt /* No flags */ 2614656e1f0SBenjamin Herrenschmidt info->flags = 0; 2624656e1f0SBenjamin Herrenschmidt info->slb_size = 64; 2634656e1f0SBenjamin Herrenschmidt 2644656e1f0SBenjamin Herrenschmidt /* Standard 4k base page size segment */ 2654656e1f0SBenjamin Herrenschmidt info->sps[0].page_shift = 12; 2664656e1f0SBenjamin Herrenschmidt info->sps[0].slb_enc = 0; 2674656e1f0SBenjamin Herrenschmidt info->sps[0].enc[0].page_shift = 12; 2684656e1f0SBenjamin Herrenschmidt info->sps[0].enc[0].pte_enc = 0; 2694656e1f0SBenjamin Herrenschmidt 2704656e1f0SBenjamin Herrenschmidt /* Standard 16M large page size segment */ 2714656e1f0SBenjamin Herrenschmidt info->sps[1].page_shift = 24; 2724656e1f0SBenjamin Herrenschmidt info->sps[1].slb_enc = SLB_VSID_L; 2734656e1f0SBenjamin Herrenschmidt info->sps[1].enc[0].page_shift = 24; 2744656e1f0SBenjamin Herrenschmidt info->sps[1].enc[0].pte_enc = 0; 2754656e1f0SBenjamin Herrenschmidt } else { 2764656e1f0SBenjamin Herrenschmidt int i = 0; 2774656e1f0SBenjamin Herrenschmidt 2784656e1f0SBenjamin Herrenschmidt /* HV KVM has backing store size restrictions */ 2794656e1f0SBenjamin Herrenschmidt info->flags = KVM_PPC_PAGE_SIZES_REAL; 2804656e1f0SBenjamin Herrenschmidt 2814656e1f0SBenjamin Herrenschmidt if (env->mmu_model & POWERPC_MMU_1TSEG) { 2824656e1f0SBenjamin Herrenschmidt info->flags |= KVM_PPC_1T_SEGMENTS; 2834656e1f0SBenjamin Herrenschmidt } 2844656e1f0SBenjamin Herrenschmidt 285aa4bb587SBenjamin Herrenschmidt if (env->mmu_model == POWERPC_MMU_2_06 || 286aa4bb587SBenjamin Herrenschmidt env->mmu_model == POWERPC_MMU_2_07) { 2874656e1f0SBenjamin Herrenschmidt info->slb_size = 32; 2884656e1f0SBenjamin Herrenschmidt } else { 2894656e1f0SBenjamin Herrenschmidt info->slb_size = 64; 2904656e1f0SBenjamin Herrenschmidt } 2914656e1f0SBenjamin Herrenschmidt 2924656e1f0SBenjamin Herrenschmidt /* Standard 4k base page size segment */ 2934656e1f0SBenjamin Herrenschmidt info->sps[i].page_shift = 12; 2944656e1f0SBenjamin Herrenschmidt info->sps[i].slb_enc = 0; 2954656e1f0SBenjamin Herrenschmidt info->sps[i].enc[0].page_shift = 12; 2964656e1f0SBenjamin Herrenschmidt info->sps[i].enc[0].pte_enc = 0; 2974656e1f0SBenjamin Herrenschmidt i++; 2984656e1f0SBenjamin Herrenschmidt 299aa4bb587SBenjamin Herrenschmidt /* 64K on MMU 2.06 and later */ 300aa4bb587SBenjamin Herrenschmidt if (env->mmu_model == POWERPC_MMU_2_06 || 301aa4bb587SBenjamin Herrenschmidt env->mmu_model == POWERPC_MMU_2_07) { 3024656e1f0SBenjamin Herrenschmidt info->sps[i].page_shift = 16; 3034656e1f0SBenjamin Herrenschmidt info->sps[i].slb_enc = 0x110; 3044656e1f0SBenjamin Herrenschmidt info->sps[i].enc[0].page_shift = 16; 3054656e1f0SBenjamin Herrenschmidt info->sps[i].enc[0].pte_enc = 1; 3064656e1f0SBenjamin Herrenschmidt i++; 3074656e1f0SBenjamin Herrenschmidt } 3084656e1f0SBenjamin Herrenschmidt 3094656e1f0SBenjamin Herrenschmidt /* Standard 16M large page size segment */ 3104656e1f0SBenjamin Herrenschmidt info->sps[i].page_shift = 24; 3114656e1f0SBenjamin Herrenschmidt info->sps[i].slb_enc = SLB_VSID_L; 3124656e1f0SBenjamin Herrenschmidt info->sps[i].enc[0].page_shift = 24; 3134656e1f0SBenjamin Herrenschmidt info->sps[i].enc[0].pte_enc = 0; 3144656e1f0SBenjamin Herrenschmidt } 3154656e1f0SBenjamin Herrenschmidt } 3164656e1f0SBenjamin Herrenschmidt 317a60f24b5SAndreas Färber static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info) 3184656e1f0SBenjamin Herrenschmidt { 319a60f24b5SAndreas Färber CPUState *cs = CPU(cpu); 3204656e1f0SBenjamin Herrenschmidt int ret; 3214656e1f0SBenjamin Herrenschmidt 322a60f24b5SAndreas Färber if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { 323a60f24b5SAndreas Färber ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_SMMU_INFO, info); 3244656e1f0SBenjamin Herrenschmidt if (ret == 0) { 3254656e1f0SBenjamin Herrenschmidt return; 3264656e1f0SBenjamin Herrenschmidt } 3274656e1f0SBenjamin Herrenschmidt } 3284656e1f0SBenjamin Herrenschmidt 329a60f24b5SAndreas Färber kvm_get_fallback_smmu_info(cpu, info); 3304656e1f0SBenjamin Herrenschmidt } 3314656e1f0SBenjamin Herrenschmidt 3322d103aaeSMichael Roth static long gethugepagesize(const char *mem_path) 3334656e1f0SBenjamin Herrenschmidt { 3344656e1f0SBenjamin Herrenschmidt struct statfs fs; 3354656e1f0SBenjamin Herrenschmidt int ret; 3364656e1f0SBenjamin Herrenschmidt 3374656e1f0SBenjamin Herrenschmidt do { 3384656e1f0SBenjamin Herrenschmidt ret = statfs(mem_path, &fs); 3394656e1f0SBenjamin Herrenschmidt } while (ret != 0 && errno == EINTR); 3404656e1f0SBenjamin Herrenschmidt 3414656e1f0SBenjamin Herrenschmidt if (ret != 0) { 3424656e1f0SBenjamin Herrenschmidt fprintf(stderr, "Couldn't statfs() memory path: %s\n", 3434656e1f0SBenjamin Herrenschmidt strerror(errno)); 3444656e1f0SBenjamin Herrenschmidt exit(1); 3454656e1f0SBenjamin Herrenschmidt } 3464656e1f0SBenjamin Herrenschmidt 3474656e1f0SBenjamin Herrenschmidt #define HUGETLBFS_MAGIC 0x958458f6 3484656e1f0SBenjamin Herrenschmidt 3494656e1f0SBenjamin Herrenschmidt if (fs.f_type != HUGETLBFS_MAGIC) { 3504656e1f0SBenjamin Herrenschmidt /* Explicit mempath, but it's ordinary pages */ 3514656e1f0SBenjamin Herrenschmidt return getpagesize(); 3524656e1f0SBenjamin Herrenschmidt } 3534656e1f0SBenjamin Herrenschmidt 3544656e1f0SBenjamin Herrenschmidt /* It's hugepage, return the huge page size */ 3554656e1f0SBenjamin Herrenschmidt return fs.f_bsize; 3564656e1f0SBenjamin Herrenschmidt } 3574656e1f0SBenjamin Herrenschmidt 3583be5cc23SMarkus Armbruster /* 3593be5cc23SMarkus Armbruster * FIXME TOCTTOU: this iterates over memory backends' mem-path, which 3603be5cc23SMarkus Armbruster * may or may not name the same files / on the same filesystem now as 3613be5cc23SMarkus Armbruster * when we actually open and map them. Iterate over the file 3623be5cc23SMarkus Armbruster * descriptors instead, and use qemu_fd_getpagesize(). 3633be5cc23SMarkus Armbruster */ 3642d103aaeSMichael Roth static int find_max_supported_pagesize(Object *obj, void *opaque) 3652d103aaeSMichael Roth { 3662d103aaeSMichael Roth char *mem_path; 3672d103aaeSMichael Roth long *hpsize_min = opaque; 3682d103aaeSMichael Roth 3692d103aaeSMichael Roth if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { 3702d103aaeSMichael Roth mem_path = object_property_get_str(obj, "mem-path", NULL); 3712d103aaeSMichael Roth if (mem_path) { 3722d103aaeSMichael Roth long hpsize = gethugepagesize(mem_path); 3732d103aaeSMichael Roth if (hpsize < *hpsize_min) { 3742d103aaeSMichael Roth *hpsize_min = hpsize; 3752d103aaeSMichael Roth } 3762d103aaeSMichael Roth } else { 3772d103aaeSMichael Roth *hpsize_min = getpagesize(); 3782d103aaeSMichael Roth } 3792d103aaeSMichael Roth } 3802d103aaeSMichael Roth 3812d103aaeSMichael Roth return 0; 3822d103aaeSMichael Roth } 3832d103aaeSMichael Roth 3842d103aaeSMichael Roth static long getrampagesize(void) 3852d103aaeSMichael Roth { 3862d103aaeSMichael Roth long hpsize = LONG_MAX; 3873d4f2534SThomas Huth long mainrampagesize; 3882d103aaeSMichael Roth Object *memdev_root; 3892d103aaeSMichael Roth 3902d103aaeSMichael Roth if (mem_path) { 3913d4f2534SThomas Huth mainrampagesize = gethugepagesize(mem_path); 3923d4f2534SThomas Huth } else { 3933d4f2534SThomas Huth mainrampagesize = getpagesize(); 3942d103aaeSMichael Roth } 3952d103aaeSMichael Roth 3962d103aaeSMichael Roth /* it's possible we have memory-backend objects with 3972d103aaeSMichael Roth * hugepage-backed RAM. these may get mapped into system 3982d103aaeSMichael Roth * address space via -numa parameters or memory hotplug 3992d103aaeSMichael Roth * hooks. we want to take these into account, but we 4002d103aaeSMichael Roth * also want to make sure these supported hugepage 4012d103aaeSMichael Roth * sizes are applicable across the entire range of memory 4022d103aaeSMichael Roth * we may boot from, so we take the min across all 4032d103aaeSMichael Roth * backends, and assume normal pages in cases where a 4042d103aaeSMichael Roth * backend isn't backed by hugepages. 4052d103aaeSMichael Roth */ 4062d103aaeSMichael Roth memdev_root = object_resolve_path("/objects", NULL); 4073d4f2534SThomas Huth if (memdev_root) { 4082d103aaeSMichael Roth object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize); 4093d4f2534SThomas Huth } 4103d4f2534SThomas Huth if (hpsize == LONG_MAX) { 4113d4f2534SThomas Huth /* No additional memory regions found ==> Report main RAM page size */ 4123d4f2534SThomas Huth return mainrampagesize; 41386b50f2eSThomas Huth } 41486b50f2eSThomas Huth 415159d2e39SThomas Huth /* If NUMA is disabled or the NUMA nodes are not backed with a 4163d4f2534SThomas Huth * memory-backend, then there is at least one node using "normal" RAM, 4173d4f2534SThomas Huth * so if its page size is smaller we have got to report that size instead. 418159d2e39SThomas Huth */ 4193d4f2534SThomas Huth if (hpsize > mainrampagesize && 4203d4f2534SThomas Huth (nb_numa_nodes == 0 || numa_info[0].node_memdev == NULL)) { 42186b50f2eSThomas Huth static bool warned; 42286b50f2eSThomas Huth if (!warned) { 42386b50f2eSThomas Huth error_report("Huge page support disabled (n/a for main memory)."); 42486b50f2eSThomas Huth warned = true; 42586b50f2eSThomas Huth } 4263d4f2534SThomas Huth return mainrampagesize; 42786b50f2eSThomas Huth } 42886b50f2eSThomas Huth 42986b50f2eSThomas Huth return hpsize; 4302d103aaeSMichael Roth } 4312d103aaeSMichael Roth 4324656e1f0SBenjamin Herrenschmidt static bool kvm_valid_page_size(uint32_t flags, long rampgsize, uint32_t shift) 4334656e1f0SBenjamin Herrenschmidt { 4344656e1f0SBenjamin Herrenschmidt if (!(flags & KVM_PPC_PAGE_SIZES_REAL)) { 4354656e1f0SBenjamin Herrenschmidt return true; 4364656e1f0SBenjamin Herrenschmidt } 4374656e1f0SBenjamin Herrenschmidt 4384656e1f0SBenjamin Herrenschmidt return (1ul << shift) <= rampgsize; 4394656e1f0SBenjamin Herrenschmidt } 4404656e1f0SBenjamin Herrenschmidt 441a60f24b5SAndreas Färber static void kvm_fixup_page_sizes(PowerPCCPU *cpu) 4424656e1f0SBenjamin Herrenschmidt { 4434656e1f0SBenjamin Herrenschmidt static struct kvm_ppc_smmu_info smmu_info; 4444656e1f0SBenjamin Herrenschmidt static bool has_smmu_info; 445a60f24b5SAndreas Färber CPUPPCState *env = &cpu->env; 4464656e1f0SBenjamin Herrenschmidt long rampagesize; 4474656e1f0SBenjamin Herrenschmidt int iq, ik, jq, jk; 4480d594f55SThomas Huth bool has_64k_pages = false; 4494656e1f0SBenjamin Herrenschmidt 4504656e1f0SBenjamin Herrenschmidt /* We only handle page sizes for 64-bit server guests for now */ 4514656e1f0SBenjamin Herrenschmidt if (!(env->mmu_model & POWERPC_MMU_64)) { 4524656e1f0SBenjamin Herrenschmidt return; 4534656e1f0SBenjamin Herrenschmidt } 4544656e1f0SBenjamin Herrenschmidt 4554656e1f0SBenjamin Herrenschmidt /* Collect MMU info from kernel if not already */ 4564656e1f0SBenjamin Herrenschmidt if (!has_smmu_info) { 457a60f24b5SAndreas Färber kvm_get_smmu_info(cpu, &smmu_info); 4584656e1f0SBenjamin Herrenschmidt has_smmu_info = true; 4594656e1f0SBenjamin Herrenschmidt } 4604656e1f0SBenjamin Herrenschmidt 4614656e1f0SBenjamin Herrenschmidt rampagesize = getrampagesize(); 4624656e1f0SBenjamin Herrenschmidt 4634656e1f0SBenjamin Herrenschmidt /* Convert to QEMU form */ 4644656e1f0SBenjamin Herrenschmidt memset(&env->sps, 0, sizeof(env->sps)); 4654656e1f0SBenjamin Herrenschmidt 46690da0d5aSBenjamin Herrenschmidt /* If we have HV KVM, we need to forbid CI large pages if our 46790da0d5aSBenjamin Herrenschmidt * host page size is smaller than 64K. 46890da0d5aSBenjamin Herrenschmidt */ 46990da0d5aSBenjamin Herrenschmidt if (smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL) { 47090da0d5aSBenjamin Herrenschmidt env->ci_large_pages = getpagesize() >= 0x10000; 47190da0d5aSBenjamin Herrenschmidt } 47290da0d5aSBenjamin Herrenschmidt 47308215d8fSAlexander Graf /* 47408215d8fSAlexander Graf * XXX This loop should be an entry wide AND of the capabilities that 47508215d8fSAlexander Graf * the selected CPU has with the capabilities that KVM supports. 47608215d8fSAlexander Graf */ 4774656e1f0SBenjamin Herrenschmidt for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) { 4784656e1f0SBenjamin Herrenschmidt struct ppc_one_seg_page_size *qsps = &env->sps.sps[iq]; 4794656e1f0SBenjamin Herrenschmidt struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik]; 4804656e1f0SBenjamin Herrenschmidt 4814656e1f0SBenjamin Herrenschmidt if (!kvm_valid_page_size(smmu_info.flags, rampagesize, 4824656e1f0SBenjamin Herrenschmidt ksps->page_shift)) { 4834656e1f0SBenjamin Herrenschmidt continue; 4844656e1f0SBenjamin Herrenschmidt } 4854656e1f0SBenjamin Herrenschmidt qsps->page_shift = ksps->page_shift; 4864656e1f0SBenjamin Herrenschmidt qsps->slb_enc = ksps->slb_enc; 4874656e1f0SBenjamin Herrenschmidt for (jk = jq = 0; jk < KVM_PPC_PAGE_SIZES_MAX_SZ; jk++) { 4884656e1f0SBenjamin Herrenschmidt if (!kvm_valid_page_size(smmu_info.flags, rampagesize, 4894656e1f0SBenjamin Herrenschmidt ksps->enc[jk].page_shift)) { 4904656e1f0SBenjamin Herrenschmidt continue; 4914656e1f0SBenjamin Herrenschmidt } 4920d594f55SThomas Huth if (ksps->enc[jk].page_shift == 16) { 4930d594f55SThomas Huth has_64k_pages = true; 4940d594f55SThomas Huth } 4954656e1f0SBenjamin Herrenschmidt qsps->enc[jq].page_shift = ksps->enc[jk].page_shift; 4964656e1f0SBenjamin Herrenschmidt qsps->enc[jq].pte_enc = ksps->enc[jk].pte_enc; 4974656e1f0SBenjamin Herrenschmidt if (++jq >= PPC_PAGE_SIZES_MAX_SZ) { 4984656e1f0SBenjamin Herrenschmidt break; 4994656e1f0SBenjamin Herrenschmidt } 5004656e1f0SBenjamin Herrenschmidt } 5014656e1f0SBenjamin Herrenschmidt if (++iq >= PPC_PAGE_SIZES_MAX_SZ) { 5024656e1f0SBenjamin Herrenschmidt break; 5034656e1f0SBenjamin Herrenschmidt } 5044656e1f0SBenjamin Herrenschmidt } 5054656e1f0SBenjamin Herrenschmidt env->slb_nr = smmu_info.slb_size; 50608215d8fSAlexander Graf if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { 5074656e1f0SBenjamin Herrenschmidt env->mmu_model &= ~POWERPC_MMU_1TSEG; 5084656e1f0SBenjamin Herrenschmidt } 5090d594f55SThomas Huth if (!has_64k_pages) { 5100d594f55SThomas Huth env->mmu_model &= ~POWERPC_MMU_64K; 5110d594f55SThomas Huth } 5124656e1f0SBenjamin Herrenschmidt } 5134656e1f0SBenjamin Herrenschmidt #else /* defined (TARGET_PPC64) */ 5144656e1f0SBenjamin Herrenschmidt 515a60f24b5SAndreas Färber static inline void kvm_fixup_page_sizes(PowerPCCPU *cpu) 5164656e1f0SBenjamin Herrenschmidt { 5174656e1f0SBenjamin Herrenschmidt } 5184656e1f0SBenjamin Herrenschmidt 5194656e1f0SBenjamin Herrenschmidt #endif /* !defined (TARGET_PPC64) */ 5204656e1f0SBenjamin Herrenschmidt 521b164e48eSEduardo Habkost unsigned long kvm_arch_vcpu_id(CPUState *cpu) 522b164e48eSEduardo Habkost { 5230f20ba62SAlexey Kardashevskiy return ppc_get_vcpu_dt_id(POWERPC_CPU(cpu)); 524b164e48eSEduardo Habkost } 525b164e48eSEduardo Habkost 52688365d17SBharat Bhushan /* e500 supports 2 h/w breakpoint and 2 watchpoint. 52788365d17SBharat Bhushan * book3s supports only 1 watchpoint, so array size 52888365d17SBharat Bhushan * of 4 is sufficient for now. 52988365d17SBharat Bhushan */ 53088365d17SBharat Bhushan #define MAX_HW_BKPTS 4 53188365d17SBharat Bhushan 53288365d17SBharat Bhushan static struct HWBreakpoint { 53388365d17SBharat Bhushan target_ulong addr; 53488365d17SBharat Bhushan int type; 53588365d17SBharat Bhushan } hw_debug_points[MAX_HW_BKPTS]; 53688365d17SBharat Bhushan 53788365d17SBharat Bhushan static CPUWatchpoint hw_watchpoint; 53888365d17SBharat Bhushan 53988365d17SBharat Bhushan /* Default there is no breakpoint and watchpoint supported */ 54088365d17SBharat Bhushan static int max_hw_breakpoint; 54188365d17SBharat Bhushan static int max_hw_watchpoint; 54288365d17SBharat Bhushan static int nb_hw_breakpoint; 54388365d17SBharat Bhushan static int nb_hw_watchpoint; 54488365d17SBharat Bhushan 54588365d17SBharat Bhushan static void kvmppc_hw_debug_points_init(CPUPPCState *cenv) 54688365d17SBharat Bhushan { 54788365d17SBharat Bhushan if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 54888365d17SBharat Bhushan max_hw_breakpoint = 2; 54988365d17SBharat Bhushan max_hw_watchpoint = 2; 55088365d17SBharat Bhushan } 55188365d17SBharat Bhushan 55288365d17SBharat Bhushan if ((max_hw_breakpoint + max_hw_watchpoint) > MAX_HW_BKPTS) { 55388365d17SBharat Bhushan fprintf(stderr, "Error initializing h/w breakpoints\n"); 55488365d17SBharat Bhushan return; 55588365d17SBharat Bhushan } 55688365d17SBharat Bhushan } 55788365d17SBharat Bhushan 55820d695a9SAndreas Färber int kvm_arch_init_vcpu(CPUState *cs) 5595666ca4aSScott Wood { 56020d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 56120d695a9SAndreas Färber CPUPPCState *cenv = &cpu->env; 5625666ca4aSScott Wood int ret; 5635666ca4aSScott Wood 5644656e1f0SBenjamin Herrenschmidt /* Gather server mmu info from KVM and update the CPU state */ 565a60f24b5SAndreas Färber kvm_fixup_page_sizes(cpu); 5664656e1f0SBenjamin Herrenschmidt 5674656e1f0SBenjamin Herrenschmidt /* Synchronize sregs with kvm */ 5681bc22652SAndreas Färber ret = kvm_arch_sync_sregs(cpu); 5695666ca4aSScott Wood if (ret) { 570388e47c7SThomas Huth if (ret == -EINVAL) { 571388e47c7SThomas Huth error_report("Register sync failed... If you're using kvm-hv.ko," 572388e47c7SThomas Huth " only \"-cpu host\" is possible"); 573388e47c7SThomas Huth } 5745666ca4aSScott Wood return ret; 5755666ca4aSScott Wood } 576861bbc80SAlexander Graf 577bc72ad67SAlex Bligh idle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kvm_kick_cpu, cpu); 578c821c2bdSAlexander Graf 57993dd5e85SScott Wood switch (cenv->mmu_model) { 58093dd5e85SScott Wood case POWERPC_MMU_BOOKE206: 5817f516c96SThomas Huth /* This target supports access to KVM's guest TLB */ 5821bc22652SAndreas Färber ret = kvm_booke206_tlb_init(cpu); 58393dd5e85SScott Wood break; 5847f516c96SThomas Huth case POWERPC_MMU_2_07: 5857f516c96SThomas Huth if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) { 5867f516c96SThomas Huth /* KVM-HV has transactional memory on POWER8 also without the 5877f516c96SThomas Huth * KVM_CAP_PPC_HTM extension, so enable it here instead. */ 5887f516c96SThomas Huth cap_htm = true; 5897f516c96SThomas Huth } 5907f516c96SThomas Huth break; 59193dd5e85SScott Wood default: 59293dd5e85SScott Wood break; 59393dd5e85SScott Wood } 59493dd5e85SScott Wood 5953c902d44SBharat Bhushan kvm_get_one_reg(cs, KVM_REG_PPC_DEBUG_INST, &debug_inst_opcode); 59688365d17SBharat Bhushan kvmppc_hw_debug_points_init(cenv); 5973c902d44SBharat Bhushan 598861bbc80SAlexander Graf return ret; 599d76d1650Saurel32 } 600d76d1650Saurel32 6011bc22652SAndreas Färber static void kvm_sw_tlb_put(PowerPCCPU *cpu) 60293dd5e85SScott Wood { 6031bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 6041bc22652SAndreas Färber CPUState *cs = CPU(cpu); 60593dd5e85SScott Wood struct kvm_dirty_tlb dirty_tlb; 60693dd5e85SScott Wood unsigned char *bitmap; 60793dd5e85SScott Wood int ret; 60893dd5e85SScott Wood 60993dd5e85SScott Wood if (!env->kvm_sw_tlb) { 61093dd5e85SScott Wood return; 61193dd5e85SScott Wood } 61293dd5e85SScott Wood 61393dd5e85SScott Wood bitmap = g_malloc((env->nb_tlb + 7) / 8); 61493dd5e85SScott Wood memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8); 61593dd5e85SScott Wood 61693dd5e85SScott Wood dirty_tlb.bitmap = (uintptr_t)bitmap; 61793dd5e85SScott Wood dirty_tlb.num_dirty = env->nb_tlb; 61893dd5e85SScott Wood 6191bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_DIRTY_TLB, &dirty_tlb); 62093dd5e85SScott Wood if (ret) { 62193dd5e85SScott Wood fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n", 62293dd5e85SScott Wood __func__, strerror(-ret)); 62393dd5e85SScott Wood } 62493dd5e85SScott Wood 62593dd5e85SScott Wood g_free(bitmap); 62693dd5e85SScott Wood } 62793dd5e85SScott Wood 628d67d40eaSDavid Gibson static void kvm_get_one_spr(CPUState *cs, uint64_t id, int spr) 629d67d40eaSDavid Gibson { 630d67d40eaSDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 631d67d40eaSDavid Gibson CPUPPCState *env = &cpu->env; 632d67d40eaSDavid Gibson union { 633d67d40eaSDavid Gibson uint32_t u32; 634d67d40eaSDavid Gibson uint64_t u64; 635d67d40eaSDavid Gibson } val; 636d67d40eaSDavid Gibson struct kvm_one_reg reg = { 637d67d40eaSDavid Gibson .id = id, 638d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 639d67d40eaSDavid Gibson }; 640d67d40eaSDavid Gibson int ret; 641d67d40eaSDavid Gibson 642d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 643d67d40eaSDavid Gibson if (ret != 0) { 644b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_get(spr, strerror(errno)); 645d67d40eaSDavid Gibson } else { 646d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 647d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 648d67d40eaSDavid Gibson env->spr[spr] = val.u32; 649d67d40eaSDavid Gibson break; 650d67d40eaSDavid Gibson 651d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 652d67d40eaSDavid Gibson env->spr[spr] = val.u64; 653d67d40eaSDavid Gibson break; 654d67d40eaSDavid Gibson 655d67d40eaSDavid Gibson default: 656d67d40eaSDavid Gibson /* Don't handle this size yet */ 657d67d40eaSDavid Gibson abort(); 658d67d40eaSDavid Gibson } 659d67d40eaSDavid Gibson } 660d67d40eaSDavid Gibson } 661d67d40eaSDavid Gibson 662d67d40eaSDavid Gibson static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr) 663d67d40eaSDavid Gibson { 664d67d40eaSDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 665d67d40eaSDavid Gibson CPUPPCState *env = &cpu->env; 666d67d40eaSDavid Gibson union { 667d67d40eaSDavid Gibson uint32_t u32; 668d67d40eaSDavid Gibson uint64_t u64; 669d67d40eaSDavid Gibson } val; 670d67d40eaSDavid Gibson struct kvm_one_reg reg = { 671d67d40eaSDavid Gibson .id = id, 672d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 673d67d40eaSDavid Gibson }; 674d67d40eaSDavid Gibson int ret; 675d67d40eaSDavid Gibson 676d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 677d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 678d67d40eaSDavid Gibson val.u32 = env->spr[spr]; 679d67d40eaSDavid Gibson break; 680d67d40eaSDavid Gibson 681d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 682d67d40eaSDavid Gibson val.u64 = env->spr[spr]; 683d67d40eaSDavid Gibson break; 684d67d40eaSDavid Gibson 685d67d40eaSDavid Gibson default: 686d67d40eaSDavid Gibson /* Don't handle this size yet */ 687d67d40eaSDavid Gibson abort(); 688d67d40eaSDavid Gibson } 689d67d40eaSDavid Gibson 690d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 691d67d40eaSDavid Gibson if (ret != 0) { 692b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_set(spr, strerror(errno)); 693d67d40eaSDavid Gibson } 694d67d40eaSDavid Gibson } 695d67d40eaSDavid Gibson 69670b79849SDavid Gibson static int kvm_put_fp(CPUState *cs) 69770b79849SDavid Gibson { 69870b79849SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 69970b79849SDavid Gibson CPUPPCState *env = &cpu->env; 70070b79849SDavid Gibson struct kvm_one_reg reg; 70170b79849SDavid Gibson int i; 70270b79849SDavid Gibson int ret; 70370b79849SDavid Gibson 70470b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 70570b79849SDavid Gibson uint64_t fpscr = env->fpscr; 70670b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 70770b79849SDavid Gibson 70870b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 70970b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 71070b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 71170b79849SDavid Gibson if (ret < 0) { 712da56ff91SPeter Maydell DPRINTF("Unable to set FPSCR to KVM: %s\n", strerror(errno)); 71370b79849SDavid Gibson return ret; 71470b79849SDavid Gibson } 71570b79849SDavid Gibson 71670b79849SDavid Gibson for (i = 0; i < 32; i++) { 71770b79849SDavid Gibson uint64_t vsr[2]; 71870b79849SDavid Gibson 7193a4b791bSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 72070b79849SDavid Gibson vsr[0] = float64_val(env->fpr[i]); 72170b79849SDavid Gibson vsr[1] = env->vsr[i]; 7223a4b791bSGreg Kurz #else 7233a4b791bSGreg Kurz vsr[0] = env->vsr[i]; 7243a4b791bSGreg Kurz vsr[1] = float64_val(env->fpr[i]); 7253a4b791bSGreg Kurz #endif 72670b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 72770b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 72870b79849SDavid Gibson 72970b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 73070b79849SDavid Gibson if (ret < 0) { 731da56ff91SPeter Maydell DPRINTF("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR", 73270b79849SDavid Gibson i, strerror(errno)); 73370b79849SDavid Gibson return ret; 73470b79849SDavid Gibson } 73570b79849SDavid Gibson } 73670b79849SDavid Gibson } 73770b79849SDavid Gibson 73870b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 73970b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 74070b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 74170b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 74270b79849SDavid Gibson if (ret < 0) { 743da56ff91SPeter Maydell DPRINTF("Unable to set VSCR to KVM: %s\n", strerror(errno)); 74470b79849SDavid Gibson return ret; 74570b79849SDavid Gibson } 74670b79849SDavid Gibson 74770b79849SDavid Gibson for (i = 0; i < 32; i++) { 74870b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 74970b79849SDavid Gibson reg.addr = (uintptr_t)&env->avr[i]; 75070b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 75170b79849SDavid Gibson if (ret < 0) { 752da56ff91SPeter Maydell DPRINTF("Unable to set VR%d to KVM: %s\n", i, strerror(errno)); 75370b79849SDavid Gibson return ret; 75470b79849SDavid Gibson } 75570b79849SDavid Gibson } 75670b79849SDavid Gibson } 75770b79849SDavid Gibson 75870b79849SDavid Gibson return 0; 75970b79849SDavid Gibson } 76070b79849SDavid Gibson 76170b79849SDavid Gibson static int kvm_get_fp(CPUState *cs) 76270b79849SDavid Gibson { 76370b79849SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 76470b79849SDavid Gibson CPUPPCState *env = &cpu->env; 76570b79849SDavid Gibson struct kvm_one_reg reg; 76670b79849SDavid Gibson int i; 76770b79849SDavid Gibson int ret; 76870b79849SDavid Gibson 76970b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 77070b79849SDavid Gibson uint64_t fpscr; 77170b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 77270b79849SDavid Gibson 77370b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 77470b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 77570b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 77670b79849SDavid Gibson if (ret < 0) { 777da56ff91SPeter Maydell DPRINTF("Unable to get FPSCR from KVM: %s\n", strerror(errno)); 77870b79849SDavid Gibson return ret; 77970b79849SDavid Gibson } else { 78070b79849SDavid Gibson env->fpscr = fpscr; 78170b79849SDavid Gibson } 78270b79849SDavid Gibson 78370b79849SDavid Gibson for (i = 0; i < 32; i++) { 78470b79849SDavid Gibson uint64_t vsr[2]; 78570b79849SDavid Gibson 78670b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 78770b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 78870b79849SDavid Gibson 78970b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 79070b79849SDavid Gibson if (ret < 0) { 791da56ff91SPeter Maydell DPRINTF("Unable to get %s%d from KVM: %s\n", 79270b79849SDavid Gibson vsx ? "VSR" : "FPR", i, strerror(errno)); 79370b79849SDavid Gibson return ret; 79470b79849SDavid Gibson } else { 7953a4b791bSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 79670b79849SDavid Gibson env->fpr[i] = vsr[0]; 79770b79849SDavid Gibson if (vsx) { 79870b79849SDavid Gibson env->vsr[i] = vsr[1]; 79970b79849SDavid Gibson } 8003a4b791bSGreg Kurz #else 8013a4b791bSGreg Kurz env->fpr[i] = vsr[1]; 8023a4b791bSGreg Kurz if (vsx) { 8033a4b791bSGreg Kurz env->vsr[i] = vsr[0]; 8043a4b791bSGreg Kurz } 8053a4b791bSGreg Kurz #endif 80670b79849SDavid Gibson } 80770b79849SDavid Gibson } 80870b79849SDavid Gibson } 80970b79849SDavid Gibson 81070b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 81170b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 81270b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 81370b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 81470b79849SDavid Gibson if (ret < 0) { 815da56ff91SPeter Maydell DPRINTF("Unable to get VSCR from KVM: %s\n", strerror(errno)); 81670b79849SDavid Gibson return ret; 81770b79849SDavid Gibson } 81870b79849SDavid Gibson 81970b79849SDavid Gibson for (i = 0; i < 32; i++) { 82070b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 82170b79849SDavid Gibson reg.addr = (uintptr_t)&env->avr[i]; 82270b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 82370b79849SDavid Gibson if (ret < 0) { 824da56ff91SPeter Maydell DPRINTF("Unable to get VR%d from KVM: %s\n", 82570b79849SDavid Gibson i, strerror(errno)); 82670b79849SDavid Gibson return ret; 82770b79849SDavid Gibson } 82870b79849SDavid Gibson } 82970b79849SDavid Gibson } 83070b79849SDavid Gibson 83170b79849SDavid Gibson return 0; 83270b79849SDavid Gibson } 83370b79849SDavid Gibson 8349b00ea49SDavid Gibson #if defined(TARGET_PPC64) 8359b00ea49SDavid Gibson static int kvm_get_vpa(CPUState *cs) 8369b00ea49SDavid Gibson { 8379b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 8389b00ea49SDavid Gibson CPUPPCState *env = &cpu->env; 8399b00ea49SDavid Gibson struct kvm_one_reg reg; 8409b00ea49SDavid Gibson int ret; 8419b00ea49SDavid Gibson 8429b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8439b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->vpa_addr; 8449b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 8459b00ea49SDavid Gibson if (ret < 0) { 846da56ff91SPeter Maydell DPRINTF("Unable to get VPA address from KVM: %s\n", strerror(errno)); 8479b00ea49SDavid Gibson return ret; 8489b00ea49SDavid Gibson } 8499b00ea49SDavid Gibson 8509b00ea49SDavid Gibson assert((uintptr_t)&env->slb_shadow_size 8519b00ea49SDavid Gibson == ((uintptr_t)&env->slb_shadow_addr + 8)); 8529b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 8539b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->slb_shadow_addr; 8549b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 8559b00ea49SDavid Gibson if (ret < 0) { 856da56ff91SPeter Maydell DPRINTF("Unable to get SLB shadow state from KVM: %s\n", 8579b00ea49SDavid Gibson strerror(errno)); 8589b00ea49SDavid Gibson return ret; 8599b00ea49SDavid Gibson } 8609b00ea49SDavid Gibson 8619b00ea49SDavid Gibson assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8)); 8629b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 8639b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->dtl_addr; 8649b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 8659b00ea49SDavid Gibson if (ret < 0) { 866da56ff91SPeter Maydell DPRINTF("Unable to get dispatch trace log state from KVM: %s\n", 8679b00ea49SDavid Gibson strerror(errno)); 8689b00ea49SDavid Gibson return ret; 8699b00ea49SDavid Gibson } 8709b00ea49SDavid Gibson 8719b00ea49SDavid Gibson return 0; 8729b00ea49SDavid Gibson } 8739b00ea49SDavid Gibson 8749b00ea49SDavid Gibson static int kvm_put_vpa(CPUState *cs) 8759b00ea49SDavid Gibson { 8769b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 8779b00ea49SDavid Gibson CPUPPCState *env = &cpu->env; 8789b00ea49SDavid Gibson struct kvm_one_reg reg; 8799b00ea49SDavid Gibson int ret; 8809b00ea49SDavid Gibson 8819b00ea49SDavid Gibson /* SLB shadow or DTL can't be registered unless a master VPA is 8829b00ea49SDavid Gibson * registered. That means when restoring state, if a VPA *is* 8839b00ea49SDavid Gibson * registered, we need to set that up first. If not, we need to 8849b00ea49SDavid Gibson * deregister the others before deregistering the master VPA */ 8859b00ea49SDavid Gibson assert(env->vpa_addr || !(env->slb_shadow_addr || env->dtl_addr)); 8869b00ea49SDavid Gibson 8879b00ea49SDavid Gibson if (env->vpa_addr) { 8889b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8899b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->vpa_addr; 8909b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8919b00ea49SDavid Gibson if (ret < 0) { 892da56ff91SPeter Maydell DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno)); 8939b00ea49SDavid Gibson return ret; 8949b00ea49SDavid Gibson } 8959b00ea49SDavid Gibson } 8969b00ea49SDavid Gibson 8979b00ea49SDavid Gibson assert((uintptr_t)&env->slb_shadow_size 8989b00ea49SDavid Gibson == ((uintptr_t)&env->slb_shadow_addr + 8)); 8999b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 9009b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->slb_shadow_addr; 9019b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 9029b00ea49SDavid Gibson if (ret < 0) { 903da56ff91SPeter Maydell DPRINTF("Unable to set SLB shadow state to KVM: %s\n", strerror(errno)); 9049b00ea49SDavid Gibson return ret; 9059b00ea49SDavid Gibson } 9069b00ea49SDavid Gibson 9079b00ea49SDavid Gibson assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8)); 9089b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 9099b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->dtl_addr; 9109b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 9119b00ea49SDavid Gibson if (ret < 0) { 912da56ff91SPeter Maydell DPRINTF("Unable to set dispatch trace log state to KVM: %s\n", 9139b00ea49SDavid Gibson strerror(errno)); 9149b00ea49SDavid Gibson return ret; 9159b00ea49SDavid Gibson } 9169b00ea49SDavid Gibson 9179b00ea49SDavid Gibson if (!env->vpa_addr) { 9189b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 9199b00ea49SDavid Gibson reg.addr = (uintptr_t)&env->vpa_addr; 9209b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 9219b00ea49SDavid Gibson if (ret < 0) { 922da56ff91SPeter Maydell DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno)); 9239b00ea49SDavid Gibson return ret; 9249b00ea49SDavid Gibson } 9259b00ea49SDavid Gibson } 9269b00ea49SDavid Gibson 9279b00ea49SDavid Gibson return 0; 9289b00ea49SDavid Gibson } 9299b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 9309b00ea49SDavid Gibson 931e5c0d3ceSDavid Gibson int kvmppc_put_books_sregs(PowerPCCPU *cpu) 932a7a00a72SDavid Gibson { 933a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 934a7a00a72SDavid Gibson struct kvm_sregs sregs; 935a7a00a72SDavid Gibson int i; 936a7a00a72SDavid Gibson 937a7a00a72SDavid Gibson sregs.pvr = env->spr[SPR_PVR]; 938a7a00a72SDavid Gibson 939a7a00a72SDavid Gibson sregs.u.s.sdr1 = env->spr[SPR_SDR1]; 940a7a00a72SDavid Gibson 941a7a00a72SDavid Gibson /* Sync SLB */ 942a7a00a72SDavid Gibson #ifdef TARGET_PPC64 943a7a00a72SDavid Gibson for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 944a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; 945a7a00a72SDavid Gibson if (env->slb[i].esid & SLB_ESID_V) { 946a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe |= i; 947a7a00a72SDavid Gibson } 948a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; 949a7a00a72SDavid Gibson } 950a7a00a72SDavid Gibson #endif 951a7a00a72SDavid Gibson 952a7a00a72SDavid Gibson /* Sync SRs */ 953a7a00a72SDavid Gibson for (i = 0; i < 16; i++) { 954a7a00a72SDavid Gibson sregs.u.s.ppc32.sr[i] = env->sr[i]; 955a7a00a72SDavid Gibson } 956a7a00a72SDavid Gibson 957a7a00a72SDavid Gibson /* Sync BATs */ 958a7a00a72SDavid Gibson for (i = 0; i < 8; i++) { 959a7a00a72SDavid Gibson /* Beware. We have to swap upper and lower bits here */ 960a7a00a72SDavid Gibson sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) 961a7a00a72SDavid Gibson | env->DBAT[1][i]; 962a7a00a72SDavid Gibson sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) 963a7a00a72SDavid Gibson | env->IBAT[1][i]; 964a7a00a72SDavid Gibson } 965a7a00a72SDavid Gibson 966a7a00a72SDavid Gibson return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); 967a7a00a72SDavid Gibson } 968a7a00a72SDavid Gibson 96920d695a9SAndreas Färber int kvm_arch_put_registers(CPUState *cs, int level) 970d76d1650Saurel32 { 97120d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 97220d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 973d76d1650Saurel32 struct kvm_regs regs; 974d76d1650Saurel32 int ret; 975d76d1650Saurel32 int i; 976d76d1650Saurel32 9771bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 9781bc22652SAndreas Färber if (ret < 0) { 979d76d1650Saurel32 return ret; 9801bc22652SAndreas Färber } 981d76d1650Saurel32 982d76d1650Saurel32 regs.ctr = env->ctr; 983d76d1650Saurel32 regs.lr = env->lr; 984da91a00fSRichard Henderson regs.xer = cpu_read_xer(env); 985d76d1650Saurel32 regs.msr = env->msr; 986d76d1650Saurel32 regs.pc = env->nip; 987d76d1650Saurel32 988d76d1650Saurel32 regs.srr0 = env->spr[SPR_SRR0]; 989d76d1650Saurel32 regs.srr1 = env->spr[SPR_SRR1]; 990d76d1650Saurel32 991d76d1650Saurel32 regs.sprg0 = env->spr[SPR_SPRG0]; 992d76d1650Saurel32 regs.sprg1 = env->spr[SPR_SPRG1]; 993d76d1650Saurel32 regs.sprg2 = env->spr[SPR_SPRG2]; 994d76d1650Saurel32 regs.sprg3 = env->spr[SPR_SPRG3]; 995d76d1650Saurel32 regs.sprg4 = env->spr[SPR_SPRG4]; 996d76d1650Saurel32 regs.sprg5 = env->spr[SPR_SPRG5]; 997d76d1650Saurel32 regs.sprg6 = env->spr[SPR_SPRG6]; 998d76d1650Saurel32 regs.sprg7 = env->spr[SPR_SPRG7]; 999d76d1650Saurel32 100090dc8812SScott Wood regs.pid = env->spr[SPR_BOOKE_PID]; 100190dc8812SScott Wood 1002d76d1650Saurel32 for (i = 0;i < 32; i++) 1003d76d1650Saurel32 regs.gpr[i] = env->gpr[i]; 1004d76d1650Saurel32 10054bddaf55SAlexey Kardashevskiy regs.cr = 0; 10064bddaf55SAlexey Kardashevskiy for (i = 0; i < 8; i++) { 10074bddaf55SAlexey Kardashevskiy regs.cr |= (env->crf[i] & 15) << (4 * (7 - i)); 10084bddaf55SAlexey Kardashevskiy } 10094bddaf55SAlexey Kardashevskiy 10101bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 1011d76d1650Saurel32 if (ret < 0) 1012d76d1650Saurel32 return ret; 1013d76d1650Saurel32 101470b79849SDavid Gibson kvm_put_fp(cs); 101570b79849SDavid Gibson 101693dd5e85SScott Wood if (env->tlb_dirty) { 10171bc22652SAndreas Färber kvm_sw_tlb_put(cpu); 101893dd5e85SScott Wood env->tlb_dirty = false; 101993dd5e85SScott Wood } 102093dd5e85SScott Wood 1021f1af19d7SDavid Gibson if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) { 1022a7a00a72SDavid Gibson ret = kvmppc_put_books_sregs(cpu); 1023a7a00a72SDavid Gibson if (ret < 0) { 1024f1af19d7SDavid Gibson return ret; 1025f1af19d7SDavid Gibson } 1026f1af19d7SDavid Gibson } 1027f1af19d7SDavid Gibson 1028f1af19d7SDavid Gibson if (cap_hior && (level >= KVM_PUT_RESET_STATE)) { 1029d67d40eaSDavid Gibson kvm_put_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 1030d67d40eaSDavid Gibson } 1031f1af19d7SDavid Gibson 1032d67d40eaSDavid Gibson if (cap_one_reg) { 1033d67d40eaSDavid Gibson int i; 1034d67d40eaSDavid Gibson 1035d67d40eaSDavid Gibson /* We deliberately ignore errors here, for kernels which have 1036d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 1037d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 1038d67d40eaSDavid Gibson * work, at least until we try to migrate. */ 1039d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 1040d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 1041d67d40eaSDavid Gibson 1042d67d40eaSDavid Gibson if (id != 0) { 1043d67d40eaSDavid Gibson kvm_put_one_spr(cs, id, i); 1044d67d40eaSDavid Gibson } 1045f1af19d7SDavid Gibson } 10469b00ea49SDavid Gibson 10479b00ea49SDavid Gibson #ifdef TARGET_PPC64 104880b3f79bSAlexey Kardashevskiy if (msr_ts) { 104980b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 105080b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 105180b3f79bSAlexey Kardashevskiy } 105280b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 105380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 105480b3f79bSAlexey Kardashevskiy } 105580b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 105680b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 105780b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 105880b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 105980b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 106080b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 106180b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 106280b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 106380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 106480b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 106580b3f79bSAlexey Kardashevskiy } 106680b3f79bSAlexey Kardashevskiy 10679b00ea49SDavid Gibson if (cap_papr) { 10689b00ea49SDavid Gibson if (kvm_put_vpa(cs) < 0) { 1069da56ff91SPeter Maydell DPRINTF("Warning: Unable to set VPA information to KVM\n"); 10709b00ea49SDavid Gibson } 10719b00ea49SDavid Gibson } 107298a8b524SAlexey Kardashevskiy 107398a8b524SAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 10749b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 1075f1af19d7SDavid Gibson } 1076f1af19d7SDavid Gibson 1077d76d1650Saurel32 return ret; 1078d76d1650Saurel32 } 1079d76d1650Saurel32 1080c371c2e3SBharat Bhushan static void kvm_sync_excp(CPUPPCState *env, int vector, int ivor) 1081c371c2e3SBharat Bhushan { 1082c371c2e3SBharat Bhushan env->excp_vectors[vector] = env->spr[ivor] + env->spr[SPR_BOOKE_IVPR]; 1083c371c2e3SBharat Bhushan } 1084c371c2e3SBharat Bhushan 1085a7a00a72SDavid Gibson static int kvmppc_get_booke_sregs(PowerPCCPU *cpu) 1086d76d1650Saurel32 { 108720d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1088ba5e5090SAlexander Graf struct kvm_sregs sregs; 1089a7a00a72SDavid Gibson int ret; 1090d76d1650Saurel32 1091a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 109290dc8812SScott Wood if (ret < 0) { 109390dc8812SScott Wood return ret; 109490dc8812SScott Wood } 109590dc8812SScott Wood 109690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_BASE) { 109790dc8812SScott Wood env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0; 109890dc8812SScott Wood env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1; 109990dc8812SScott Wood env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr; 110090dc8812SScott Wood env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear; 110190dc8812SScott Wood env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr; 110290dc8812SScott Wood env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr; 110390dc8812SScott Wood env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr; 110490dc8812SScott Wood env->spr[SPR_DECR] = sregs.u.e.dec; 110590dc8812SScott Wood env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff; 110690dc8812SScott Wood env->spr[SPR_TBU] = sregs.u.e.tb >> 32; 110790dc8812SScott Wood env->spr[SPR_VRSAVE] = sregs.u.e.vrsave; 110890dc8812SScott Wood } 110990dc8812SScott Wood 111090dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206) { 111190dc8812SScott Wood env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir; 111290dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0; 111390dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1; 111490dc8812SScott Wood env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar; 111590dc8812SScott Wood env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr; 111690dc8812SScott Wood } 111790dc8812SScott Wood 111890dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_64) { 111990dc8812SScott Wood env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr; 112090dc8812SScott Wood } 112190dc8812SScott Wood 112290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPRG8) { 112390dc8812SScott Wood env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8; 112490dc8812SScott Wood } 112590dc8812SScott Wood 112690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_IVOR) { 112790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0]; 1128c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_CRITICAL, SPR_BOOKE_IVOR0); 112990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1]; 1130c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_MCHECK, SPR_BOOKE_IVOR1); 113190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2]; 1132c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DSI, SPR_BOOKE_IVOR2); 113390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3]; 1134c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ISI, SPR_BOOKE_IVOR3); 113590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4]; 1136c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EXTERNAL, SPR_BOOKE_IVOR4); 113790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5]; 1138c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ALIGN, SPR_BOOKE_IVOR5); 113990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6]; 1140c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_PROGRAM, SPR_BOOKE_IVOR6); 114190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7]; 1142c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FPU, SPR_BOOKE_IVOR7); 114390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8]; 1144c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SYSCALL, SPR_BOOKE_IVOR8); 114590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9]; 1146c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_APU, SPR_BOOKE_IVOR9); 114790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10]; 1148c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DECR, SPR_BOOKE_IVOR10); 114990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11]; 1150c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FIT, SPR_BOOKE_IVOR11); 115190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12]; 1152c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_WDT, SPR_BOOKE_IVOR12); 115390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13]; 1154c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DTLB, SPR_BOOKE_IVOR13); 115590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14]; 1156c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ITLB, SPR_BOOKE_IVOR14); 115790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15]; 1158c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DEBUG, SPR_BOOKE_IVOR15); 115990dc8812SScott Wood 116090dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPE) { 116190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0]; 1162c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SPEU, SPR_BOOKE_IVOR32); 116390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1]; 1164c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPDI, SPR_BOOKE_IVOR33); 116590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2]; 1166c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPRI, SPR_BOOKE_IVOR34); 116790dc8812SScott Wood } 116890dc8812SScott Wood 116990dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PM) { 117090dc8812SScott Wood env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3]; 1171c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EPERFM, SPR_BOOKE_IVOR35); 117290dc8812SScott Wood } 117390dc8812SScott Wood 117490dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PC) { 117590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4]; 1176c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORI, SPR_BOOKE_IVOR36); 117790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5]; 1178c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORCI, SPR_BOOKE_IVOR37); 117990dc8812SScott Wood } 118090dc8812SScott Wood } 118190dc8812SScott Wood 118290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) { 118390dc8812SScott Wood env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0; 118490dc8812SScott Wood env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1; 118590dc8812SScott Wood env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2; 118690dc8812SScott Wood env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff; 118790dc8812SScott Wood env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4; 118890dc8812SScott Wood env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6; 118990dc8812SScott Wood env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32; 119090dc8812SScott Wood env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg; 119190dc8812SScott Wood env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0]; 119290dc8812SScott Wood env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1]; 119390dc8812SScott Wood } 119490dc8812SScott Wood 119590dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_EXP) { 119690dc8812SScott Wood env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr; 119790dc8812SScott Wood } 119890dc8812SScott Wood 119990dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PD) { 120090dc8812SScott Wood env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc; 120190dc8812SScott Wood env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc; 120290dc8812SScott Wood } 120390dc8812SScott Wood 120490dc8812SScott Wood if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) { 120590dc8812SScott Wood env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr; 120690dc8812SScott Wood env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar; 120790dc8812SScott Wood env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0; 120890dc8812SScott Wood 120990dc8812SScott Wood if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) { 121090dc8812SScott Wood env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1; 121190dc8812SScott Wood env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2; 121290dc8812SScott Wood } 121390dc8812SScott Wood } 1214a7a00a72SDavid Gibson 1215a7a00a72SDavid Gibson return 0; 1216fafc0b6aSAlexander Graf } 121790dc8812SScott Wood 1218a7a00a72SDavid Gibson static int kvmppc_get_books_sregs(PowerPCCPU *cpu) 1219a7a00a72SDavid Gibson { 1220a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1221a7a00a72SDavid Gibson struct kvm_sregs sregs; 1222a7a00a72SDavid Gibson int ret; 1223a7a00a72SDavid Gibson int i; 1224a7a00a72SDavid Gibson 1225a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 122690dc8812SScott Wood if (ret < 0) { 122790dc8812SScott Wood return ret; 122890dc8812SScott Wood } 122990dc8812SScott Wood 1230f3c75d42SAneesh Kumar K.V if (!env->external_htab) { 1231bb593904SDavid Gibson ppc_store_sdr1(env, sregs.u.s.sdr1); 1232f3c75d42SAneesh Kumar K.V } 1233ba5e5090SAlexander Graf 1234ba5e5090SAlexander Graf /* Sync SLB */ 123582c09f2fSAlexander Graf #ifdef TARGET_PPC64 12364b4d4a21SAneesh Kumar K.V /* 12374b4d4a21SAneesh Kumar K.V * The packed SLB array we get from KVM_GET_SREGS only contains 1238a7a00a72SDavid Gibson * information about valid entries. So we flush our internal copy 1239a7a00a72SDavid Gibson * to get rid of stale ones, then put all valid SLB entries back 1240a7a00a72SDavid Gibson * in. 12414b4d4a21SAneesh Kumar K.V */ 12424b4d4a21SAneesh Kumar K.V memset(env->slb, 0, sizeof(env->slb)); 1243d83af167SAneesh Kumar K.V for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 12444b4d4a21SAneesh Kumar K.V target_ulong rb = sregs.u.s.ppc64.slb[i].slbe; 12454b4d4a21SAneesh Kumar K.V target_ulong rs = sregs.u.s.ppc64.slb[i].slbv; 12464b4d4a21SAneesh Kumar K.V /* 12474b4d4a21SAneesh Kumar K.V * Only restore valid entries 12484b4d4a21SAneesh Kumar K.V */ 12494b4d4a21SAneesh Kumar K.V if (rb & SLB_ESID_V) { 1250bcd81230SDavid Gibson ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs); 12514b4d4a21SAneesh Kumar K.V } 1252ba5e5090SAlexander Graf } 125382c09f2fSAlexander Graf #endif 1254ba5e5090SAlexander Graf 1255ba5e5090SAlexander Graf /* Sync SRs */ 1256ba5e5090SAlexander Graf for (i = 0; i < 16; i++) { 1257ba5e5090SAlexander Graf env->sr[i] = sregs.u.s.ppc32.sr[i]; 1258ba5e5090SAlexander Graf } 1259ba5e5090SAlexander Graf 1260ba5e5090SAlexander Graf /* Sync BATs */ 1261ba5e5090SAlexander Graf for (i = 0; i < 8; i++) { 1262ba5e5090SAlexander Graf env->DBAT[0][i] = sregs.u.s.ppc32.dbat[i] & 0xffffffff; 1263ba5e5090SAlexander Graf env->DBAT[1][i] = sregs.u.s.ppc32.dbat[i] >> 32; 1264ba5e5090SAlexander Graf env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff; 1265ba5e5090SAlexander Graf env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32; 1266ba5e5090SAlexander Graf } 1267a7a00a72SDavid Gibson 1268a7a00a72SDavid Gibson return 0; 1269a7a00a72SDavid Gibson } 1270a7a00a72SDavid Gibson 1271a7a00a72SDavid Gibson int kvm_arch_get_registers(CPUState *cs) 1272a7a00a72SDavid Gibson { 1273a7a00a72SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 1274a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1275a7a00a72SDavid Gibson struct kvm_regs regs; 1276a7a00a72SDavid Gibson uint32_t cr; 1277a7a00a72SDavid Gibson int i, ret; 1278a7a00a72SDavid Gibson 1279a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1280a7a00a72SDavid Gibson if (ret < 0) 1281a7a00a72SDavid Gibson return ret; 1282a7a00a72SDavid Gibson 1283a7a00a72SDavid Gibson cr = regs.cr; 1284a7a00a72SDavid Gibson for (i = 7; i >= 0; i--) { 1285a7a00a72SDavid Gibson env->crf[i] = cr & 15; 1286a7a00a72SDavid Gibson cr >>= 4; 1287a7a00a72SDavid Gibson } 1288a7a00a72SDavid Gibson 1289a7a00a72SDavid Gibson env->ctr = regs.ctr; 1290a7a00a72SDavid Gibson env->lr = regs.lr; 1291a7a00a72SDavid Gibson cpu_write_xer(env, regs.xer); 1292a7a00a72SDavid Gibson env->msr = regs.msr; 1293a7a00a72SDavid Gibson env->nip = regs.pc; 1294a7a00a72SDavid Gibson 1295a7a00a72SDavid Gibson env->spr[SPR_SRR0] = regs.srr0; 1296a7a00a72SDavid Gibson env->spr[SPR_SRR1] = regs.srr1; 1297a7a00a72SDavid Gibson 1298a7a00a72SDavid Gibson env->spr[SPR_SPRG0] = regs.sprg0; 1299a7a00a72SDavid Gibson env->spr[SPR_SPRG1] = regs.sprg1; 1300a7a00a72SDavid Gibson env->spr[SPR_SPRG2] = regs.sprg2; 1301a7a00a72SDavid Gibson env->spr[SPR_SPRG3] = regs.sprg3; 1302a7a00a72SDavid Gibson env->spr[SPR_SPRG4] = regs.sprg4; 1303a7a00a72SDavid Gibson env->spr[SPR_SPRG5] = regs.sprg5; 1304a7a00a72SDavid Gibson env->spr[SPR_SPRG6] = regs.sprg6; 1305a7a00a72SDavid Gibson env->spr[SPR_SPRG7] = regs.sprg7; 1306a7a00a72SDavid Gibson 1307a7a00a72SDavid Gibson env->spr[SPR_BOOKE_PID] = regs.pid; 1308a7a00a72SDavid Gibson 1309a7a00a72SDavid Gibson for (i = 0;i < 32; i++) 1310a7a00a72SDavid Gibson env->gpr[i] = regs.gpr[i]; 1311a7a00a72SDavid Gibson 1312a7a00a72SDavid Gibson kvm_get_fp(cs); 1313a7a00a72SDavid Gibson 1314a7a00a72SDavid Gibson if (cap_booke_sregs) { 1315a7a00a72SDavid Gibson ret = kvmppc_get_booke_sregs(cpu); 1316a7a00a72SDavid Gibson if (ret < 0) { 1317a7a00a72SDavid Gibson return ret; 1318a7a00a72SDavid Gibson } 1319a7a00a72SDavid Gibson } 1320a7a00a72SDavid Gibson 1321a7a00a72SDavid Gibson if (cap_segstate) { 1322a7a00a72SDavid Gibson ret = kvmppc_get_books_sregs(cpu); 1323a7a00a72SDavid Gibson if (ret < 0) { 1324a7a00a72SDavid Gibson return ret; 1325a7a00a72SDavid Gibson } 1326fafc0b6aSAlexander Graf } 1327ba5e5090SAlexander Graf 1328d67d40eaSDavid Gibson if (cap_hior) { 1329d67d40eaSDavid Gibson kvm_get_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 1330d67d40eaSDavid Gibson } 1331d67d40eaSDavid Gibson 1332d67d40eaSDavid Gibson if (cap_one_reg) { 1333d67d40eaSDavid Gibson int i; 1334d67d40eaSDavid Gibson 1335d67d40eaSDavid Gibson /* We deliberately ignore errors here, for kernels which have 1336d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 1337d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 1338d67d40eaSDavid Gibson * work, at least until we try to migrate. */ 1339d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 1340d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 1341d67d40eaSDavid Gibson 1342d67d40eaSDavid Gibson if (id != 0) { 1343d67d40eaSDavid Gibson kvm_get_one_spr(cs, id, i); 1344d67d40eaSDavid Gibson } 1345d67d40eaSDavid Gibson } 13469b00ea49SDavid Gibson 13479b00ea49SDavid Gibson #ifdef TARGET_PPC64 134880b3f79bSAlexey Kardashevskiy if (msr_ts) { 134980b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 135080b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 135180b3f79bSAlexey Kardashevskiy } 135280b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 135380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 135480b3f79bSAlexey Kardashevskiy } 135580b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 135680b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 135780b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 135880b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 135980b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 136080b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 136180b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 136280b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 136380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 136480b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 136580b3f79bSAlexey Kardashevskiy } 136680b3f79bSAlexey Kardashevskiy 13679b00ea49SDavid Gibson if (cap_papr) { 13689b00ea49SDavid Gibson if (kvm_get_vpa(cs) < 0) { 1369da56ff91SPeter Maydell DPRINTF("Warning: Unable to get VPA information from KVM\n"); 13709b00ea49SDavid Gibson } 13719b00ea49SDavid Gibson } 137298a8b524SAlexey Kardashevskiy 137398a8b524SAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 13749b00ea49SDavid Gibson #endif 1375d67d40eaSDavid Gibson } 1376d67d40eaSDavid Gibson 1377d76d1650Saurel32 return 0; 1378d76d1650Saurel32 } 1379d76d1650Saurel32 13801bc22652SAndreas Färber int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level) 1381fc87e185SAlexander Graf { 1382fc87e185SAlexander Graf unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET; 1383fc87e185SAlexander Graf 1384fc87e185SAlexander Graf if (irq != PPC_INTERRUPT_EXT) { 1385fc87e185SAlexander Graf return 0; 1386fc87e185SAlexander Graf } 1387fc87e185SAlexander Graf 1388fc87e185SAlexander Graf if (!kvm_enabled() || !cap_interrupt_unset || !cap_interrupt_level) { 1389fc87e185SAlexander Graf return 0; 1390fc87e185SAlexander Graf } 1391fc87e185SAlexander Graf 13921bc22652SAndreas Färber kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); 1393fc87e185SAlexander Graf 1394fc87e185SAlexander Graf return 0; 1395fc87e185SAlexander Graf } 1396fc87e185SAlexander Graf 139716415335SAlexander Graf #if defined(TARGET_PPCEMB) 139816415335SAlexander Graf #define PPC_INPUT_INT PPC40x_INPUT_INT 139916415335SAlexander Graf #elif defined(TARGET_PPC64) 140016415335SAlexander Graf #define PPC_INPUT_INT PPC970_INPUT_INT 140116415335SAlexander Graf #else 140216415335SAlexander Graf #define PPC_INPUT_INT PPC6xx_INPUT_INT 140316415335SAlexander Graf #endif 140416415335SAlexander Graf 140520d695a9SAndreas Färber void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 1406d76d1650Saurel32 { 140720d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 140820d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1409d76d1650Saurel32 int r; 1410d76d1650Saurel32 unsigned irq; 1411d76d1650Saurel32 14124b8523eeSJan Kiszka qemu_mutex_lock_iothread(); 14134b8523eeSJan Kiszka 14145cbdb3a3SStefan Weil /* PowerPC QEMU tracks the various core input pins (interrupt, critical 1415d76d1650Saurel32 * interrupt, reset, etc) in PPC-specific env->irq_input_state. */ 1416fc87e185SAlexander Graf if (!cap_interrupt_level && 1417fc87e185SAlexander Graf run->ready_for_interrupt_injection && 1418259186a7SAndreas Färber (cs->interrupt_request & CPU_INTERRUPT_HARD) && 141916415335SAlexander Graf (env->irq_input_state & (1<<PPC_INPUT_INT))) 1420d76d1650Saurel32 { 1421d76d1650Saurel32 /* For now KVM disregards the 'irq' argument. However, in the 1422d76d1650Saurel32 * future KVM could cache it in-kernel to avoid a heavyweight exit 1423d76d1650Saurel32 * when reading the UIC. 1424d76d1650Saurel32 */ 1425fc87e185SAlexander Graf irq = KVM_INTERRUPT_SET; 1426d76d1650Saurel32 1427da56ff91SPeter Maydell DPRINTF("injected interrupt %d\n", irq); 14281bc22652SAndreas Färber r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq); 142955e5c285SAndreas Färber if (r < 0) { 143055e5c285SAndreas Färber printf("cpu %d fail inject %x\n", cs->cpu_index, irq); 143155e5c285SAndreas Färber } 1432c821c2bdSAlexander Graf 1433c821c2bdSAlexander Graf /* Always wake up soon in case the interrupt was level based */ 1434bc72ad67SAlex Bligh timer_mod(idle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 143573bcb24dSRutuja Shah (NANOSECONDS_PER_SECOND / 50)); 1436d76d1650Saurel32 } 1437d76d1650Saurel32 1438d76d1650Saurel32 /* We don't know if there are more interrupts pending after this. However, 1439d76d1650Saurel32 * the guest will return to userspace in the course of handling this one 1440d76d1650Saurel32 * anyways, so we will get a chance to deliver the rest. */ 14414b8523eeSJan Kiszka 14424b8523eeSJan Kiszka qemu_mutex_unlock_iothread(); 1443d76d1650Saurel32 } 1444d76d1650Saurel32 14454c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 1446d76d1650Saurel32 { 14474c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 1448d76d1650Saurel32 } 1449d76d1650Saurel32 145020d695a9SAndreas Färber int kvm_arch_process_async_events(CPUState *cs) 14510af691d7SMarcelo Tosatti { 1452259186a7SAndreas Färber return cs->halted; 14530af691d7SMarcelo Tosatti } 14540af691d7SMarcelo Tosatti 1455259186a7SAndreas Färber static int kvmppc_handle_halt(PowerPCCPU *cpu) 1456d76d1650Saurel32 { 1457259186a7SAndreas Färber CPUState *cs = CPU(cpu); 1458259186a7SAndreas Färber CPUPPCState *env = &cpu->env; 1459259186a7SAndreas Färber 1460259186a7SAndreas Färber if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) { 1461259186a7SAndreas Färber cs->halted = 1; 146227103424SAndreas Färber cs->exception_index = EXCP_HLT; 1463d76d1650Saurel32 } 1464d76d1650Saurel32 1465bb4ea393SJan Kiszka return 0; 1466d76d1650Saurel32 } 1467d76d1650Saurel32 1468d76d1650Saurel32 /* map dcr access to existing qemu dcr emulation */ 14691328c2bfSAndreas Färber static int kvmppc_handle_dcr_read(CPUPPCState *env, uint32_t dcrn, uint32_t *data) 1470d76d1650Saurel32 { 1471d76d1650Saurel32 if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) 1472d76d1650Saurel32 fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn); 1473d76d1650Saurel32 1474bb4ea393SJan Kiszka return 0; 1475d76d1650Saurel32 } 1476d76d1650Saurel32 14771328c2bfSAndreas Färber static int kvmppc_handle_dcr_write(CPUPPCState *env, uint32_t dcrn, uint32_t data) 1478d76d1650Saurel32 { 1479d76d1650Saurel32 if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) 1480d76d1650Saurel32 fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn); 1481d76d1650Saurel32 1482bb4ea393SJan Kiszka return 0; 1483d76d1650Saurel32 } 1484d76d1650Saurel32 14858a0548f9SBharat Bhushan int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 14868a0548f9SBharat Bhushan { 14878a0548f9SBharat Bhushan /* Mixed endian case is not handled */ 14888a0548f9SBharat Bhushan uint32_t sc = debug_inst_opcode; 14898a0548f9SBharat Bhushan 14908a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 14918a0548f9SBharat Bhushan sizeof(sc), 0) || 14928a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 1)) { 14938a0548f9SBharat Bhushan return -EINVAL; 14948a0548f9SBharat Bhushan } 14958a0548f9SBharat Bhushan 14968a0548f9SBharat Bhushan return 0; 14978a0548f9SBharat Bhushan } 14988a0548f9SBharat Bhushan 14998a0548f9SBharat Bhushan int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 15008a0548f9SBharat Bhushan { 15018a0548f9SBharat Bhushan uint32_t sc; 15028a0548f9SBharat Bhushan 15038a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 0) || 15048a0548f9SBharat Bhushan sc != debug_inst_opcode || 15058a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 15068a0548f9SBharat Bhushan sizeof(sc), 1)) { 15078a0548f9SBharat Bhushan return -EINVAL; 15088a0548f9SBharat Bhushan } 15098a0548f9SBharat Bhushan 15108a0548f9SBharat Bhushan return 0; 15118a0548f9SBharat Bhushan } 15128a0548f9SBharat Bhushan 151388365d17SBharat Bhushan static int find_hw_breakpoint(target_ulong addr, int type) 151488365d17SBharat Bhushan { 151588365d17SBharat Bhushan int n; 151688365d17SBharat Bhushan 151788365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 151888365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 151988365d17SBharat Bhushan 152088365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 152188365d17SBharat Bhushan if (hw_debug_points[n].addr == addr && 152288365d17SBharat Bhushan hw_debug_points[n].type == type) { 152388365d17SBharat Bhushan return n; 152488365d17SBharat Bhushan } 152588365d17SBharat Bhushan } 152688365d17SBharat Bhushan 152788365d17SBharat Bhushan return -1; 152888365d17SBharat Bhushan } 152988365d17SBharat Bhushan 153088365d17SBharat Bhushan static int find_hw_watchpoint(target_ulong addr, int *flag) 153188365d17SBharat Bhushan { 153288365d17SBharat Bhushan int n; 153388365d17SBharat Bhushan 153488365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_ACCESS); 153588365d17SBharat Bhushan if (n >= 0) { 153688365d17SBharat Bhushan *flag = BP_MEM_ACCESS; 153788365d17SBharat Bhushan return n; 153888365d17SBharat Bhushan } 153988365d17SBharat Bhushan 154088365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_WRITE); 154188365d17SBharat Bhushan if (n >= 0) { 154288365d17SBharat Bhushan *flag = BP_MEM_WRITE; 154388365d17SBharat Bhushan return n; 154488365d17SBharat Bhushan } 154588365d17SBharat Bhushan 154688365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_READ); 154788365d17SBharat Bhushan if (n >= 0) { 154888365d17SBharat Bhushan *flag = BP_MEM_READ; 154988365d17SBharat Bhushan return n; 155088365d17SBharat Bhushan } 155188365d17SBharat Bhushan 155288365d17SBharat Bhushan return -1; 155388365d17SBharat Bhushan } 155488365d17SBharat Bhushan 155588365d17SBharat Bhushan int kvm_arch_insert_hw_breakpoint(target_ulong addr, 155688365d17SBharat Bhushan target_ulong len, int type) 155788365d17SBharat Bhushan { 155888365d17SBharat Bhushan if ((nb_hw_breakpoint + nb_hw_watchpoint) >= ARRAY_SIZE(hw_debug_points)) { 155988365d17SBharat Bhushan return -ENOBUFS; 156088365d17SBharat Bhushan } 156188365d17SBharat Bhushan 156288365d17SBharat Bhushan hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].addr = addr; 156388365d17SBharat Bhushan hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].type = type; 156488365d17SBharat Bhushan 156588365d17SBharat Bhushan switch (type) { 156688365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 156788365d17SBharat Bhushan if (nb_hw_breakpoint >= max_hw_breakpoint) { 156888365d17SBharat Bhushan return -ENOBUFS; 156988365d17SBharat Bhushan } 157088365d17SBharat Bhushan 157188365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 157288365d17SBharat Bhushan return -EEXIST; 157388365d17SBharat Bhushan } 157488365d17SBharat Bhushan 157588365d17SBharat Bhushan nb_hw_breakpoint++; 157688365d17SBharat Bhushan break; 157788365d17SBharat Bhushan 157888365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 157988365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 158088365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 158188365d17SBharat Bhushan if (nb_hw_watchpoint >= max_hw_watchpoint) { 158288365d17SBharat Bhushan return -ENOBUFS; 158388365d17SBharat Bhushan } 158488365d17SBharat Bhushan 158588365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 158688365d17SBharat Bhushan return -EEXIST; 158788365d17SBharat Bhushan } 158888365d17SBharat Bhushan 158988365d17SBharat Bhushan nb_hw_watchpoint++; 159088365d17SBharat Bhushan break; 159188365d17SBharat Bhushan 159288365d17SBharat Bhushan default: 159388365d17SBharat Bhushan return -ENOSYS; 159488365d17SBharat Bhushan } 159588365d17SBharat Bhushan 159688365d17SBharat Bhushan return 0; 159788365d17SBharat Bhushan } 159888365d17SBharat Bhushan 159988365d17SBharat Bhushan int kvm_arch_remove_hw_breakpoint(target_ulong addr, 160088365d17SBharat Bhushan target_ulong len, int type) 160188365d17SBharat Bhushan { 160288365d17SBharat Bhushan int n; 160388365d17SBharat Bhushan 160488365d17SBharat Bhushan n = find_hw_breakpoint(addr, type); 160588365d17SBharat Bhushan if (n < 0) { 160688365d17SBharat Bhushan return -ENOENT; 160788365d17SBharat Bhushan } 160888365d17SBharat Bhushan 160988365d17SBharat Bhushan switch (type) { 161088365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 161188365d17SBharat Bhushan nb_hw_breakpoint--; 161288365d17SBharat Bhushan break; 161388365d17SBharat Bhushan 161488365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 161588365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 161688365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 161788365d17SBharat Bhushan nb_hw_watchpoint--; 161888365d17SBharat Bhushan break; 161988365d17SBharat Bhushan 162088365d17SBharat Bhushan default: 162188365d17SBharat Bhushan return -ENOSYS; 162288365d17SBharat Bhushan } 162388365d17SBharat Bhushan hw_debug_points[n] = hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint]; 162488365d17SBharat Bhushan 162588365d17SBharat Bhushan return 0; 162688365d17SBharat Bhushan } 162788365d17SBharat Bhushan 162888365d17SBharat Bhushan void kvm_arch_remove_all_hw_breakpoints(void) 162988365d17SBharat Bhushan { 163088365d17SBharat Bhushan nb_hw_breakpoint = nb_hw_watchpoint = 0; 163188365d17SBharat Bhushan } 163288365d17SBharat Bhushan 16338a0548f9SBharat Bhushan void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 16348a0548f9SBharat Bhushan { 163588365d17SBharat Bhushan int n; 163688365d17SBharat Bhushan 16378a0548f9SBharat Bhushan /* Software Breakpoint updates */ 16388a0548f9SBharat Bhushan if (kvm_sw_breakpoints_active(cs)) { 16398a0548f9SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 16408a0548f9SBharat Bhushan } 164188365d17SBharat Bhushan 164288365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 164388365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 164488365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) <= ARRAY_SIZE(dbg->arch.bp)); 164588365d17SBharat Bhushan 164688365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 164788365d17SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; 164888365d17SBharat Bhushan memset(dbg->arch.bp, 0, sizeof(dbg->arch.bp)); 164988365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 165088365d17SBharat Bhushan switch (hw_debug_points[n].type) { 165188365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 165288365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_BREAKPOINT; 165388365d17SBharat Bhushan break; 165488365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 165588365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE; 165688365d17SBharat Bhushan break; 165788365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 165888365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_READ; 165988365d17SBharat Bhushan break; 166088365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 166188365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE | 166288365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_READ; 166388365d17SBharat Bhushan break; 166488365d17SBharat Bhushan default: 166588365d17SBharat Bhushan cpu_abort(cs, "Unsupported breakpoint type\n"); 166688365d17SBharat Bhushan } 166788365d17SBharat Bhushan dbg->arch.bp[n].addr = hw_debug_points[n].addr; 166888365d17SBharat Bhushan } 166988365d17SBharat Bhushan } 16708a0548f9SBharat Bhushan } 16718a0548f9SBharat Bhushan 16728a0548f9SBharat Bhushan static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) 16738a0548f9SBharat Bhushan { 16748a0548f9SBharat Bhushan CPUState *cs = CPU(cpu); 16758a0548f9SBharat Bhushan CPUPPCState *env = &cpu->env; 16768a0548f9SBharat Bhushan struct kvm_debug_exit_arch *arch_info = &run->debug.arch; 16778a0548f9SBharat Bhushan int handle = 0; 167888365d17SBharat Bhushan int n; 167988365d17SBharat Bhushan int flag = 0; 16808a0548f9SBharat Bhushan 168188365d17SBharat Bhushan if (cs->singlestep_enabled) { 168288365d17SBharat Bhushan handle = 1; 168388365d17SBharat Bhushan } else if (arch_info->status) { 168488365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 168588365d17SBharat Bhushan if (arch_info->status & KVMPPC_DEBUG_BREAKPOINT) { 168688365d17SBharat Bhushan n = find_hw_breakpoint(arch_info->address, GDB_BREAKPOINT_HW); 168788365d17SBharat Bhushan if (n >= 0) { 168888365d17SBharat Bhushan handle = 1; 168988365d17SBharat Bhushan } 169088365d17SBharat Bhushan } else if (arch_info->status & (KVMPPC_DEBUG_WATCH_READ | 169188365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_WRITE)) { 169288365d17SBharat Bhushan n = find_hw_watchpoint(arch_info->address, &flag); 169388365d17SBharat Bhushan if (n >= 0) { 169488365d17SBharat Bhushan handle = 1; 169588365d17SBharat Bhushan cs->watchpoint_hit = &hw_watchpoint; 169688365d17SBharat Bhushan hw_watchpoint.vaddr = hw_debug_points[n].addr; 169788365d17SBharat Bhushan hw_watchpoint.flags = flag; 169888365d17SBharat Bhushan } 169988365d17SBharat Bhushan } 170088365d17SBharat Bhushan } 170188365d17SBharat Bhushan } else if (kvm_find_sw_breakpoint(cs, arch_info->address)) { 17028a0548f9SBharat Bhushan handle = 1; 17038a0548f9SBharat Bhushan } else { 17048a0548f9SBharat Bhushan /* QEMU is not able to handle debug exception, so inject 17058a0548f9SBharat Bhushan * program exception to guest; 17068a0548f9SBharat Bhushan * Yes program exception NOT debug exception !! 170788365d17SBharat Bhushan * When QEMU is using debug resources then debug exception must 170888365d17SBharat Bhushan * be always set. To achieve this we set MSR_DE and also set 170988365d17SBharat Bhushan * MSRP_DEP so guest cannot change MSR_DE. 171088365d17SBharat Bhushan * When emulating debug resource for guest we want guest 171188365d17SBharat Bhushan * to control MSR_DE (enable/disable debug interrupt on need). 171288365d17SBharat Bhushan * Supporting both configurations are NOT possible. 171388365d17SBharat Bhushan * So the result is that we cannot share debug resources 171488365d17SBharat Bhushan * between QEMU and Guest on BOOKE architecture. 171588365d17SBharat Bhushan * In the current design QEMU gets the priority over guest, 171688365d17SBharat Bhushan * this means that if QEMU is using debug resources then guest 171788365d17SBharat Bhushan * cannot use them; 17188a0548f9SBharat Bhushan * For software breakpoint QEMU uses a privileged instruction; 17198a0548f9SBharat Bhushan * So there cannot be any reason that we are here for guest 17208a0548f9SBharat Bhushan * set debug exception, only possibility is guest executed a 17218a0548f9SBharat Bhushan * privileged / illegal instruction and that's why we are 17228a0548f9SBharat Bhushan * injecting a program interrupt. 17238a0548f9SBharat Bhushan */ 17248a0548f9SBharat Bhushan 17258a0548f9SBharat Bhushan cpu_synchronize_state(cs); 17268a0548f9SBharat Bhushan /* env->nip is PC, so increment this by 4 to use 17278a0548f9SBharat Bhushan * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4. 17288a0548f9SBharat Bhushan */ 17298a0548f9SBharat Bhushan env->nip += 4; 17308a0548f9SBharat Bhushan cs->exception_index = POWERPC_EXCP_PROGRAM; 17318a0548f9SBharat Bhushan env->error_code = POWERPC_EXCP_INVAL; 17328a0548f9SBharat Bhushan ppc_cpu_do_interrupt(cs); 17338a0548f9SBharat Bhushan } 17348a0548f9SBharat Bhushan 17358a0548f9SBharat Bhushan return handle; 17368a0548f9SBharat Bhushan } 17378a0548f9SBharat Bhushan 173820d695a9SAndreas Färber int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 1739d76d1650Saurel32 { 174020d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 174120d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1742bb4ea393SJan Kiszka int ret; 1743d76d1650Saurel32 17444b8523eeSJan Kiszka qemu_mutex_lock_iothread(); 17454b8523eeSJan Kiszka 1746d76d1650Saurel32 switch (run->exit_reason) { 1747d76d1650Saurel32 case KVM_EXIT_DCR: 1748d76d1650Saurel32 if (run->dcr.is_write) { 1749da56ff91SPeter Maydell DPRINTF("handle dcr write\n"); 1750d76d1650Saurel32 ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); 1751d76d1650Saurel32 } else { 1752da56ff91SPeter Maydell DPRINTF("handle dcr read\n"); 1753d76d1650Saurel32 ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); 1754d76d1650Saurel32 } 1755d76d1650Saurel32 break; 1756d76d1650Saurel32 case KVM_EXIT_HLT: 1757da56ff91SPeter Maydell DPRINTF("handle halt\n"); 1758259186a7SAndreas Färber ret = kvmppc_handle_halt(cpu); 1759d76d1650Saurel32 break; 1760c6304a4aSDavid Gibson #if defined(TARGET_PPC64) 1761f61b4bedSAlexander Graf case KVM_EXIT_PAPR_HCALL: 1762da56ff91SPeter Maydell DPRINTF("handle PAPR hypercall\n"); 176320d695a9SAndreas Färber run->papr_hcall.ret = spapr_hypercall(cpu, 1764aa100fa4SAndreas Färber run->papr_hcall.nr, 1765f61b4bedSAlexander Graf run->papr_hcall.args); 176678e8fde2SDavid Gibson ret = 0; 1767f61b4bedSAlexander Graf break; 1768f61b4bedSAlexander Graf #endif 17695b95b8b9SAlexander Graf case KVM_EXIT_EPR: 1770da56ff91SPeter Maydell DPRINTF("handle epr\n"); 1771933b19eaSAlexander Graf run->epr.epr = ldl_phys(cs->as, env->mpic_iack); 17725b95b8b9SAlexander Graf ret = 0; 17735b95b8b9SAlexander Graf break; 177431f2cb8fSBharat Bhushan case KVM_EXIT_WATCHDOG: 1775da56ff91SPeter Maydell DPRINTF("handle watchdog expiry\n"); 177631f2cb8fSBharat Bhushan watchdog_perform_action(); 177731f2cb8fSBharat Bhushan ret = 0; 177831f2cb8fSBharat Bhushan break; 177931f2cb8fSBharat Bhushan 17808a0548f9SBharat Bhushan case KVM_EXIT_DEBUG: 17818a0548f9SBharat Bhushan DPRINTF("handle debug exception\n"); 17828a0548f9SBharat Bhushan if (kvm_handle_debug(cpu, run)) { 17838a0548f9SBharat Bhushan ret = EXCP_DEBUG; 17848a0548f9SBharat Bhushan break; 17858a0548f9SBharat Bhushan } 17868a0548f9SBharat Bhushan /* re-enter, this exception was guest-internal */ 17878a0548f9SBharat Bhushan ret = 0; 17888a0548f9SBharat Bhushan break; 17898a0548f9SBharat Bhushan 179073aaec4aSJan Kiszka default: 179173aaec4aSJan Kiszka fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); 179273aaec4aSJan Kiszka ret = -1; 179373aaec4aSJan Kiszka break; 1794d76d1650Saurel32 } 1795d76d1650Saurel32 17964b8523eeSJan Kiszka qemu_mutex_unlock_iothread(); 1797d76d1650Saurel32 return ret; 1798d76d1650Saurel32 } 1799d76d1650Saurel32 180031f2cb8fSBharat Bhushan int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 180131f2cb8fSBharat Bhushan { 180231f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 180331f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 180431f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 180531f2cb8fSBharat Bhushan .id = KVM_REG_PPC_OR_TSR, 180631f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 180731f2cb8fSBharat Bhushan }; 180831f2cb8fSBharat Bhushan 180931f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 181031f2cb8fSBharat Bhushan } 181131f2cb8fSBharat Bhushan 181231f2cb8fSBharat Bhushan int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 181331f2cb8fSBharat Bhushan { 181431f2cb8fSBharat Bhushan 181531f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 181631f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 181731f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 181831f2cb8fSBharat Bhushan .id = KVM_REG_PPC_CLEAR_TSR, 181931f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 182031f2cb8fSBharat Bhushan }; 182131f2cb8fSBharat Bhushan 182231f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 182331f2cb8fSBharat Bhushan } 182431f2cb8fSBharat Bhushan 182531f2cb8fSBharat Bhushan int kvmppc_set_tcr(PowerPCCPU *cpu) 182631f2cb8fSBharat Bhushan { 182731f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 182831f2cb8fSBharat Bhushan CPUPPCState *env = &cpu->env; 182931f2cb8fSBharat Bhushan uint32_t tcr = env->spr[SPR_BOOKE_TCR]; 183031f2cb8fSBharat Bhushan 183131f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 183231f2cb8fSBharat Bhushan .id = KVM_REG_PPC_TCR, 183331f2cb8fSBharat Bhushan .addr = (uintptr_t) &tcr, 183431f2cb8fSBharat Bhushan }; 183531f2cb8fSBharat Bhushan 183631f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 183731f2cb8fSBharat Bhushan } 183831f2cb8fSBharat Bhushan 183931f2cb8fSBharat Bhushan int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu) 184031f2cb8fSBharat Bhushan { 184131f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 184231f2cb8fSBharat Bhushan int ret; 184331f2cb8fSBharat Bhushan 184431f2cb8fSBharat Bhushan if (!kvm_enabled()) { 184531f2cb8fSBharat Bhushan return -1; 184631f2cb8fSBharat Bhushan } 184731f2cb8fSBharat Bhushan 184831f2cb8fSBharat Bhushan if (!cap_ppc_watchdog) { 184931f2cb8fSBharat Bhushan printf("warning: KVM does not support watchdog"); 185031f2cb8fSBharat Bhushan return -1; 185131f2cb8fSBharat Bhushan } 185231f2cb8fSBharat Bhushan 185348add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_BOOKE_WATCHDOG, 0); 185431f2cb8fSBharat Bhushan if (ret < 0) { 185531f2cb8fSBharat Bhushan fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n", 185631f2cb8fSBharat Bhushan __func__, strerror(-ret)); 185731f2cb8fSBharat Bhushan return ret; 185831f2cb8fSBharat Bhushan } 185931f2cb8fSBharat Bhushan 186031f2cb8fSBharat Bhushan return ret; 186131f2cb8fSBharat Bhushan } 186231f2cb8fSBharat Bhushan 1863dc333cd6SAlexander Graf static int read_cpuinfo(const char *field, char *value, int len) 1864dc333cd6SAlexander Graf { 1865dc333cd6SAlexander Graf FILE *f; 1866dc333cd6SAlexander Graf int ret = -1; 1867dc333cd6SAlexander Graf int field_len = strlen(field); 1868dc333cd6SAlexander Graf char line[512]; 1869dc333cd6SAlexander Graf 1870dc333cd6SAlexander Graf f = fopen("/proc/cpuinfo", "r"); 1871dc333cd6SAlexander Graf if (!f) { 1872dc333cd6SAlexander Graf return -1; 1873dc333cd6SAlexander Graf } 1874dc333cd6SAlexander Graf 1875dc333cd6SAlexander Graf do { 1876dc333cd6SAlexander Graf if (!fgets(line, sizeof(line), f)) { 1877dc333cd6SAlexander Graf break; 1878dc333cd6SAlexander Graf } 1879dc333cd6SAlexander Graf if (!strncmp(line, field, field_len)) { 1880ae215068SJim Meyering pstrcpy(value, len, line); 1881dc333cd6SAlexander Graf ret = 0; 1882dc333cd6SAlexander Graf break; 1883dc333cd6SAlexander Graf } 1884dc333cd6SAlexander Graf } while(*line); 1885dc333cd6SAlexander Graf 1886dc333cd6SAlexander Graf fclose(f); 1887dc333cd6SAlexander Graf 1888dc333cd6SAlexander Graf return ret; 1889dc333cd6SAlexander Graf } 1890dc333cd6SAlexander Graf 1891dc333cd6SAlexander Graf uint32_t kvmppc_get_tbfreq(void) 1892dc333cd6SAlexander Graf { 1893dc333cd6SAlexander Graf char line[512]; 1894dc333cd6SAlexander Graf char *ns; 189573bcb24dSRutuja Shah uint32_t retval = NANOSECONDS_PER_SECOND; 1896dc333cd6SAlexander Graf 1897dc333cd6SAlexander Graf if (read_cpuinfo("timebase", line, sizeof(line))) { 1898dc333cd6SAlexander Graf return retval; 1899dc333cd6SAlexander Graf } 1900dc333cd6SAlexander Graf 1901dc333cd6SAlexander Graf if (!(ns = strchr(line, ':'))) { 1902dc333cd6SAlexander Graf return retval; 1903dc333cd6SAlexander Graf } 1904dc333cd6SAlexander Graf 1905dc333cd6SAlexander Graf ns++; 1906dc333cd6SAlexander Graf 1907f9b8e7f6SShraddha Barke return atoi(ns); 1908ef951443SNikunj A Dadhania } 1909ef951443SNikunj A Dadhania 1910ef951443SNikunj A Dadhania bool kvmppc_get_host_serial(char **value) 1911ef951443SNikunj A Dadhania { 1912ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/system-id", value, NULL, 1913ef951443SNikunj A Dadhania NULL); 1914ef951443SNikunj A Dadhania } 1915ef951443SNikunj A Dadhania 1916ef951443SNikunj A Dadhania bool kvmppc_get_host_model(char **value) 1917ef951443SNikunj A Dadhania { 1918ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/model", value, NULL, NULL); 1919dc333cd6SAlexander Graf } 19204513d923SGleb Natapov 1921eadaada1SAlexander Graf /* Try to find a device tree node for a CPU with clock-frequency property */ 1922eadaada1SAlexander Graf static int kvmppc_find_cpu_dt(char *buf, int buf_len) 1923eadaada1SAlexander Graf { 1924eadaada1SAlexander Graf struct dirent *dirp; 1925eadaada1SAlexander Graf DIR *dp; 1926eadaada1SAlexander Graf 1927eadaada1SAlexander Graf if ((dp = opendir(PROC_DEVTREE_CPU)) == NULL) { 1928eadaada1SAlexander Graf printf("Can't open directory " PROC_DEVTREE_CPU "\n"); 1929eadaada1SAlexander Graf return -1; 1930eadaada1SAlexander Graf } 1931eadaada1SAlexander Graf 1932eadaada1SAlexander Graf buf[0] = '\0'; 1933eadaada1SAlexander Graf while ((dirp = readdir(dp)) != NULL) { 1934eadaada1SAlexander Graf FILE *f; 1935eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s/clock-frequency", PROC_DEVTREE_CPU, 1936eadaada1SAlexander Graf dirp->d_name); 1937eadaada1SAlexander Graf f = fopen(buf, "r"); 1938eadaada1SAlexander Graf if (f) { 1939eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s", PROC_DEVTREE_CPU, dirp->d_name); 1940eadaada1SAlexander Graf fclose(f); 1941eadaada1SAlexander Graf break; 1942eadaada1SAlexander Graf } 1943eadaada1SAlexander Graf buf[0] = '\0'; 1944eadaada1SAlexander Graf } 1945eadaada1SAlexander Graf closedir(dp); 1946eadaada1SAlexander Graf if (buf[0] == '\0') { 1947eadaada1SAlexander Graf printf("Unknown host!\n"); 1948eadaada1SAlexander Graf return -1; 1949eadaada1SAlexander Graf } 1950eadaada1SAlexander Graf 1951eadaada1SAlexander Graf return 0; 1952eadaada1SAlexander Graf } 1953eadaada1SAlexander Graf 19547d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_dt(const char *filename) 1955eadaada1SAlexander Graf { 19569bc884b7SDavid Gibson union { 19579bc884b7SDavid Gibson uint32_t v32; 19589bc884b7SDavid Gibson uint64_t v64; 19599bc884b7SDavid Gibson } u; 1960eadaada1SAlexander Graf FILE *f; 1961eadaada1SAlexander Graf int len; 1962eadaada1SAlexander Graf 19637d94a30bSSukadev Bhattiprolu f = fopen(filename, "rb"); 1964eadaada1SAlexander Graf if (!f) { 1965eadaada1SAlexander Graf return -1; 1966eadaada1SAlexander Graf } 1967eadaada1SAlexander Graf 19689bc884b7SDavid Gibson len = fread(&u, 1, sizeof(u), f); 1969eadaada1SAlexander Graf fclose(f); 1970eadaada1SAlexander Graf switch (len) { 19719bc884b7SDavid Gibson case 4: 19729bc884b7SDavid Gibson /* property is a 32-bit quantity */ 19739bc884b7SDavid Gibson return be32_to_cpu(u.v32); 19749bc884b7SDavid Gibson case 8: 19759bc884b7SDavid Gibson return be64_to_cpu(u.v64); 1976eadaada1SAlexander Graf } 1977eadaada1SAlexander Graf 1978eadaada1SAlexander Graf return 0; 1979eadaada1SAlexander Graf } 1980eadaada1SAlexander Graf 19817d94a30bSSukadev Bhattiprolu /* Read a CPU node property from the host device tree that's a single 19827d94a30bSSukadev Bhattiprolu * integer (32-bit or 64-bit). Returns 0 if anything goes wrong 19837d94a30bSSukadev Bhattiprolu * (can't find or open the property, or doesn't understand the 19847d94a30bSSukadev Bhattiprolu * format) */ 19857d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_cpu_dt(const char *propname) 19867d94a30bSSukadev Bhattiprolu { 19877d94a30bSSukadev Bhattiprolu char buf[PATH_MAX], *tmp; 19887d94a30bSSukadev Bhattiprolu uint64_t val; 19897d94a30bSSukadev Bhattiprolu 19907d94a30bSSukadev Bhattiprolu if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { 19917d94a30bSSukadev Bhattiprolu return -1; 19927d94a30bSSukadev Bhattiprolu } 19937d94a30bSSukadev Bhattiprolu 19947d94a30bSSukadev Bhattiprolu tmp = g_strdup_printf("%s/%s", buf, propname); 19957d94a30bSSukadev Bhattiprolu val = kvmppc_read_int_dt(tmp); 19967d94a30bSSukadev Bhattiprolu g_free(tmp); 19977d94a30bSSukadev Bhattiprolu 19987d94a30bSSukadev Bhattiprolu return val; 19997d94a30bSSukadev Bhattiprolu } 20007d94a30bSSukadev Bhattiprolu 20019bc884b7SDavid Gibson uint64_t kvmppc_get_clockfreq(void) 20029bc884b7SDavid Gibson { 20039bc884b7SDavid Gibson return kvmppc_read_int_cpu_dt("clock-frequency"); 20049bc884b7SDavid Gibson } 20059bc884b7SDavid Gibson 20066659394fSDavid Gibson uint32_t kvmppc_get_vmx(void) 20076659394fSDavid Gibson { 20086659394fSDavid Gibson return kvmppc_read_int_cpu_dt("ibm,vmx"); 20096659394fSDavid Gibson } 20106659394fSDavid Gibson 20116659394fSDavid Gibson uint32_t kvmppc_get_dfp(void) 20126659394fSDavid Gibson { 20136659394fSDavid Gibson return kvmppc_read_int_cpu_dt("ibm,dfp"); 20146659394fSDavid Gibson } 20156659394fSDavid Gibson 20161a61a9aeSStuart Yoder static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo) 201745024f09SAlexander Graf { 2018a60f24b5SAndreas Färber PowerPCCPU *cpu = ppc_env_get_cpu(env); 2019a60f24b5SAndreas Färber CPUState *cs = CPU(cpu); 202045024f09SAlexander Graf 20216fd33a75SAlexander Graf if (kvm_vm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) && 20221a61a9aeSStuart Yoder !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) { 20231a61a9aeSStuart Yoder return 0; 20241a61a9aeSStuart Yoder } 202545024f09SAlexander Graf 20261a61a9aeSStuart Yoder return 1; 20271a61a9aeSStuart Yoder } 20281a61a9aeSStuart Yoder 20291a61a9aeSStuart Yoder int kvmppc_get_hasidle(CPUPPCState *env) 20301a61a9aeSStuart Yoder { 20311a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 20321a61a9aeSStuart Yoder 20331a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo) && 20341a61a9aeSStuart Yoder (pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) { 20351a61a9aeSStuart Yoder return 1; 20361a61a9aeSStuart Yoder } 20371a61a9aeSStuart Yoder 20381a61a9aeSStuart Yoder return 0; 20391a61a9aeSStuart Yoder } 20401a61a9aeSStuart Yoder 20411a61a9aeSStuart Yoder int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) 20421a61a9aeSStuart Yoder { 20431a61a9aeSStuart Yoder uint32_t *hc = (uint32_t*)buf; 20441a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 20451a61a9aeSStuart Yoder 20461a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo)) { 20471a61a9aeSStuart Yoder memcpy(buf, pvinfo.hcall, buf_len); 204845024f09SAlexander Graf return 0; 204945024f09SAlexander Graf } 205045024f09SAlexander Graf 205145024f09SAlexander Graf /* 2052d13fc32eSAlexander Graf * Fallback to always fail hypercalls regardless of endianness: 205345024f09SAlexander Graf * 2054d13fc32eSAlexander Graf * tdi 0,r0,72 (becomes b .+8 in wrong endian, nop in good endian) 205545024f09SAlexander Graf * li r3, -1 2056d13fc32eSAlexander Graf * b .+8 (becomes nop in wrong endian) 2057d13fc32eSAlexander Graf * bswap32(li r3, -1) 205845024f09SAlexander Graf */ 205945024f09SAlexander Graf 2060d13fc32eSAlexander Graf hc[0] = cpu_to_be32(0x08000048); 2061d13fc32eSAlexander Graf hc[1] = cpu_to_be32(0x3860ffff); 2062d13fc32eSAlexander Graf hc[2] = cpu_to_be32(0x48000008); 2063d13fc32eSAlexander Graf hc[3] = cpu_to_be32(bswap32(0x3860ffff)); 206445024f09SAlexander Graf 20650ddbd053SAlexey Kardashevskiy return 1; 206645024f09SAlexander Graf } 206745024f09SAlexander Graf 2068026bfd89SDavid Gibson static inline int kvmppc_enable_hcall(KVMState *s, target_ulong hcall) 2069026bfd89SDavid Gibson { 2070026bfd89SDavid Gibson return kvm_vm_enable_cap(s, KVM_CAP_PPC_ENABLE_HCALL, 0, hcall, 1); 2071026bfd89SDavid Gibson } 2072026bfd89SDavid Gibson 2073026bfd89SDavid Gibson void kvmppc_enable_logical_ci_hcalls(void) 2074026bfd89SDavid Gibson { 2075026bfd89SDavid Gibson /* 2076026bfd89SDavid Gibson * FIXME: it would be nice if we could detect the cases where 2077026bfd89SDavid Gibson * we're using a device which requires the in kernel 2078026bfd89SDavid Gibson * implementation of these hcalls, but the kernel lacks them and 2079026bfd89SDavid Gibson * produce a warning. 2080026bfd89SDavid Gibson */ 2081026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_LOAD); 2082026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_STORE); 2083026bfd89SDavid Gibson } 2084026bfd89SDavid Gibson 2085ef9971ddSAlexey Kardashevskiy void kvmppc_enable_set_mode_hcall(void) 2086ef9971ddSAlexey Kardashevskiy { 2087ef9971ddSAlexey Kardashevskiy kvmppc_enable_hcall(kvm_state, H_SET_MODE); 2088ef9971ddSAlexey Kardashevskiy } 2089ef9971ddSAlexey Kardashevskiy 20905145ad4fSNathan Whitehorn void kvmppc_enable_clear_ref_mod_hcalls(void) 20915145ad4fSNathan Whitehorn { 20925145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_REF); 20935145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD); 20945145ad4fSNathan Whitehorn } 20955145ad4fSNathan Whitehorn 20961bc22652SAndreas Färber void kvmppc_set_papr(PowerPCCPU *cpu) 2097f61b4bedSAlexander Graf { 20981bc22652SAndreas Färber CPUState *cs = CPU(cpu); 2099f61b4bedSAlexander Graf int ret; 2100f61b4bedSAlexander Graf 210148add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0); 2102f61b4bedSAlexander Graf if (ret) { 2103072ed5f2SThomas Huth error_report("This vCPU type or KVM version does not support PAPR"); 2104072ed5f2SThomas Huth exit(1); 2105f61b4bedSAlexander Graf } 21069b00ea49SDavid Gibson 21079b00ea49SDavid Gibson /* Update the capability flag so we sync the right information 21089b00ea49SDavid Gibson * with kvm */ 21099b00ea49SDavid Gibson cap_papr = 1; 2110f1af19d7SDavid Gibson } 2111f61b4bedSAlexander Graf 2112d6e166c0SDavid Gibson int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr) 21136db5bb0fSAlexey Kardashevskiy { 2114d6e166c0SDavid Gibson return kvm_set_one_reg(CPU(cpu), KVM_REG_PPC_ARCH_COMPAT, &compat_pvr); 21156db5bb0fSAlexey Kardashevskiy } 21166db5bb0fSAlexey Kardashevskiy 21175b95b8b9SAlexander Graf void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy) 21185b95b8b9SAlexander Graf { 21195b95b8b9SAlexander Graf CPUState *cs = CPU(cpu); 21205b95b8b9SAlexander Graf int ret; 21215b95b8b9SAlexander Graf 212248add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_EPR, 0, mpic_proxy); 21235b95b8b9SAlexander Graf if (ret && mpic_proxy) { 2124072ed5f2SThomas Huth error_report("This KVM version does not support EPR"); 2125072ed5f2SThomas Huth exit(1); 21265b95b8b9SAlexander Graf } 21275b95b8b9SAlexander Graf } 21285b95b8b9SAlexander Graf 2129e97c3636SDavid Gibson int kvmppc_smt_threads(void) 2130e97c3636SDavid Gibson { 2131e97c3636SDavid Gibson return cap_ppc_smt ? cap_ppc_smt : 1; 2132e97c3636SDavid Gibson } 2133e97c3636SDavid Gibson 21347f763a5dSDavid Gibson #ifdef TARGET_PPC64 2135658fa66bSAlexey Kardashevskiy off_t kvmppc_alloc_rma(void **rma) 2136354ac20aSDavid Gibson { 2137354ac20aSDavid Gibson off_t size; 2138354ac20aSDavid Gibson int fd; 2139354ac20aSDavid Gibson struct kvm_allocate_rma ret; 2140354ac20aSDavid Gibson 2141354ac20aSDavid Gibson /* If cap_ppc_rma == 0, contiguous RMA allocation is not supported 2142354ac20aSDavid Gibson * if cap_ppc_rma == 1, contiguous RMA allocation is supported, but 2143354ac20aSDavid Gibson * not necessary on this hardware 2144354ac20aSDavid Gibson * if cap_ppc_rma == 2, contiguous RMA allocation is needed on this hardware 2145354ac20aSDavid Gibson * 2146354ac20aSDavid Gibson * FIXME: We should allow the user to force contiguous RMA 2147354ac20aSDavid Gibson * allocation in the cap_ppc_rma==1 case. 2148354ac20aSDavid Gibson */ 2149354ac20aSDavid Gibson if (cap_ppc_rma < 2) { 2150354ac20aSDavid Gibson return 0; 2151354ac20aSDavid Gibson } 2152354ac20aSDavid Gibson 2153354ac20aSDavid Gibson fd = kvm_vm_ioctl(kvm_state, KVM_ALLOCATE_RMA, &ret); 2154354ac20aSDavid Gibson if (fd < 0) { 2155354ac20aSDavid Gibson fprintf(stderr, "KVM: Error on KVM_ALLOCATE_RMA: %s\n", 2156354ac20aSDavid Gibson strerror(errno)); 2157354ac20aSDavid Gibson return -1; 2158354ac20aSDavid Gibson } 2159354ac20aSDavid Gibson 2160354ac20aSDavid Gibson size = MIN(ret.rma_size, 256ul << 20); 2161354ac20aSDavid Gibson 2162658fa66bSAlexey Kardashevskiy *rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 2163658fa66bSAlexey Kardashevskiy if (*rma == MAP_FAILED) { 2164354ac20aSDavid Gibson fprintf(stderr, "KVM: Error mapping RMA: %s\n", strerror(errno)); 2165354ac20aSDavid Gibson return -1; 2166354ac20aSDavid Gibson }; 2167354ac20aSDavid Gibson 2168354ac20aSDavid Gibson return size; 2169354ac20aSDavid Gibson } 2170354ac20aSDavid Gibson 21717f763a5dSDavid Gibson uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift) 21727f763a5dSDavid Gibson { 2173f36951c1SDavid Gibson struct kvm_ppc_smmu_info info; 2174f36951c1SDavid Gibson long rampagesize, best_page_shift; 2175f36951c1SDavid Gibson int i; 2176f36951c1SDavid Gibson 21777f763a5dSDavid Gibson if (cap_ppc_rma >= 2) { 21787f763a5dSDavid Gibson return current_size; 21797f763a5dSDavid Gibson } 2180f36951c1SDavid Gibson 2181f36951c1SDavid Gibson /* Find the largest hardware supported page size that's less than 2182f36951c1SDavid Gibson * or equal to the (logical) backing page size of guest RAM */ 2183182735efSAndreas Färber kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info); 2184f36951c1SDavid Gibson rampagesize = getrampagesize(); 2185f36951c1SDavid Gibson best_page_shift = 0; 2186f36951c1SDavid Gibson 2187f36951c1SDavid Gibson for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) { 2188f36951c1SDavid Gibson struct kvm_ppc_one_seg_page_size *sps = &info.sps[i]; 2189f36951c1SDavid Gibson 2190f36951c1SDavid Gibson if (!sps->page_shift) { 2191f36951c1SDavid Gibson continue; 2192f36951c1SDavid Gibson } 2193f36951c1SDavid Gibson 2194f36951c1SDavid Gibson if ((sps->page_shift > best_page_shift) 2195f36951c1SDavid Gibson && ((1UL << sps->page_shift) <= rampagesize)) { 2196f36951c1SDavid Gibson best_page_shift = sps->page_shift; 2197f36951c1SDavid Gibson } 2198f36951c1SDavid Gibson } 2199f36951c1SDavid Gibson 22007f763a5dSDavid Gibson return MIN(current_size, 2201f36951c1SDavid Gibson 1ULL << (best_page_shift + hash_shift - 7)); 22027f763a5dSDavid Gibson } 22037f763a5dSDavid Gibson #endif 22047f763a5dSDavid Gibson 2205da95324eSAlexey Kardashevskiy bool kvmppc_spapr_use_multitce(void) 2206da95324eSAlexey Kardashevskiy { 2207da95324eSAlexey Kardashevskiy return cap_spapr_multitce; 2208da95324eSAlexey Kardashevskiy } 2209da95324eSAlexey Kardashevskiy 22109bb62a07SAlexey Kardashevskiy void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd, 22116a81dd17SDavid Gibson bool need_vfio) 22120f5cb298SDavid Gibson { 22130f5cb298SDavid Gibson struct kvm_create_spapr_tce args = { 22140f5cb298SDavid Gibson .liobn = liobn, 22150f5cb298SDavid Gibson .window_size = window_size, 22160f5cb298SDavid Gibson }; 22170f5cb298SDavid Gibson long len; 22180f5cb298SDavid Gibson int fd; 22190f5cb298SDavid Gibson void *table; 22200f5cb298SDavid Gibson 2221b5aec396SDavid Gibson /* Must set fd to -1 so we don't try to munmap when called for 2222b5aec396SDavid Gibson * destroying the table, which the upper layers -will- do 2223b5aec396SDavid Gibson */ 2224b5aec396SDavid Gibson *pfd = -1; 22256a81dd17SDavid Gibson if (!cap_spapr_tce || (need_vfio && !cap_spapr_vfio)) { 22260f5cb298SDavid Gibson return NULL; 22270f5cb298SDavid Gibson } 22280f5cb298SDavid Gibson 22290f5cb298SDavid Gibson fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); 22300f5cb298SDavid Gibson if (fd < 0) { 2231b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", 2232b5aec396SDavid Gibson liobn); 22330f5cb298SDavid Gibson return NULL; 22340f5cb298SDavid Gibson } 22350f5cb298SDavid Gibson 2236a83000f5SAnthony Liguori len = (window_size / SPAPR_TCE_PAGE_SIZE) * sizeof(uint64_t); 22370f5cb298SDavid Gibson /* FIXME: round this up to page size */ 22380f5cb298SDavid Gibson 223974b41e56SDavid Gibson table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 22400f5cb298SDavid Gibson if (table == MAP_FAILED) { 2241b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n", 2242b5aec396SDavid Gibson liobn); 22430f5cb298SDavid Gibson close(fd); 22440f5cb298SDavid Gibson return NULL; 22450f5cb298SDavid Gibson } 22460f5cb298SDavid Gibson 22470f5cb298SDavid Gibson *pfd = fd; 22480f5cb298SDavid Gibson return table; 22490f5cb298SDavid Gibson } 22500f5cb298SDavid Gibson 2251523e7b8aSAlexey Kardashevskiy int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t nb_table) 22520f5cb298SDavid Gibson { 22530f5cb298SDavid Gibson long len; 22540f5cb298SDavid Gibson 22550f5cb298SDavid Gibson if (fd < 0) { 22560f5cb298SDavid Gibson return -1; 22570f5cb298SDavid Gibson } 22580f5cb298SDavid Gibson 2259523e7b8aSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22600f5cb298SDavid Gibson if ((munmap(table, len) < 0) || 22610f5cb298SDavid Gibson (close(fd) < 0)) { 2262b5aec396SDavid Gibson fprintf(stderr, "KVM: Unexpected error removing TCE table: %s", 2263b5aec396SDavid Gibson strerror(errno)); 22640f5cb298SDavid Gibson /* Leak the table */ 22650f5cb298SDavid Gibson } 22660f5cb298SDavid Gibson 22670f5cb298SDavid Gibson return 0; 22680f5cb298SDavid Gibson } 22690f5cb298SDavid Gibson 22707f763a5dSDavid Gibson int kvmppc_reset_htab(int shift_hint) 22717f763a5dSDavid Gibson { 22727f763a5dSDavid Gibson uint32_t shift = shift_hint; 22737f763a5dSDavid Gibson 2274ace9a2cbSDavid Gibson if (!kvm_enabled()) { 2275ace9a2cbSDavid Gibson /* Full emulation, tell caller to allocate htab itself */ 2276ace9a2cbSDavid Gibson return 0; 2277ace9a2cbSDavid Gibson } 2278ace9a2cbSDavid Gibson if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { 22797f763a5dSDavid Gibson int ret; 22807f763a5dSDavid Gibson ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift); 2281ace9a2cbSDavid Gibson if (ret == -ENOTTY) { 2282ace9a2cbSDavid Gibson /* At least some versions of PR KVM advertise the 2283ace9a2cbSDavid Gibson * capability, but don't implement the ioctl(). Oops. 2284ace9a2cbSDavid Gibson * Return 0 so that we allocate the htab in qemu, as is 2285ace9a2cbSDavid Gibson * correct for PR. */ 2286ace9a2cbSDavid Gibson return 0; 2287ace9a2cbSDavid Gibson } else if (ret < 0) { 22887f763a5dSDavid Gibson return ret; 22897f763a5dSDavid Gibson } 22907f763a5dSDavid Gibson return shift; 22917f763a5dSDavid Gibson } 22927f763a5dSDavid Gibson 2293ace9a2cbSDavid Gibson /* We have a kernel that predates the htab reset calls. For PR 2294ace9a2cbSDavid Gibson * KVM, we need to allocate the htab ourselves, for an HV KVM of 229596c9cff0SThomas Huth * this era, it has allocated a 16MB fixed size hash table already. */ 229696c9cff0SThomas Huth if (kvmppc_is_pr(kvm_state)) { 2297ace9a2cbSDavid Gibson /* PR - tell caller to allocate htab */ 22987f763a5dSDavid Gibson return 0; 2299ace9a2cbSDavid Gibson } else { 2300ace9a2cbSDavid Gibson /* HV - assume 16MB kernel allocated htab */ 2301ace9a2cbSDavid Gibson return 24; 2302ace9a2cbSDavid Gibson } 23037f763a5dSDavid Gibson } 23047f763a5dSDavid Gibson 2305a1e98583SDavid Gibson static inline uint32_t mfpvr(void) 2306a1e98583SDavid Gibson { 2307a1e98583SDavid Gibson uint32_t pvr; 2308a1e98583SDavid Gibson 2309a1e98583SDavid Gibson asm ("mfpvr %0" 2310a1e98583SDavid Gibson : "=r"(pvr)); 2311a1e98583SDavid Gibson return pvr; 2312a1e98583SDavid Gibson } 2313a1e98583SDavid Gibson 2314a7342588SDavid Gibson static void alter_insns(uint64_t *word, uint64_t flags, bool on) 2315a7342588SDavid Gibson { 2316a7342588SDavid Gibson if (on) { 2317a7342588SDavid Gibson *word |= flags; 2318a7342588SDavid Gibson } else { 2319a7342588SDavid Gibson *word &= ~flags; 2320a7342588SDavid Gibson } 2321a7342588SDavid Gibson } 2322a7342588SDavid Gibson 23232985b86bSAndreas Färber static void kvmppc_host_cpu_initfn(Object *obj) 2324a1e98583SDavid Gibson { 23252985b86bSAndreas Färber assert(kvm_enabled()); 23262985b86bSAndreas Färber } 23272985b86bSAndreas Färber 23282985b86bSAndreas Färber static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) 23292985b86bSAndreas Färber { 23304c315c27SMarkus Armbruster DeviceClass *dc = DEVICE_CLASS(oc); 23312985b86bSAndreas Färber PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); 2332a7342588SDavid Gibson uint32_t vmx = kvmppc_get_vmx(); 2333a7342588SDavid Gibson uint32_t dfp = kvmppc_get_dfp(); 23340cbad81fSDavid Gibson uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size"); 23350cbad81fSDavid Gibson uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); 2336a1e98583SDavid Gibson 2337cfe34f44SAndreas Färber /* Now fix up the class with information we can query from the host */ 23383bc9ccc0SAlexey Kardashevskiy pcc->pvr = mfpvr(); 2339a7342588SDavid Gibson 234070bca53fSAlexander Graf if (vmx != -1) { 234170bca53fSAlexander Graf /* Only override when we know what the host supports */ 2342cfe34f44SAndreas Färber alter_insns(&pcc->insns_flags, PPC_ALTIVEC, vmx > 0); 2343cfe34f44SAndreas Färber alter_insns(&pcc->insns_flags2, PPC2_VSX, vmx > 1); 234470bca53fSAlexander Graf } 234570bca53fSAlexander Graf if (dfp != -1) { 234670bca53fSAlexander Graf /* Only override when we know what the host supports */ 2347cfe34f44SAndreas Färber alter_insns(&pcc->insns_flags2, PPC2_DFP, dfp); 234870bca53fSAlexander Graf } 23490cbad81fSDavid Gibson 23500cbad81fSDavid Gibson if (dcache_size != -1) { 23510cbad81fSDavid Gibson pcc->l1_dcache_size = dcache_size; 23520cbad81fSDavid Gibson } 23530cbad81fSDavid Gibson 23540cbad81fSDavid Gibson if (icache_size != -1) { 23550cbad81fSDavid Gibson pcc->l1_icache_size = icache_size; 23560cbad81fSDavid Gibson } 23574c315c27SMarkus Armbruster 23584c315c27SMarkus Armbruster /* Reason: kvmppc_host_cpu_initfn() dies when !kvm_enabled() */ 23594c315c27SMarkus Armbruster dc->cannot_destroy_with_object_finalize_yet = true; 2360a1e98583SDavid Gibson } 2361a1e98583SDavid Gibson 23623b961124SStuart Yoder bool kvmppc_has_cap_epr(void) 23633b961124SStuart Yoder { 23643b961124SStuart Yoder return cap_epr; 23653b961124SStuart Yoder } 23663b961124SStuart Yoder 23677c43bca0SAneesh Kumar K.V bool kvmppc_has_cap_htab_fd(void) 23687c43bca0SAneesh Kumar K.V { 23697c43bca0SAneesh Kumar K.V return cap_htab_fd; 23707c43bca0SAneesh Kumar K.V } 23717c43bca0SAneesh Kumar K.V 237287a91de6SAlexander Graf bool kvmppc_has_cap_fixup_hcalls(void) 237387a91de6SAlexander Graf { 237487a91de6SAlexander Graf return cap_fixup_hcalls; 237587a91de6SAlexander Graf } 237687a91de6SAlexander Graf 2377bac3bf28SThomas Huth bool kvmppc_has_cap_htm(void) 2378bac3bf28SThomas Huth { 2379bac3bf28SThomas Huth return cap_htm; 2380bac3bf28SThomas Huth } 2381bac3bf28SThomas Huth 23825b79b1caSAlexey Kardashevskiy static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) 23835b79b1caSAlexey Kardashevskiy { 23845b79b1caSAlexey Kardashevskiy ObjectClass *oc = OBJECT_CLASS(pcc); 23855b79b1caSAlexey Kardashevskiy 23865b79b1caSAlexey Kardashevskiy while (oc && !object_class_is_abstract(oc)) { 23875b79b1caSAlexey Kardashevskiy oc = object_class_get_parent(oc); 23885b79b1caSAlexey Kardashevskiy } 23895b79b1caSAlexey Kardashevskiy assert(oc); 23905b79b1caSAlexey Kardashevskiy 23915b79b1caSAlexey Kardashevskiy return POWERPC_CPU_CLASS(oc); 23925b79b1caSAlexey Kardashevskiy } 23935b79b1caSAlexey Kardashevskiy 239452b2519cSThomas Huth PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) 239552b2519cSThomas Huth { 239652b2519cSThomas Huth uint32_t host_pvr = mfpvr(); 239752b2519cSThomas Huth PowerPCCPUClass *pvr_pcc; 239852b2519cSThomas Huth 239952b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr(host_pvr); 240052b2519cSThomas Huth if (pvr_pcc == NULL) { 240152b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr); 240252b2519cSThomas Huth } 240352b2519cSThomas Huth 240452b2519cSThomas Huth return pvr_pcc; 240552b2519cSThomas Huth } 240652b2519cSThomas Huth 24075ba4576bSAndreas Färber static int kvm_ppc_register_host_cpu_type(void) 24085ba4576bSAndreas Färber { 24095ba4576bSAndreas Färber TypeInfo type_info = { 24105ba4576bSAndreas Färber .name = TYPE_HOST_POWERPC_CPU, 24115ba4576bSAndreas Färber .instance_init = kvmppc_host_cpu_initfn, 24125ba4576bSAndreas Färber .class_init = kvmppc_host_cpu_class_init, 24135ba4576bSAndreas Färber }; 24145ba4576bSAndreas Färber PowerPCCPUClass *pvr_pcc; 24155b79b1caSAlexey Kardashevskiy DeviceClass *dc; 2416*715d4b96SThomas Huth int i; 24175ba4576bSAndreas Färber 241852b2519cSThomas Huth pvr_pcc = kvm_ppc_get_host_cpu_class(); 24193bc9ccc0SAlexey Kardashevskiy if (pvr_pcc == NULL) { 24205ba4576bSAndreas Färber return -1; 24215ba4576bSAndreas Färber } 24225ba4576bSAndreas Färber type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); 24235ba4576bSAndreas Färber type_register(&type_info); 24245b79b1caSAlexey Kardashevskiy 24253b542549SBharata B Rao #if defined(TARGET_PPC64) 24263b542549SBharata B Rao type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host"); 24273b542549SBharata B Rao type_info.parent = TYPE_SPAPR_CPU_CORE, 24287ebaf795SBharata B Rao type_info.instance_size = sizeof(sPAPRCPUCore); 24297ebaf795SBharata B Rao type_info.instance_init = NULL; 24307ebaf795SBharata B Rao type_info.class_init = spapr_cpu_core_class_init; 24317ebaf795SBharata B Rao type_info.class_data = (void *) "host"; 24323b542549SBharata B Rao type_register(&type_info); 24333b542549SBharata B Rao g_free((void *)type_info.name); 24343b542549SBharata B Rao #endif 24353b542549SBharata B Rao 2436*715d4b96SThomas Huth /* 2437*715d4b96SThomas Huth * Update generic CPU family class alias (e.g. on a POWER8NVL host, 2438*715d4b96SThomas Huth * we want "POWER8" to be a "family" alias that points to the current 2439*715d4b96SThomas Huth * host CPU type, too) 2440*715d4b96SThomas Huth */ 2441*715d4b96SThomas Huth dc = DEVICE_CLASS(ppc_cpu_get_family_class(pvr_pcc)); 2442*715d4b96SThomas Huth for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { 2443*715d4b96SThomas Huth if (strcmp(ppc_cpu_aliases[i].alias, dc->desc) == 0) { 2444*715d4b96SThomas Huth ObjectClass *oc = OBJECT_CLASS(pvr_pcc); 2445*715d4b96SThomas Huth char *suffix; 2446*715d4b96SThomas Huth 2447*715d4b96SThomas Huth ppc_cpu_aliases[i].model = g_strdup(object_class_get_name(oc)); 2448*715d4b96SThomas Huth suffix = strstr(ppc_cpu_aliases[i].model, "-"TYPE_POWERPC_CPU); 2449*715d4b96SThomas Huth if (suffix) { 2450*715d4b96SThomas Huth *suffix = 0; 2451*715d4b96SThomas Huth } 2452*715d4b96SThomas Huth ppc_cpu_aliases[i].oc = oc; 2453*715d4b96SThomas Huth break; 2454*715d4b96SThomas Huth } 2455*715d4b96SThomas Huth } 2456*715d4b96SThomas Huth 24575ba4576bSAndreas Färber return 0; 24585ba4576bSAndreas Färber } 24595ba4576bSAndreas Färber 2460feaa64c4SDavid Gibson int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function) 2461feaa64c4SDavid Gibson { 2462feaa64c4SDavid Gibson struct kvm_rtas_token_args args = { 2463feaa64c4SDavid Gibson .token = token, 2464feaa64c4SDavid Gibson }; 2465feaa64c4SDavid Gibson 2466feaa64c4SDavid Gibson if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_RTAS)) { 2467feaa64c4SDavid Gibson return -ENOENT; 2468feaa64c4SDavid Gibson } 2469feaa64c4SDavid Gibson 2470feaa64c4SDavid Gibson strncpy(args.name, function, sizeof(args.name)); 2471feaa64c4SDavid Gibson 2472feaa64c4SDavid Gibson return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args); 2473feaa64c4SDavid Gibson } 247412b1143bSDavid Gibson 2475e68cb8b4SAlexey Kardashevskiy int kvmppc_get_htab_fd(bool write) 2476e68cb8b4SAlexey Kardashevskiy { 2477e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_fd s = { 2478e68cb8b4SAlexey Kardashevskiy .flags = write ? KVM_GET_HTAB_WRITE : 0, 2479e68cb8b4SAlexey Kardashevskiy .start_index = 0, 2480e68cb8b4SAlexey Kardashevskiy }; 2481e68cb8b4SAlexey Kardashevskiy 2482e68cb8b4SAlexey Kardashevskiy if (!cap_htab_fd) { 2483e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "KVM version doesn't support saving the hash table\n"); 2484e68cb8b4SAlexey Kardashevskiy return -1; 2485e68cb8b4SAlexey Kardashevskiy } 2486e68cb8b4SAlexey Kardashevskiy 2487e68cb8b4SAlexey Kardashevskiy return kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s); 2488e68cb8b4SAlexey Kardashevskiy } 2489e68cb8b4SAlexey Kardashevskiy 2490e68cb8b4SAlexey Kardashevskiy int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) 2491e68cb8b4SAlexey Kardashevskiy { 2492bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 2493e68cb8b4SAlexey Kardashevskiy uint8_t buf[bufsize]; 2494e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2495e68cb8b4SAlexey Kardashevskiy 2496e68cb8b4SAlexey Kardashevskiy do { 2497e68cb8b4SAlexey Kardashevskiy rc = read(fd, buf, bufsize); 2498e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2499e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error reading data from KVM HTAB fd: %s\n", 2500e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2501e68cb8b4SAlexey Kardashevskiy return rc; 2502e68cb8b4SAlexey Kardashevskiy } else if (rc) { 2503e094c4c1SCédric Le Goater uint8_t *buffer = buf; 2504e094c4c1SCédric Le Goater ssize_t n = rc; 2505e094c4c1SCédric Le Goater while (n) { 2506e094c4c1SCédric Le Goater struct kvm_get_htab_header *head = 2507e094c4c1SCédric Le Goater (struct kvm_get_htab_header *) buffer; 2508e094c4c1SCédric Le Goater size_t chunksize = sizeof(*head) + 2509e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid; 2510e094c4c1SCédric Le Goater 2511e094c4c1SCédric Le Goater qemu_put_be32(f, head->index); 2512e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_valid); 2513e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_invalid); 2514e094c4c1SCédric Le Goater qemu_put_buffer(f, (void *)(head + 1), 2515e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid); 2516e094c4c1SCédric Le Goater 2517e094c4c1SCédric Le Goater buffer += chunksize; 2518e094c4c1SCédric Le Goater n -= chunksize; 2519e094c4c1SCédric Le Goater } 2520e68cb8b4SAlexey Kardashevskiy } 2521e68cb8b4SAlexey Kardashevskiy } while ((rc != 0) 2522e68cb8b4SAlexey Kardashevskiy && ((max_ns < 0) 2523bc72ad67SAlex Bligh || ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns))); 2524e68cb8b4SAlexey Kardashevskiy 2525e68cb8b4SAlexey Kardashevskiy return (rc == 0) ? 1 : 0; 2526e68cb8b4SAlexey Kardashevskiy } 2527e68cb8b4SAlexey Kardashevskiy 2528e68cb8b4SAlexey Kardashevskiy int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, 2529e68cb8b4SAlexey Kardashevskiy uint16_t n_valid, uint16_t n_invalid) 2530e68cb8b4SAlexey Kardashevskiy { 2531e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_header *buf; 2532e68cb8b4SAlexey Kardashevskiy size_t chunksize = sizeof(*buf) + n_valid*HASH_PTE_SIZE_64; 2533e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2534e68cb8b4SAlexey Kardashevskiy 2535e68cb8b4SAlexey Kardashevskiy buf = alloca(chunksize); 2536e68cb8b4SAlexey Kardashevskiy buf->index = index; 2537e68cb8b4SAlexey Kardashevskiy buf->n_valid = n_valid; 2538e68cb8b4SAlexey Kardashevskiy buf->n_invalid = n_invalid; 2539e68cb8b4SAlexey Kardashevskiy 2540e68cb8b4SAlexey Kardashevskiy qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64*n_valid); 2541e68cb8b4SAlexey Kardashevskiy 2542e68cb8b4SAlexey Kardashevskiy rc = write(fd, buf, chunksize); 2543e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2544e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error writing KVM hash table: %s\n", 2545e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2546e68cb8b4SAlexey Kardashevskiy return rc; 2547e68cb8b4SAlexey Kardashevskiy } 2548e68cb8b4SAlexey Kardashevskiy if (rc != chunksize) { 2549e68cb8b4SAlexey Kardashevskiy /* We should never get a short write on a single chunk */ 2550e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Short write, restoring KVM hash table\n"); 2551e68cb8b4SAlexey Kardashevskiy return -1; 2552e68cb8b4SAlexey Kardashevskiy } 2553e68cb8b4SAlexey Kardashevskiy return 0; 2554e68cb8b4SAlexey Kardashevskiy } 2555e68cb8b4SAlexey Kardashevskiy 255620d695a9SAndreas Färber bool kvm_arch_stop_on_emulation_error(CPUState *cpu) 25574513d923SGleb Natapov { 25584513d923SGleb Natapov return true; 25594513d923SGleb Natapov } 2560a1b87fe0SJan Kiszka 256120d695a9SAndreas Färber int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) 2562a1b87fe0SJan Kiszka { 2563a1b87fe0SJan Kiszka return 1; 2564a1b87fe0SJan Kiszka } 2565a1b87fe0SJan Kiszka 2566a1b87fe0SJan Kiszka int kvm_arch_on_sigbus(int code, void *addr) 2567a1b87fe0SJan Kiszka { 2568a1b87fe0SJan Kiszka return 1; 2569a1b87fe0SJan Kiszka } 257082169660SScott Wood 257182169660SScott Wood void kvm_arch_init_irq_routing(KVMState *s) 257282169660SScott Wood { 257382169660SScott Wood } 2574c65f9a07SGreg Kurz 25757c43bca0SAneesh Kumar K.V struct kvm_get_htab_buf { 25767c43bca0SAneesh Kumar K.V struct kvm_get_htab_header header; 25777c43bca0SAneesh Kumar K.V /* 25787c43bca0SAneesh Kumar K.V * We require one extra byte for read 25797c43bca0SAneesh Kumar K.V */ 25807c43bca0SAneesh Kumar K.V target_ulong hpte[(HPTES_PER_GROUP * 2) + 1]; 25817c43bca0SAneesh Kumar K.V }; 25827c43bca0SAneesh Kumar K.V 25837c43bca0SAneesh Kumar K.V uint64_t kvmppc_hash64_read_pteg(PowerPCCPU *cpu, target_ulong pte_index) 25847c43bca0SAneesh Kumar K.V { 25857c43bca0SAneesh Kumar K.V int htab_fd; 25867c43bca0SAneesh Kumar K.V struct kvm_get_htab_fd ghf; 25877c43bca0SAneesh Kumar K.V struct kvm_get_htab_buf *hpte_buf; 25887c43bca0SAneesh Kumar K.V 25897c43bca0SAneesh Kumar K.V ghf.flags = 0; 25907c43bca0SAneesh Kumar K.V ghf.start_index = pte_index; 25917c43bca0SAneesh Kumar K.V htab_fd = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &ghf); 25927c43bca0SAneesh Kumar K.V if (htab_fd < 0) { 25937c43bca0SAneesh Kumar K.V goto error_out; 25947c43bca0SAneesh Kumar K.V } 25957c43bca0SAneesh Kumar K.V 25967c43bca0SAneesh Kumar K.V hpte_buf = g_malloc0(sizeof(*hpte_buf)); 25977c43bca0SAneesh Kumar K.V /* 25987c43bca0SAneesh Kumar K.V * Read the hpte group 25997c43bca0SAneesh Kumar K.V */ 26007c43bca0SAneesh Kumar K.V if (read(htab_fd, hpte_buf, sizeof(*hpte_buf)) < 0) { 26017c43bca0SAneesh Kumar K.V goto out_close; 26027c43bca0SAneesh Kumar K.V } 26037c43bca0SAneesh Kumar K.V 26047c43bca0SAneesh Kumar K.V close(htab_fd); 26057c43bca0SAneesh Kumar K.V return (uint64_t)(uintptr_t) hpte_buf->hpte; 26067c43bca0SAneesh Kumar K.V 26077c43bca0SAneesh Kumar K.V out_close: 26087c43bca0SAneesh Kumar K.V g_free(hpte_buf); 26097c43bca0SAneesh Kumar K.V close(htab_fd); 26107c43bca0SAneesh Kumar K.V error_out: 26117c43bca0SAneesh Kumar K.V return 0; 26127c43bca0SAneesh Kumar K.V } 26137c43bca0SAneesh Kumar K.V 26147c43bca0SAneesh Kumar K.V void kvmppc_hash64_free_pteg(uint64_t token) 26157c43bca0SAneesh Kumar K.V { 26167c43bca0SAneesh Kumar K.V struct kvm_get_htab_buf *htab_buf; 26177c43bca0SAneesh Kumar K.V 26187c43bca0SAneesh Kumar K.V htab_buf = container_of((void *)(uintptr_t) token, struct kvm_get_htab_buf, 26197c43bca0SAneesh Kumar K.V hpte); 26207c43bca0SAneesh Kumar K.V g_free(htab_buf); 26217c43bca0SAneesh Kumar K.V return; 26227c43bca0SAneesh Kumar K.V } 2623c1385933SAneesh Kumar K.V 2624c1385933SAneesh Kumar K.V void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index, 2625c1385933SAneesh Kumar K.V target_ulong pte0, target_ulong pte1) 2626c1385933SAneesh Kumar K.V { 2627c1385933SAneesh Kumar K.V int htab_fd; 2628c1385933SAneesh Kumar K.V struct kvm_get_htab_fd ghf; 2629c1385933SAneesh Kumar K.V struct kvm_get_htab_buf hpte_buf; 2630c1385933SAneesh Kumar K.V 2631c1385933SAneesh Kumar K.V ghf.flags = 0; 2632c1385933SAneesh Kumar K.V ghf.start_index = 0; /* Ignored */ 2633c1385933SAneesh Kumar K.V htab_fd = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &ghf); 2634c1385933SAneesh Kumar K.V if (htab_fd < 0) { 2635c1385933SAneesh Kumar K.V goto error_out; 2636c1385933SAneesh Kumar K.V } 2637c1385933SAneesh Kumar K.V 2638c1385933SAneesh Kumar K.V hpte_buf.header.n_valid = 1; 2639c1385933SAneesh Kumar K.V hpte_buf.header.n_invalid = 0; 2640c1385933SAneesh Kumar K.V hpte_buf.header.index = pte_index; 2641c1385933SAneesh Kumar K.V hpte_buf.hpte[0] = pte0; 2642c1385933SAneesh Kumar K.V hpte_buf.hpte[1] = pte1; 2643c1385933SAneesh Kumar K.V /* 2644c1385933SAneesh Kumar K.V * Write the hpte entry. 2645c1385933SAneesh Kumar K.V * CAUTION: write() has the warn_unused_result attribute. Hence we 2646c1385933SAneesh Kumar K.V * need to check the return value, even though we do nothing. 2647c1385933SAneesh Kumar K.V */ 2648c1385933SAneesh Kumar K.V if (write(htab_fd, &hpte_buf, sizeof(hpte_buf)) < 0) { 2649c1385933SAneesh Kumar K.V goto out_close; 2650c1385933SAneesh Kumar K.V } 2651c1385933SAneesh Kumar K.V 2652c1385933SAneesh Kumar K.V out_close: 2653c1385933SAneesh Kumar K.V close(htab_fd); 2654c1385933SAneesh Kumar K.V return; 2655c1385933SAneesh Kumar K.V 2656c1385933SAneesh Kumar K.V error_out: 2657c1385933SAneesh Kumar K.V return; 2658c1385933SAneesh Kumar K.V } 26599e03a040SFrank Blaschka 26609e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 2661dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 26629e03a040SFrank Blaschka { 26639e03a040SFrank Blaschka return 0; 26649e03a040SFrank Blaschka } 26651850b6b7SEric Auger 266638d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 266738d87493SPeter Xu int vector, PCIDevice *dev) 266838d87493SPeter Xu { 266938d87493SPeter Xu return 0; 267038d87493SPeter Xu } 267138d87493SPeter Xu 267238d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 267338d87493SPeter Xu { 267438d87493SPeter Xu return 0; 267538d87493SPeter Xu } 267638d87493SPeter Xu 26771850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 26781850b6b7SEric Auger { 26791850b6b7SEric Auger return data & 0xffff; 26801850b6b7SEric Auger } 26814d9392beSThomas Huth 26824d9392beSThomas Huth int kvmppc_enable_hwrng(void) 26834d9392beSThomas Huth { 26844d9392beSThomas Huth if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG)) { 26854d9392beSThomas Huth return -1; 26864d9392beSThomas Huth } 26874d9392beSThomas Huth 26884d9392beSThomas Huth return kvmppc_enable_hcall(kvm_state, H_RANDOM); 26894d9392beSThomas Huth } 2690