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" 2530f4b05bSDavid Gibson #include "qapi/error.h" 26072ed5f2SThomas Huth #include "qemu/error-report.h" 2733c11879SPaolo Bonzini #include "cpu.h" 28715d4b96SThomas Huth #include "cpu-models.h" 291de7afc9SPaolo Bonzini #include "qemu/timer.h" 30b3946626SVincent Palatin #include "sysemu/hw_accel.h" 31d76d1650Saurel32 #include "kvm_ppc.h" 329c17d615SPaolo Bonzini #include "sysemu/cpus.h" 339c17d615SPaolo Bonzini #include "sysemu/device_tree.h" 34d5aea6f3SDavid Gibson #include "mmu-hash64.h" 35d76d1650Saurel32 36f61b4bedSAlexander Graf #include "hw/sysbus.h" 370d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 387ebaf795SBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 39650d103dSMarkus Armbruster #include "hw/hw.h" 4098a8b524SAlexey Kardashevskiy #include "hw/ppc/ppc.h" 41ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h" 4231f2cb8fSBharat Bhushan #include "sysemu/watchdog.h" 43b36f100eSAlexey Kardashevskiy #include "trace.h" 4488365d17SBharat Bhushan #include "exec/gdbstub.h" 454c663752SPaolo Bonzini #include "exec/memattrs.h" 469c607668SAlexey Kardashevskiy #include "exec/ram_addr.h" 472d103aaeSMichael Roth #include "sysemu/hostmem.h" 48f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 49db725815SMarkus Armbruster #include "qemu/main-loop.h" 509c607668SAlexey Kardashevskiy #include "qemu/mmap-alloc.h" 51f3d9f303SSam Bobroff #include "elf.h" 52c64abd1fSSam Bobroff #include "sysemu/kvm_int.h" 53f61b4bedSAlexander Graf 54eadaada1SAlexander Graf #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" 55eadaada1SAlexander Graf 5694a8d39aSJan Kiszka const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 5794a8d39aSJan Kiszka KVM_CAP_LAST_INFO 5894a8d39aSJan Kiszka }; 5994a8d39aSJan Kiszka 60c995e942SDavid Gibson static int cap_interrupt_unset; 6190dc8812SScott Wood static int cap_segstate; 6290dc8812SScott Wood static int cap_booke_sregs; 63e97c3636SDavid Gibson static int cap_ppc_smt; 64fa98fbfcSSam Bobroff static int cap_ppc_smt_possible; 650f5cb298SDavid Gibson static int cap_spapr_tce; 66d6ee2a7cSAlexey Kardashevskiy static int cap_spapr_tce_64; 67da95324eSAlexey Kardashevskiy static int cap_spapr_multitce; 689bb62a07SAlexey Kardashevskiy static int cap_spapr_vfio; 69f1af19d7SDavid Gibson static int cap_hior; 70d67d40eaSDavid Gibson static int cap_one_reg; 713b961124SStuart Yoder static int cap_epr; 7231f2cb8fSBharat Bhushan static int cap_ppc_watchdog; 739b00ea49SDavid Gibson static int cap_papr; 74e68cb8b4SAlexey Kardashevskiy static int cap_htab_fd; 7587a91de6SAlexander Graf static int cap_fixup_hcalls; 76bac3bf28SThomas Huth static int cap_htm; /* Hardware transactional memory support */ 77cf1c4cceSSam Bobroff static int cap_mmu_radix; 78cf1c4cceSSam Bobroff static int cap_mmu_hash_v3; 7938afd772SCédric Le Goater static int cap_xive; 80b55d295eSDavid Gibson static int cap_resize_hpt; 81c363a37aSDaniel Henrique Barboza static int cap_ppc_pvr_compat; 828acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_cache; 838acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_bounds_check; 848acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_indirect_branch; 858ff43ee4SSuraj Jitindar Singh static int cap_ppc_count_cache_flush_assist; 86b9a477b7SSuraj Jitindar Singh static int cap_ppc_nested_kvm_hv; 877d050527SSuraj Jitindar Singh static int cap_large_decr; 88fc87e185SAlexander Graf 893c902d44SBharat Bhushan static uint32_t debug_inst_opcode; 903c902d44SBharat Bhushan 91c995e942SDavid Gibson /* 92c995e942SDavid Gibson * Check whether we are running with KVM-PR (instead of KVM-HV). This 9396c9cff0SThomas Huth * should only be used for fallback tests - generally we should use 9496c9cff0SThomas Huth * explicit capabilities for the features we want, rather than 95c995e942SDavid Gibson * assuming what is/isn't available depending on the KVM variant. 96c995e942SDavid Gibson */ 9796c9cff0SThomas Huth static bool kvmppc_is_pr(KVMState *ks) 9896c9cff0SThomas Huth { 9996c9cff0SThomas Huth /* Assume KVM-PR if the GET_PVINFO capability is available */ 10070a0c19eSGreg Kurz return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; 10196c9cff0SThomas Huth } 10296c9cff0SThomas Huth 103*165dc3edSDavid Gibson static int kvm_ppc_register_host_cpu_type(void); 1048acc2ae5SSuraj Jitindar Singh static void kvmppc_get_cpu_characteristics(KVMState *s); 1057d050527SSuraj Jitindar Singh static int kvmppc_get_dec_bits(void); 1065ba4576bSAndreas Färber 107b16565b3SMarcel Apfelbaum int kvm_arch_init(MachineState *ms, KVMState *s) 108d76d1650Saurel32 { 109fc87e185SAlexander Graf cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ); 11090dc8812SScott Wood cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE); 11190dc8812SScott Wood cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS); 1126977afdaSGreg Kurz cap_ppc_smt_possible = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE); 1130f5cb298SDavid Gibson cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); 114d6ee2a7cSAlexey Kardashevskiy cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64); 115da95324eSAlexey Kardashevskiy cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE); 1169ded780cSAlexey Kardashevskiy cap_spapr_vfio = kvm_vm_check_extension(s, KVM_CAP_SPAPR_TCE_VFIO); 117d67d40eaSDavid Gibson cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG); 118f1af19d7SDavid Gibson cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR); 1193b961124SStuart Yoder cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR); 12031f2cb8fSBharat Bhushan cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG); 121c995e942SDavid Gibson /* 122c995e942SDavid Gibson * Note: we don't set cap_papr here, because this capability is 123c995e942SDavid Gibson * only activated after this by kvmppc_set_papr() 124c995e942SDavid Gibson */ 1256977afdaSGreg Kurz cap_htab_fd = kvm_vm_check_extension(s, KVM_CAP_PPC_HTAB_FD); 12687a91de6SAlexander Graf cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL); 127fa98fbfcSSam Bobroff cap_ppc_smt = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT); 128bac3bf28SThomas Huth cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM); 129cf1c4cceSSam Bobroff cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX); 130cf1c4cceSSam Bobroff cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3); 13138afd772SCédric Le Goater cap_xive = kvm_vm_check_extension(s, KVM_CAP_PPC_IRQ_XIVE); 132b55d295eSDavid Gibson cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT); 1338acc2ae5SSuraj Jitindar Singh kvmppc_get_cpu_characteristics(s); 134b9a477b7SSuraj Jitindar Singh cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV); 1357d050527SSuraj Jitindar Singh cap_large_decr = kvmppc_get_dec_bits(); 136c363a37aSDaniel Henrique Barboza /* 137c363a37aSDaniel Henrique Barboza * Note: setting it to false because there is not such capability 138c363a37aSDaniel Henrique Barboza * in KVM at this moment. 139c363a37aSDaniel Henrique Barboza * 140c363a37aSDaniel Henrique Barboza * TODO: call kvm_vm_check_extension() with the right capability 141c995e942SDavid Gibson * after the kernel starts implementing it. 142c995e942SDavid Gibson */ 143c363a37aSDaniel Henrique Barboza cap_ppc_pvr_compat = false; 144fc87e185SAlexander Graf 1451e8f51e8SShivaprasad G Bhat if (!kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL)) { 1461e8f51e8SShivaprasad G Bhat error_report("KVM: Host kernel doesn't have level irq capability"); 1471e8f51e8SShivaprasad G Bhat exit(1); 148fc87e185SAlexander Graf } 149fc87e185SAlexander Graf 150*165dc3edSDavid Gibson kvm_ppc_register_host_cpu_type(); 1515ba4576bSAndreas Färber 152d76d1650Saurel32 return 0; 153d76d1650Saurel32 } 154d76d1650Saurel32 155d525ffabSPaolo Bonzini int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) 156d525ffabSPaolo Bonzini { 157d525ffabSPaolo Bonzini return 0; 158d525ffabSPaolo Bonzini } 159d525ffabSPaolo Bonzini 1601bc22652SAndreas Färber static int kvm_arch_sync_sregs(PowerPCCPU *cpu) 161d76d1650Saurel32 { 1621bc22652SAndreas Färber CPUPPCState *cenv = &cpu->env; 1631bc22652SAndreas Färber CPUState *cs = CPU(cpu); 164861bbc80SAlexander Graf struct kvm_sregs sregs; 1655666ca4aSScott Wood int ret; 1665666ca4aSScott Wood 1675666ca4aSScott Wood if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 168c995e942SDavid Gibson /* 169c995e942SDavid Gibson * What we're really trying to say is "if we're on BookE, we 170c995e942SDavid Gibson * use the native PVR for now". This is the only sane way to 171c995e942SDavid Gibson * check it though, so we potentially confuse users that they 172c995e942SDavid Gibson * can run BookE guests on BookS. Let's hope nobody dares 173c995e942SDavid Gibson * enough :) 174c995e942SDavid Gibson */ 1755666ca4aSScott Wood return 0; 1765666ca4aSScott Wood } else { 17790dc8812SScott Wood if (!cap_segstate) { 17864e07be5SAlexander Graf fprintf(stderr, "kvm error: missing PVR setting capability\n"); 17964e07be5SAlexander Graf return -ENOSYS; 1805666ca4aSScott Wood } 1815666ca4aSScott Wood } 1825666ca4aSScott Wood 1831bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); 1845666ca4aSScott Wood if (ret) { 1855666ca4aSScott Wood return ret; 1865666ca4aSScott Wood } 187861bbc80SAlexander Graf 188861bbc80SAlexander Graf sregs.pvr = cenv->spr[SPR_PVR]; 1891bc22652SAndreas Färber return kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); 1905666ca4aSScott Wood } 1915666ca4aSScott Wood 19293dd5e85SScott Wood /* Set up a shared TLB array with KVM */ 1931bc22652SAndreas Färber static int kvm_booke206_tlb_init(PowerPCCPU *cpu) 19493dd5e85SScott Wood { 1951bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 1961bc22652SAndreas Färber CPUState *cs = CPU(cpu); 19793dd5e85SScott Wood struct kvm_book3e_206_tlb_params params = {}; 19893dd5e85SScott Wood struct kvm_config_tlb cfg = {}; 19993dd5e85SScott Wood unsigned int entries = 0; 20093dd5e85SScott Wood int ret, i; 20193dd5e85SScott Wood 20293dd5e85SScott Wood if (!kvm_enabled() || 203a60f24b5SAndreas Färber !kvm_check_extension(cs->kvm_state, KVM_CAP_SW_TLB)) { 20493dd5e85SScott Wood return 0; 20593dd5e85SScott Wood } 20693dd5e85SScott Wood 20793dd5e85SScott Wood assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN); 20893dd5e85SScott Wood 20993dd5e85SScott Wood for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 21093dd5e85SScott Wood params.tlb_sizes[i] = booke206_tlb_size(env, i); 21193dd5e85SScott Wood params.tlb_ways[i] = booke206_tlb_ways(env, i); 21293dd5e85SScott Wood entries += params.tlb_sizes[i]; 21393dd5e85SScott Wood } 21493dd5e85SScott Wood 21593dd5e85SScott Wood assert(entries == env->nb_tlb); 21693dd5e85SScott Wood assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t)); 21793dd5e85SScott Wood 21893dd5e85SScott Wood env->tlb_dirty = true; 21993dd5e85SScott Wood 22093dd5e85SScott Wood cfg.array = (uintptr_t)env->tlb.tlbm; 22193dd5e85SScott Wood cfg.array_len = sizeof(ppcmas_tlb_t) * entries; 22293dd5e85SScott Wood cfg.params = (uintptr_t)¶ms; 22393dd5e85SScott Wood cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV; 22493dd5e85SScott Wood 22548add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_SW_TLB, 0, (uintptr_t)&cfg); 22693dd5e85SScott Wood if (ret < 0) { 22793dd5e85SScott Wood fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n", 22893dd5e85SScott Wood __func__, strerror(-ret)); 22993dd5e85SScott Wood return ret; 23093dd5e85SScott Wood } 23193dd5e85SScott Wood 23293dd5e85SScott Wood env->kvm_sw_tlb = true; 23393dd5e85SScott Wood return 0; 23493dd5e85SScott Wood } 23593dd5e85SScott Wood 2364656e1f0SBenjamin Herrenschmidt 2374656e1f0SBenjamin Herrenschmidt #if defined(TARGET_PPC64) 238ab256960SGreg Kurz static void kvm_get_smmu_info(struct kvm_ppc_smmu_info *info, Error **errp) 2394656e1f0SBenjamin Herrenschmidt { 2404656e1f0SBenjamin Herrenschmidt int ret; 2414656e1f0SBenjamin Herrenschmidt 242ab256960SGreg Kurz assert(kvm_state != NULL); 243ab256960SGreg Kurz 244ab256960SGreg Kurz if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { 24571d0f1eaSGreg Kurz error_setg(errp, "KVM doesn't expose the MMU features it supports"); 24671d0f1eaSGreg Kurz error_append_hint(errp, "Consider switching to a newer KVM\n"); 24771d0f1eaSGreg Kurz return; 24871d0f1eaSGreg Kurz } 24971d0f1eaSGreg Kurz 250ab256960SGreg Kurz ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_SMMU_INFO, info); 2514656e1f0SBenjamin Herrenschmidt if (ret == 0) { 2524656e1f0SBenjamin Herrenschmidt return; 2534656e1f0SBenjamin Herrenschmidt } 2544656e1f0SBenjamin Herrenschmidt 25571d0f1eaSGreg Kurz error_setg_errno(errp, -ret, 25671d0f1eaSGreg Kurz "KVM failed to provide the MMU features it supports"); 2574656e1f0SBenjamin Herrenschmidt } 2584656e1f0SBenjamin Herrenschmidt 259c64abd1fSSam Bobroff struct ppc_radix_page_info *kvm_get_radix_page_info(void) 260c64abd1fSSam Bobroff { 261c64abd1fSSam Bobroff KVMState *s = KVM_STATE(current_machine->accelerator); 262c64abd1fSSam Bobroff struct ppc_radix_page_info *radix_page_info; 263c64abd1fSSam Bobroff struct kvm_ppc_rmmu_info rmmu_info; 264c64abd1fSSam Bobroff int i; 265c64abd1fSSam Bobroff 266c64abd1fSSam Bobroff if (!kvm_check_extension(s, KVM_CAP_PPC_MMU_RADIX)) { 267c64abd1fSSam Bobroff return NULL; 268c64abd1fSSam Bobroff } 269c64abd1fSSam Bobroff if (kvm_vm_ioctl(s, KVM_PPC_GET_RMMU_INFO, &rmmu_info)) { 270c64abd1fSSam Bobroff return NULL; 271c64abd1fSSam Bobroff } 272c64abd1fSSam Bobroff radix_page_info = g_malloc0(sizeof(*radix_page_info)); 273c64abd1fSSam Bobroff radix_page_info->count = 0; 274c64abd1fSSam Bobroff for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { 275c64abd1fSSam Bobroff if (rmmu_info.ap_encodings[i]) { 276c64abd1fSSam Bobroff radix_page_info->entries[i] = rmmu_info.ap_encodings[i]; 277c64abd1fSSam Bobroff radix_page_info->count++; 278c64abd1fSSam Bobroff } 279c64abd1fSSam Bobroff } 280c64abd1fSSam Bobroff return radix_page_info; 281c64abd1fSSam Bobroff } 282c64abd1fSSam Bobroff 283b4db5413SSuraj Jitindar Singh target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu, 284b4db5413SSuraj Jitindar Singh bool radix, bool gtse, 285b4db5413SSuraj Jitindar Singh uint64_t proc_tbl) 286b4db5413SSuraj Jitindar Singh { 287b4db5413SSuraj Jitindar Singh CPUState *cs = CPU(cpu); 288b4db5413SSuraj Jitindar Singh int ret; 289b4db5413SSuraj Jitindar Singh uint64_t flags = 0; 290b4db5413SSuraj Jitindar Singh struct kvm_ppc_mmuv3_cfg cfg = { 291b4db5413SSuraj Jitindar Singh .process_table = proc_tbl, 292b4db5413SSuraj Jitindar Singh }; 293b4db5413SSuraj Jitindar Singh 294b4db5413SSuraj Jitindar Singh if (radix) { 295b4db5413SSuraj Jitindar Singh flags |= KVM_PPC_MMUV3_RADIX; 296b4db5413SSuraj Jitindar Singh } 297b4db5413SSuraj Jitindar Singh if (gtse) { 298b4db5413SSuraj Jitindar Singh flags |= KVM_PPC_MMUV3_GTSE; 299b4db5413SSuraj Jitindar Singh } 300b4db5413SSuraj Jitindar Singh cfg.flags = flags; 301b4db5413SSuraj Jitindar Singh ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_CONFIGURE_V3_MMU, &cfg); 302b4db5413SSuraj Jitindar Singh switch (ret) { 303b4db5413SSuraj Jitindar Singh case 0: 304b4db5413SSuraj Jitindar Singh return H_SUCCESS; 305b4db5413SSuraj Jitindar Singh case -EINVAL: 306b4db5413SSuraj Jitindar Singh return H_PARAMETER; 307b4db5413SSuraj Jitindar Singh case -ENODEV: 308b4db5413SSuraj Jitindar Singh return H_NOT_AVAILABLE; 309b4db5413SSuraj Jitindar Singh default: 310b4db5413SSuraj Jitindar Singh return H_HARDWARE; 311b4db5413SSuraj Jitindar Singh } 312b4db5413SSuraj Jitindar Singh } 313b4db5413SSuraj Jitindar Singh 31424c6863cSDavid Gibson bool kvmppc_hpt_needs_host_contiguous_pages(void) 31524c6863cSDavid Gibson { 31624c6863cSDavid Gibson static struct kvm_ppc_smmu_info smmu_info; 31724c6863cSDavid Gibson 31824c6863cSDavid Gibson if (!kvm_enabled()) { 31924c6863cSDavid Gibson return false; 32024c6863cSDavid Gibson } 32124c6863cSDavid Gibson 322ab256960SGreg Kurz kvm_get_smmu_info(&smmu_info, &error_fatal); 32324c6863cSDavid Gibson return !!(smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL); 32424c6863cSDavid Gibson } 32524c6863cSDavid Gibson 326e5ca28ecSDavid Gibson void kvm_check_mmu(PowerPCCPU *cpu, Error **errp) 3274656e1f0SBenjamin Herrenschmidt { 328e5ca28ecSDavid Gibson struct kvm_ppc_smmu_info smmu_info; 3294656e1f0SBenjamin Herrenschmidt int iq, ik, jq, jk; 33071d0f1eaSGreg Kurz Error *local_err = NULL; 3314656e1f0SBenjamin Herrenschmidt 332e5ca28ecSDavid Gibson /* For now, we only have anything to check on hash64 MMUs */ 333e5ca28ecSDavid Gibson if (!cpu->hash64_opts || !kvm_enabled()) { 3344656e1f0SBenjamin Herrenschmidt return; 3354656e1f0SBenjamin Herrenschmidt } 3364656e1f0SBenjamin Herrenschmidt 337ab256960SGreg Kurz kvm_get_smmu_info(&smmu_info, &local_err); 33871d0f1eaSGreg Kurz if (local_err) { 33971d0f1eaSGreg Kurz error_propagate(errp, local_err); 34071d0f1eaSGreg Kurz return; 34171d0f1eaSGreg Kurz } 342e5ca28ecSDavid Gibson 343e5ca28ecSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG) 344e5ca28ecSDavid Gibson && !(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { 345e5ca28ecSDavid Gibson error_setg(errp, 346e5ca28ecSDavid Gibson "KVM does not support 1TiB segments which guest expects"); 347e5ca28ecSDavid Gibson return; 3484656e1f0SBenjamin Herrenschmidt } 3494656e1f0SBenjamin Herrenschmidt 350e5ca28ecSDavid Gibson if (smmu_info.slb_size < cpu->hash64_opts->slb_size) { 351e5ca28ecSDavid Gibson error_setg(errp, "KVM only supports %u SLB entries, but guest needs %u", 352e5ca28ecSDavid Gibson smmu_info.slb_size, cpu->hash64_opts->slb_size); 353e5ca28ecSDavid Gibson return; 35490da0d5aSBenjamin Herrenschmidt } 35590da0d5aSBenjamin Herrenschmidt 35608215d8fSAlexander Graf /* 357e5ca28ecSDavid Gibson * Verify that every pagesize supported by the cpu model is 358e5ca28ecSDavid Gibson * supported by KVM with the same encodings 35908215d8fSAlexander Graf */ 360e5ca28ecSDavid Gibson for (iq = 0; iq < ARRAY_SIZE(cpu->hash64_opts->sps); iq++) { 361b07c59f7SDavid Gibson PPCHash64SegmentPageSizes *qsps = &cpu->hash64_opts->sps[iq]; 362e5ca28ecSDavid Gibson struct kvm_ppc_one_seg_page_size *ksps; 3634656e1f0SBenjamin Herrenschmidt 364e5ca28ecSDavid Gibson for (ik = 0; ik < ARRAY_SIZE(smmu_info.sps); ik++) { 365e5ca28ecSDavid Gibson if (qsps->page_shift == smmu_info.sps[ik].page_shift) { 3664656e1f0SBenjamin Herrenschmidt break; 3674656e1f0SBenjamin Herrenschmidt } 3684656e1f0SBenjamin Herrenschmidt } 369e5ca28ecSDavid Gibson if (ik >= ARRAY_SIZE(smmu_info.sps)) { 370e5ca28ecSDavid Gibson error_setg(errp, "KVM doesn't support for base page shift %u", 371e5ca28ecSDavid Gibson qsps->page_shift); 372e5ca28ecSDavid Gibson return; 373e5ca28ecSDavid Gibson } 374e5ca28ecSDavid Gibson 375e5ca28ecSDavid Gibson ksps = &smmu_info.sps[ik]; 376e5ca28ecSDavid Gibson if (ksps->slb_enc != qsps->slb_enc) { 377e5ca28ecSDavid Gibson error_setg(errp, 378e5ca28ecSDavid Gibson "KVM uses SLB encoding 0x%x for page shift %u, but guest expects 0x%x", 379e5ca28ecSDavid Gibson ksps->slb_enc, ksps->page_shift, qsps->slb_enc); 380e5ca28ecSDavid Gibson return; 381e5ca28ecSDavid Gibson } 382e5ca28ecSDavid Gibson 383e5ca28ecSDavid Gibson for (jq = 0; jq < ARRAY_SIZE(qsps->enc); jq++) { 384e5ca28ecSDavid Gibson for (jk = 0; jk < ARRAY_SIZE(ksps->enc); jk++) { 385e5ca28ecSDavid Gibson if (qsps->enc[jq].page_shift == ksps->enc[jk].page_shift) { 3864656e1f0SBenjamin Herrenschmidt break; 3874656e1f0SBenjamin Herrenschmidt } 3884656e1f0SBenjamin Herrenschmidt } 3894656e1f0SBenjamin Herrenschmidt 390e5ca28ecSDavid Gibson if (jk >= ARRAY_SIZE(ksps->enc)) { 391e5ca28ecSDavid Gibson error_setg(errp, "KVM doesn't support page shift %u/%u", 392e5ca28ecSDavid Gibson qsps->enc[jq].page_shift, qsps->page_shift); 393e5ca28ecSDavid Gibson return; 394e5ca28ecSDavid Gibson } 395e5ca28ecSDavid Gibson if (qsps->enc[jq].pte_enc != ksps->enc[jk].pte_enc) { 396e5ca28ecSDavid Gibson error_setg(errp, 397e5ca28ecSDavid Gibson "KVM uses PTE encoding 0x%x for page shift %u/%u, but guest expects 0x%x", 398e5ca28ecSDavid Gibson ksps->enc[jk].pte_enc, qsps->enc[jq].page_shift, 399e5ca28ecSDavid Gibson qsps->page_shift, qsps->enc[jq].pte_enc); 400e5ca28ecSDavid Gibson return; 401e5ca28ecSDavid Gibson } 402e5ca28ecSDavid Gibson } 4034656e1f0SBenjamin Herrenschmidt } 4044656e1f0SBenjamin Herrenschmidt 405e5ca28ecSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 406c995e942SDavid Gibson /* 407c995e942SDavid Gibson * Mostly what guest pagesizes we can use are related to the 408e5ca28ecSDavid Gibson * host pages used to map guest RAM, which is handled in the 409e5ca28ecSDavid Gibson * platform code. Cache-Inhibited largepages (64k) however are 410e5ca28ecSDavid Gibson * used for I/O, so if they're mapped to the host at all it 411e5ca28ecSDavid Gibson * will be a normal mapping, not a special hugepage one used 412c995e942SDavid Gibson * for RAM. 413c995e942SDavid Gibson */ 414038adc2fSWei Yang if (qemu_real_host_page_size < 0x10000) { 415e5ca28ecSDavid Gibson error_setg(errp, 416e5ca28ecSDavid Gibson "KVM can't supply 64kiB CI pages, which guest expects"); 417e5ca28ecSDavid Gibson } 418e5ca28ecSDavid Gibson } 419e5ca28ecSDavid Gibson } 4204656e1f0SBenjamin Herrenschmidt #endif /* !defined (TARGET_PPC64) */ 4214656e1f0SBenjamin Herrenschmidt 422b164e48eSEduardo Habkost unsigned long kvm_arch_vcpu_id(CPUState *cpu) 423b164e48eSEduardo Habkost { 4242e886fb3SSam Bobroff return POWERPC_CPU(cpu)->vcpu_id; 425b164e48eSEduardo Habkost } 426b164e48eSEduardo Habkost 427c995e942SDavid Gibson /* 428c995e942SDavid Gibson * e500 supports 2 h/w breakpoint and 2 watchpoint. book3s supports 429c995e942SDavid Gibson * only 1 watchpoint, so array size of 4 is sufficient for now. 43088365d17SBharat Bhushan */ 43188365d17SBharat Bhushan #define MAX_HW_BKPTS 4 43288365d17SBharat Bhushan 43388365d17SBharat Bhushan static struct HWBreakpoint { 43488365d17SBharat Bhushan target_ulong addr; 43588365d17SBharat Bhushan int type; 43688365d17SBharat Bhushan } hw_debug_points[MAX_HW_BKPTS]; 43788365d17SBharat Bhushan 43888365d17SBharat Bhushan static CPUWatchpoint hw_watchpoint; 43988365d17SBharat Bhushan 44088365d17SBharat Bhushan /* Default there is no breakpoint and watchpoint supported */ 44188365d17SBharat Bhushan static int max_hw_breakpoint; 44288365d17SBharat Bhushan static int max_hw_watchpoint; 44388365d17SBharat Bhushan static int nb_hw_breakpoint; 44488365d17SBharat Bhushan static int nb_hw_watchpoint; 44588365d17SBharat Bhushan 44688365d17SBharat Bhushan static void kvmppc_hw_debug_points_init(CPUPPCState *cenv) 44788365d17SBharat Bhushan { 44888365d17SBharat Bhushan if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 44988365d17SBharat Bhushan max_hw_breakpoint = 2; 45088365d17SBharat Bhushan max_hw_watchpoint = 2; 45188365d17SBharat Bhushan } 45288365d17SBharat Bhushan 45388365d17SBharat Bhushan if ((max_hw_breakpoint + max_hw_watchpoint) > MAX_HW_BKPTS) { 45488365d17SBharat Bhushan fprintf(stderr, "Error initializing h/w breakpoints\n"); 45588365d17SBharat Bhushan return; 45688365d17SBharat Bhushan } 45788365d17SBharat Bhushan } 45888365d17SBharat Bhushan 45920d695a9SAndreas Färber int kvm_arch_init_vcpu(CPUState *cs) 4605666ca4aSScott Wood { 46120d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 46220d695a9SAndreas Färber CPUPPCState *cenv = &cpu->env; 4635666ca4aSScott Wood int ret; 4645666ca4aSScott Wood 4654656e1f0SBenjamin Herrenschmidt /* Synchronize sregs with kvm */ 4661bc22652SAndreas Färber ret = kvm_arch_sync_sregs(cpu); 4675666ca4aSScott Wood if (ret) { 468388e47c7SThomas Huth if (ret == -EINVAL) { 469388e47c7SThomas Huth error_report("Register sync failed... If you're using kvm-hv.ko," 470388e47c7SThomas Huth " only \"-cpu host\" is possible"); 471388e47c7SThomas Huth } 4725666ca4aSScott Wood return ret; 4735666ca4aSScott Wood } 474861bbc80SAlexander Graf 47593dd5e85SScott Wood switch (cenv->mmu_model) { 47693dd5e85SScott Wood case POWERPC_MMU_BOOKE206: 4777f516c96SThomas Huth /* This target supports access to KVM's guest TLB */ 4781bc22652SAndreas Färber ret = kvm_booke206_tlb_init(cpu); 47993dd5e85SScott Wood break; 4807f516c96SThomas Huth case POWERPC_MMU_2_07: 4817f516c96SThomas Huth if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) { 482c995e942SDavid Gibson /* 483c995e942SDavid Gibson * KVM-HV has transactional memory on POWER8 also without 484c995e942SDavid Gibson * the KVM_CAP_PPC_HTM extension, so enable it here 485c995e942SDavid Gibson * instead as long as it's availble to userspace on the 486c995e942SDavid Gibson * host. 487c995e942SDavid Gibson */ 488f3d9f303SSam Bobroff if (qemu_getauxval(AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) { 4897f516c96SThomas Huth cap_htm = true; 4907f516c96SThomas Huth } 491f3d9f303SSam Bobroff } 4927f516c96SThomas Huth break; 49393dd5e85SScott Wood default: 49493dd5e85SScott Wood break; 49593dd5e85SScott Wood } 49693dd5e85SScott Wood 4973c902d44SBharat Bhushan kvm_get_one_reg(cs, KVM_REG_PPC_DEBUG_INST, &debug_inst_opcode); 49888365d17SBharat Bhushan kvmppc_hw_debug_points_init(cenv); 4993c902d44SBharat Bhushan 500861bbc80SAlexander Graf return ret; 501d76d1650Saurel32 } 502d76d1650Saurel32 503b1115c99SLiran Alon int kvm_arch_destroy_vcpu(CPUState *cs) 504b1115c99SLiran Alon { 505b1115c99SLiran Alon return 0; 506b1115c99SLiran Alon } 507b1115c99SLiran Alon 5081bc22652SAndreas Färber static void kvm_sw_tlb_put(PowerPCCPU *cpu) 50993dd5e85SScott Wood { 5101bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 5111bc22652SAndreas Färber CPUState *cs = CPU(cpu); 51293dd5e85SScott Wood struct kvm_dirty_tlb dirty_tlb; 51393dd5e85SScott Wood unsigned char *bitmap; 51493dd5e85SScott Wood int ret; 51593dd5e85SScott Wood 51693dd5e85SScott Wood if (!env->kvm_sw_tlb) { 51793dd5e85SScott Wood return; 51893dd5e85SScott Wood } 51993dd5e85SScott Wood 52093dd5e85SScott Wood bitmap = g_malloc((env->nb_tlb + 7) / 8); 52193dd5e85SScott Wood memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8); 52293dd5e85SScott Wood 52393dd5e85SScott Wood dirty_tlb.bitmap = (uintptr_t)bitmap; 52493dd5e85SScott Wood dirty_tlb.num_dirty = env->nb_tlb; 52593dd5e85SScott Wood 5261bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_DIRTY_TLB, &dirty_tlb); 52793dd5e85SScott Wood if (ret) { 52893dd5e85SScott Wood fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n", 52993dd5e85SScott Wood __func__, strerror(-ret)); 53093dd5e85SScott Wood } 53193dd5e85SScott Wood 53293dd5e85SScott Wood g_free(bitmap); 53393dd5e85SScott Wood } 53493dd5e85SScott Wood 535d67d40eaSDavid Gibson static void kvm_get_one_spr(CPUState *cs, uint64_t id, int spr) 536d67d40eaSDavid Gibson { 537d67d40eaSDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 538d67d40eaSDavid Gibson CPUPPCState *env = &cpu->env; 539d67d40eaSDavid Gibson union { 540d67d40eaSDavid Gibson uint32_t u32; 541d67d40eaSDavid Gibson uint64_t u64; 542d67d40eaSDavid Gibson } val; 543d67d40eaSDavid Gibson struct kvm_one_reg reg = { 544d67d40eaSDavid Gibson .id = id, 545d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 546d67d40eaSDavid Gibson }; 547d67d40eaSDavid Gibson int ret; 548d67d40eaSDavid Gibson 549d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 550d67d40eaSDavid Gibson if (ret != 0) { 551b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_get(spr, strerror(errno)); 552d67d40eaSDavid Gibson } else { 553d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 554d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 555d67d40eaSDavid Gibson env->spr[spr] = val.u32; 556d67d40eaSDavid Gibson break; 557d67d40eaSDavid Gibson 558d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 559d67d40eaSDavid Gibson env->spr[spr] = val.u64; 560d67d40eaSDavid Gibson break; 561d67d40eaSDavid Gibson 562d67d40eaSDavid Gibson default: 563d67d40eaSDavid Gibson /* Don't handle this size yet */ 564d67d40eaSDavid Gibson abort(); 565d67d40eaSDavid Gibson } 566d67d40eaSDavid Gibson } 567d67d40eaSDavid Gibson } 568d67d40eaSDavid Gibson 569d67d40eaSDavid Gibson static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr) 570d67d40eaSDavid Gibson { 571d67d40eaSDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 572d67d40eaSDavid Gibson CPUPPCState *env = &cpu->env; 573d67d40eaSDavid Gibson union { 574d67d40eaSDavid Gibson uint32_t u32; 575d67d40eaSDavid Gibson uint64_t u64; 576d67d40eaSDavid Gibson } val; 577d67d40eaSDavid Gibson struct kvm_one_reg reg = { 578d67d40eaSDavid Gibson .id = id, 579d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 580d67d40eaSDavid Gibson }; 581d67d40eaSDavid Gibson int ret; 582d67d40eaSDavid Gibson 583d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 584d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 585d67d40eaSDavid Gibson val.u32 = env->spr[spr]; 586d67d40eaSDavid Gibson break; 587d67d40eaSDavid Gibson 588d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 589d67d40eaSDavid Gibson val.u64 = env->spr[spr]; 590d67d40eaSDavid Gibson break; 591d67d40eaSDavid Gibson 592d67d40eaSDavid Gibson default: 593d67d40eaSDavid Gibson /* Don't handle this size yet */ 594d67d40eaSDavid Gibson abort(); 595d67d40eaSDavid Gibson } 596d67d40eaSDavid Gibson 597d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 598d67d40eaSDavid Gibson if (ret != 0) { 599b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_set(spr, strerror(errno)); 600d67d40eaSDavid Gibson } 601d67d40eaSDavid Gibson } 602d67d40eaSDavid Gibson 60370b79849SDavid Gibson static int kvm_put_fp(CPUState *cs) 60470b79849SDavid Gibson { 60570b79849SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 60670b79849SDavid Gibson CPUPPCState *env = &cpu->env; 60770b79849SDavid Gibson struct kvm_one_reg reg; 60870b79849SDavid Gibson int i; 60970b79849SDavid Gibson int ret; 61070b79849SDavid Gibson 61170b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 61270b79849SDavid Gibson uint64_t fpscr = env->fpscr; 61370b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 61470b79849SDavid Gibson 61570b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 61670b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 61770b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 61870b79849SDavid Gibson if (ret < 0) { 6198d83cbf1SGreg Kurz trace_kvm_failed_fpscr_set(strerror(errno)); 62070b79849SDavid Gibson return ret; 62170b79849SDavid Gibson } 62270b79849SDavid Gibson 62370b79849SDavid Gibson for (i = 0; i < 32; i++) { 62470b79849SDavid Gibson uint64_t vsr[2]; 625ef96e3aeSMark Cave-Ayland uint64_t *fpr = cpu_fpr_ptr(&cpu->env, i); 626ef96e3aeSMark Cave-Ayland uint64_t *vsrl = cpu_vsrl_ptr(&cpu->env, i); 62770b79849SDavid Gibson 6283a4b791bSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 629ef96e3aeSMark Cave-Ayland vsr[0] = float64_val(*fpr); 630ef96e3aeSMark Cave-Ayland vsr[1] = *vsrl; 6313a4b791bSGreg Kurz #else 632ef96e3aeSMark Cave-Ayland vsr[0] = *vsrl; 633ef96e3aeSMark Cave-Ayland vsr[1] = float64_val(*fpr); 6343a4b791bSGreg Kurz #endif 63570b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 63670b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 63770b79849SDavid Gibson 63870b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 63970b79849SDavid Gibson if (ret < 0) { 6408d83cbf1SGreg Kurz trace_kvm_failed_fp_set(vsx ? "VSR" : "FPR", i, 6418d83cbf1SGreg Kurz strerror(errno)); 64270b79849SDavid Gibson return ret; 64370b79849SDavid Gibson } 64470b79849SDavid Gibson } 64570b79849SDavid Gibson } 64670b79849SDavid Gibson 64770b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 64870b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 64970b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 65070b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 65170b79849SDavid Gibson if (ret < 0) { 6528d83cbf1SGreg Kurz trace_kvm_failed_vscr_set(strerror(errno)); 65370b79849SDavid Gibson return ret; 65470b79849SDavid Gibson } 65570b79849SDavid Gibson 65670b79849SDavid Gibson for (i = 0; i < 32; i++) { 65770b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 658ef96e3aeSMark Cave-Ayland reg.addr = (uintptr_t)cpu_avr_ptr(env, i); 65970b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 66070b79849SDavid Gibson if (ret < 0) { 6618d83cbf1SGreg Kurz trace_kvm_failed_vr_set(i, strerror(errno)); 66270b79849SDavid Gibson return ret; 66370b79849SDavid Gibson } 66470b79849SDavid Gibson } 66570b79849SDavid Gibson } 66670b79849SDavid Gibson 66770b79849SDavid Gibson return 0; 66870b79849SDavid Gibson } 66970b79849SDavid Gibson 67070b79849SDavid Gibson static int kvm_get_fp(CPUState *cs) 67170b79849SDavid Gibson { 67270b79849SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 67370b79849SDavid Gibson CPUPPCState *env = &cpu->env; 67470b79849SDavid Gibson struct kvm_one_reg reg; 67570b79849SDavid Gibson int i; 67670b79849SDavid Gibson int ret; 67770b79849SDavid Gibson 67870b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 67970b79849SDavid Gibson uint64_t fpscr; 68070b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 68170b79849SDavid Gibson 68270b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 68370b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 68470b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 68570b79849SDavid Gibson if (ret < 0) { 6868d83cbf1SGreg Kurz trace_kvm_failed_fpscr_get(strerror(errno)); 68770b79849SDavid Gibson return ret; 68870b79849SDavid Gibson } else { 68970b79849SDavid Gibson env->fpscr = fpscr; 69070b79849SDavid Gibson } 69170b79849SDavid Gibson 69270b79849SDavid Gibson for (i = 0; i < 32; i++) { 69370b79849SDavid Gibson uint64_t vsr[2]; 694ef96e3aeSMark Cave-Ayland uint64_t *fpr = cpu_fpr_ptr(&cpu->env, i); 695ef96e3aeSMark Cave-Ayland uint64_t *vsrl = cpu_vsrl_ptr(&cpu->env, i); 69670b79849SDavid Gibson 69770b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 69870b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 69970b79849SDavid Gibson 70070b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 70170b79849SDavid Gibson if (ret < 0) { 7028d83cbf1SGreg Kurz trace_kvm_failed_fp_get(vsx ? "VSR" : "FPR", i, 7038d83cbf1SGreg Kurz strerror(errno)); 70470b79849SDavid Gibson return ret; 70570b79849SDavid Gibson } else { 7063a4b791bSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 707ef96e3aeSMark Cave-Ayland *fpr = vsr[0]; 70870b79849SDavid Gibson if (vsx) { 709ef96e3aeSMark Cave-Ayland *vsrl = vsr[1]; 71070b79849SDavid Gibson } 7113a4b791bSGreg Kurz #else 712ef96e3aeSMark Cave-Ayland *fpr = vsr[1]; 7133a4b791bSGreg Kurz if (vsx) { 714ef96e3aeSMark Cave-Ayland *vsrl = vsr[0]; 7153a4b791bSGreg Kurz } 7163a4b791bSGreg Kurz #endif 71770b79849SDavid Gibson } 71870b79849SDavid Gibson } 71970b79849SDavid Gibson } 72070b79849SDavid Gibson 72170b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 72270b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 72370b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 72470b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 72570b79849SDavid Gibson if (ret < 0) { 7268d83cbf1SGreg Kurz trace_kvm_failed_vscr_get(strerror(errno)); 72770b79849SDavid Gibson return ret; 72870b79849SDavid Gibson } 72970b79849SDavid Gibson 73070b79849SDavid Gibson for (i = 0; i < 32; i++) { 73170b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 732ef96e3aeSMark Cave-Ayland reg.addr = (uintptr_t)cpu_avr_ptr(env, i); 73370b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 73470b79849SDavid Gibson if (ret < 0) { 7358d83cbf1SGreg Kurz trace_kvm_failed_vr_get(i, strerror(errno)); 73670b79849SDavid Gibson return ret; 73770b79849SDavid Gibson } 73870b79849SDavid Gibson } 73970b79849SDavid Gibson } 74070b79849SDavid Gibson 74170b79849SDavid Gibson return 0; 74270b79849SDavid Gibson } 74370b79849SDavid Gibson 7449b00ea49SDavid Gibson #if defined(TARGET_PPC64) 7459b00ea49SDavid Gibson static int kvm_get_vpa(CPUState *cs) 7469b00ea49SDavid Gibson { 7479b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 748ce2918cbSDavid Gibson SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 7499b00ea49SDavid Gibson struct kvm_one_reg reg; 7509b00ea49SDavid Gibson int ret; 7519b00ea49SDavid Gibson 7529b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 7537388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 7549b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7559b00ea49SDavid Gibson if (ret < 0) { 7568d83cbf1SGreg Kurz trace_kvm_failed_vpa_addr_get(strerror(errno)); 7579b00ea49SDavid Gibson return ret; 7589b00ea49SDavid Gibson } 7599b00ea49SDavid Gibson 7607388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->slb_shadow_size 7617388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->slb_shadow_addr + 8)); 7629b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 7637388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr; 7649b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7659b00ea49SDavid Gibson if (ret < 0) { 7668d83cbf1SGreg Kurz trace_kvm_failed_slb_get(strerror(errno)); 7679b00ea49SDavid Gibson return ret; 7689b00ea49SDavid Gibson } 7699b00ea49SDavid Gibson 7707388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->dtl_size 7717388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->dtl_addr + 8)); 7729b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 7737388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->dtl_addr; 7749b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7759b00ea49SDavid Gibson if (ret < 0) { 7768d83cbf1SGreg Kurz trace_kvm_failed_dtl_get(strerror(errno)); 7779b00ea49SDavid Gibson return ret; 7789b00ea49SDavid Gibson } 7799b00ea49SDavid Gibson 7809b00ea49SDavid Gibson return 0; 7819b00ea49SDavid Gibson } 7829b00ea49SDavid Gibson 7839b00ea49SDavid Gibson static int kvm_put_vpa(CPUState *cs) 7849b00ea49SDavid Gibson { 7859b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 786ce2918cbSDavid Gibson SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 7879b00ea49SDavid Gibson struct kvm_one_reg reg; 7889b00ea49SDavid Gibson int ret; 7899b00ea49SDavid Gibson 790c995e942SDavid Gibson /* 791c995e942SDavid Gibson * SLB shadow or DTL can't be registered unless a master VPA is 7929b00ea49SDavid Gibson * registered. That means when restoring state, if a VPA *is* 7939b00ea49SDavid Gibson * registered, we need to set that up first. If not, we need to 794c995e942SDavid Gibson * deregister the others before deregistering the master VPA 795c995e942SDavid Gibson */ 7967388efafSDavid Gibson assert(spapr_cpu->vpa_addr 7977388efafSDavid Gibson || !(spapr_cpu->slb_shadow_addr || spapr_cpu->dtl_addr)); 7989b00ea49SDavid Gibson 7997388efafSDavid Gibson if (spapr_cpu->vpa_addr) { 8009b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8017388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 8029b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8039b00ea49SDavid Gibson if (ret < 0) { 8048d83cbf1SGreg Kurz trace_kvm_failed_vpa_addr_set(strerror(errno)); 8059b00ea49SDavid Gibson return ret; 8069b00ea49SDavid Gibson } 8079b00ea49SDavid Gibson } 8089b00ea49SDavid Gibson 8097388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->slb_shadow_size 8107388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->slb_shadow_addr + 8)); 8119b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 8127388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr; 8139b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8149b00ea49SDavid Gibson if (ret < 0) { 8158d83cbf1SGreg Kurz trace_kvm_failed_slb_set(strerror(errno)); 8169b00ea49SDavid Gibson return ret; 8179b00ea49SDavid Gibson } 8189b00ea49SDavid Gibson 8197388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->dtl_size 8207388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->dtl_addr + 8)); 8219b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 8227388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->dtl_addr; 8239b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8249b00ea49SDavid Gibson if (ret < 0) { 8258d83cbf1SGreg Kurz trace_kvm_failed_dtl_set(strerror(errno)); 8269b00ea49SDavid Gibson return ret; 8279b00ea49SDavid Gibson } 8289b00ea49SDavid Gibson 8297388efafSDavid Gibson if (!spapr_cpu->vpa_addr) { 8309b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8317388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 8329b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8339b00ea49SDavid Gibson if (ret < 0) { 8348d83cbf1SGreg Kurz trace_kvm_failed_null_vpa_addr_set(strerror(errno)); 8359b00ea49SDavid Gibson return ret; 8369b00ea49SDavid Gibson } 8379b00ea49SDavid Gibson } 8389b00ea49SDavid Gibson 8399b00ea49SDavid Gibson return 0; 8409b00ea49SDavid Gibson } 8419b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 8429b00ea49SDavid Gibson 843e5c0d3ceSDavid Gibson int kvmppc_put_books_sregs(PowerPCCPU *cpu) 844a7a00a72SDavid Gibson { 845a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 846a7a00a72SDavid Gibson struct kvm_sregs sregs; 847a7a00a72SDavid Gibson int i; 848a7a00a72SDavid Gibson 849a7a00a72SDavid Gibson sregs.pvr = env->spr[SPR_PVR]; 850a7a00a72SDavid Gibson 8511ec26c75SGreg Kurz if (cpu->vhyp) { 8521ec26c75SGreg Kurz PPCVirtualHypervisorClass *vhc = 8531ec26c75SGreg Kurz PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 8541ec26c75SGreg Kurz sregs.u.s.sdr1 = vhc->encode_hpt_for_kvm_pr(cpu->vhyp); 8551ec26c75SGreg Kurz } else { 856a7a00a72SDavid Gibson sregs.u.s.sdr1 = env->spr[SPR_SDR1]; 8571ec26c75SGreg Kurz } 858a7a00a72SDavid Gibson 859a7a00a72SDavid Gibson /* Sync SLB */ 860a7a00a72SDavid Gibson #ifdef TARGET_PPC64 861a7a00a72SDavid Gibson for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 862a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; 863a7a00a72SDavid Gibson if (env->slb[i].esid & SLB_ESID_V) { 864a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe |= i; 865a7a00a72SDavid Gibson } 866a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; 867a7a00a72SDavid Gibson } 868a7a00a72SDavid Gibson #endif 869a7a00a72SDavid Gibson 870a7a00a72SDavid Gibson /* Sync SRs */ 871a7a00a72SDavid Gibson for (i = 0; i < 16; i++) { 872a7a00a72SDavid Gibson sregs.u.s.ppc32.sr[i] = env->sr[i]; 873a7a00a72SDavid Gibson } 874a7a00a72SDavid Gibson 875a7a00a72SDavid Gibson /* Sync BATs */ 876a7a00a72SDavid Gibson for (i = 0; i < 8; i++) { 877a7a00a72SDavid Gibson /* Beware. We have to swap upper and lower bits here */ 878a7a00a72SDavid Gibson sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) 879a7a00a72SDavid Gibson | env->DBAT[1][i]; 880a7a00a72SDavid Gibson sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) 881a7a00a72SDavid Gibson | env->IBAT[1][i]; 882a7a00a72SDavid Gibson } 883a7a00a72SDavid Gibson 884a7a00a72SDavid Gibson return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); 885a7a00a72SDavid Gibson } 886a7a00a72SDavid Gibson 88720d695a9SAndreas Färber int kvm_arch_put_registers(CPUState *cs, int level) 888d76d1650Saurel32 { 88920d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 89020d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 891d76d1650Saurel32 struct kvm_regs regs; 892d76d1650Saurel32 int ret; 893d76d1650Saurel32 int i; 894d76d1650Saurel32 8951bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 8961bc22652SAndreas Färber if (ret < 0) { 897d76d1650Saurel32 return ret; 8981bc22652SAndreas Färber } 899d76d1650Saurel32 900d76d1650Saurel32 regs.ctr = env->ctr; 901d76d1650Saurel32 regs.lr = env->lr; 902da91a00fSRichard Henderson regs.xer = cpu_read_xer(env); 903d76d1650Saurel32 regs.msr = env->msr; 904d76d1650Saurel32 regs.pc = env->nip; 905d76d1650Saurel32 906d76d1650Saurel32 regs.srr0 = env->spr[SPR_SRR0]; 907d76d1650Saurel32 regs.srr1 = env->spr[SPR_SRR1]; 908d76d1650Saurel32 909d76d1650Saurel32 regs.sprg0 = env->spr[SPR_SPRG0]; 910d76d1650Saurel32 regs.sprg1 = env->spr[SPR_SPRG1]; 911d76d1650Saurel32 regs.sprg2 = env->spr[SPR_SPRG2]; 912d76d1650Saurel32 regs.sprg3 = env->spr[SPR_SPRG3]; 913d76d1650Saurel32 regs.sprg4 = env->spr[SPR_SPRG4]; 914d76d1650Saurel32 regs.sprg5 = env->spr[SPR_SPRG5]; 915d76d1650Saurel32 regs.sprg6 = env->spr[SPR_SPRG6]; 916d76d1650Saurel32 regs.sprg7 = env->spr[SPR_SPRG7]; 917d76d1650Saurel32 91890dc8812SScott Wood regs.pid = env->spr[SPR_BOOKE_PID]; 91990dc8812SScott Wood 920c995e942SDavid Gibson for (i = 0; i < 32; i++) { 921d76d1650Saurel32 regs.gpr[i] = env->gpr[i]; 922c995e942SDavid Gibson } 923d76d1650Saurel32 9244bddaf55SAlexey Kardashevskiy regs.cr = 0; 9254bddaf55SAlexey Kardashevskiy for (i = 0; i < 8; i++) { 9264bddaf55SAlexey Kardashevskiy regs.cr |= (env->crf[i] & 15) << (4 * (7 - i)); 9274bddaf55SAlexey Kardashevskiy } 9284bddaf55SAlexey Kardashevskiy 9291bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 930c995e942SDavid Gibson if (ret < 0) { 931d76d1650Saurel32 return ret; 932c995e942SDavid Gibson } 933d76d1650Saurel32 93470b79849SDavid Gibson kvm_put_fp(cs); 93570b79849SDavid Gibson 93693dd5e85SScott Wood if (env->tlb_dirty) { 9371bc22652SAndreas Färber kvm_sw_tlb_put(cpu); 93893dd5e85SScott Wood env->tlb_dirty = false; 93993dd5e85SScott Wood } 94093dd5e85SScott Wood 941f1af19d7SDavid Gibson if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) { 942a7a00a72SDavid Gibson ret = kvmppc_put_books_sregs(cpu); 943a7a00a72SDavid Gibson if (ret < 0) { 944f1af19d7SDavid Gibson return ret; 945f1af19d7SDavid Gibson } 946f1af19d7SDavid Gibson } 947f1af19d7SDavid Gibson 948f1af19d7SDavid Gibson if (cap_hior && (level >= KVM_PUT_RESET_STATE)) { 949d67d40eaSDavid Gibson kvm_put_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 950d67d40eaSDavid Gibson } 951f1af19d7SDavid Gibson 952d67d40eaSDavid Gibson if (cap_one_reg) { 953d67d40eaSDavid Gibson int i; 954d67d40eaSDavid Gibson 955c995e942SDavid Gibson /* 956c995e942SDavid Gibson * We deliberately ignore errors here, for kernels which have 957d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 958d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 959c995e942SDavid Gibson * work, at least until we try to migrate. 960c995e942SDavid Gibson */ 961d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 962d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 963d67d40eaSDavid Gibson 964d67d40eaSDavid Gibson if (id != 0) { 965d67d40eaSDavid Gibson kvm_put_one_spr(cs, id, i); 966d67d40eaSDavid Gibson } 967f1af19d7SDavid Gibson } 9689b00ea49SDavid Gibson 9699b00ea49SDavid Gibson #ifdef TARGET_PPC64 97080b3f79bSAlexey Kardashevskiy if (msr_ts) { 97180b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 97280b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 97380b3f79bSAlexey Kardashevskiy } 97480b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 97580b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 97680b3f79bSAlexey Kardashevskiy } 97780b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 97880b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 97980b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 98080b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 98180b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 98280b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 98380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 98480b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 98580b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 98680b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 98780b3f79bSAlexey Kardashevskiy } 98880b3f79bSAlexey Kardashevskiy 9899b00ea49SDavid Gibson if (cap_papr) { 9909b00ea49SDavid Gibson if (kvm_put_vpa(cs) < 0) { 9918d83cbf1SGreg Kurz trace_kvm_failed_put_vpa(); 9929b00ea49SDavid Gibson } 9939b00ea49SDavid Gibson } 99498a8b524SAlexey Kardashevskiy 99598a8b524SAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 996972bd576SAlexey Kardashevskiy 997972bd576SAlexey Kardashevskiy if (level > KVM_PUT_RUNTIME_STATE) { 998972bd576SAlexey Kardashevskiy kvm_put_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES); 999972bd576SAlexey Kardashevskiy } 10009b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 1001f1af19d7SDavid Gibson } 1002f1af19d7SDavid Gibson 1003d76d1650Saurel32 return ret; 1004d76d1650Saurel32 } 1005d76d1650Saurel32 1006c371c2e3SBharat Bhushan static void kvm_sync_excp(CPUPPCState *env, int vector, int ivor) 1007c371c2e3SBharat Bhushan { 1008c371c2e3SBharat Bhushan env->excp_vectors[vector] = env->spr[ivor] + env->spr[SPR_BOOKE_IVPR]; 1009c371c2e3SBharat Bhushan } 1010c371c2e3SBharat Bhushan 1011a7a00a72SDavid Gibson static int kvmppc_get_booke_sregs(PowerPCCPU *cpu) 1012d76d1650Saurel32 { 101320d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1014ba5e5090SAlexander Graf struct kvm_sregs sregs; 1015a7a00a72SDavid Gibson int ret; 1016d76d1650Saurel32 1017a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 101890dc8812SScott Wood if (ret < 0) { 101990dc8812SScott Wood return ret; 102090dc8812SScott Wood } 102190dc8812SScott Wood 102290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_BASE) { 102390dc8812SScott Wood env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0; 102490dc8812SScott Wood env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1; 102590dc8812SScott Wood env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr; 102690dc8812SScott Wood env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear; 102790dc8812SScott Wood env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr; 102890dc8812SScott Wood env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr; 102990dc8812SScott Wood env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr; 103090dc8812SScott Wood env->spr[SPR_DECR] = sregs.u.e.dec; 103190dc8812SScott Wood env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff; 103290dc8812SScott Wood env->spr[SPR_TBU] = sregs.u.e.tb >> 32; 103390dc8812SScott Wood env->spr[SPR_VRSAVE] = sregs.u.e.vrsave; 103490dc8812SScott Wood } 103590dc8812SScott Wood 103690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206) { 103790dc8812SScott Wood env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir; 103890dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0; 103990dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1; 104090dc8812SScott Wood env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar; 104190dc8812SScott Wood env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr; 104290dc8812SScott Wood } 104390dc8812SScott Wood 104490dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_64) { 104590dc8812SScott Wood env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr; 104690dc8812SScott Wood } 104790dc8812SScott Wood 104890dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPRG8) { 104990dc8812SScott Wood env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8; 105090dc8812SScott Wood } 105190dc8812SScott Wood 105290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_IVOR) { 105390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0]; 1054c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_CRITICAL, SPR_BOOKE_IVOR0); 105590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1]; 1056c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_MCHECK, SPR_BOOKE_IVOR1); 105790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2]; 1058c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DSI, SPR_BOOKE_IVOR2); 105990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3]; 1060c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ISI, SPR_BOOKE_IVOR3); 106190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4]; 1062c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EXTERNAL, SPR_BOOKE_IVOR4); 106390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5]; 1064c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ALIGN, SPR_BOOKE_IVOR5); 106590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6]; 1066c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_PROGRAM, SPR_BOOKE_IVOR6); 106790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7]; 1068c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FPU, SPR_BOOKE_IVOR7); 106990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8]; 1070c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SYSCALL, SPR_BOOKE_IVOR8); 107190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9]; 1072c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_APU, SPR_BOOKE_IVOR9); 107390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10]; 1074c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DECR, SPR_BOOKE_IVOR10); 107590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11]; 1076c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FIT, SPR_BOOKE_IVOR11); 107790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12]; 1078c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_WDT, SPR_BOOKE_IVOR12); 107990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13]; 1080c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DTLB, SPR_BOOKE_IVOR13); 108190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14]; 1082c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ITLB, SPR_BOOKE_IVOR14); 108390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15]; 1084c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DEBUG, SPR_BOOKE_IVOR15); 108590dc8812SScott Wood 108690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPE) { 108790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0]; 1088c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SPEU, SPR_BOOKE_IVOR32); 108990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1]; 1090c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPDI, SPR_BOOKE_IVOR33); 109190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2]; 1092c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPRI, SPR_BOOKE_IVOR34); 109390dc8812SScott Wood } 109490dc8812SScott Wood 109590dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PM) { 109690dc8812SScott Wood env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3]; 1097c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EPERFM, SPR_BOOKE_IVOR35); 109890dc8812SScott Wood } 109990dc8812SScott Wood 110090dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PC) { 110190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4]; 1102c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORI, SPR_BOOKE_IVOR36); 110390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5]; 1104c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORCI, SPR_BOOKE_IVOR37); 110590dc8812SScott Wood } 110690dc8812SScott Wood } 110790dc8812SScott Wood 110890dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) { 110990dc8812SScott Wood env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0; 111090dc8812SScott Wood env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1; 111190dc8812SScott Wood env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2; 111290dc8812SScott Wood env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff; 111390dc8812SScott Wood env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4; 111490dc8812SScott Wood env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6; 111590dc8812SScott Wood env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32; 111690dc8812SScott Wood env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg; 111790dc8812SScott Wood env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0]; 111890dc8812SScott Wood env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1]; 111990dc8812SScott Wood } 112090dc8812SScott Wood 112190dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_EXP) { 112290dc8812SScott Wood env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr; 112390dc8812SScott Wood } 112490dc8812SScott Wood 112590dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PD) { 112690dc8812SScott Wood env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc; 112790dc8812SScott Wood env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc; 112890dc8812SScott Wood } 112990dc8812SScott Wood 113090dc8812SScott Wood if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) { 113190dc8812SScott Wood env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr; 113290dc8812SScott Wood env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar; 113390dc8812SScott Wood env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0; 113490dc8812SScott Wood 113590dc8812SScott Wood if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) { 113690dc8812SScott Wood env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1; 113790dc8812SScott Wood env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2; 113890dc8812SScott Wood } 113990dc8812SScott Wood } 1140a7a00a72SDavid Gibson 1141a7a00a72SDavid Gibson return 0; 1142fafc0b6aSAlexander Graf } 114390dc8812SScott Wood 1144a7a00a72SDavid Gibson static int kvmppc_get_books_sregs(PowerPCCPU *cpu) 1145a7a00a72SDavid Gibson { 1146a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1147a7a00a72SDavid Gibson struct kvm_sregs sregs; 1148a7a00a72SDavid Gibson int ret; 1149a7a00a72SDavid Gibson int i; 1150a7a00a72SDavid Gibson 1151a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 115290dc8812SScott Wood if (ret < 0) { 115390dc8812SScott Wood return ret; 115490dc8812SScott Wood } 115590dc8812SScott Wood 1156e57ca75cSDavid Gibson if (!cpu->vhyp) { 1157bb593904SDavid Gibson ppc_store_sdr1(env, sregs.u.s.sdr1); 1158f3c75d42SAneesh Kumar K.V } 1159ba5e5090SAlexander Graf 1160ba5e5090SAlexander Graf /* Sync SLB */ 116182c09f2fSAlexander Graf #ifdef TARGET_PPC64 11624b4d4a21SAneesh Kumar K.V /* 11634b4d4a21SAneesh Kumar K.V * The packed SLB array we get from KVM_GET_SREGS only contains 1164a7a00a72SDavid Gibson * information about valid entries. So we flush our internal copy 1165a7a00a72SDavid Gibson * to get rid of stale ones, then put all valid SLB entries back 1166a7a00a72SDavid Gibson * in. 11674b4d4a21SAneesh Kumar K.V */ 11684b4d4a21SAneesh Kumar K.V memset(env->slb, 0, sizeof(env->slb)); 1169d83af167SAneesh Kumar K.V for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 11704b4d4a21SAneesh Kumar K.V target_ulong rb = sregs.u.s.ppc64.slb[i].slbe; 11714b4d4a21SAneesh Kumar K.V target_ulong rs = sregs.u.s.ppc64.slb[i].slbv; 11724b4d4a21SAneesh Kumar K.V /* 11734b4d4a21SAneesh Kumar K.V * Only restore valid entries 11744b4d4a21SAneesh Kumar K.V */ 11754b4d4a21SAneesh Kumar K.V if (rb & SLB_ESID_V) { 1176bcd81230SDavid Gibson ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs); 11774b4d4a21SAneesh Kumar K.V } 1178ba5e5090SAlexander Graf } 117982c09f2fSAlexander Graf #endif 1180ba5e5090SAlexander Graf 1181ba5e5090SAlexander Graf /* Sync SRs */ 1182ba5e5090SAlexander Graf for (i = 0; i < 16; i++) { 1183ba5e5090SAlexander Graf env->sr[i] = sregs.u.s.ppc32.sr[i]; 1184ba5e5090SAlexander Graf } 1185ba5e5090SAlexander Graf 1186ba5e5090SAlexander Graf /* Sync BATs */ 1187ba5e5090SAlexander Graf for (i = 0; i < 8; i++) { 1188ba5e5090SAlexander Graf env->DBAT[0][i] = sregs.u.s.ppc32.dbat[i] & 0xffffffff; 1189ba5e5090SAlexander Graf env->DBAT[1][i] = sregs.u.s.ppc32.dbat[i] >> 32; 1190ba5e5090SAlexander Graf env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff; 1191ba5e5090SAlexander Graf env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32; 1192ba5e5090SAlexander Graf } 1193a7a00a72SDavid Gibson 1194a7a00a72SDavid Gibson return 0; 1195a7a00a72SDavid Gibson } 1196a7a00a72SDavid Gibson 1197a7a00a72SDavid Gibson int kvm_arch_get_registers(CPUState *cs) 1198a7a00a72SDavid Gibson { 1199a7a00a72SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 1200a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1201a7a00a72SDavid Gibson struct kvm_regs regs; 1202a7a00a72SDavid Gibson uint32_t cr; 1203a7a00a72SDavid Gibson int i, ret; 1204a7a00a72SDavid Gibson 1205a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1206c995e942SDavid Gibson if (ret < 0) { 1207a7a00a72SDavid Gibson return ret; 1208c995e942SDavid Gibson } 1209a7a00a72SDavid Gibson 1210a7a00a72SDavid Gibson cr = regs.cr; 1211a7a00a72SDavid Gibson for (i = 7; i >= 0; i--) { 1212a7a00a72SDavid Gibson env->crf[i] = cr & 15; 1213a7a00a72SDavid Gibson cr >>= 4; 1214a7a00a72SDavid Gibson } 1215a7a00a72SDavid Gibson 1216a7a00a72SDavid Gibson env->ctr = regs.ctr; 1217a7a00a72SDavid Gibson env->lr = regs.lr; 1218a7a00a72SDavid Gibson cpu_write_xer(env, regs.xer); 1219a7a00a72SDavid Gibson env->msr = regs.msr; 1220a7a00a72SDavid Gibson env->nip = regs.pc; 1221a7a00a72SDavid Gibson 1222a7a00a72SDavid Gibson env->spr[SPR_SRR0] = regs.srr0; 1223a7a00a72SDavid Gibson env->spr[SPR_SRR1] = regs.srr1; 1224a7a00a72SDavid Gibson 1225a7a00a72SDavid Gibson env->spr[SPR_SPRG0] = regs.sprg0; 1226a7a00a72SDavid Gibson env->spr[SPR_SPRG1] = regs.sprg1; 1227a7a00a72SDavid Gibson env->spr[SPR_SPRG2] = regs.sprg2; 1228a7a00a72SDavid Gibson env->spr[SPR_SPRG3] = regs.sprg3; 1229a7a00a72SDavid Gibson env->spr[SPR_SPRG4] = regs.sprg4; 1230a7a00a72SDavid Gibson env->spr[SPR_SPRG5] = regs.sprg5; 1231a7a00a72SDavid Gibson env->spr[SPR_SPRG6] = regs.sprg6; 1232a7a00a72SDavid Gibson env->spr[SPR_SPRG7] = regs.sprg7; 1233a7a00a72SDavid Gibson 1234a7a00a72SDavid Gibson env->spr[SPR_BOOKE_PID] = regs.pid; 1235a7a00a72SDavid Gibson 1236c995e942SDavid Gibson for (i = 0; i < 32; i++) { 1237a7a00a72SDavid Gibson env->gpr[i] = regs.gpr[i]; 1238c995e942SDavid Gibson } 1239a7a00a72SDavid Gibson 1240a7a00a72SDavid Gibson kvm_get_fp(cs); 1241a7a00a72SDavid Gibson 1242a7a00a72SDavid Gibson if (cap_booke_sregs) { 1243a7a00a72SDavid Gibson ret = kvmppc_get_booke_sregs(cpu); 1244a7a00a72SDavid Gibson if (ret < 0) { 1245a7a00a72SDavid Gibson return ret; 1246a7a00a72SDavid Gibson } 1247a7a00a72SDavid Gibson } 1248a7a00a72SDavid Gibson 1249a7a00a72SDavid Gibson if (cap_segstate) { 1250a7a00a72SDavid Gibson ret = kvmppc_get_books_sregs(cpu); 1251a7a00a72SDavid Gibson if (ret < 0) { 1252a7a00a72SDavid Gibson return ret; 1253a7a00a72SDavid Gibson } 1254fafc0b6aSAlexander Graf } 1255ba5e5090SAlexander Graf 1256d67d40eaSDavid Gibson if (cap_hior) { 1257d67d40eaSDavid Gibson kvm_get_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 1258d67d40eaSDavid Gibson } 1259d67d40eaSDavid Gibson 1260d67d40eaSDavid Gibson if (cap_one_reg) { 1261d67d40eaSDavid Gibson int i; 1262d67d40eaSDavid Gibson 1263c995e942SDavid Gibson /* 1264c995e942SDavid Gibson * We deliberately ignore errors here, for kernels which have 1265d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 1266d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 1267c995e942SDavid Gibson * work, at least until we try to migrate. 1268c995e942SDavid Gibson */ 1269d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 1270d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 1271d67d40eaSDavid Gibson 1272d67d40eaSDavid Gibson if (id != 0) { 1273d67d40eaSDavid Gibson kvm_get_one_spr(cs, id, i); 1274d67d40eaSDavid Gibson } 1275d67d40eaSDavid Gibson } 12769b00ea49SDavid Gibson 12779b00ea49SDavid Gibson #ifdef TARGET_PPC64 127880b3f79bSAlexey Kardashevskiy if (msr_ts) { 127980b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 128080b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 128180b3f79bSAlexey Kardashevskiy } 128280b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 128380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 128480b3f79bSAlexey Kardashevskiy } 128580b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 128680b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 128780b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 128880b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 128980b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 129080b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 129180b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 129280b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 129380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 129480b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 129580b3f79bSAlexey Kardashevskiy } 129680b3f79bSAlexey Kardashevskiy 12979b00ea49SDavid Gibson if (cap_papr) { 12989b00ea49SDavid Gibson if (kvm_get_vpa(cs) < 0) { 12998d83cbf1SGreg Kurz trace_kvm_failed_get_vpa(); 13009b00ea49SDavid Gibson } 13019b00ea49SDavid Gibson } 130298a8b524SAlexey Kardashevskiy 130398a8b524SAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 1304972bd576SAlexey Kardashevskiy kvm_get_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES); 13059b00ea49SDavid Gibson #endif 1306d67d40eaSDavid Gibson } 1307d67d40eaSDavid Gibson 1308d76d1650Saurel32 return 0; 1309d76d1650Saurel32 } 1310d76d1650Saurel32 13111bc22652SAndreas Färber int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level) 1312fc87e185SAlexander Graf { 1313fc87e185SAlexander Graf unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET; 1314fc87e185SAlexander Graf 1315fc87e185SAlexander Graf if (irq != PPC_INTERRUPT_EXT) { 1316fc87e185SAlexander Graf return 0; 1317fc87e185SAlexander Graf } 1318fc87e185SAlexander Graf 13191e8f51e8SShivaprasad G Bhat if (!kvm_enabled() || !cap_interrupt_unset) { 1320fc87e185SAlexander Graf return 0; 1321fc87e185SAlexander Graf } 1322fc87e185SAlexander Graf 13231bc22652SAndreas Färber kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); 1324fc87e185SAlexander Graf 1325fc87e185SAlexander Graf return 0; 1326fc87e185SAlexander Graf } 1327fc87e185SAlexander Graf 1328a69dc537SThomas Huth #if defined(TARGET_PPC64) 132916415335SAlexander Graf #define PPC_INPUT_INT PPC970_INPUT_INT 133016415335SAlexander Graf #else 133116415335SAlexander Graf #define PPC_INPUT_INT PPC6xx_INPUT_INT 133216415335SAlexander Graf #endif 133316415335SAlexander Graf 133420d695a9SAndreas Färber void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 1335d76d1650Saurel32 { 13361e8f51e8SShivaprasad G Bhat return; 1337d76d1650Saurel32 } 1338d76d1650Saurel32 13394c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 1340d76d1650Saurel32 { 13414c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 1342d76d1650Saurel32 } 1343d76d1650Saurel32 134420d695a9SAndreas Färber int kvm_arch_process_async_events(CPUState *cs) 13450af691d7SMarcelo Tosatti { 1346259186a7SAndreas Färber return cs->halted; 13470af691d7SMarcelo Tosatti } 13480af691d7SMarcelo Tosatti 1349259186a7SAndreas Färber static int kvmppc_handle_halt(PowerPCCPU *cpu) 1350d76d1650Saurel32 { 1351259186a7SAndreas Färber CPUState *cs = CPU(cpu); 1352259186a7SAndreas Färber CPUPPCState *env = &cpu->env; 1353259186a7SAndreas Färber 1354259186a7SAndreas Färber if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) { 1355259186a7SAndreas Färber cs->halted = 1; 135627103424SAndreas Färber cs->exception_index = EXCP_HLT; 1357d76d1650Saurel32 } 1358d76d1650Saurel32 1359bb4ea393SJan Kiszka return 0; 1360d76d1650Saurel32 } 1361d76d1650Saurel32 1362d76d1650Saurel32 /* map dcr access to existing qemu dcr emulation */ 1363c995e942SDavid Gibson static int kvmppc_handle_dcr_read(CPUPPCState *env, 1364c995e942SDavid Gibson uint32_t dcrn, uint32_t *data) 1365d76d1650Saurel32 { 1366c995e942SDavid Gibson if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) { 1367d76d1650Saurel32 fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn); 1368c995e942SDavid Gibson } 1369d76d1650Saurel32 1370bb4ea393SJan Kiszka return 0; 1371d76d1650Saurel32 } 1372d76d1650Saurel32 1373c995e942SDavid Gibson static int kvmppc_handle_dcr_write(CPUPPCState *env, 1374c995e942SDavid Gibson uint32_t dcrn, uint32_t data) 1375d76d1650Saurel32 { 1376c995e942SDavid Gibson if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) { 1377d76d1650Saurel32 fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn); 1378c995e942SDavid Gibson } 1379d76d1650Saurel32 1380bb4ea393SJan Kiszka return 0; 1381d76d1650Saurel32 } 1382d76d1650Saurel32 13838a0548f9SBharat Bhushan int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 13848a0548f9SBharat Bhushan { 13858a0548f9SBharat Bhushan /* Mixed endian case is not handled */ 13868a0548f9SBharat Bhushan uint32_t sc = debug_inst_opcode; 13878a0548f9SBharat Bhushan 13888a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 13898a0548f9SBharat Bhushan sizeof(sc), 0) || 13908a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 1)) { 13918a0548f9SBharat Bhushan return -EINVAL; 13928a0548f9SBharat Bhushan } 13938a0548f9SBharat Bhushan 13948a0548f9SBharat Bhushan return 0; 13958a0548f9SBharat Bhushan } 13968a0548f9SBharat Bhushan 13978a0548f9SBharat Bhushan int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 13988a0548f9SBharat Bhushan { 13998a0548f9SBharat Bhushan uint32_t sc; 14008a0548f9SBharat Bhushan 14018a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 0) || 14028a0548f9SBharat Bhushan sc != debug_inst_opcode || 14038a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 14048a0548f9SBharat Bhushan sizeof(sc), 1)) { 14058a0548f9SBharat Bhushan return -EINVAL; 14068a0548f9SBharat Bhushan } 14078a0548f9SBharat Bhushan 14088a0548f9SBharat Bhushan return 0; 14098a0548f9SBharat Bhushan } 14108a0548f9SBharat Bhushan 141188365d17SBharat Bhushan static int find_hw_breakpoint(target_ulong addr, int type) 141288365d17SBharat Bhushan { 141388365d17SBharat Bhushan int n; 141488365d17SBharat Bhushan 141588365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 141688365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 141788365d17SBharat Bhushan 141888365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 141988365d17SBharat Bhushan if (hw_debug_points[n].addr == addr && 142088365d17SBharat Bhushan hw_debug_points[n].type == type) { 142188365d17SBharat Bhushan return n; 142288365d17SBharat Bhushan } 142388365d17SBharat Bhushan } 142488365d17SBharat Bhushan 142588365d17SBharat Bhushan return -1; 142688365d17SBharat Bhushan } 142788365d17SBharat Bhushan 142888365d17SBharat Bhushan static int find_hw_watchpoint(target_ulong addr, int *flag) 142988365d17SBharat Bhushan { 143088365d17SBharat Bhushan int n; 143188365d17SBharat Bhushan 143288365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_ACCESS); 143388365d17SBharat Bhushan if (n >= 0) { 143488365d17SBharat Bhushan *flag = BP_MEM_ACCESS; 143588365d17SBharat Bhushan return n; 143688365d17SBharat Bhushan } 143788365d17SBharat Bhushan 143888365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_WRITE); 143988365d17SBharat Bhushan if (n >= 0) { 144088365d17SBharat Bhushan *flag = BP_MEM_WRITE; 144188365d17SBharat Bhushan return n; 144288365d17SBharat Bhushan } 144388365d17SBharat Bhushan 144488365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_READ); 144588365d17SBharat Bhushan if (n >= 0) { 144688365d17SBharat Bhushan *flag = BP_MEM_READ; 144788365d17SBharat Bhushan return n; 144888365d17SBharat Bhushan } 144988365d17SBharat Bhushan 145088365d17SBharat Bhushan return -1; 145188365d17SBharat Bhushan } 145288365d17SBharat Bhushan 145388365d17SBharat Bhushan int kvm_arch_insert_hw_breakpoint(target_ulong addr, 145488365d17SBharat Bhushan target_ulong len, int type) 145588365d17SBharat Bhushan { 145688365d17SBharat Bhushan if ((nb_hw_breakpoint + nb_hw_watchpoint) >= ARRAY_SIZE(hw_debug_points)) { 145788365d17SBharat Bhushan return -ENOBUFS; 145888365d17SBharat Bhushan } 145988365d17SBharat Bhushan 146088365d17SBharat Bhushan hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].addr = addr; 146188365d17SBharat Bhushan hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].type = type; 146288365d17SBharat Bhushan 146388365d17SBharat Bhushan switch (type) { 146488365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 146588365d17SBharat Bhushan if (nb_hw_breakpoint >= max_hw_breakpoint) { 146688365d17SBharat Bhushan return -ENOBUFS; 146788365d17SBharat Bhushan } 146888365d17SBharat Bhushan 146988365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 147088365d17SBharat Bhushan return -EEXIST; 147188365d17SBharat Bhushan } 147288365d17SBharat Bhushan 147388365d17SBharat Bhushan nb_hw_breakpoint++; 147488365d17SBharat Bhushan break; 147588365d17SBharat Bhushan 147688365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 147788365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 147888365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 147988365d17SBharat Bhushan if (nb_hw_watchpoint >= max_hw_watchpoint) { 148088365d17SBharat Bhushan return -ENOBUFS; 148188365d17SBharat Bhushan } 148288365d17SBharat Bhushan 148388365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 148488365d17SBharat Bhushan return -EEXIST; 148588365d17SBharat Bhushan } 148688365d17SBharat Bhushan 148788365d17SBharat Bhushan nb_hw_watchpoint++; 148888365d17SBharat Bhushan break; 148988365d17SBharat Bhushan 149088365d17SBharat Bhushan default: 149188365d17SBharat Bhushan return -ENOSYS; 149288365d17SBharat Bhushan } 149388365d17SBharat Bhushan 149488365d17SBharat Bhushan return 0; 149588365d17SBharat Bhushan } 149688365d17SBharat Bhushan 149788365d17SBharat Bhushan int kvm_arch_remove_hw_breakpoint(target_ulong addr, 149888365d17SBharat Bhushan target_ulong len, int type) 149988365d17SBharat Bhushan { 150088365d17SBharat Bhushan int n; 150188365d17SBharat Bhushan 150288365d17SBharat Bhushan n = find_hw_breakpoint(addr, type); 150388365d17SBharat Bhushan if (n < 0) { 150488365d17SBharat Bhushan return -ENOENT; 150588365d17SBharat Bhushan } 150688365d17SBharat Bhushan 150788365d17SBharat Bhushan switch (type) { 150888365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 150988365d17SBharat Bhushan nb_hw_breakpoint--; 151088365d17SBharat Bhushan break; 151188365d17SBharat Bhushan 151288365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 151388365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 151488365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 151588365d17SBharat Bhushan nb_hw_watchpoint--; 151688365d17SBharat Bhushan break; 151788365d17SBharat Bhushan 151888365d17SBharat Bhushan default: 151988365d17SBharat Bhushan return -ENOSYS; 152088365d17SBharat Bhushan } 152188365d17SBharat Bhushan hw_debug_points[n] = hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint]; 152288365d17SBharat Bhushan 152388365d17SBharat Bhushan return 0; 152488365d17SBharat Bhushan } 152588365d17SBharat Bhushan 152688365d17SBharat Bhushan void kvm_arch_remove_all_hw_breakpoints(void) 152788365d17SBharat Bhushan { 152888365d17SBharat Bhushan nb_hw_breakpoint = nb_hw_watchpoint = 0; 152988365d17SBharat Bhushan } 153088365d17SBharat Bhushan 15318a0548f9SBharat Bhushan void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 15328a0548f9SBharat Bhushan { 153388365d17SBharat Bhushan int n; 153488365d17SBharat Bhushan 15358a0548f9SBharat Bhushan /* Software Breakpoint updates */ 15368a0548f9SBharat Bhushan if (kvm_sw_breakpoints_active(cs)) { 15378a0548f9SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 15388a0548f9SBharat Bhushan } 153988365d17SBharat Bhushan 154088365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 154188365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 154288365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) <= ARRAY_SIZE(dbg->arch.bp)); 154388365d17SBharat Bhushan 154488365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 154588365d17SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; 154688365d17SBharat Bhushan memset(dbg->arch.bp, 0, sizeof(dbg->arch.bp)); 154788365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 154888365d17SBharat Bhushan switch (hw_debug_points[n].type) { 154988365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 155088365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_BREAKPOINT; 155188365d17SBharat Bhushan break; 155288365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 155388365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE; 155488365d17SBharat Bhushan break; 155588365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 155688365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_READ; 155788365d17SBharat Bhushan break; 155888365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 155988365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE | 156088365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_READ; 156188365d17SBharat Bhushan break; 156288365d17SBharat Bhushan default: 156388365d17SBharat Bhushan cpu_abort(cs, "Unsupported breakpoint type\n"); 156488365d17SBharat Bhushan } 156588365d17SBharat Bhushan dbg->arch.bp[n].addr = hw_debug_points[n].addr; 156688365d17SBharat Bhushan } 156788365d17SBharat Bhushan } 15688a0548f9SBharat Bhushan } 15698a0548f9SBharat Bhushan 15702cbd1581SFabiano Rosas static int kvm_handle_hw_breakpoint(CPUState *cs, 15712cbd1581SFabiano Rosas struct kvm_debug_exit_arch *arch_info) 15728a0548f9SBharat Bhushan { 15738a0548f9SBharat Bhushan int handle = 0; 157488365d17SBharat Bhushan int n; 157588365d17SBharat Bhushan int flag = 0; 15768a0548f9SBharat Bhushan 157788365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 157888365d17SBharat Bhushan if (arch_info->status & KVMPPC_DEBUG_BREAKPOINT) { 157988365d17SBharat Bhushan n = find_hw_breakpoint(arch_info->address, GDB_BREAKPOINT_HW); 158088365d17SBharat Bhushan if (n >= 0) { 158188365d17SBharat Bhushan handle = 1; 158288365d17SBharat Bhushan } 158388365d17SBharat Bhushan } else if (arch_info->status & (KVMPPC_DEBUG_WATCH_READ | 158488365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_WRITE)) { 158588365d17SBharat Bhushan n = find_hw_watchpoint(arch_info->address, &flag); 158688365d17SBharat Bhushan if (n >= 0) { 158788365d17SBharat Bhushan handle = 1; 158888365d17SBharat Bhushan cs->watchpoint_hit = &hw_watchpoint; 158988365d17SBharat Bhushan hw_watchpoint.vaddr = hw_debug_points[n].addr; 159088365d17SBharat Bhushan hw_watchpoint.flags = flag; 159188365d17SBharat Bhushan } 159288365d17SBharat Bhushan } 159388365d17SBharat Bhushan } 15942cbd1581SFabiano Rosas return handle; 15952cbd1581SFabiano Rosas } 15962cbd1581SFabiano Rosas 1597468e3a1aSFabiano Rosas static int kvm_handle_singlestep(void) 1598468e3a1aSFabiano Rosas { 1599468e3a1aSFabiano Rosas return 1; 1600468e3a1aSFabiano Rosas } 1601468e3a1aSFabiano Rosas 1602468e3a1aSFabiano Rosas static int kvm_handle_sw_breakpoint(void) 1603468e3a1aSFabiano Rosas { 1604468e3a1aSFabiano Rosas return 1; 1605468e3a1aSFabiano Rosas } 1606468e3a1aSFabiano Rosas 16072cbd1581SFabiano Rosas static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) 16082cbd1581SFabiano Rosas { 16092cbd1581SFabiano Rosas CPUState *cs = CPU(cpu); 16102cbd1581SFabiano Rosas CPUPPCState *env = &cpu->env; 16112cbd1581SFabiano Rosas struct kvm_debug_exit_arch *arch_info = &run->debug.arch; 16122cbd1581SFabiano Rosas 16132cbd1581SFabiano Rosas if (cs->singlestep_enabled) { 1614468e3a1aSFabiano Rosas return kvm_handle_singlestep(); 1615468e3a1aSFabiano Rosas } 1616468e3a1aSFabiano Rosas 1617468e3a1aSFabiano Rosas if (arch_info->status) { 1618468e3a1aSFabiano Rosas return kvm_handle_hw_breakpoint(cs, arch_info); 1619468e3a1aSFabiano Rosas } 1620468e3a1aSFabiano Rosas 1621468e3a1aSFabiano Rosas if (kvm_find_sw_breakpoint(cs, arch_info->address)) { 1622468e3a1aSFabiano Rosas return kvm_handle_sw_breakpoint(); 1623468e3a1aSFabiano Rosas } 1624468e3a1aSFabiano Rosas 1625468e3a1aSFabiano Rosas /* 1626468e3a1aSFabiano Rosas * QEMU is not able to handle debug exception, so inject 16278a0548f9SBharat Bhushan * program exception to guest; 16288a0548f9SBharat Bhushan * Yes program exception NOT debug exception !! 162988365d17SBharat Bhushan * When QEMU is using debug resources then debug exception must 163088365d17SBharat Bhushan * be always set. To achieve this we set MSR_DE and also set 163188365d17SBharat Bhushan * MSRP_DEP so guest cannot change MSR_DE. 163288365d17SBharat Bhushan * When emulating debug resource for guest we want guest 163388365d17SBharat Bhushan * to control MSR_DE (enable/disable debug interrupt on need). 163488365d17SBharat Bhushan * Supporting both configurations are NOT possible. 163588365d17SBharat Bhushan * So the result is that we cannot share debug resources 163688365d17SBharat Bhushan * between QEMU and Guest on BOOKE architecture. 163788365d17SBharat Bhushan * In the current design QEMU gets the priority over guest, 163888365d17SBharat Bhushan * this means that if QEMU is using debug resources then guest 163988365d17SBharat Bhushan * cannot use them; 16408a0548f9SBharat Bhushan * For software breakpoint QEMU uses a privileged instruction; 16418a0548f9SBharat Bhushan * So there cannot be any reason that we are here for guest 16428a0548f9SBharat Bhushan * set debug exception, only possibility is guest executed a 16438a0548f9SBharat Bhushan * privileged / illegal instruction and that's why we are 16448a0548f9SBharat Bhushan * injecting a program interrupt. 16458a0548f9SBharat Bhushan */ 16468a0548f9SBharat Bhushan cpu_synchronize_state(cs); 1647468e3a1aSFabiano Rosas /* 1648468e3a1aSFabiano Rosas * env->nip is PC, so increment this by 4 to use 16498a0548f9SBharat Bhushan * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4. 16508a0548f9SBharat Bhushan */ 16518a0548f9SBharat Bhushan env->nip += 4; 16528a0548f9SBharat Bhushan cs->exception_index = POWERPC_EXCP_PROGRAM; 16538a0548f9SBharat Bhushan env->error_code = POWERPC_EXCP_INVAL; 16548a0548f9SBharat Bhushan ppc_cpu_do_interrupt(cs); 16558a0548f9SBharat Bhushan 1656468e3a1aSFabiano Rosas return 0; 16578a0548f9SBharat Bhushan } 16588a0548f9SBharat Bhushan 165920d695a9SAndreas Färber int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 1660d76d1650Saurel32 { 166120d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 166220d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1663bb4ea393SJan Kiszka int ret; 1664d76d1650Saurel32 16654b8523eeSJan Kiszka qemu_mutex_lock_iothread(); 16664b8523eeSJan Kiszka 1667d76d1650Saurel32 switch (run->exit_reason) { 1668d76d1650Saurel32 case KVM_EXIT_DCR: 1669d76d1650Saurel32 if (run->dcr.is_write) { 16708d83cbf1SGreg Kurz trace_kvm_handle_dcr_write(); 1671d76d1650Saurel32 ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); 1672d76d1650Saurel32 } else { 1673228152c2SBoxuan Li trace_kvm_handle_dcr_read(); 1674d76d1650Saurel32 ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); 1675d76d1650Saurel32 } 1676d76d1650Saurel32 break; 1677d76d1650Saurel32 case KVM_EXIT_HLT: 16788d83cbf1SGreg Kurz trace_kvm_handle_halt(); 1679259186a7SAndreas Färber ret = kvmppc_handle_halt(cpu); 1680d76d1650Saurel32 break; 1681c6304a4aSDavid Gibson #if defined(TARGET_PPC64) 1682f61b4bedSAlexander Graf case KVM_EXIT_PAPR_HCALL: 16838d83cbf1SGreg Kurz trace_kvm_handle_papr_hcall(); 168420d695a9SAndreas Färber run->papr_hcall.ret = spapr_hypercall(cpu, 1685aa100fa4SAndreas Färber run->papr_hcall.nr, 1686f61b4bedSAlexander Graf run->papr_hcall.args); 168778e8fde2SDavid Gibson ret = 0; 1688f61b4bedSAlexander Graf break; 1689f61b4bedSAlexander Graf #endif 16905b95b8b9SAlexander Graf case KVM_EXIT_EPR: 16918d83cbf1SGreg Kurz trace_kvm_handle_epr(); 1692933b19eaSAlexander Graf run->epr.epr = ldl_phys(cs->as, env->mpic_iack); 16935b95b8b9SAlexander Graf ret = 0; 16945b95b8b9SAlexander Graf break; 169531f2cb8fSBharat Bhushan case KVM_EXIT_WATCHDOG: 16968d83cbf1SGreg Kurz trace_kvm_handle_watchdog_expiry(); 169731f2cb8fSBharat Bhushan watchdog_perform_action(); 169831f2cb8fSBharat Bhushan ret = 0; 169931f2cb8fSBharat Bhushan break; 170031f2cb8fSBharat Bhushan 17018a0548f9SBharat Bhushan case KVM_EXIT_DEBUG: 17028d83cbf1SGreg Kurz trace_kvm_handle_debug_exception(); 17038a0548f9SBharat Bhushan if (kvm_handle_debug(cpu, run)) { 17048a0548f9SBharat Bhushan ret = EXCP_DEBUG; 17058a0548f9SBharat Bhushan break; 17068a0548f9SBharat Bhushan } 17078a0548f9SBharat Bhushan /* re-enter, this exception was guest-internal */ 17088a0548f9SBharat Bhushan ret = 0; 17098a0548f9SBharat Bhushan break; 17108a0548f9SBharat Bhushan 171173aaec4aSJan Kiszka default: 171273aaec4aSJan Kiszka fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); 171373aaec4aSJan Kiszka ret = -1; 171473aaec4aSJan Kiszka break; 1715d76d1650Saurel32 } 1716d76d1650Saurel32 17174b8523eeSJan Kiszka qemu_mutex_unlock_iothread(); 1718d76d1650Saurel32 return ret; 1719d76d1650Saurel32 } 1720d76d1650Saurel32 172131f2cb8fSBharat Bhushan int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 172231f2cb8fSBharat Bhushan { 172331f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 172431f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 172531f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 172631f2cb8fSBharat Bhushan .id = KVM_REG_PPC_OR_TSR, 172731f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 172831f2cb8fSBharat Bhushan }; 172931f2cb8fSBharat Bhushan 173031f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 173131f2cb8fSBharat Bhushan } 173231f2cb8fSBharat Bhushan 173331f2cb8fSBharat Bhushan int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 173431f2cb8fSBharat Bhushan { 173531f2cb8fSBharat Bhushan 173631f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 173731f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 173831f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 173931f2cb8fSBharat Bhushan .id = KVM_REG_PPC_CLEAR_TSR, 174031f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 174131f2cb8fSBharat Bhushan }; 174231f2cb8fSBharat Bhushan 174331f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 174431f2cb8fSBharat Bhushan } 174531f2cb8fSBharat Bhushan 174631f2cb8fSBharat Bhushan int kvmppc_set_tcr(PowerPCCPU *cpu) 174731f2cb8fSBharat Bhushan { 174831f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 174931f2cb8fSBharat Bhushan CPUPPCState *env = &cpu->env; 175031f2cb8fSBharat Bhushan uint32_t tcr = env->spr[SPR_BOOKE_TCR]; 175131f2cb8fSBharat Bhushan 175231f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 175331f2cb8fSBharat Bhushan .id = KVM_REG_PPC_TCR, 175431f2cb8fSBharat Bhushan .addr = (uintptr_t) &tcr, 175531f2cb8fSBharat Bhushan }; 175631f2cb8fSBharat Bhushan 175731f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 175831f2cb8fSBharat Bhushan } 175931f2cb8fSBharat Bhushan 176031f2cb8fSBharat Bhushan int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu) 176131f2cb8fSBharat Bhushan { 176231f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 176331f2cb8fSBharat Bhushan int ret; 176431f2cb8fSBharat Bhushan 176531f2cb8fSBharat Bhushan if (!kvm_enabled()) { 176631f2cb8fSBharat Bhushan return -1; 176731f2cb8fSBharat Bhushan } 176831f2cb8fSBharat Bhushan 176931f2cb8fSBharat Bhushan if (!cap_ppc_watchdog) { 177031f2cb8fSBharat Bhushan printf("warning: KVM does not support watchdog"); 177131f2cb8fSBharat Bhushan return -1; 177231f2cb8fSBharat Bhushan } 177331f2cb8fSBharat Bhushan 177448add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_BOOKE_WATCHDOG, 0); 177531f2cb8fSBharat Bhushan if (ret < 0) { 177631f2cb8fSBharat Bhushan fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n", 177731f2cb8fSBharat Bhushan __func__, strerror(-ret)); 177831f2cb8fSBharat Bhushan return ret; 177931f2cb8fSBharat Bhushan } 178031f2cb8fSBharat Bhushan 178131f2cb8fSBharat Bhushan return ret; 178231f2cb8fSBharat Bhushan } 178331f2cb8fSBharat Bhushan 1784dc333cd6SAlexander Graf static int read_cpuinfo(const char *field, char *value, int len) 1785dc333cd6SAlexander Graf { 1786dc333cd6SAlexander Graf FILE *f; 1787dc333cd6SAlexander Graf int ret = -1; 1788dc333cd6SAlexander Graf int field_len = strlen(field); 1789dc333cd6SAlexander Graf char line[512]; 1790dc333cd6SAlexander Graf 1791dc333cd6SAlexander Graf f = fopen("/proc/cpuinfo", "r"); 1792dc333cd6SAlexander Graf if (!f) { 1793dc333cd6SAlexander Graf return -1; 1794dc333cd6SAlexander Graf } 1795dc333cd6SAlexander Graf 1796dc333cd6SAlexander Graf do { 1797dc333cd6SAlexander Graf if (!fgets(line, sizeof(line), f)) { 1798dc333cd6SAlexander Graf break; 1799dc333cd6SAlexander Graf } 1800dc333cd6SAlexander Graf if (!strncmp(line, field, field_len)) { 1801ae215068SJim Meyering pstrcpy(value, len, line); 1802dc333cd6SAlexander Graf ret = 0; 1803dc333cd6SAlexander Graf break; 1804dc333cd6SAlexander Graf } 1805dc333cd6SAlexander Graf } while (*line); 1806dc333cd6SAlexander Graf 1807dc333cd6SAlexander Graf fclose(f); 1808dc333cd6SAlexander Graf 1809dc333cd6SAlexander Graf return ret; 1810dc333cd6SAlexander Graf } 1811dc333cd6SAlexander Graf 1812dc333cd6SAlexander Graf uint32_t kvmppc_get_tbfreq(void) 1813dc333cd6SAlexander Graf { 1814dc333cd6SAlexander Graf char line[512]; 1815dc333cd6SAlexander Graf char *ns; 181673bcb24dSRutuja Shah uint32_t retval = NANOSECONDS_PER_SECOND; 1817dc333cd6SAlexander Graf 1818dc333cd6SAlexander Graf if (read_cpuinfo("timebase", line, sizeof(line))) { 1819dc333cd6SAlexander Graf return retval; 1820dc333cd6SAlexander Graf } 1821dc333cd6SAlexander Graf 1822c995e942SDavid Gibson ns = strchr(line, ':'); 1823c995e942SDavid Gibson if (!ns) { 1824dc333cd6SAlexander Graf return retval; 1825dc333cd6SAlexander Graf } 1826dc333cd6SAlexander Graf 1827dc333cd6SAlexander Graf ns++; 1828dc333cd6SAlexander Graf 1829f9b8e7f6SShraddha Barke return atoi(ns); 1830ef951443SNikunj A Dadhania } 1831ef951443SNikunj A Dadhania 1832ef951443SNikunj A Dadhania bool kvmppc_get_host_serial(char **value) 1833ef951443SNikunj A Dadhania { 1834ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/system-id", value, NULL, 1835ef951443SNikunj A Dadhania NULL); 1836ef951443SNikunj A Dadhania } 1837ef951443SNikunj A Dadhania 1838ef951443SNikunj A Dadhania bool kvmppc_get_host_model(char **value) 1839ef951443SNikunj A Dadhania { 1840ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/model", value, NULL, NULL); 1841dc333cd6SAlexander Graf } 18424513d923SGleb Natapov 1843eadaada1SAlexander Graf /* Try to find a device tree node for a CPU with clock-frequency property */ 1844eadaada1SAlexander Graf static int kvmppc_find_cpu_dt(char *buf, int buf_len) 1845eadaada1SAlexander Graf { 1846eadaada1SAlexander Graf struct dirent *dirp; 1847eadaada1SAlexander Graf DIR *dp; 1848eadaada1SAlexander Graf 1849c995e942SDavid Gibson dp = opendir(PROC_DEVTREE_CPU); 1850c995e942SDavid Gibson if (!dp) { 1851eadaada1SAlexander Graf printf("Can't open directory " PROC_DEVTREE_CPU "\n"); 1852eadaada1SAlexander Graf return -1; 1853eadaada1SAlexander Graf } 1854eadaada1SAlexander Graf 1855eadaada1SAlexander Graf buf[0] = '\0'; 1856eadaada1SAlexander Graf while ((dirp = readdir(dp)) != NULL) { 1857eadaada1SAlexander Graf FILE *f; 1858eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s/clock-frequency", PROC_DEVTREE_CPU, 1859eadaada1SAlexander Graf dirp->d_name); 1860eadaada1SAlexander Graf f = fopen(buf, "r"); 1861eadaada1SAlexander Graf if (f) { 1862eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s", PROC_DEVTREE_CPU, dirp->d_name); 1863eadaada1SAlexander Graf fclose(f); 1864eadaada1SAlexander Graf break; 1865eadaada1SAlexander Graf } 1866eadaada1SAlexander Graf buf[0] = '\0'; 1867eadaada1SAlexander Graf } 1868eadaada1SAlexander Graf closedir(dp); 1869eadaada1SAlexander Graf if (buf[0] == '\0') { 1870eadaada1SAlexander Graf printf("Unknown host!\n"); 1871eadaada1SAlexander Graf return -1; 1872eadaada1SAlexander Graf } 1873eadaada1SAlexander Graf 1874eadaada1SAlexander Graf return 0; 1875eadaada1SAlexander Graf } 1876eadaada1SAlexander Graf 18777d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_dt(const char *filename) 1878eadaada1SAlexander Graf { 18799bc884b7SDavid Gibson union { 18809bc884b7SDavid Gibson uint32_t v32; 18819bc884b7SDavid Gibson uint64_t v64; 18829bc884b7SDavid Gibson } u; 1883eadaada1SAlexander Graf FILE *f; 1884eadaada1SAlexander Graf int len; 1885eadaada1SAlexander Graf 18867d94a30bSSukadev Bhattiprolu f = fopen(filename, "rb"); 1887eadaada1SAlexander Graf if (!f) { 1888eadaada1SAlexander Graf return -1; 1889eadaada1SAlexander Graf } 1890eadaada1SAlexander Graf 18919bc884b7SDavid Gibson len = fread(&u, 1, sizeof(u), f); 1892eadaada1SAlexander Graf fclose(f); 1893eadaada1SAlexander Graf switch (len) { 18949bc884b7SDavid Gibson case 4: 18959bc884b7SDavid Gibson /* property is a 32-bit quantity */ 18969bc884b7SDavid Gibson return be32_to_cpu(u.v32); 18979bc884b7SDavid Gibson case 8: 18989bc884b7SDavid Gibson return be64_to_cpu(u.v64); 1899eadaada1SAlexander Graf } 1900eadaada1SAlexander Graf 1901eadaada1SAlexander Graf return 0; 1902eadaada1SAlexander Graf } 1903eadaada1SAlexander Graf 1904c995e942SDavid Gibson /* 1905c995e942SDavid Gibson * Read a CPU node property from the host device tree that's a single 19067d94a30bSSukadev Bhattiprolu * integer (32-bit or 64-bit). Returns 0 if anything goes wrong 1907c995e942SDavid Gibson * (can't find or open the property, or doesn't understand the format) 1908c995e942SDavid Gibson */ 19097d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_cpu_dt(const char *propname) 19107d94a30bSSukadev Bhattiprolu { 19117d94a30bSSukadev Bhattiprolu char buf[PATH_MAX], *tmp; 19127d94a30bSSukadev Bhattiprolu uint64_t val; 19137d94a30bSSukadev Bhattiprolu 19147d94a30bSSukadev Bhattiprolu if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { 19157d94a30bSSukadev Bhattiprolu return -1; 19167d94a30bSSukadev Bhattiprolu } 19177d94a30bSSukadev Bhattiprolu 19187d94a30bSSukadev Bhattiprolu tmp = g_strdup_printf("%s/%s", buf, propname); 19197d94a30bSSukadev Bhattiprolu val = kvmppc_read_int_dt(tmp); 19207d94a30bSSukadev Bhattiprolu g_free(tmp); 19217d94a30bSSukadev Bhattiprolu 19227d94a30bSSukadev Bhattiprolu return val; 19237d94a30bSSukadev Bhattiprolu } 19247d94a30bSSukadev Bhattiprolu 19259bc884b7SDavid Gibson uint64_t kvmppc_get_clockfreq(void) 19269bc884b7SDavid Gibson { 19279bc884b7SDavid Gibson return kvmppc_read_int_cpu_dt("clock-frequency"); 19289bc884b7SDavid Gibson } 19299bc884b7SDavid Gibson 19307d050527SSuraj Jitindar Singh static int kvmppc_get_dec_bits(void) 19317d050527SSuraj Jitindar Singh { 19327d050527SSuraj Jitindar Singh int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits"); 19337d050527SSuraj Jitindar Singh 19347d050527SSuraj Jitindar Singh if (nr_bits > 0) { 19357d050527SSuraj Jitindar Singh return nr_bits; 19367d050527SSuraj Jitindar Singh } 19377d050527SSuraj Jitindar Singh return 0; 19387d050527SSuraj Jitindar Singh } 19397d050527SSuraj Jitindar Singh 19401a61a9aeSStuart Yoder static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo) 194145024f09SAlexander Graf { 1942db70b311SRichard Henderson CPUState *cs = env_cpu(env); 194345024f09SAlexander Graf 19446fd33a75SAlexander Graf if (kvm_vm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) && 19451a61a9aeSStuart Yoder !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) { 19461a61a9aeSStuart Yoder return 0; 19471a61a9aeSStuart Yoder } 194845024f09SAlexander Graf 19491a61a9aeSStuart Yoder return 1; 19501a61a9aeSStuart Yoder } 19511a61a9aeSStuart Yoder 19521a61a9aeSStuart Yoder int kvmppc_get_hasidle(CPUPPCState *env) 19531a61a9aeSStuart Yoder { 19541a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 19551a61a9aeSStuart Yoder 19561a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo) && 19571a61a9aeSStuart Yoder (pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) { 19581a61a9aeSStuart Yoder return 1; 19591a61a9aeSStuart Yoder } 19601a61a9aeSStuart Yoder 19611a61a9aeSStuart Yoder return 0; 19621a61a9aeSStuart Yoder } 19631a61a9aeSStuart Yoder 19641a61a9aeSStuart Yoder int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) 19651a61a9aeSStuart Yoder { 19661a61a9aeSStuart Yoder uint32_t *hc = (uint32_t *)buf; 19671a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 19681a61a9aeSStuart Yoder 19691a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo)) { 19701a61a9aeSStuart Yoder memcpy(buf, pvinfo.hcall, buf_len); 197145024f09SAlexander Graf return 0; 197245024f09SAlexander Graf } 197345024f09SAlexander Graf 197445024f09SAlexander Graf /* 1975d13fc32eSAlexander Graf * Fallback to always fail hypercalls regardless of endianness: 197645024f09SAlexander Graf * 1977d13fc32eSAlexander Graf * tdi 0,r0,72 (becomes b .+8 in wrong endian, nop in good endian) 197845024f09SAlexander Graf * li r3, -1 1979d13fc32eSAlexander Graf * b .+8 (becomes nop in wrong endian) 1980d13fc32eSAlexander Graf * bswap32(li r3, -1) 198145024f09SAlexander Graf */ 198245024f09SAlexander Graf 1983d13fc32eSAlexander Graf hc[0] = cpu_to_be32(0x08000048); 1984d13fc32eSAlexander Graf hc[1] = cpu_to_be32(0x3860ffff); 1985d13fc32eSAlexander Graf hc[2] = cpu_to_be32(0x48000008); 1986d13fc32eSAlexander Graf hc[3] = cpu_to_be32(bswap32(0x3860ffff)); 198745024f09SAlexander Graf 19880ddbd053SAlexey Kardashevskiy return 1; 198945024f09SAlexander Graf } 199045024f09SAlexander Graf 1991026bfd89SDavid Gibson static inline int kvmppc_enable_hcall(KVMState *s, target_ulong hcall) 1992026bfd89SDavid Gibson { 1993026bfd89SDavid Gibson return kvm_vm_enable_cap(s, KVM_CAP_PPC_ENABLE_HCALL, 0, hcall, 1); 1994026bfd89SDavid Gibson } 1995026bfd89SDavid Gibson 1996026bfd89SDavid Gibson void kvmppc_enable_logical_ci_hcalls(void) 1997026bfd89SDavid Gibson { 1998026bfd89SDavid Gibson /* 1999026bfd89SDavid Gibson * FIXME: it would be nice if we could detect the cases where 2000026bfd89SDavid Gibson * we're using a device which requires the in kernel 2001026bfd89SDavid Gibson * implementation of these hcalls, but the kernel lacks them and 2002026bfd89SDavid Gibson * produce a warning. 2003026bfd89SDavid Gibson */ 2004026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_LOAD); 2005026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_STORE); 2006026bfd89SDavid Gibson } 2007026bfd89SDavid Gibson 2008ef9971ddSAlexey Kardashevskiy void kvmppc_enable_set_mode_hcall(void) 2009ef9971ddSAlexey Kardashevskiy { 2010ef9971ddSAlexey Kardashevskiy kvmppc_enable_hcall(kvm_state, H_SET_MODE); 2011ef9971ddSAlexey Kardashevskiy } 2012ef9971ddSAlexey Kardashevskiy 20135145ad4fSNathan Whitehorn void kvmppc_enable_clear_ref_mod_hcalls(void) 20145145ad4fSNathan Whitehorn { 20155145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_REF); 20165145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD); 20175145ad4fSNathan Whitehorn } 20185145ad4fSNathan Whitehorn 201968f9f708SSuraj Jitindar Singh void kvmppc_enable_h_page_init(void) 202068f9f708SSuraj Jitindar Singh { 202168f9f708SSuraj Jitindar Singh kvmppc_enable_hcall(kvm_state, H_PAGE_INIT); 202268f9f708SSuraj Jitindar Singh } 202368f9f708SSuraj Jitindar Singh 20241bc22652SAndreas Färber void kvmppc_set_papr(PowerPCCPU *cpu) 2025f61b4bedSAlexander Graf { 20261bc22652SAndreas Färber CPUState *cs = CPU(cpu); 2027f61b4bedSAlexander Graf int ret; 2028f61b4bedSAlexander Graf 2029da20aed1SDavid Gibson if (!kvm_enabled()) { 2030da20aed1SDavid Gibson return; 2031da20aed1SDavid Gibson } 2032da20aed1SDavid Gibson 203348add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0); 2034f61b4bedSAlexander Graf if (ret) { 2035072ed5f2SThomas Huth error_report("This vCPU type or KVM version does not support PAPR"); 2036072ed5f2SThomas Huth exit(1); 2037f61b4bedSAlexander Graf } 20389b00ea49SDavid Gibson 2039c995e942SDavid Gibson /* 2040c995e942SDavid Gibson * Update the capability flag so we sync the right information 2041c995e942SDavid Gibson * with kvm 2042c995e942SDavid Gibson */ 20439b00ea49SDavid Gibson cap_papr = 1; 2044f1af19d7SDavid Gibson } 2045f61b4bedSAlexander Graf 2046d6e166c0SDavid Gibson int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr) 20476db5bb0fSAlexey Kardashevskiy { 2048d6e166c0SDavid Gibson return kvm_set_one_reg(CPU(cpu), KVM_REG_PPC_ARCH_COMPAT, &compat_pvr); 20496db5bb0fSAlexey Kardashevskiy } 20506db5bb0fSAlexey Kardashevskiy 20515b95b8b9SAlexander Graf void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy) 20525b95b8b9SAlexander Graf { 20535b95b8b9SAlexander Graf CPUState *cs = CPU(cpu); 20545b95b8b9SAlexander Graf int ret; 20555b95b8b9SAlexander Graf 205648add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_EPR, 0, mpic_proxy); 20575b95b8b9SAlexander Graf if (ret && mpic_proxy) { 2058072ed5f2SThomas Huth error_report("This KVM version does not support EPR"); 2059072ed5f2SThomas Huth exit(1); 20605b95b8b9SAlexander Graf } 20615b95b8b9SAlexander Graf } 20625b95b8b9SAlexander Graf 2063e97c3636SDavid Gibson int kvmppc_smt_threads(void) 2064e97c3636SDavid Gibson { 2065e97c3636SDavid Gibson return cap_ppc_smt ? cap_ppc_smt : 1; 2066e97c3636SDavid Gibson } 2067e97c3636SDavid Gibson 2068fa98fbfcSSam Bobroff int kvmppc_set_smt_threads(int smt) 2069fa98fbfcSSam Bobroff { 2070fa98fbfcSSam Bobroff int ret; 2071fa98fbfcSSam Bobroff 2072fa98fbfcSSam Bobroff ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SMT, 0, smt, 0); 2073fa98fbfcSSam Bobroff if (!ret) { 2074fa98fbfcSSam Bobroff cap_ppc_smt = smt; 2075fa98fbfcSSam Bobroff } 2076fa98fbfcSSam Bobroff return ret; 2077fa98fbfcSSam Bobroff } 2078fa98fbfcSSam Bobroff 2079fa98fbfcSSam Bobroff void kvmppc_hint_smt_possible(Error **errp) 2080fa98fbfcSSam Bobroff { 2081fa98fbfcSSam Bobroff int i; 2082fa98fbfcSSam Bobroff GString *g; 2083fa98fbfcSSam Bobroff char *s; 2084fa98fbfcSSam Bobroff 2085fa98fbfcSSam Bobroff assert(kvm_enabled()); 2086fa98fbfcSSam Bobroff if (cap_ppc_smt_possible) { 2087fa98fbfcSSam Bobroff g = g_string_new("Available VSMT modes:"); 2088fa98fbfcSSam Bobroff for (i = 63; i >= 0; i--) { 2089fa98fbfcSSam Bobroff if ((1UL << i) & cap_ppc_smt_possible) { 2090fa98fbfcSSam Bobroff g_string_append_printf(g, " %lu", (1UL << i)); 2091fa98fbfcSSam Bobroff } 2092fa98fbfcSSam Bobroff } 2093fa98fbfcSSam Bobroff s = g_string_free(g, false); 2094fa98fbfcSSam Bobroff error_append_hint(errp, "%s.\n", s); 2095fa98fbfcSSam Bobroff g_free(s); 2096fa98fbfcSSam Bobroff } else { 2097fa98fbfcSSam Bobroff error_append_hint(errp, 2098fa98fbfcSSam Bobroff "This KVM seems to be too old to support VSMT.\n"); 2099fa98fbfcSSam Bobroff } 2100fa98fbfcSSam Bobroff } 2101fa98fbfcSSam Bobroff 2102fa98fbfcSSam Bobroff 21037f763a5dSDavid Gibson #ifdef TARGET_PPC64 21047f763a5dSDavid Gibson uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift) 21057f763a5dSDavid Gibson { 2106f36951c1SDavid Gibson struct kvm_ppc_smmu_info info; 2107f36951c1SDavid Gibson long rampagesize, best_page_shift; 2108f36951c1SDavid Gibson int i; 2109f36951c1SDavid Gibson 2110c995e942SDavid Gibson /* 2111c995e942SDavid Gibson * Find the largest hardware supported page size that's less than 2112c995e942SDavid Gibson * or equal to the (logical) backing page size of guest RAM 2113c995e942SDavid Gibson */ 2114ab256960SGreg Kurz kvm_get_smmu_info(&info, &error_fatal); 2115905b7ee4SDavid Hildenbrand rampagesize = qemu_minrampagesize(); 2116f36951c1SDavid Gibson best_page_shift = 0; 2117f36951c1SDavid Gibson 2118f36951c1SDavid Gibson for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) { 2119f36951c1SDavid Gibson struct kvm_ppc_one_seg_page_size *sps = &info.sps[i]; 2120f36951c1SDavid Gibson 2121f36951c1SDavid Gibson if (!sps->page_shift) { 2122f36951c1SDavid Gibson continue; 2123f36951c1SDavid Gibson } 2124f36951c1SDavid Gibson 2125f36951c1SDavid Gibson if ((sps->page_shift > best_page_shift) 2126f36951c1SDavid Gibson && ((1UL << sps->page_shift) <= rampagesize)) { 2127f36951c1SDavid Gibson best_page_shift = sps->page_shift; 2128f36951c1SDavid Gibson } 2129f36951c1SDavid Gibson } 2130f36951c1SDavid Gibson 21317f763a5dSDavid Gibson return MIN(current_size, 2132f36951c1SDavid Gibson 1ULL << (best_page_shift + hash_shift - 7)); 21337f763a5dSDavid Gibson } 21347f763a5dSDavid Gibson #endif 21357f763a5dSDavid Gibson 2136da95324eSAlexey Kardashevskiy bool kvmppc_spapr_use_multitce(void) 2137da95324eSAlexey Kardashevskiy { 2138da95324eSAlexey Kardashevskiy return cap_spapr_multitce; 2139da95324eSAlexey Kardashevskiy } 2140da95324eSAlexey Kardashevskiy 21413dc410aeSAlexey Kardashevskiy int kvmppc_spapr_enable_inkernel_multitce(void) 21423dc410aeSAlexey Kardashevskiy { 21433dc410aeSAlexey Kardashevskiy int ret; 21443dc410aeSAlexey Kardashevskiy 21453dc410aeSAlexey Kardashevskiy ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_ENABLE_HCALL, 0, 21463dc410aeSAlexey Kardashevskiy H_PUT_TCE_INDIRECT, 1); 21473dc410aeSAlexey Kardashevskiy if (!ret) { 21483dc410aeSAlexey Kardashevskiy ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_ENABLE_HCALL, 0, 21493dc410aeSAlexey Kardashevskiy H_STUFF_TCE, 1); 21503dc410aeSAlexey Kardashevskiy } 21513dc410aeSAlexey Kardashevskiy 21523dc410aeSAlexey Kardashevskiy return ret; 21533dc410aeSAlexey Kardashevskiy } 21543dc410aeSAlexey Kardashevskiy 2155d6ee2a7cSAlexey Kardashevskiy void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift, 2156d6ee2a7cSAlexey Kardashevskiy uint64_t bus_offset, uint32_t nb_table, 2157d6ee2a7cSAlexey Kardashevskiy int *pfd, bool need_vfio) 21580f5cb298SDavid Gibson { 21590f5cb298SDavid Gibson long len; 21600f5cb298SDavid Gibson int fd; 21610f5cb298SDavid Gibson void *table; 21620f5cb298SDavid Gibson 2163c995e942SDavid Gibson /* 2164c995e942SDavid Gibson * Must set fd to -1 so we don't try to munmap when called for 2165b5aec396SDavid Gibson * destroying the table, which the upper layers -will- do 2166b5aec396SDavid Gibson */ 2167b5aec396SDavid Gibson *pfd = -1; 21686a81dd17SDavid Gibson if (!cap_spapr_tce || (need_vfio && !cap_spapr_vfio)) { 21690f5cb298SDavid Gibson return NULL; 21700f5cb298SDavid Gibson } 21710f5cb298SDavid Gibson 2172d6ee2a7cSAlexey Kardashevskiy if (cap_spapr_tce_64) { 2173d6ee2a7cSAlexey Kardashevskiy struct kvm_create_spapr_tce_64 args = { 2174d6ee2a7cSAlexey Kardashevskiy .liobn = liobn, 2175d6ee2a7cSAlexey Kardashevskiy .page_shift = page_shift, 2176d6ee2a7cSAlexey Kardashevskiy .offset = bus_offset >> page_shift, 2177d6ee2a7cSAlexey Kardashevskiy .size = nb_table, 2178d6ee2a7cSAlexey Kardashevskiy .flags = 0 2179d6ee2a7cSAlexey Kardashevskiy }; 2180d6ee2a7cSAlexey Kardashevskiy fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE_64, &args); 2181d6ee2a7cSAlexey Kardashevskiy if (fd < 0) { 2182d6ee2a7cSAlexey Kardashevskiy fprintf(stderr, 2183d6ee2a7cSAlexey Kardashevskiy "KVM: Failed to create TCE64 table for liobn 0x%x\n", 2184d6ee2a7cSAlexey Kardashevskiy liobn); 2185d6ee2a7cSAlexey Kardashevskiy return NULL; 2186d6ee2a7cSAlexey Kardashevskiy } 2187d6ee2a7cSAlexey Kardashevskiy } else if (cap_spapr_tce) { 2188d6ee2a7cSAlexey Kardashevskiy uint64_t window_size = (uint64_t) nb_table << page_shift; 2189d6ee2a7cSAlexey Kardashevskiy struct kvm_create_spapr_tce args = { 2190d6ee2a7cSAlexey Kardashevskiy .liobn = liobn, 2191d6ee2a7cSAlexey Kardashevskiy .window_size = window_size, 2192d6ee2a7cSAlexey Kardashevskiy }; 2193d6ee2a7cSAlexey Kardashevskiy if ((window_size != args.window_size) || bus_offset) { 2194d6ee2a7cSAlexey Kardashevskiy return NULL; 2195d6ee2a7cSAlexey Kardashevskiy } 21960f5cb298SDavid Gibson fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); 21970f5cb298SDavid Gibson if (fd < 0) { 2198b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", 2199b5aec396SDavid Gibson liobn); 22000f5cb298SDavid Gibson return NULL; 22010f5cb298SDavid Gibson } 2202d6ee2a7cSAlexey Kardashevskiy } else { 2203d6ee2a7cSAlexey Kardashevskiy return NULL; 2204d6ee2a7cSAlexey Kardashevskiy } 22050f5cb298SDavid Gibson 2206d6ee2a7cSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22070f5cb298SDavid Gibson /* FIXME: round this up to page size */ 22080f5cb298SDavid Gibson 220974b41e56SDavid Gibson table = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 22100f5cb298SDavid Gibson if (table == MAP_FAILED) { 2211b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n", 2212b5aec396SDavid Gibson liobn); 22130f5cb298SDavid Gibson close(fd); 22140f5cb298SDavid Gibson return NULL; 22150f5cb298SDavid Gibson } 22160f5cb298SDavid Gibson 22170f5cb298SDavid Gibson *pfd = fd; 22180f5cb298SDavid Gibson return table; 22190f5cb298SDavid Gibson } 22200f5cb298SDavid Gibson 2221523e7b8aSAlexey Kardashevskiy int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t nb_table) 22220f5cb298SDavid Gibson { 22230f5cb298SDavid Gibson long len; 22240f5cb298SDavid Gibson 22250f5cb298SDavid Gibson if (fd < 0) { 22260f5cb298SDavid Gibson return -1; 22270f5cb298SDavid Gibson } 22280f5cb298SDavid Gibson 2229523e7b8aSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22300f5cb298SDavid Gibson if ((munmap(table, len) < 0) || 22310f5cb298SDavid Gibson (close(fd) < 0)) { 2232b5aec396SDavid Gibson fprintf(stderr, "KVM: Unexpected error removing TCE table: %s", 2233b5aec396SDavid Gibson strerror(errno)); 22340f5cb298SDavid Gibson /* Leak the table */ 22350f5cb298SDavid Gibson } 22360f5cb298SDavid Gibson 22370f5cb298SDavid Gibson return 0; 22380f5cb298SDavid Gibson } 22390f5cb298SDavid Gibson 22407f763a5dSDavid Gibson int kvmppc_reset_htab(int shift_hint) 22417f763a5dSDavid Gibson { 22427f763a5dSDavid Gibson uint32_t shift = shift_hint; 22437f763a5dSDavid Gibson 2244ace9a2cbSDavid Gibson if (!kvm_enabled()) { 2245ace9a2cbSDavid Gibson /* Full emulation, tell caller to allocate htab itself */ 2246ace9a2cbSDavid Gibson return 0; 2247ace9a2cbSDavid Gibson } 22486977afdaSGreg Kurz if (kvm_vm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { 22497f763a5dSDavid Gibson int ret; 22507f763a5dSDavid Gibson ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift); 2251ace9a2cbSDavid Gibson if (ret == -ENOTTY) { 2252c995e942SDavid Gibson /* 2253c995e942SDavid Gibson * At least some versions of PR KVM advertise the 2254ace9a2cbSDavid Gibson * capability, but don't implement the ioctl(). Oops. 2255ace9a2cbSDavid Gibson * Return 0 so that we allocate the htab in qemu, as is 2256c995e942SDavid Gibson * correct for PR. 2257c995e942SDavid Gibson */ 2258ace9a2cbSDavid Gibson return 0; 2259ace9a2cbSDavid Gibson } else if (ret < 0) { 22607f763a5dSDavid Gibson return ret; 22617f763a5dSDavid Gibson } 22627f763a5dSDavid Gibson return shift; 22637f763a5dSDavid Gibson } 22647f763a5dSDavid Gibson 2265c995e942SDavid Gibson /* 2266c995e942SDavid Gibson * We have a kernel that predates the htab reset calls. For PR 2267ace9a2cbSDavid Gibson * KVM, we need to allocate the htab ourselves, for an HV KVM of 2268c995e942SDavid Gibson * this era, it has allocated a 16MB fixed size hash table 2269c995e942SDavid Gibson * already. 2270c995e942SDavid Gibson */ 227196c9cff0SThomas Huth if (kvmppc_is_pr(kvm_state)) { 2272ace9a2cbSDavid Gibson /* PR - tell caller to allocate htab */ 22737f763a5dSDavid Gibson return 0; 2274ace9a2cbSDavid Gibson } else { 2275ace9a2cbSDavid Gibson /* HV - assume 16MB kernel allocated htab */ 2276ace9a2cbSDavid Gibson return 24; 2277ace9a2cbSDavid Gibson } 22787f763a5dSDavid Gibson } 22797f763a5dSDavid Gibson 2280a1e98583SDavid Gibson static inline uint32_t mfpvr(void) 2281a1e98583SDavid Gibson { 2282a1e98583SDavid Gibson uint32_t pvr; 2283a1e98583SDavid Gibson 2284a1e98583SDavid Gibson asm ("mfpvr %0" 2285a1e98583SDavid Gibson : "=r"(pvr)); 2286a1e98583SDavid Gibson return pvr; 2287a1e98583SDavid Gibson } 2288a1e98583SDavid Gibson 2289a7342588SDavid Gibson static void alter_insns(uint64_t *word, uint64_t flags, bool on) 2290a7342588SDavid Gibson { 2291a7342588SDavid Gibson if (on) { 2292a7342588SDavid Gibson *word |= flags; 2293a7342588SDavid Gibson } else { 2294a7342588SDavid Gibson *word &= ~flags; 2295a7342588SDavid Gibson } 2296a7342588SDavid Gibson } 2297a7342588SDavid Gibson 22982985b86bSAndreas Färber static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) 22992985b86bSAndreas Färber { 23002985b86bSAndreas Färber PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); 23010cbad81fSDavid Gibson uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size"); 23020cbad81fSDavid Gibson uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); 2303a1e98583SDavid Gibson 2304cfe34f44SAndreas Färber /* Now fix up the class with information we can query from the host */ 23053bc9ccc0SAlexey Kardashevskiy pcc->pvr = mfpvr(); 2306a7342588SDavid Gibson 23073f2ca480SDavid Gibson alter_insns(&pcc->insns_flags, PPC_ALTIVEC, 23083f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); 23093f2ca480SDavid Gibson alter_insns(&pcc->insns_flags2, PPC2_VSX, 23103f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_VSX); 23113f2ca480SDavid Gibson alter_insns(&pcc->insns_flags2, PPC2_DFP, 23123f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_DFP); 23130cbad81fSDavid Gibson 23140cbad81fSDavid Gibson if (dcache_size != -1) { 23150cbad81fSDavid Gibson pcc->l1_dcache_size = dcache_size; 23160cbad81fSDavid Gibson } 23170cbad81fSDavid Gibson 23180cbad81fSDavid Gibson if (icache_size != -1) { 23190cbad81fSDavid Gibson pcc->l1_icache_size = icache_size; 23200cbad81fSDavid Gibson } 2321c64abd1fSSam Bobroff 2322c64abd1fSSam Bobroff #if defined(TARGET_PPC64) 2323c64abd1fSSam Bobroff pcc->radix_page_info = kvm_get_radix_page_info(); 23245f3066d8SDavid Gibson 23255f3066d8SDavid Gibson if ((pcc->pvr & 0xffffff00) == CPU_POWERPC_POWER9_DD1) { 23265f3066d8SDavid Gibson /* 23275f3066d8SDavid Gibson * POWER9 DD1 has some bugs which make it not really ISA 3.00 23285f3066d8SDavid Gibson * compliant. More importantly, advertising ISA 3.00 23295f3066d8SDavid Gibson * architected mode may prevent guests from activating 23305f3066d8SDavid Gibson * necessary DD1 workarounds. 23315f3066d8SDavid Gibson */ 23325f3066d8SDavid Gibson pcc->pcr_supported &= ~(PCR_COMPAT_3_00 | PCR_COMPAT_2_07 23335f3066d8SDavid Gibson | PCR_COMPAT_2_06 | PCR_COMPAT_2_05); 23345f3066d8SDavid Gibson } 2335c64abd1fSSam Bobroff #endif /* defined(TARGET_PPC64) */ 2336a1e98583SDavid Gibson } 2337a1e98583SDavid Gibson 23383b961124SStuart Yoder bool kvmppc_has_cap_epr(void) 23393b961124SStuart Yoder { 23403b961124SStuart Yoder return cap_epr; 23413b961124SStuart Yoder } 23423b961124SStuart Yoder 234387a91de6SAlexander Graf bool kvmppc_has_cap_fixup_hcalls(void) 234487a91de6SAlexander Graf { 234587a91de6SAlexander Graf return cap_fixup_hcalls; 234687a91de6SAlexander Graf } 234787a91de6SAlexander Graf 2348bac3bf28SThomas Huth bool kvmppc_has_cap_htm(void) 2349bac3bf28SThomas Huth { 2350bac3bf28SThomas Huth return cap_htm; 2351bac3bf28SThomas Huth } 2352bac3bf28SThomas Huth 2353cf1c4cceSSam Bobroff bool kvmppc_has_cap_mmu_radix(void) 2354cf1c4cceSSam Bobroff { 2355cf1c4cceSSam Bobroff return cap_mmu_radix; 2356cf1c4cceSSam Bobroff } 2357cf1c4cceSSam Bobroff 2358cf1c4cceSSam Bobroff bool kvmppc_has_cap_mmu_hash_v3(void) 2359cf1c4cceSSam Bobroff { 2360cf1c4cceSSam Bobroff return cap_mmu_hash_v3; 2361cf1c4cceSSam Bobroff } 2362cf1c4cceSSam Bobroff 2363072f416aSSuraj Jitindar Singh static bool kvmppc_power8_host(void) 2364072f416aSSuraj Jitindar Singh { 2365072f416aSSuraj Jitindar Singh bool ret = false; 2366072f416aSSuraj Jitindar Singh #ifdef TARGET_PPC64 2367072f416aSSuraj Jitindar Singh { 2368072f416aSSuraj Jitindar Singh uint32_t base_pvr = CPU_POWERPC_POWER_SERVER_MASK & mfpvr(); 2369072f416aSSuraj Jitindar Singh ret = (base_pvr == CPU_POWERPC_POWER8E_BASE) || 2370072f416aSSuraj Jitindar Singh (base_pvr == CPU_POWERPC_POWER8NVL_BASE) || 2371072f416aSSuraj Jitindar Singh (base_pvr == CPU_POWERPC_POWER8_BASE); 2372072f416aSSuraj Jitindar Singh } 2373072f416aSSuraj Jitindar Singh #endif /* TARGET_PPC64 */ 2374072f416aSSuraj Jitindar Singh return ret; 2375072f416aSSuraj Jitindar Singh } 2376072f416aSSuraj Jitindar Singh 23778fea7044SSuraj Jitindar Singh static int parse_cap_ppc_safe_cache(struct kvm_ppc_cpu_char c) 23788fea7044SSuraj Jitindar Singh { 2379072f416aSSuraj Jitindar Singh bool l1d_thread_priv_req = !kvmppc_power8_host(); 2380072f416aSSuraj Jitindar Singh 23818fea7044SSuraj Jitindar Singh if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) { 23828fea7044SSuraj Jitindar Singh return 2; 2383072f416aSSuraj Jitindar Singh } else if ((!l1d_thread_priv_req || 2384072f416aSSuraj Jitindar Singh c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) && 23858fea7044SSuraj Jitindar Singh (c.character & c.character_mask 23868fea7044SSuraj Jitindar Singh & (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) { 23878fea7044SSuraj Jitindar Singh return 1; 23888fea7044SSuraj Jitindar Singh } 23898fea7044SSuraj Jitindar Singh 23908fea7044SSuraj Jitindar Singh return 0; 23918fea7044SSuraj Jitindar Singh } 23928fea7044SSuraj Jitindar Singh 23938fea7044SSuraj Jitindar Singh static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c) 23948fea7044SSuraj Jitindar Singh { 23958fea7044SSuraj Jitindar Singh if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) { 23968fea7044SSuraj Jitindar Singh return 2; 23978fea7044SSuraj Jitindar Singh } else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) { 23988fea7044SSuraj Jitindar Singh return 1; 23998fea7044SSuraj Jitindar Singh } 24008fea7044SSuraj Jitindar Singh 24018fea7044SSuraj Jitindar Singh return 0; 24028fea7044SSuraj Jitindar Singh } 24038fea7044SSuraj Jitindar Singh 24048fea7044SSuraj Jitindar Singh static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) 24058fea7044SSuraj Jitindar Singh { 2406399b2896SSuraj Jitindar Singh if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) && 2407399b2896SSuraj Jitindar Singh (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) && 2408399b2896SSuraj Jitindar Singh (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) { 2409399b2896SSuraj Jitindar Singh return SPAPR_CAP_FIXED_NA; 2410399b2896SSuraj Jitindar Singh } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) { 2411399b2896SSuraj Jitindar Singh return SPAPR_CAP_WORKAROUND; 2412399b2896SSuraj Jitindar Singh } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { 24138fea7044SSuraj Jitindar Singh return SPAPR_CAP_FIXED_CCD; 24148fea7044SSuraj Jitindar Singh } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { 24158fea7044SSuraj Jitindar Singh return SPAPR_CAP_FIXED_IBS; 24168fea7044SSuraj Jitindar Singh } 24178fea7044SSuraj Jitindar Singh 24188fea7044SSuraj Jitindar Singh return 0; 24198fea7044SSuraj Jitindar Singh } 24208fea7044SSuraj Jitindar Singh 24218ff43ee4SSuraj Jitindar Singh static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) 24228ff43ee4SSuraj Jitindar Singh { 24238ff43ee4SSuraj Jitindar Singh if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) { 24248ff43ee4SSuraj Jitindar Singh return 1; 24258ff43ee4SSuraj Jitindar Singh } 24268ff43ee4SSuraj Jitindar Singh return 0; 24278ff43ee4SSuraj Jitindar Singh } 24288ff43ee4SSuraj Jitindar Singh 242938afd772SCédric Le Goater bool kvmppc_has_cap_xive(void) 243038afd772SCédric Le Goater { 243138afd772SCédric Le Goater return cap_xive; 243238afd772SCédric Le Goater } 243338afd772SCédric Le Goater 24348acc2ae5SSuraj Jitindar Singh static void kvmppc_get_cpu_characteristics(KVMState *s) 24358acc2ae5SSuraj Jitindar Singh { 24368acc2ae5SSuraj Jitindar Singh struct kvm_ppc_cpu_char c; 24378acc2ae5SSuraj Jitindar Singh int ret; 24388acc2ae5SSuraj Jitindar Singh 24398acc2ae5SSuraj Jitindar Singh /* Assume broken */ 24408acc2ae5SSuraj Jitindar Singh cap_ppc_safe_cache = 0; 24418acc2ae5SSuraj Jitindar Singh cap_ppc_safe_bounds_check = 0; 24428acc2ae5SSuraj Jitindar Singh cap_ppc_safe_indirect_branch = 0; 24438acc2ae5SSuraj Jitindar Singh 24448acc2ae5SSuraj Jitindar Singh ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR); 24458acc2ae5SSuraj Jitindar Singh if (!ret) { 24468acc2ae5SSuraj Jitindar Singh return; 24478acc2ae5SSuraj Jitindar Singh } 24488acc2ae5SSuraj Jitindar Singh ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c); 24498acc2ae5SSuraj Jitindar Singh if (ret < 0) { 24508acc2ae5SSuraj Jitindar Singh return; 24518acc2ae5SSuraj Jitindar Singh } 24528fea7044SSuraj Jitindar Singh 24538fea7044SSuraj Jitindar Singh cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); 24548fea7044SSuraj Jitindar Singh cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); 24558fea7044SSuraj Jitindar Singh cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); 24568ff43ee4SSuraj Jitindar Singh cap_ppc_count_cache_flush_assist = 24578ff43ee4SSuraj Jitindar Singh parse_cap_ppc_count_cache_flush_assist(c); 24588acc2ae5SSuraj Jitindar Singh } 24598acc2ae5SSuraj Jitindar Singh 24608acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_cache(void) 24618acc2ae5SSuraj Jitindar Singh { 24628acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_cache; 24638acc2ae5SSuraj Jitindar Singh } 24648acc2ae5SSuraj Jitindar Singh 24658acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_bounds_check(void) 24668acc2ae5SSuraj Jitindar Singh { 24678acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_bounds_check; 24688acc2ae5SSuraj Jitindar Singh } 24698acc2ae5SSuraj Jitindar Singh 24708acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_indirect_branch(void) 24718acc2ae5SSuraj Jitindar Singh { 24728acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_indirect_branch; 24738acc2ae5SSuraj Jitindar Singh } 24748acc2ae5SSuraj Jitindar Singh 24758ff43ee4SSuraj Jitindar Singh int kvmppc_get_cap_count_cache_flush_assist(void) 24768ff43ee4SSuraj Jitindar Singh { 24778ff43ee4SSuraj Jitindar Singh return cap_ppc_count_cache_flush_assist; 24788ff43ee4SSuraj Jitindar Singh } 24798ff43ee4SSuraj Jitindar Singh 2480b9a477b7SSuraj Jitindar Singh bool kvmppc_has_cap_nested_kvm_hv(void) 2481b9a477b7SSuraj Jitindar Singh { 2482b9a477b7SSuraj Jitindar Singh return !!cap_ppc_nested_kvm_hv; 2483b9a477b7SSuraj Jitindar Singh } 2484b9a477b7SSuraj Jitindar Singh 2485b9a477b7SSuraj Jitindar Singh int kvmppc_set_cap_nested_kvm_hv(int enable) 2486b9a477b7SSuraj Jitindar Singh { 2487b9a477b7SSuraj Jitindar Singh return kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_NESTED_HV, 0, enable); 2488b9a477b7SSuraj Jitindar Singh } 2489b9a477b7SSuraj Jitindar Singh 24909ded780cSAlexey Kardashevskiy bool kvmppc_has_cap_spapr_vfio(void) 24919ded780cSAlexey Kardashevskiy { 24929ded780cSAlexey Kardashevskiy return cap_spapr_vfio; 24939ded780cSAlexey Kardashevskiy } 24949ded780cSAlexey Kardashevskiy 24957d050527SSuraj Jitindar Singh int kvmppc_get_cap_large_decr(void) 24967d050527SSuraj Jitindar Singh { 24977d050527SSuraj Jitindar Singh return cap_large_decr; 24987d050527SSuraj Jitindar Singh } 24997d050527SSuraj Jitindar Singh 25007d050527SSuraj Jitindar Singh int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable) 25017d050527SSuraj Jitindar Singh { 25027d050527SSuraj Jitindar Singh CPUState *cs = CPU(cpu); 25037d050527SSuraj Jitindar Singh uint64_t lpcr; 25047d050527SSuraj Jitindar Singh 25057d050527SSuraj Jitindar Singh kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25067d050527SSuraj Jitindar Singh /* Do we need to modify the LPCR? */ 25077d050527SSuraj Jitindar Singh if (!!(lpcr & LPCR_LD) != !!enable) { 25087d050527SSuraj Jitindar Singh if (enable) { 25097d050527SSuraj Jitindar Singh lpcr |= LPCR_LD; 25107d050527SSuraj Jitindar Singh } else { 25117d050527SSuraj Jitindar Singh lpcr &= ~LPCR_LD; 25127d050527SSuraj Jitindar Singh } 25137d050527SSuraj Jitindar Singh kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25147d050527SSuraj Jitindar Singh kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25157d050527SSuraj Jitindar Singh 25167d050527SSuraj Jitindar Singh if (!!(lpcr & LPCR_LD) != !!enable) { 25177d050527SSuraj Jitindar Singh return -1; 25187d050527SSuraj Jitindar Singh } 25197d050527SSuraj Jitindar Singh } 25207d050527SSuraj Jitindar Singh 25217d050527SSuraj Jitindar Singh return 0; 25227d050527SSuraj Jitindar Singh } 25237d050527SSuraj Jitindar Singh 252452b2519cSThomas Huth PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) 252552b2519cSThomas Huth { 252652b2519cSThomas Huth uint32_t host_pvr = mfpvr(); 252752b2519cSThomas Huth PowerPCCPUClass *pvr_pcc; 252852b2519cSThomas Huth 252952b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr(host_pvr); 253052b2519cSThomas Huth if (pvr_pcc == NULL) { 253152b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr); 253252b2519cSThomas Huth } 253352b2519cSThomas Huth 253452b2519cSThomas Huth return pvr_pcc; 253552b2519cSThomas Huth } 253652b2519cSThomas Huth 2537*165dc3edSDavid Gibson static void pseries_machine_class_fixup(ObjectClass *oc, void *opaque) 2538*165dc3edSDavid Gibson { 2539*165dc3edSDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); 2540*165dc3edSDavid Gibson 2541*165dc3edSDavid Gibson mc->default_cpu_type = TYPE_HOST_POWERPC_CPU; 2542*165dc3edSDavid Gibson } 2543*165dc3edSDavid Gibson 2544*165dc3edSDavid Gibson static int kvm_ppc_register_host_cpu_type(void) 25455ba4576bSAndreas Färber { 25465ba4576bSAndreas Färber TypeInfo type_info = { 25475ba4576bSAndreas Färber .name = TYPE_HOST_POWERPC_CPU, 25485ba4576bSAndreas Färber .class_init = kvmppc_host_cpu_class_init, 25495ba4576bSAndreas Färber }; 25505ba4576bSAndreas Färber PowerPCCPUClass *pvr_pcc; 255192e926e1SGreg Kurz ObjectClass *oc; 25525b79b1caSAlexey Kardashevskiy DeviceClass *dc; 2553715d4b96SThomas Huth int i; 25545ba4576bSAndreas Färber 255552b2519cSThomas Huth pvr_pcc = kvm_ppc_get_host_cpu_class(); 25563bc9ccc0SAlexey Kardashevskiy if (pvr_pcc == NULL) { 25575ba4576bSAndreas Färber return -1; 25585ba4576bSAndreas Färber } 25595ba4576bSAndreas Färber type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); 25605ba4576bSAndreas Färber type_register(&type_info); 25612e9c10ebSIgor Mammedov /* override TCG default cpu type with 'host' cpu model */ 2562*165dc3edSDavid Gibson object_class_foreach(pseries_machine_class_fixup, TYPE_SPAPR_MACHINE, 2563*165dc3edSDavid Gibson false, NULL); 25645b79b1caSAlexey Kardashevskiy 256592e926e1SGreg Kurz oc = object_class_by_name(type_info.name); 256692e926e1SGreg Kurz g_assert(oc); 256792e926e1SGreg Kurz 2568715d4b96SThomas Huth /* 2569715d4b96SThomas Huth * Update generic CPU family class alias (e.g. on a POWER8NVL host, 2570715d4b96SThomas Huth * we want "POWER8" to be a "family" alias that points to the current 2571715d4b96SThomas Huth * host CPU type, too) 2572715d4b96SThomas Huth */ 2573715d4b96SThomas Huth dc = DEVICE_CLASS(ppc_cpu_get_family_class(pvr_pcc)); 2574715d4b96SThomas Huth for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { 2575c5354f54SIgor Mammedov if (strcasecmp(ppc_cpu_aliases[i].alias, dc->desc) == 0) { 2576715d4b96SThomas Huth char *suffix; 2577715d4b96SThomas Huth 2578715d4b96SThomas Huth ppc_cpu_aliases[i].model = g_strdup(object_class_get_name(oc)); 2579c9137065SIgor Mammedov suffix = strstr(ppc_cpu_aliases[i].model, POWERPC_CPU_TYPE_SUFFIX); 2580715d4b96SThomas Huth if (suffix) { 2581715d4b96SThomas Huth *suffix = 0; 2582715d4b96SThomas Huth } 2583715d4b96SThomas Huth break; 2584715d4b96SThomas Huth } 2585715d4b96SThomas Huth } 2586715d4b96SThomas Huth 25875ba4576bSAndreas Färber return 0; 25885ba4576bSAndreas Färber } 25895ba4576bSAndreas Färber 2590feaa64c4SDavid Gibson int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function) 2591feaa64c4SDavid Gibson { 2592feaa64c4SDavid Gibson struct kvm_rtas_token_args args = { 2593feaa64c4SDavid Gibson .token = token, 2594feaa64c4SDavid Gibson }; 2595feaa64c4SDavid Gibson 2596feaa64c4SDavid Gibson if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_RTAS)) { 2597feaa64c4SDavid Gibson return -ENOENT; 2598feaa64c4SDavid Gibson } 2599feaa64c4SDavid Gibson 26007701aeedSCédric Le Goater strncpy(args.name, function, sizeof(args.name) - 1); 2601feaa64c4SDavid Gibson 2602feaa64c4SDavid Gibson return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args); 2603feaa64c4SDavid Gibson } 260412b1143bSDavid Gibson 260514b0d748SGreg Kurz int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp) 2606e68cb8b4SAlexey Kardashevskiy { 2607e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_fd s = { 2608e68cb8b4SAlexey Kardashevskiy .flags = write ? KVM_GET_HTAB_WRITE : 0, 260914b0d748SGreg Kurz .start_index = index, 2610e68cb8b4SAlexey Kardashevskiy }; 261182be8e73SGreg Kurz int ret; 2612e68cb8b4SAlexey Kardashevskiy 2613e68cb8b4SAlexey Kardashevskiy if (!cap_htab_fd) { 261414b0d748SGreg Kurz error_setg(errp, "KVM version doesn't support %s the HPT", 261514b0d748SGreg Kurz write ? "writing" : "reading"); 261682be8e73SGreg Kurz return -ENOTSUP; 2617e68cb8b4SAlexey Kardashevskiy } 2618e68cb8b4SAlexey Kardashevskiy 261982be8e73SGreg Kurz ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s); 262082be8e73SGreg Kurz if (ret < 0) { 262114b0d748SGreg Kurz error_setg(errp, "Unable to open fd for %s HPT %s KVM: %s", 262214b0d748SGreg Kurz write ? "writing" : "reading", write ? "to" : "from", 262314b0d748SGreg Kurz strerror(errno)); 262482be8e73SGreg Kurz return -errno; 262582be8e73SGreg Kurz } 262682be8e73SGreg Kurz 262782be8e73SGreg Kurz return ret; 2628e68cb8b4SAlexey Kardashevskiy } 2629e68cb8b4SAlexey Kardashevskiy 2630e68cb8b4SAlexey Kardashevskiy int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) 2631e68cb8b4SAlexey Kardashevskiy { 2632bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 2633e68cb8b4SAlexey Kardashevskiy uint8_t buf[bufsize]; 2634e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2635e68cb8b4SAlexey Kardashevskiy 2636e68cb8b4SAlexey Kardashevskiy do { 2637e68cb8b4SAlexey Kardashevskiy rc = read(fd, buf, bufsize); 2638e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2639e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error reading data from KVM HTAB fd: %s\n", 2640e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2641e68cb8b4SAlexey Kardashevskiy return rc; 2642e68cb8b4SAlexey Kardashevskiy } else if (rc) { 2643e094c4c1SCédric Le Goater uint8_t *buffer = buf; 2644e094c4c1SCédric Le Goater ssize_t n = rc; 2645e094c4c1SCédric Le Goater while (n) { 2646e094c4c1SCédric Le Goater struct kvm_get_htab_header *head = 2647e094c4c1SCédric Le Goater (struct kvm_get_htab_header *) buffer; 2648e094c4c1SCédric Le Goater size_t chunksize = sizeof(*head) + 2649e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid; 2650e094c4c1SCédric Le Goater 2651e094c4c1SCédric Le Goater qemu_put_be32(f, head->index); 2652e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_valid); 2653e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_invalid); 2654e094c4c1SCédric Le Goater qemu_put_buffer(f, (void *)(head + 1), 2655e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid); 2656e094c4c1SCédric Le Goater 2657e094c4c1SCédric Le Goater buffer += chunksize; 2658e094c4c1SCédric Le Goater n -= chunksize; 2659e094c4c1SCédric Le Goater } 2660e68cb8b4SAlexey Kardashevskiy } 2661e68cb8b4SAlexey Kardashevskiy } while ((rc != 0) 2662c995e942SDavid Gibson && ((max_ns < 0) || 2663c995e942SDavid Gibson ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns))); 2664e68cb8b4SAlexey Kardashevskiy 2665e68cb8b4SAlexey Kardashevskiy return (rc == 0) ? 1 : 0; 2666e68cb8b4SAlexey Kardashevskiy } 2667e68cb8b4SAlexey Kardashevskiy 2668e68cb8b4SAlexey Kardashevskiy int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, 2669e68cb8b4SAlexey Kardashevskiy uint16_t n_valid, uint16_t n_invalid) 2670e68cb8b4SAlexey Kardashevskiy { 2671e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_header *buf; 2672e68cb8b4SAlexey Kardashevskiy size_t chunksize = sizeof(*buf) + n_valid * HASH_PTE_SIZE_64; 2673e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2674e68cb8b4SAlexey Kardashevskiy 2675e68cb8b4SAlexey Kardashevskiy buf = alloca(chunksize); 2676e68cb8b4SAlexey Kardashevskiy buf->index = index; 2677e68cb8b4SAlexey Kardashevskiy buf->n_valid = n_valid; 2678e68cb8b4SAlexey Kardashevskiy buf->n_invalid = n_invalid; 2679e68cb8b4SAlexey Kardashevskiy 2680e68cb8b4SAlexey Kardashevskiy qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64 * n_valid); 2681e68cb8b4SAlexey Kardashevskiy 2682e68cb8b4SAlexey Kardashevskiy rc = write(fd, buf, chunksize); 2683e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2684e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error writing KVM hash table: %s\n", 2685e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2686e68cb8b4SAlexey Kardashevskiy return rc; 2687e68cb8b4SAlexey Kardashevskiy } 2688e68cb8b4SAlexey Kardashevskiy if (rc != chunksize) { 2689e68cb8b4SAlexey Kardashevskiy /* We should never get a short write on a single chunk */ 2690e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Short write, restoring KVM hash table\n"); 2691e68cb8b4SAlexey Kardashevskiy return -1; 2692e68cb8b4SAlexey Kardashevskiy } 2693e68cb8b4SAlexey Kardashevskiy return 0; 2694e68cb8b4SAlexey Kardashevskiy } 2695e68cb8b4SAlexey Kardashevskiy 269620d695a9SAndreas Färber bool kvm_arch_stop_on_emulation_error(CPUState *cpu) 26974513d923SGleb Natapov { 26984513d923SGleb Natapov return true; 26994513d923SGleb Natapov } 2700a1b87fe0SJan Kiszka 270182169660SScott Wood void kvm_arch_init_irq_routing(KVMState *s) 270282169660SScott Wood { 270382169660SScott Wood } 2704c65f9a07SGreg Kurz 27051ad9f0a4SDavid Gibson void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr ptex, int n) 27061ad9f0a4SDavid Gibson { 27071ad9f0a4SDavid Gibson int fd, rc; 27081ad9f0a4SDavid Gibson int i; 27097c43bca0SAneesh Kumar K.V 271014b0d748SGreg Kurz fd = kvmppc_get_htab_fd(false, ptex, &error_abort); 27111ad9f0a4SDavid Gibson 27121ad9f0a4SDavid Gibson i = 0; 27131ad9f0a4SDavid Gibson while (i < n) { 27141ad9f0a4SDavid Gibson struct kvm_get_htab_header *hdr; 27151ad9f0a4SDavid Gibson int m = n < HPTES_PER_GROUP ? n : HPTES_PER_GROUP; 27161ad9f0a4SDavid Gibson char buf[sizeof(*hdr) + m * HASH_PTE_SIZE_64]; 27171ad9f0a4SDavid Gibson 27181ad9f0a4SDavid Gibson rc = read(fd, buf, sizeof(buf)); 27191ad9f0a4SDavid Gibson if (rc < 0) { 27201ad9f0a4SDavid Gibson hw_error("kvmppc_read_hptes: Unable to read HPTEs"); 27211ad9f0a4SDavid Gibson } 27221ad9f0a4SDavid Gibson 27231ad9f0a4SDavid Gibson hdr = (struct kvm_get_htab_header *)buf; 27241ad9f0a4SDavid Gibson while ((i < n) && ((char *)hdr < (buf + rc))) { 2725a36593e1SAlexey Kardashevskiy int invalid = hdr->n_invalid, valid = hdr->n_valid; 27261ad9f0a4SDavid Gibson 27271ad9f0a4SDavid Gibson if (hdr->index != (ptex + i)) { 27281ad9f0a4SDavid Gibson hw_error("kvmppc_read_hptes: Unexpected HPTE index %"PRIu32 27291ad9f0a4SDavid Gibson " != (%"HWADDR_PRIu" + %d", hdr->index, ptex, i); 27301ad9f0a4SDavid Gibson } 27311ad9f0a4SDavid Gibson 2732a36593e1SAlexey Kardashevskiy if (n - i < valid) { 2733a36593e1SAlexey Kardashevskiy valid = n - i; 2734a36593e1SAlexey Kardashevskiy } 2735a36593e1SAlexey Kardashevskiy memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * valid); 2736a36593e1SAlexey Kardashevskiy i += valid; 27371ad9f0a4SDavid Gibson 27381ad9f0a4SDavid Gibson if ((n - i) < invalid) { 27391ad9f0a4SDavid Gibson invalid = n - i; 27401ad9f0a4SDavid Gibson } 27411ad9f0a4SDavid Gibson memset(hptes + i, 0, invalid * HASH_PTE_SIZE_64); 2742a36593e1SAlexey Kardashevskiy i += invalid; 27431ad9f0a4SDavid Gibson 27441ad9f0a4SDavid Gibson hdr = (struct kvm_get_htab_header *) 27451ad9f0a4SDavid Gibson ((char *)(hdr + 1) + HASH_PTE_SIZE_64 * hdr->n_valid); 27461ad9f0a4SDavid Gibson } 27471ad9f0a4SDavid Gibson } 27481ad9f0a4SDavid Gibson 27491ad9f0a4SDavid Gibson close(fd); 27501ad9f0a4SDavid Gibson } 27511ad9f0a4SDavid Gibson 27521ad9f0a4SDavid Gibson void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) 27537c43bca0SAneesh Kumar K.V { 27541ad9f0a4SDavid Gibson int fd, rc; 27551ad9f0a4SDavid Gibson struct { 27561ad9f0a4SDavid Gibson struct kvm_get_htab_header hdr; 27571ad9f0a4SDavid Gibson uint64_t pte0; 27581ad9f0a4SDavid Gibson uint64_t pte1; 27591ad9f0a4SDavid Gibson } buf; 2760c1385933SAneesh Kumar K.V 276114b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0 /* Ignored */, &error_abort); 2762c1385933SAneesh Kumar K.V 27631ad9f0a4SDavid Gibson buf.hdr.n_valid = 1; 27641ad9f0a4SDavid Gibson buf.hdr.n_invalid = 0; 27651ad9f0a4SDavid Gibson buf.hdr.index = ptex; 27661ad9f0a4SDavid Gibson buf.pte0 = cpu_to_be64(pte0); 27671ad9f0a4SDavid Gibson buf.pte1 = cpu_to_be64(pte1); 27681ad9f0a4SDavid Gibson 27691ad9f0a4SDavid Gibson rc = write(fd, &buf, sizeof(buf)); 27701ad9f0a4SDavid Gibson if (rc != sizeof(buf)) { 27711ad9f0a4SDavid Gibson hw_error("kvmppc_write_hpte: Unable to update KVM HPT"); 2772c1385933SAneesh Kumar K.V } 27731ad9f0a4SDavid Gibson close(fd); 2774c1385933SAneesh Kumar K.V } 27759e03a040SFrank Blaschka 27769e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 2777dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 27789e03a040SFrank Blaschka { 27799e03a040SFrank Blaschka return 0; 27809e03a040SFrank Blaschka } 27811850b6b7SEric Auger 278238d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 278338d87493SPeter Xu int vector, PCIDevice *dev) 278438d87493SPeter Xu { 278538d87493SPeter Xu return 0; 278638d87493SPeter Xu } 278738d87493SPeter Xu 278838d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 278938d87493SPeter Xu { 279038d87493SPeter Xu return 0; 279138d87493SPeter Xu } 279238d87493SPeter Xu 27931850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 27941850b6b7SEric Auger { 27951850b6b7SEric Auger return data & 0xffff; 27961850b6b7SEric Auger } 27974d9392beSThomas Huth 27984d9392beSThomas Huth int kvmppc_enable_hwrng(void) 27994d9392beSThomas Huth { 28004d9392beSThomas Huth if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG)) { 28014d9392beSThomas Huth return -1; 28024d9392beSThomas Huth } 28034d9392beSThomas Huth 28044d9392beSThomas Huth return kvmppc_enable_hcall(kvm_state, H_RANDOM); 28054d9392beSThomas Huth } 280630f4b05bSDavid Gibson 280730f4b05bSDavid Gibson void kvmppc_check_papr_resize_hpt(Error **errp) 280830f4b05bSDavid Gibson { 280930f4b05bSDavid Gibson if (!kvm_enabled()) { 2810b55d295eSDavid Gibson return; /* No KVM, we're good */ 2811b55d295eSDavid Gibson } 2812b55d295eSDavid Gibson 2813b55d295eSDavid Gibson if (cap_resize_hpt) { 2814b55d295eSDavid Gibson return; /* Kernel has explicit support, we're good */ 2815b55d295eSDavid Gibson } 2816b55d295eSDavid Gibson 2817b55d295eSDavid Gibson /* Otherwise fallback on looking for PR KVM */ 2818b55d295eSDavid Gibson if (kvmppc_is_pr(kvm_state)) { 281930f4b05bSDavid Gibson return; 282030f4b05bSDavid Gibson } 282130f4b05bSDavid Gibson 282230f4b05bSDavid Gibson error_setg(errp, 282330f4b05bSDavid Gibson "Hash page table resizing not available with this KVM version"); 282430f4b05bSDavid Gibson } 2825b55d295eSDavid Gibson 2826b55d295eSDavid Gibson int kvmppc_resize_hpt_prepare(PowerPCCPU *cpu, target_ulong flags, int shift) 2827b55d295eSDavid Gibson { 2828b55d295eSDavid Gibson CPUState *cs = CPU(cpu); 2829b55d295eSDavid Gibson struct kvm_ppc_resize_hpt rhpt = { 2830b55d295eSDavid Gibson .flags = flags, 2831b55d295eSDavid Gibson .shift = shift, 2832b55d295eSDavid Gibson }; 2833b55d295eSDavid Gibson 2834b55d295eSDavid Gibson if (!cap_resize_hpt) { 2835b55d295eSDavid Gibson return -ENOSYS; 2836b55d295eSDavid Gibson } 2837b55d295eSDavid Gibson 2838b55d295eSDavid Gibson return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_PREPARE, &rhpt); 2839b55d295eSDavid Gibson } 2840b55d295eSDavid Gibson 2841b55d295eSDavid Gibson int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, target_ulong flags, int shift) 2842b55d295eSDavid Gibson { 2843b55d295eSDavid Gibson CPUState *cs = CPU(cpu); 2844b55d295eSDavid Gibson struct kvm_ppc_resize_hpt rhpt = { 2845b55d295eSDavid Gibson .flags = flags, 2846b55d295eSDavid Gibson .shift = shift, 2847b55d295eSDavid Gibson }; 2848b55d295eSDavid Gibson 2849b55d295eSDavid Gibson if (!cap_resize_hpt) { 2850b55d295eSDavid Gibson return -ENOSYS; 2851b55d295eSDavid Gibson } 2852b55d295eSDavid Gibson 2853b55d295eSDavid Gibson return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_COMMIT, &rhpt); 2854b55d295eSDavid Gibson } 2855b55d295eSDavid Gibson 2856c363a37aSDaniel Henrique Barboza /* 2857c363a37aSDaniel Henrique Barboza * This is a helper function to detect a post migration scenario 2858c363a37aSDaniel Henrique Barboza * in which a guest, running as KVM-HV, freezes in cpu_post_load because 2859c363a37aSDaniel Henrique Barboza * the guest kernel can't handle a PVR value other than the actual host 2860c363a37aSDaniel Henrique Barboza * PVR in KVM_SET_SREGS, even if pvr_match() returns true. 2861c363a37aSDaniel Henrique Barboza * 2862c363a37aSDaniel Henrique Barboza * If we don't have cap_ppc_pvr_compat and we're not running in PR 2863c363a37aSDaniel Henrique Barboza * (so, we're HV), return true. The workaround itself is done in 2864c363a37aSDaniel Henrique Barboza * cpu_post_load. 2865c363a37aSDaniel Henrique Barboza * 2866c363a37aSDaniel Henrique Barboza * The order here is important: we'll only check for KVM PR as a 2867c363a37aSDaniel Henrique Barboza * fallback if the guest kernel can't handle the situation itself. 2868c363a37aSDaniel Henrique Barboza * We need to avoid as much as possible querying the running KVM type 2869c363a37aSDaniel Henrique Barboza * in QEMU level. 2870c363a37aSDaniel Henrique Barboza */ 2871c363a37aSDaniel Henrique Barboza bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu) 2872c363a37aSDaniel Henrique Barboza { 2873c363a37aSDaniel Henrique Barboza CPUState *cs = CPU(cpu); 2874c363a37aSDaniel Henrique Barboza 2875c363a37aSDaniel Henrique Barboza if (!kvm_enabled()) { 2876c363a37aSDaniel Henrique Barboza return false; 2877c363a37aSDaniel Henrique Barboza } 2878c363a37aSDaniel Henrique Barboza 2879c363a37aSDaniel Henrique Barboza if (cap_ppc_pvr_compat) { 2880c363a37aSDaniel Henrique Barboza return false; 2881c363a37aSDaniel Henrique Barboza } 2882c363a37aSDaniel Henrique Barboza 2883c363a37aSDaniel Henrique Barboza return !kvmppc_is_pr(cs->kvm_state); 2884c363a37aSDaniel Henrique Barboza } 2885a84f7179SNikunj A Dadhania 2886a84f7179SNikunj A Dadhania void kvmppc_set_reg_ppc_online(PowerPCCPU *cpu, unsigned int online) 2887a84f7179SNikunj A Dadhania { 2888a84f7179SNikunj A Dadhania CPUState *cs = CPU(cpu); 2889a84f7179SNikunj A Dadhania 2890a84f7179SNikunj A Dadhania if (kvm_enabled()) { 2891a84f7179SNikunj A Dadhania kvm_set_one_reg(cs, KVM_REG_PPC_ONLINE, &online); 2892a84f7179SNikunj A Dadhania } 2893a84f7179SNikunj A Dadhania } 28949723295aSGreg Kurz 28959723295aSGreg Kurz void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) 28969723295aSGreg Kurz { 28979723295aSGreg Kurz CPUState *cs = CPU(cpu); 28989723295aSGreg Kurz 28999723295aSGreg Kurz if (kvm_enabled()) { 29009723295aSGreg Kurz kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &tb_offset); 29019723295aSGreg Kurz } 29029723295aSGreg Kurz } 2903