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 2430f4b05bSDavid Gibson #include "qapi/error.h" 25072ed5f2SThomas Huth #include "qemu/error-report.h" 2633c11879SPaolo Bonzini #include "cpu.h" 27715d4b96SThomas Huth #include "cpu-models.h" 281de7afc9SPaolo Bonzini #include "qemu/timer.h" 29*32cad1ffSPhilippe Mathieu-Daudé #include "system/hw_accel.h" 30d76d1650Saurel32 #include "kvm_ppc.h" 31*32cad1ffSPhilippe Mathieu-Daudé #include "system/cpus.h" 32*32cad1ffSPhilippe Mathieu-Daudé #include "system/device_tree.h" 33d5aea6f3SDavid Gibson #include "mmu-hash64.h" 34d76d1650Saurel32 350d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 367ebaf795SBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 37650d103dSMarkus Armbruster #include "hw/hw.h" 3898a8b524SAlexey Kardashevskiy #include "hw/ppc/ppc.h" 39ca77ee28SMarkus Armbruster #include "migration/qemu-file-types.h" 40*32cad1ffSPhilippe Mathieu-Daudé #include "system/watchdog.h" 41b36f100eSAlexey Kardashevskiy #include "trace.h" 425b7d54d4SAlex Bennée #include "gdbstub/enums.h" 434c663752SPaolo Bonzini #include "exec/memattrs.h" 449c607668SAlexey Kardashevskiy #include "exec/ram_addr.h" 45*32cad1ffSPhilippe Mathieu-Daudé #include "system/hostmem.h" 46f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 47db725815SMarkus Armbruster #include "qemu/main-loop.h" 489c607668SAlexey Kardashevskiy #include "qemu/mmap-alloc.h" 49f3d9f303SSam Bobroff #include "elf.h" 50*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm_int.h" 51*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h" 52cfb52d07SHarsh Prateek Bora #include "hw/core/accel-cpu.h" 53f61b4bedSAlexander Graf 54566abdb4SPaolo Bonzini #include CONFIG_DEVICES 55566abdb4SPaolo Bonzini 56eadaada1SAlexander Graf #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" 57eadaada1SAlexander Graf 586e0552a3SFabiano Rosas #define DEBUG_RETURN_GUEST 0 596e0552a3SFabiano Rosas #define DEBUG_RETURN_GDB 1 606e0552a3SFabiano Rosas 6194a8d39aSJan Kiszka const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 6294a8d39aSJan Kiszka KVM_CAP_LAST_INFO 6394a8d39aSJan Kiszka }; 6494a8d39aSJan Kiszka 65c995e942SDavid Gibson static int cap_interrupt_unset; 6690dc8812SScott Wood static int cap_segstate; 6790dc8812SScott Wood static int cap_booke_sregs; 68e97c3636SDavid Gibson static int cap_ppc_smt; 69fa98fbfcSSam Bobroff static int cap_ppc_smt_possible; 700f5cb298SDavid Gibson static int cap_spapr_tce; 71d6ee2a7cSAlexey Kardashevskiy static int cap_spapr_tce_64; 72da95324eSAlexey Kardashevskiy static int cap_spapr_multitce; 739bb62a07SAlexey Kardashevskiy static int cap_spapr_vfio; 74f1af19d7SDavid Gibson static int cap_hior; 75d67d40eaSDavid Gibson static int cap_one_reg; 763b961124SStuart Yoder static int cap_epr; 7731f2cb8fSBharat Bhushan static int cap_ppc_watchdog; 78e68cb8b4SAlexey Kardashevskiy static int cap_htab_fd; 7987a91de6SAlexander Graf static int cap_fixup_hcalls; 80bac3bf28SThomas Huth static int cap_htm; /* Hardware transactional memory support */ 81cf1c4cceSSam Bobroff static int cap_mmu_radix; 82cf1c4cceSSam Bobroff static int cap_mmu_hash_v3; 8338afd772SCédric Le Goater static int cap_xive; 84b55d295eSDavid Gibson static int cap_resize_hpt; 85c363a37aSDaniel Henrique Barboza static int cap_ppc_pvr_compat; 868acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_cache; 878acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_bounds_check; 888acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_indirect_branch; 898ff43ee4SSuraj Jitindar Singh static int cap_ppc_count_cache_flush_assist; 90b9a477b7SSuraj Jitindar Singh static int cap_ppc_nested_kvm_hv; 917d050527SSuraj Jitindar Singh static int cap_large_decr; 92ec010c00SNicholas Piggin static int cap_fwnmi; 9382123b75SBharata B Rao static int cap_rpt_invalidate; 94ccc5a4c5SNicholas Piggin static int cap_ail_mode_3; 95fc87e185SAlexander Graf 96566abdb4SPaolo Bonzini #ifdef CONFIG_PSERIES 97566abdb4SPaolo Bonzini static int cap_papr; 98566abdb4SPaolo Bonzini #else 99566abdb4SPaolo Bonzini #define cap_papr (0) 100566abdb4SPaolo Bonzini #endif 101566abdb4SPaolo Bonzini 1023c902d44SBharat Bhushan static uint32_t debug_inst_opcode; 1033c902d44SBharat Bhushan 104c995e942SDavid Gibson /* 105c995e942SDavid Gibson * Check whether we are running with KVM-PR (instead of KVM-HV). This 10696c9cff0SThomas Huth * should only be used for fallback tests - generally we should use 10796c9cff0SThomas Huth * explicit capabilities for the features we want, rather than 108c995e942SDavid Gibson * assuming what is/isn't available depending on the KVM variant. 109c995e942SDavid Gibson */ 11096c9cff0SThomas Huth static bool kvmppc_is_pr(KVMState *ks) 11196c9cff0SThomas Huth { 11296c9cff0SThomas Huth /* Assume KVM-PR if the GET_PVINFO capability is available */ 11370a0c19eSGreg Kurz return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; 11496c9cff0SThomas Huth } 11596c9cff0SThomas Huth 116165dc3edSDavid Gibson static int kvm_ppc_register_host_cpu_type(void); 1178acc2ae5SSuraj Jitindar Singh static void kvmppc_get_cpu_characteristics(KVMState *s); 1187d050527SSuraj Jitindar Singh static int kvmppc_get_dec_bits(void); 1195ba4576bSAndreas Färber 1205e0d6590SAkihiko Odaki int kvm_arch_get_default_type(MachineState *ms) 1215e0d6590SAkihiko Odaki { 1225e0d6590SAkihiko Odaki return 0; 1235e0d6590SAkihiko Odaki } 1245e0d6590SAkihiko Odaki 125b16565b3SMarcel Apfelbaum int kvm_arch_init(MachineState *ms, KVMState *s) 126d76d1650Saurel32 { 127fc87e185SAlexander Graf cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ); 12890dc8812SScott Wood cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE); 12990dc8812SScott Wood cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS); 1306977afdaSGreg Kurz cap_ppc_smt_possible = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE); 1310f5cb298SDavid Gibson cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); 132d6ee2a7cSAlexey Kardashevskiy cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64); 133da95324eSAlexey Kardashevskiy cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE); 1349ded780cSAlexey Kardashevskiy cap_spapr_vfio = kvm_vm_check_extension(s, KVM_CAP_SPAPR_TCE_VFIO); 135d67d40eaSDavid Gibson cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG); 136f1af19d7SDavid Gibson cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR); 1373b961124SStuart Yoder cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR); 13831f2cb8fSBharat Bhushan cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG); 139c995e942SDavid Gibson /* 140c995e942SDavid Gibson * Note: we don't set cap_papr here, because this capability is 141c995e942SDavid Gibson * only activated after this by kvmppc_set_papr() 142c995e942SDavid Gibson */ 1436977afdaSGreg Kurz cap_htab_fd = kvm_vm_check_extension(s, KVM_CAP_PPC_HTAB_FD); 14487a91de6SAlexander Graf cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL); 145fa98fbfcSSam Bobroff cap_ppc_smt = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT); 146bac3bf28SThomas Huth cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM); 147cf1c4cceSSam Bobroff cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX); 148cf1c4cceSSam Bobroff cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3); 14938afd772SCédric Le Goater cap_xive = kvm_vm_check_extension(s, KVM_CAP_PPC_IRQ_XIVE); 150b55d295eSDavid Gibson cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT); 1518acc2ae5SSuraj Jitindar Singh kvmppc_get_cpu_characteristics(s); 152b9a477b7SSuraj Jitindar Singh cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV); 1537d050527SSuraj Jitindar Singh cap_large_decr = kvmppc_get_dec_bits(); 154ec010c00SNicholas Piggin cap_fwnmi = kvm_vm_check_extension(s, KVM_CAP_PPC_FWNMI); 155c363a37aSDaniel Henrique Barboza /* 156c363a37aSDaniel Henrique Barboza * Note: setting it to false because there is not such capability 157c363a37aSDaniel Henrique Barboza * in KVM at this moment. 158c363a37aSDaniel Henrique Barboza * 159c363a37aSDaniel Henrique Barboza * TODO: call kvm_vm_check_extension() with the right capability 160c995e942SDavid Gibson * after the kernel starts implementing it. 161c995e942SDavid Gibson */ 162c363a37aSDaniel Henrique Barboza cap_ppc_pvr_compat = false; 163fc87e185SAlexander Graf 1641e8f51e8SShivaprasad G Bhat if (!kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL)) { 1651e8f51e8SShivaprasad G Bhat error_report("KVM: Host kernel doesn't have level irq capability"); 1661e8f51e8SShivaprasad G Bhat exit(1); 167fc87e185SAlexander Graf } 168fc87e185SAlexander Graf 16982123b75SBharata B Rao cap_rpt_invalidate = kvm_vm_check_extension(s, KVM_CAP_PPC_RPT_INVALIDATE); 170ccc5a4c5SNicholas Piggin cap_ail_mode_3 = kvm_vm_check_extension(s, KVM_CAP_PPC_AIL_MODE_3); 171165dc3edSDavid Gibson kvm_ppc_register_host_cpu_type(); 1725ba4576bSAndreas Färber 173d76d1650Saurel32 return 0; 174d76d1650Saurel32 } 175d76d1650Saurel32 1764376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 177d525ffabSPaolo Bonzini { 178d525ffabSPaolo Bonzini return 0; 179d525ffabSPaolo Bonzini } 180d525ffabSPaolo Bonzini 1811bc22652SAndreas Färber static int kvm_arch_sync_sregs(PowerPCCPU *cpu) 182d76d1650Saurel32 { 1831bc22652SAndreas Färber CPUPPCState *cenv = &cpu->env; 1841bc22652SAndreas Färber CPUState *cs = CPU(cpu); 185861bbc80SAlexander Graf struct kvm_sregs sregs; 1865666ca4aSScott Wood int ret; 1875666ca4aSScott Wood 1885666ca4aSScott Wood if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 189c995e942SDavid Gibson /* 190c995e942SDavid Gibson * What we're really trying to say is "if we're on BookE, we 191c995e942SDavid Gibson * use the native PVR for now". This is the only sane way to 192c995e942SDavid Gibson * check it though, so we potentially confuse users that they 193c995e942SDavid Gibson * can run BookE guests on BookS. Let's hope nobody dares 194c995e942SDavid Gibson * enough :) 195c995e942SDavid Gibson */ 1965666ca4aSScott Wood return 0; 1975666ca4aSScott Wood } else { 19890dc8812SScott Wood if (!cap_segstate) { 19964e07be5SAlexander Graf fprintf(stderr, "kvm error: missing PVR setting capability\n"); 20064e07be5SAlexander Graf return -ENOSYS; 2015666ca4aSScott Wood } 2025666ca4aSScott Wood } 2035666ca4aSScott Wood 2041bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); 2055666ca4aSScott Wood if (ret) { 2065666ca4aSScott Wood return ret; 2075666ca4aSScott Wood } 208861bbc80SAlexander Graf 209861bbc80SAlexander Graf sregs.pvr = cenv->spr[SPR_PVR]; 2101bc22652SAndreas Färber return kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); 2115666ca4aSScott Wood } 2125666ca4aSScott Wood 21393dd5e85SScott Wood /* Set up a shared TLB array with KVM */ 2141bc22652SAndreas Färber static int kvm_booke206_tlb_init(PowerPCCPU *cpu) 21593dd5e85SScott Wood { 2161bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 2171bc22652SAndreas Färber CPUState *cs = CPU(cpu); 21893dd5e85SScott Wood struct kvm_book3e_206_tlb_params params = {}; 21993dd5e85SScott Wood struct kvm_config_tlb cfg = {}; 22093dd5e85SScott Wood unsigned int entries = 0; 22193dd5e85SScott Wood int ret, i; 22293dd5e85SScott Wood 22393dd5e85SScott Wood if (!kvm_enabled() || 224a60f24b5SAndreas Färber !kvm_check_extension(cs->kvm_state, KVM_CAP_SW_TLB)) { 22593dd5e85SScott Wood return 0; 22693dd5e85SScott Wood } 22793dd5e85SScott Wood 22893dd5e85SScott Wood assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN); 22993dd5e85SScott Wood 23093dd5e85SScott Wood for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 23193dd5e85SScott Wood params.tlb_sizes[i] = booke206_tlb_size(env, i); 23293dd5e85SScott Wood params.tlb_ways[i] = booke206_tlb_ways(env, i); 23393dd5e85SScott Wood entries += params.tlb_sizes[i]; 23493dd5e85SScott Wood } 23593dd5e85SScott Wood 23693dd5e85SScott Wood assert(entries == env->nb_tlb); 23793dd5e85SScott Wood assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t)); 23893dd5e85SScott Wood 23993dd5e85SScott Wood env->tlb_dirty = true; 24093dd5e85SScott Wood 24193dd5e85SScott Wood cfg.array = (uintptr_t)env->tlb.tlbm; 24293dd5e85SScott Wood cfg.array_len = sizeof(ppcmas_tlb_t) * entries; 24393dd5e85SScott Wood cfg.params = (uintptr_t)¶ms; 24493dd5e85SScott Wood cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV; 24593dd5e85SScott Wood 24648add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_SW_TLB, 0, (uintptr_t)&cfg); 24793dd5e85SScott Wood if (ret < 0) { 24893dd5e85SScott Wood fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n", 24993dd5e85SScott Wood __func__, strerror(-ret)); 25093dd5e85SScott Wood return ret; 25193dd5e85SScott Wood } 25293dd5e85SScott Wood 25393dd5e85SScott Wood env->kvm_sw_tlb = true; 25493dd5e85SScott Wood return 0; 25593dd5e85SScott Wood } 25693dd5e85SScott Wood 2574656e1f0SBenjamin Herrenschmidt 2584656e1f0SBenjamin Herrenschmidt #if defined(TARGET_PPC64) 259ab256960SGreg Kurz static void kvm_get_smmu_info(struct kvm_ppc_smmu_info *info, Error **errp) 2604656e1f0SBenjamin Herrenschmidt { 2614656e1f0SBenjamin Herrenschmidt int ret; 2624656e1f0SBenjamin Herrenschmidt 263ab256960SGreg Kurz assert(kvm_state != NULL); 264ab256960SGreg Kurz 265ab256960SGreg Kurz if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { 26671d0f1eaSGreg Kurz error_setg(errp, "KVM doesn't expose the MMU features it supports"); 26771d0f1eaSGreg Kurz error_append_hint(errp, "Consider switching to a newer KVM\n"); 26871d0f1eaSGreg Kurz return; 26971d0f1eaSGreg Kurz } 27071d0f1eaSGreg Kurz 271ab256960SGreg Kurz ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_SMMU_INFO, info); 2724656e1f0SBenjamin Herrenschmidt if (ret == 0) { 2734656e1f0SBenjamin Herrenschmidt return; 2744656e1f0SBenjamin Herrenschmidt } 2754656e1f0SBenjamin Herrenschmidt 27671d0f1eaSGreg Kurz error_setg_errno(errp, -ret, 27771d0f1eaSGreg Kurz "KVM failed to provide the MMU features it supports"); 2784656e1f0SBenjamin Herrenschmidt } 2794656e1f0SBenjamin Herrenschmidt 280aa6edf97SPhilippe Mathieu-Daudé static struct ppc_radix_page_info *kvmppc_get_radix_page_info(void) 281c64abd1fSSam Bobroff { 2824f7f5893SPhilippe Mathieu-Daudé KVMState *s = KVM_STATE(current_accel()); 283c64abd1fSSam Bobroff struct ppc_radix_page_info *radix_page_info; 28455baf4b5SDaniel Henrique Barboza struct kvm_ppc_rmmu_info rmmu_info = { }; 285c64abd1fSSam Bobroff int i; 286c64abd1fSSam Bobroff 287c64abd1fSSam Bobroff if (!kvm_check_extension(s, KVM_CAP_PPC_MMU_RADIX)) { 288c64abd1fSSam Bobroff return NULL; 289c64abd1fSSam Bobroff } 290c64abd1fSSam Bobroff if (kvm_vm_ioctl(s, KVM_PPC_GET_RMMU_INFO, &rmmu_info)) { 291c64abd1fSSam Bobroff return NULL; 292c64abd1fSSam Bobroff } 293c64abd1fSSam Bobroff radix_page_info = g_malloc0(sizeof(*radix_page_info)); 294c64abd1fSSam Bobroff radix_page_info->count = 0; 295c64abd1fSSam Bobroff for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { 296c64abd1fSSam Bobroff if (rmmu_info.ap_encodings[i]) { 297c64abd1fSSam Bobroff radix_page_info->entries[i] = rmmu_info.ap_encodings[i]; 298c64abd1fSSam Bobroff radix_page_info->count++; 299c64abd1fSSam Bobroff } 300c64abd1fSSam Bobroff } 301c64abd1fSSam Bobroff return radix_page_info; 302c64abd1fSSam Bobroff } 303c64abd1fSSam Bobroff 304b4db5413SSuraj Jitindar Singh target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu, 305b4db5413SSuraj Jitindar Singh bool radix, bool gtse, 306b4db5413SSuraj Jitindar Singh uint64_t proc_tbl) 307b4db5413SSuraj Jitindar Singh { 308b4db5413SSuraj Jitindar Singh CPUState *cs = CPU(cpu); 309b4db5413SSuraj Jitindar Singh int ret; 310b4db5413SSuraj Jitindar Singh uint64_t flags = 0; 311b4db5413SSuraj Jitindar Singh struct kvm_ppc_mmuv3_cfg cfg = { 312b4db5413SSuraj Jitindar Singh .process_table = proc_tbl, 313b4db5413SSuraj Jitindar Singh }; 314b4db5413SSuraj Jitindar Singh 315b4db5413SSuraj Jitindar Singh if (radix) { 316b4db5413SSuraj Jitindar Singh flags |= KVM_PPC_MMUV3_RADIX; 317b4db5413SSuraj Jitindar Singh } 318b4db5413SSuraj Jitindar Singh if (gtse) { 319b4db5413SSuraj Jitindar Singh flags |= KVM_PPC_MMUV3_GTSE; 320b4db5413SSuraj Jitindar Singh } 321b4db5413SSuraj Jitindar Singh cfg.flags = flags; 322b4db5413SSuraj Jitindar Singh ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_CONFIGURE_V3_MMU, &cfg); 323b4db5413SSuraj Jitindar Singh switch (ret) { 324b4db5413SSuraj Jitindar Singh case 0: 325b4db5413SSuraj Jitindar Singh return H_SUCCESS; 326b4db5413SSuraj Jitindar Singh case -EINVAL: 327b4db5413SSuraj Jitindar Singh return H_PARAMETER; 328b4db5413SSuraj Jitindar Singh case -ENODEV: 329b4db5413SSuraj Jitindar Singh return H_NOT_AVAILABLE; 330b4db5413SSuraj Jitindar Singh default: 331b4db5413SSuraj Jitindar Singh return H_HARDWARE; 332b4db5413SSuraj Jitindar Singh } 333b4db5413SSuraj Jitindar Singh } 334b4db5413SSuraj Jitindar Singh 33524c6863cSDavid Gibson bool kvmppc_hpt_needs_host_contiguous_pages(void) 33624c6863cSDavid Gibson { 33724c6863cSDavid Gibson static struct kvm_ppc_smmu_info smmu_info; 33824c6863cSDavid Gibson 33924c6863cSDavid Gibson if (!kvm_enabled()) { 34024c6863cSDavid Gibson return false; 34124c6863cSDavid Gibson } 34224c6863cSDavid Gibson 343ab256960SGreg Kurz kvm_get_smmu_info(&smmu_info, &error_fatal); 34424c6863cSDavid Gibson return !!(smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL); 34524c6863cSDavid Gibson } 34624c6863cSDavid Gibson 347e5ca28ecSDavid Gibson void kvm_check_mmu(PowerPCCPU *cpu, Error **errp) 3484656e1f0SBenjamin Herrenschmidt { 349e5ca28ecSDavid Gibson struct kvm_ppc_smmu_info smmu_info; 3504656e1f0SBenjamin Herrenschmidt int iq, ik, jq, jk; 35171d0f1eaSGreg Kurz Error *local_err = NULL; 3524656e1f0SBenjamin Herrenschmidt 353e5ca28ecSDavid Gibson /* For now, we only have anything to check on hash64 MMUs */ 354e5ca28ecSDavid Gibson if (!cpu->hash64_opts || !kvm_enabled()) { 3554656e1f0SBenjamin Herrenschmidt return; 3564656e1f0SBenjamin Herrenschmidt } 3574656e1f0SBenjamin Herrenschmidt 358ab256960SGreg Kurz kvm_get_smmu_info(&smmu_info, &local_err); 35971d0f1eaSGreg Kurz if (local_err) { 36071d0f1eaSGreg Kurz error_propagate(errp, local_err); 36171d0f1eaSGreg Kurz return; 36271d0f1eaSGreg Kurz } 363e5ca28ecSDavid Gibson 364e5ca28ecSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG) 365e5ca28ecSDavid Gibson && !(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { 366e5ca28ecSDavid Gibson error_setg(errp, 367e5ca28ecSDavid Gibson "KVM does not support 1TiB segments which guest expects"); 368e5ca28ecSDavid Gibson return; 3694656e1f0SBenjamin Herrenschmidt } 3704656e1f0SBenjamin Herrenschmidt 371e5ca28ecSDavid Gibson if (smmu_info.slb_size < cpu->hash64_opts->slb_size) { 372e5ca28ecSDavid Gibson error_setg(errp, "KVM only supports %u SLB entries, but guest needs %u", 373e5ca28ecSDavid Gibson smmu_info.slb_size, cpu->hash64_opts->slb_size); 374e5ca28ecSDavid Gibson return; 37590da0d5aSBenjamin Herrenschmidt } 37690da0d5aSBenjamin Herrenschmidt 37708215d8fSAlexander Graf /* 378e5ca28ecSDavid Gibson * Verify that every pagesize supported by the cpu model is 379e5ca28ecSDavid Gibson * supported by KVM with the same encodings 38008215d8fSAlexander Graf */ 381e5ca28ecSDavid Gibson for (iq = 0; iq < ARRAY_SIZE(cpu->hash64_opts->sps); iq++) { 382b07c59f7SDavid Gibson PPCHash64SegmentPageSizes *qsps = &cpu->hash64_opts->sps[iq]; 383e5ca28ecSDavid Gibson struct kvm_ppc_one_seg_page_size *ksps; 3844656e1f0SBenjamin Herrenschmidt 385e5ca28ecSDavid Gibson for (ik = 0; ik < ARRAY_SIZE(smmu_info.sps); ik++) { 386e5ca28ecSDavid Gibson if (qsps->page_shift == smmu_info.sps[ik].page_shift) { 3874656e1f0SBenjamin Herrenschmidt break; 3884656e1f0SBenjamin Herrenschmidt } 3894656e1f0SBenjamin Herrenschmidt } 390e5ca28ecSDavid Gibson if (ik >= ARRAY_SIZE(smmu_info.sps)) { 391e5ca28ecSDavid Gibson error_setg(errp, "KVM doesn't support for base page shift %u", 392e5ca28ecSDavid Gibson qsps->page_shift); 393e5ca28ecSDavid Gibson return; 394e5ca28ecSDavid Gibson } 395e5ca28ecSDavid Gibson 396e5ca28ecSDavid Gibson ksps = &smmu_info.sps[ik]; 397e5ca28ecSDavid Gibson if (ksps->slb_enc != qsps->slb_enc) { 398e5ca28ecSDavid Gibson error_setg(errp, 399e5ca28ecSDavid Gibson "KVM uses SLB encoding 0x%x for page shift %u, but guest expects 0x%x", 400e5ca28ecSDavid Gibson ksps->slb_enc, ksps->page_shift, qsps->slb_enc); 401e5ca28ecSDavid Gibson return; 402e5ca28ecSDavid Gibson } 403e5ca28ecSDavid Gibson 404e5ca28ecSDavid Gibson for (jq = 0; jq < ARRAY_SIZE(qsps->enc); jq++) { 405e5ca28ecSDavid Gibson for (jk = 0; jk < ARRAY_SIZE(ksps->enc); jk++) { 406e5ca28ecSDavid Gibson if (qsps->enc[jq].page_shift == ksps->enc[jk].page_shift) { 4074656e1f0SBenjamin Herrenschmidt break; 4084656e1f0SBenjamin Herrenschmidt } 4094656e1f0SBenjamin Herrenschmidt } 4104656e1f0SBenjamin Herrenschmidt 411e5ca28ecSDavid Gibson if (jk >= ARRAY_SIZE(ksps->enc)) { 412e5ca28ecSDavid Gibson error_setg(errp, "KVM doesn't support page shift %u/%u", 413e5ca28ecSDavid Gibson qsps->enc[jq].page_shift, qsps->page_shift); 414e5ca28ecSDavid Gibson return; 415e5ca28ecSDavid Gibson } 416e5ca28ecSDavid Gibson if (qsps->enc[jq].pte_enc != ksps->enc[jk].pte_enc) { 417e5ca28ecSDavid Gibson error_setg(errp, 418e5ca28ecSDavid Gibson "KVM uses PTE encoding 0x%x for page shift %u/%u, but guest expects 0x%x", 419e5ca28ecSDavid Gibson ksps->enc[jk].pte_enc, qsps->enc[jq].page_shift, 420e5ca28ecSDavid Gibson qsps->page_shift, qsps->enc[jq].pte_enc); 421e5ca28ecSDavid Gibson return; 422e5ca28ecSDavid Gibson } 423e5ca28ecSDavid Gibson } 4244656e1f0SBenjamin Herrenschmidt } 4254656e1f0SBenjamin Herrenschmidt 426e5ca28ecSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 427c995e942SDavid Gibson /* 428c995e942SDavid Gibson * Mostly what guest pagesizes we can use are related to the 429e5ca28ecSDavid Gibson * host pages used to map guest RAM, which is handled in the 430e5ca28ecSDavid Gibson * platform code. Cache-Inhibited largepages (64k) however are 431e5ca28ecSDavid Gibson * used for I/O, so if they're mapped to the host at all it 432e5ca28ecSDavid Gibson * will be a normal mapping, not a special hugepage one used 433c995e942SDavid Gibson * for RAM. 434c995e942SDavid Gibson */ 4358e3b0cbbSMarc-André Lureau if (qemu_real_host_page_size() < 0x10000) { 436e5ca28ecSDavid Gibson error_setg(errp, 437e5ca28ecSDavid Gibson "KVM can't supply 64kiB CI pages, which guest expects"); 438e5ca28ecSDavid Gibson } 439e5ca28ecSDavid Gibson } 440e5ca28ecSDavid Gibson } 4414656e1f0SBenjamin Herrenschmidt #endif /* !defined (TARGET_PPC64) */ 4424656e1f0SBenjamin Herrenschmidt 443b164e48eSEduardo Habkost unsigned long kvm_arch_vcpu_id(CPUState *cpu) 444b164e48eSEduardo Habkost { 4452e886fb3SSam Bobroff return POWERPC_CPU(cpu)->vcpu_id; 446b164e48eSEduardo Habkost } 447b164e48eSEduardo Habkost 448c995e942SDavid Gibson /* 449c995e942SDavid Gibson * e500 supports 2 h/w breakpoint and 2 watchpoint. book3s supports 450c995e942SDavid Gibson * only 1 watchpoint, so array size of 4 is sufficient for now. 45188365d17SBharat Bhushan */ 45288365d17SBharat Bhushan #define MAX_HW_BKPTS 4 45388365d17SBharat Bhushan 45488365d17SBharat Bhushan static struct HWBreakpoint { 45588365d17SBharat Bhushan target_ulong addr; 45688365d17SBharat Bhushan int type; 45788365d17SBharat Bhushan } hw_debug_points[MAX_HW_BKPTS]; 45888365d17SBharat Bhushan 45988365d17SBharat Bhushan static CPUWatchpoint hw_watchpoint; 46088365d17SBharat Bhushan 46188365d17SBharat Bhushan /* Default there is no breakpoint and watchpoint supported */ 46288365d17SBharat Bhushan static int max_hw_breakpoint; 46388365d17SBharat Bhushan static int max_hw_watchpoint; 46488365d17SBharat Bhushan static int nb_hw_breakpoint; 46588365d17SBharat Bhushan static int nb_hw_watchpoint; 46688365d17SBharat Bhushan 46788365d17SBharat Bhushan static void kvmppc_hw_debug_points_init(CPUPPCState *cenv) 46888365d17SBharat Bhushan { 46988365d17SBharat Bhushan if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 47088365d17SBharat Bhushan max_hw_breakpoint = 2; 47188365d17SBharat Bhushan max_hw_watchpoint = 2; 47288365d17SBharat Bhushan } 47388365d17SBharat Bhushan 47488365d17SBharat Bhushan if ((max_hw_breakpoint + max_hw_watchpoint) > MAX_HW_BKPTS) { 47588365d17SBharat Bhushan fprintf(stderr, "Error initializing h/w breakpoints\n"); 47688365d17SBharat Bhushan return; 47788365d17SBharat Bhushan } 47888365d17SBharat Bhushan } 47988365d17SBharat Bhushan 48020d695a9SAndreas Färber int kvm_arch_init_vcpu(CPUState *cs) 4815666ca4aSScott Wood { 48220d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 48320d695a9SAndreas Färber CPUPPCState *cenv = &cpu->env; 4845666ca4aSScott Wood int ret; 4855666ca4aSScott Wood 4864656e1f0SBenjamin Herrenschmidt /* Synchronize sregs with kvm */ 4871bc22652SAndreas Färber ret = kvm_arch_sync_sregs(cpu); 4885666ca4aSScott Wood if (ret) { 489388e47c7SThomas Huth if (ret == -EINVAL) { 490388e47c7SThomas Huth error_report("Register sync failed... If you're using kvm-hv.ko," 491388e47c7SThomas Huth " only \"-cpu host\" is possible"); 492388e47c7SThomas Huth } 4935666ca4aSScott Wood return ret; 4945666ca4aSScott Wood } 495861bbc80SAlexander Graf 49693dd5e85SScott Wood switch (cenv->mmu_model) { 49793dd5e85SScott Wood case POWERPC_MMU_BOOKE206: 4987f516c96SThomas Huth /* This target supports access to KVM's guest TLB */ 4991bc22652SAndreas Färber ret = kvm_booke206_tlb_init(cpu); 50093dd5e85SScott Wood break; 5017f516c96SThomas Huth case POWERPC_MMU_2_07: 5027f516c96SThomas Huth if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) { 503c995e942SDavid Gibson /* 504c995e942SDavid Gibson * KVM-HV has transactional memory on POWER8 also without 505c995e942SDavid Gibson * the KVM_CAP_PPC_HTM extension, so enable it here 506136fbf65Szhaolichang * instead as long as it's available to userspace on the 507c995e942SDavid Gibson * host. 508c995e942SDavid Gibson */ 509f3d9f303SSam Bobroff if (qemu_getauxval(AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) { 5107f516c96SThomas Huth cap_htm = true; 5117f516c96SThomas Huth } 512f3d9f303SSam Bobroff } 5137f516c96SThomas Huth break; 51493dd5e85SScott Wood default: 51593dd5e85SScott Wood break; 51693dd5e85SScott Wood } 51793dd5e85SScott Wood 5183c902d44SBharat Bhushan kvm_get_one_reg(cs, KVM_REG_PPC_DEBUG_INST, &debug_inst_opcode); 51988365d17SBharat Bhushan kvmppc_hw_debug_points_init(cenv); 5203c902d44SBharat Bhushan 521861bbc80SAlexander Graf return ret; 522d76d1650Saurel32 } 523d76d1650Saurel32 524b1115c99SLiran Alon int kvm_arch_destroy_vcpu(CPUState *cs) 525b1115c99SLiran Alon { 526b1115c99SLiran Alon return 0; 527b1115c99SLiran Alon } 528b1115c99SLiran Alon 5291bc22652SAndreas Färber static void kvm_sw_tlb_put(PowerPCCPU *cpu) 53093dd5e85SScott Wood { 5311bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 5321bc22652SAndreas Färber CPUState *cs = CPU(cpu); 53393dd5e85SScott Wood struct kvm_dirty_tlb dirty_tlb; 53493dd5e85SScott Wood unsigned char *bitmap; 53593dd5e85SScott Wood int ret; 53693dd5e85SScott Wood 53793dd5e85SScott Wood if (!env->kvm_sw_tlb) { 53893dd5e85SScott Wood return; 53993dd5e85SScott Wood } 54093dd5e85SScott Wood 54193dd5e85SScott Wood bitmap = g_malloc((env->nb_tlb + 7) / 8); 54293dd5e85SScott Wood memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8); 54393dd5e85SScott Wood 54493dd5e85SScott Wood dirty_tlb.bitmap = (uintptr_t)bitmap; 54593dd5e85SScott Wood dirty_tlb.num_dirty = env->nb_tlb; 54693dd5e85SScott Wood 5471bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_DIRTY_TLB, &dirty_tlb); 54893dd5e85SScott Wood if (ret) { 54993dd5e85SScott Wood fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n", 55093dd5e85SScott Wood __func__, strerror(-ret)); 55193dd5e85SScott Wood } 55293dd5e85SScott Wood 55393dd5e85SScott Wood g_free(bitmap); 55493dd5e85SScott Wood } 55593dd5e85SScott Wood 556d67d40eaSDavid Gibson static void kvm_get_one_spr(CPUState *cs, uint64_t id, int spr) 557d67d40eaSDavid Gibson { 558794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs); 559942069e0SDaniel Henrique Barboza /* Init 'val' to avoid "uninitialised value" Valgrind warnings */ 560d67d40eaSDavid Gibson union { 561d67d40eaSDavid Gibson uint32_t u32; 562d67d40eaSDavid Gibson uint64_t u64; 563942069e0SDaniel Henrique Barboza } val = { }; 564d67d40eaSDavid Gibson struct kvm_one_reg reg = { 565d67d40eaSDavid Gibson .id = id, 566d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 567d67d40eaSDavid Gibson }; 568d67d40eaSDavid Gibson int ret; 569d67d40eaSDavid Gibson 570d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 571d67d40eaSDavid Gibson if (ret != 0) { 572b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_get(spr, strerror(errno)); 573d67d40eaSDavid Gibson } else { 574d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 575d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 576d67d40eaSDavid Gibson env->spr[spr] = val.u32; 577d67d40eaSDavid Gibson break; 578d67d40eaSDavid Gibson 579d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 580d67d40eaSDavid Gibson env->spr[spr] = val.u64; 581d67d40eaSDavid Gibson break; 582d67d40eaSDavid Gibson 583d67d40eaSDavid Gibson default: 584d67d40eaSDavid Gibson /* Don't handle this size yet */ 585d67d40eaSDavid Gibson abort(); 586d67d40eaSDavid Gibson } 587d67d40eaSDavid Gibson } 588d67d40eaSDavid Gibson } 589d67d40eaSDavid Gibson 590d67d40eaSDavid Gibson static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr) 591d67d40eaSDavid Gibson { 592794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs); 593d67d40eaSDavid Gibson union { 594d67d40eaSDavid Gibson uint32_t u32; 595d67d40eaSDavid Gibson uint64_t u64; 596d67d40eaSDavid Gibson } val; 597d67d40eaSDavid Gibson struct kvm_one_reg reg = { 598d67d40eaSDavid Gibson .id = id, 599d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 600d67d40eaSDavid Gibson }; 601d67d40eaSDavid Gibson int ret; 602d67d40eaSDavid Gibson 603d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 604d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 605d67d40eaSDavid Gibson val.u32 = env->spr[spr]; 606d67d40eaSDavid Gibson break; 607d67d40eaSDavid Gibson 608d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 609d67d40eaSDavid Gibson val.u64 = env->spr[spr]; 610d67d40eaSDavid Gibson break; 611d67d40eaSDavid Gibson 612d67d40eaSDavid Gibson default: 613d67d40eaSDavid Gibson /* Don't handle this size yet */ 614d67d40eaSDavid Gibson abort(); 615d67d40eaSDavid Gibson } 616d67d40eaSDavid Gibson 617d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 618d67d40eaSDavid Gibson if (ret != 0) { 619b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_set(spr, strerror(errno)); 620d67d40eaSDavid Gibson } 621d67d40eaSDavid Gibson } 622d67d40eaSDavid Gibson 62370b79849SDavid Gibson static int kvm_put_fp(CPUState *cs) 62470b79849SDavid Gibson { 625794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs); 62670b79849SDavid Gibson struct kvm_one_reg reg; 62770b79849SDavid Gibson int i; 62870b79849SDavid Gibson int ret; 62970b79849SDavid Gibson 63070b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 63170b79849SDavid Gibson uint64_t fpscr = env->fpscr; 63270b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 63370b79849SDavid Gibson 63470b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 63570b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 63670b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 63770b79849SDavid Gibson if (ret < 0) { 6388d83cbf1SGreg Kurz trace_kvm_failed_fpscr_set(strerror(errno)); 63970b79849SDavid Gibson return ret; 64070b79849SDavid Gibson } 64170b79849SDavid Gibson 64270b79849SDavid Gibson for (i = 0; i < 32; i++) { 64370b79849SDavid Gibson uint64_t vsr[2]; 644ee1004bbSPhilippe Mathieu-Daudé uint64_t *fpr = cpu_fpr_ptr(env, i); 645ee1004bbSPhilippe Mathieu-Daudé uint64_t *vsrl = cpu_vsrl_ptr(env, i); 64670b79849SDavid Gibson 647e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 648ef96e3aeSMark Cave-Ayland vsr[0] = float64_val(*fpr); 649ef96e3aeSMark Cave-Ayland vsr[1] = *vsrl; 6503a4b791bSGreg Kurz #else 651ef96e3aeSMark Cave-Ayland vsr[0] = *vsrl; 652ef96e3aeSMark Cave-Ayland vsr[1] = float64_val(*fpr); 6533a4b791bSGreg Kurz #endif 65470b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 65570b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 65670b79849SDavid Gibson 65770b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 65870b79849SDavid Gibson if (ret < 0) { 6598d83cbf1SGreg Kurz trace_kvm_failed_fp_set(vsx ? "VSR" : "FPR", i, 6608d83cbf1SGreg Kurz strerror(errno)); 66170b79849SDavid Gibson return ret; 66270b79849SDavid Gibson } 66370b79849SDavid Gibson } 66470b79849SDavid Gibson } 66570b79849SDavid Gibson 66670b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 66770b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 66870b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 66970b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 67070b79849SDavid Gibson if (ret < 0) { 6718d83cbf1SGreg Kurz trace_kvm_failed_vscr_set(strerror(errno)); 67270b79849SDavid Gibson return ret; 67370b79849SDavid Gibson } 67470b79849SDavid Gibson 67570b79849SDavid Gibson for (i = 0; i < 32; i++) { 67670b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 677ef96e3aeSMark Cave-Ayland reg.addr = (uintptr_t)cpu_avr_ptr(env, i); 67870b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 67970b79849SDavid Gibson if (ret < 0) { 6808d83cbf1SGreg Kurz trace_kvm_failed_vr_set(i, strerror(errno)); 68170b79849SDavid Gibson return ret; 68270b79849SDavid Gibson } 68370b79849SDavid Gibson } 68470b79849SDavid Gibson } 68570b79849SDavid Gibson 68670b79849SDavid Gibson return 0; 68770b79849SDavid Gibson } 68870b79849SDavid Gibson 68970b79849SDavid Gibson static int kvm_get_fp(CPUState *cs) 69070b79849SDavid Gibson { 691794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs); 69270b79849SDavid Gibson struct kvm_one_reg reg; 69370b79849SDavid Gibson int i; 69470b79849SDavid Gibson int ret; 69570b79849SDavid Gibson 69670b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 69770b79849SDavid Gibson uint64_t fpscr; 69870b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 69970b79849SDavid Gibson 70070b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 70170b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 70270b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 70370b79849SDavid Gibson if (ret < 0) { 7048d83cbf1SGreg Kurz trace_kvm_failed_fpscr_get(strerror(errno)); 70570b79849SDavid Gibson return ret; 70670b79849SDavid Gibson } else { 70770b79849SDavid Gibson env->fpscr = fpscr; 70870b79849SDavid Gibson } 70970b79849SDavid Gibson 71070b79849SDavid Gibson for (i = 0; i < 32; i++) { 71170b79849SDavid Gibson uint64_t vsr[2]; 712ee1004bbSPhilippe Mathieu-Daudé uint64_t *fpr = cpu_fpr_ptr(env, i); 713ee1004bbSPhilippe Mathieu-Daudé uint64_t *vsrl = cpu_vsrl_ptr(env, i); 71470b79849SDavid Gibson 71570b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 71670b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 71770b79849SDavid Gibson 71870b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 71970b79849SDavid Gibson if (ret < 0) { 7208d83cbf1SGreg Kurz trace_kvm_failed_fp_get(vsx ? "VSR" : "FPR", i, 7218d83cbf1SGreg Kurz strerror(errno)); 72270b79849SDavid Gibson return ret; 72370b79849SDavid Gibson } else { 724e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 725ef96e3aeSMark Cave-Ayland *fpr = vsr[0]; 72670b79849SDavid Gibson if (vsx) { 727ef96e3aeSMark Cave-Ayland *vsrl = vsr[1]; 72870b79849SDavid Gibson } 7293a4b791bSGreg Kurz #else 730ef96e3aeSMark Cave-Ayland *fpr = vsr[1]; 7313a4b791bSGreg Kurz if (vsx) { 732ef96e3aeSMark Cave-Ayland *vsrl = vsr[0]; 7333a4b791bSGreg Kurz } 7343a4b791bSGreg Kurz #endif 73570b79849SDavid Gibson } 73670b79849SDavid Gibson } 73770b79849SDavid Gibson } 73870b79849SDavid Gibson 73970b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 74070b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 74170b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 74270b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 74370b79849SDavid Gibson if (ret < 0) { 7448d83cbf1SGreg Kurz trace_kvm_failed_vscr_get(strerror(errno)); 74570b79849SDavid Gibson return ret; 74670b79849SDavid Gibson } 74770b79849SDavid Gibson 74870b79849SDavid Gibson for (i = 0; i < 32; i++) { 74970b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 750ef96e3aeSMark Cave-Ayland reg.addr = (uintptr_t)cpu_avr_ptr(env, i); 75170b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 75270b79849SDavid Gibson if (ret < 0) { 7538d83cbf1SGreg Kurz trace_kvm_failed_vr_get(i, strerror(errno)); 75470b79849SDavid Gibson return ret; 75570b79849SDavid Gibson } 75670b79849SDavid Gibson } 75770b79849SDavid Gibson } 75870b79849SDavid Gibson 75970b79849SDavid Gibson return 0; 76070b79849SDavid Gibson } 76170b79849SDavid Gibson 7629b00ea49SDavid Gibson #if defined(TARGET_PPC64) 7639b00ea49SDavid Gibson static int kvm_get_vpa(CPUState *cs) 7649b00ea49SDavid Gibson { 7659b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 766ce2918cbSDavid Gibson SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 7679b00ea49SDavid Gibson struct kvm_one_reg reg; 7689b00ea49SDavid Gibson int ret; 7699b00ea49SDavid Gibson 7709b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 7717388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 7729b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7739b00ea49SDavid Gibson if (ret < 0) { 7748d83cbf1SGreg Kurz trace_kvm_failed_vpa_addr_get(strerror(errno)); 7759b00ea49SDavid Gibson return ret; 7769b00ea49SDavid Gibson } 7779b00ea49SDavid Gibson 7787388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->slb_shadow_size 7797388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->slb_shadow_addr + 8)); 7809b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 7817388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr; 7829b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7839b00ea49SDavid Gibson if (ret < 0) { 7848d83cbf1SGreg Kurz trace_kvm_failed_slb_get(strerror(errno)); 7859b00ea49SDavid Gibson return ret; 7869b00ea49SDavid Gibson } 7879b00ea49SDavid Gibson 7887388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->dtl_size 7897388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->dtl_addr + 8)); 7909b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 7917388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->dtl_addr; 7929b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7939b00ea49SDavid Gibson if (ret < 0) { 7948d83cbf1SGreg Kurz trace_kvm_failed_dtl_get(strerror(errno)); 7959b00ea49SDavid Gibson return ret; 7969b00ea49SDavid Gibson } 7979b00ea49SDavid Gibson 7989b00ea49SDavid Gibson return 0; 7999b00ea49SDavid Gibson } 8009b00ea49SDavid Gibson 8019b00ea49SDavid Gibson static int kvm_put_vpa(CPUState *cs) 8029b00ea49SDavid Gibson { 8039b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 804ce2918cbSDavid Gibson SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 8059b00ea49SDavid Gibson struct kvm_one_reg reg; 8069b00ea49SDavid Gibson int ret; 8079b00ea49SDavid Gibson 808c995e942SDavid Gibson /* 809c995e942SDavid Gibson * SLB shadow or DTL can't be registered unless a master VPA is 8109b00ea49SDavid Gibson * registered. That means when restoring state, if a VPA *is* 8119b00ea49SDavid Gibson * registered, we need to set that up first. If not, we need to 812c995e942SDavid Gibson * deregister the others before deregistering the master VPA 813c995e942SDavid Gibson */ 8147388efafSDavid Gibson assert(spapr_cpu->vpa_addr 8157388efafSDavid Gibson || !(spapr_cpu->slb_shadow_addr || spapr_cpu->dtl_addr)); 8169b00ea49SDavid Gibson 8177388efafSDavid Gibson if (spapr_cpu->vpa_addr) { 8189b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8197388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 8209b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8219b00ea49SDavid Gibson if (ret < 0) { 8228d83cbf1SGreg Kurz trace_kvm_failed_vpa_addr_set(strerror(errno)); 8239b00ea49SDavid Gibson return ret; 8249b00ea49SDavid Gibson } 8259b00ea49SDavid Gibson } 8269b00ea49SDavid Gibson 8277388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->slb_shadow_size 8287388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->slb_shadow_addr + 8)); 8299b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 8307388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr; 8319b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8329b00ea49SDavid Gibson if (ret < 0) { 8338d83cbf1SGreg Kurz trace_kvm_failed_slb_set(strerror(errno)); 8349b00ea49SDavid Gibson return ret; 8359b00ea49SDavid Gibson } 8369b00ea49SDavid Gibson 8377388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->dtl_size 8387388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->dtl_addr + 8)); 8399b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 8407388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->dtl_addr; 8419b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8429b00ea49SDavid Gibson if (ret < 0) { 8438d83cbf1SGreg Kurz trace_kvm_failed_dtl_set(strerror(errno)); 8449b00ea49SDavid Gibson return ret; 8459b00ea49SDavid Gibson } 8469b00ea49SDavid Gibson 8477388efafSDavid Gibson if (!spapr_cpu->vpa_addr) { 8489b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8497388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 8509b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8519b00ea49SDavid Gibson if (ret < 0) { 8528d83cbf1SGreg Kurz trace_kvm_failed_null_vpa_addr_set(strerror(errno)); 8539b00ea49SDavid Gibson return ret; 8549b00ea49SDavid Gibson } 8559b00ea49SDavid Gibson } 8569b00ea49SDavid Gibson 8579b00ea49SDavid Gibson return 0; 8589b00ea49SDavid Gibson } 8599b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 8609b00ea49SDavid Gibson 861e5c0d3ceSDavid Gibson int kvmppc_put_books_sregs(PowerPCCPU *cpu) 862a7a00a72SDavid Gibson { 863a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 864b339427cSDaniel Henrique Barboza struct kvm_sregs sregs = { }; 865a7a00a72SDavid Gibson int i; 866a7a00a72SDavid Gibson 867a7a00a72SDavid Gibson sregs.pvr = env->spr[SPR_PVR]; 868a7a00a72SDavid Gibson 8691ec26c75SGreg Kurz if (cpu->vhyp) { 870c700b5e1SNicholas Piggin sregs.u.s.sdr1 = cpu->vhyp_class->encode_hpt_for_kvm_pr(cpu->vhyp); 8711ec26c75SGreg Kurz } else { 872a7a00a72SDavid Gibson sregs.u.s.sdr1 = env->spr[SPR_SDR1]; 8731ec26c75SGreg Kurz } 874a7a00a72SDavid Gibson 875a7a00a72SDavid Gibson /* Sync SLB */ 876a7a00a72SDavid Gibson #ifdef TARGET_PPC64 877a7a00a72SDavid Gibson for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 878a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; 879a7a00a72SDavid Gibson if (env->slb[i].esid & SLB_ESID_V) { 880a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe |= i; 881a7a00a72SDavid Gibson } 882a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; 883a7a00a72SDavid Gibson } 884a7a00a72SDavid Gibson #endif 885a7a00a72SDavid Gibson 886a7a00a72SDavid Gibson /* Sync SRs */ 887a7a00a72SDavid Gibson for (i = 0; i < 16; i++) { 888a7a00a72SDavid Gibson sregs.u.s.ppc32.sr[i] = env->sr[i]; 889a7a00a72SDavid Gibson } 890a7a00a72SDavid Gibson 891a7a00a72SDavid Gibson /* Sync BATs */ 892a7a00a72SDavid Gibson for (i = 0; i < 8; i++) { 893a7a00a72SDavid Gibson /* Beware. We have to swap upper and lower bits here */ 894a7a00a72SDavid Gibson sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) 895a7a00a72SDavid Gibson | env->DBAT[1][i]; 896a7a00a72SDavid Gibson sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) 897a7a00a72SDavid Gibson | env->IBAT[1][i]; 898a7a00a72SDavid Gibson } 899a7a00a72SDavid Gibson 900a7a00a72SDavid Gibson return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); 901a7a00a72SDavid Gibson } 902a7a00a72SDavid Gibson 903a1676bb3SJulia Suvorova int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) 904d76d1650Saurel32 { 90520d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 90620d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 907d76d1650Saurel32 struct kvm_regs regs; 908d76d1650Saurel32 int ret; 909d76d1650Saurel32 int i; 910d76d1650Saurel32 9111bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 9121bc22652SAndreas Färber if (ret < 0) { 913d76d1650Saurel32 return ret; 9141bc22652SAndreas Färber } 915d76d1650Saurel32 916d76d1650Saurel32 regs.ctr = env->ctr; 917d76d1650Saurel32 regs.lr = env->lr; 918da91a00fSRichard Henderson regs.xer = cpu_read_xer(env); 919d76d1650Saurel32 regs.msr = env->msr; 920d76d1650Saurel32 regs.pc = env->nip; 921d76d1650Saurel32 922d76d1650Saurel32 regs.srr0 = env->spr[SPR_SRR0]; 923d76d1650Saurel32 regs.srr1 = env->spr[SPR_SRR1]; 924d76d1650Saurel32 925d76d1650Saurel32 regs.sprg0 = env->spr[SPR_SPRG0]; 926d76d1650Saurel32 regs.sprg1 = env->spr[SPR_SPRG1]; 927d76d1650Saurel32 regs.sprg2 = env->spr[SPR_SPRG2]; 928d76d1650Saurel32 regs.sprg3 = env->spr[SPR_SPRG3]; 929d76d1650Saurel32 regs.sprg4 = env->spr[SPR_SPRG4]; 930d76d1650Saurel32 regs.sprg5 = env->spr[SPR_SPRG5]; 931d76d1650Saurel32 regs.sprg6 = env->spr[SPR_SPRG6]; 932d76d1650Saurel32 regs.sprg7 = env->spr[SPR_SPRG7]; 933d76d1650Saurel32 93490dc8812SScott Wood regs.pid = env->spr[SPR_BOOKE_PID]; 93590dc8812SScott Wood 936c995e942SDavid Gibson for (i = 0; i < 32; i++) { 937d76d1650Saurel32 regs.gpr[i] = env->gpr[i]; 938c995e942SDavid Gibson } 939d76d1650Saurel32 9402060436aSHarsh Prateek Bora regs.cr = ppc_get_cr(env); 9414bddaf55SAlexey Kardashevskiy 9421bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 943c995e942SDavid Gibson if (ret < 0) { 944d76d1650Saurel32 return ret; 945c995e942SDavid Gibson } 946d76d1650Saurel32 94770b79849SDavid Gibson kvm_put_fp(cs); 94870b79849SDavid Gibson 94993dd5e85SScott Wood if (env->tlb_dirty) { 9501bc22652SAndreas Färber kvm_sw_tlb_put(cpu); 95193dd5e85SScott Wood env->tlb_dirty = false; 95293dd5e85SScott Wood } 95393dd5e85SScott Wood 954f1af19d7SDavid Gibson if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) { 955a7a00a72SDavid Gibson ret = kvmppc_put_books_sregs(cpu); 956a7a00a72SDavid Gibson if (ret < 0) { 957f1af19d7SDavid Gibson return ret; 958f1af19d7SDavid Gibson } 959f1af19d7SDavid Gibson } 960f1af19d7SDavid Gibson 961f1af19d7SDavid Gibson if (cap_hior && (level >= KVM_PUT_RESET_STATE)) { 962d67d40eaSDavid Gibson kvm_put_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 963d67d40eaSDavid Gibson } 964f1af19d7SDavid Gibson 965d67d40eaSDavid Gibson if (cap_one_reg) { 966c995e942SDavid Gibson /* 967c995e942SDavid Gibson * We deliberately ignore errors here, for kernels which have 968d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 969d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 970c995e942SDavid Gibson * work, at least until we try to migrate. 971c995e942SDavid Gibson */ 972d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 973d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 974d67d40eaSDavid Gibson 975d67d40eaSDavid Gibson if (id != 0) { 976d67d40eaSDavid Gibson kvm_put_one_spr(cs, id, i); 977d67d40eaSDavid Gibson } 978f1af19d7SDavid Gibson } 9799b00ea49SDavid Gibson 9809b00ea49SDavid Gibson #ifdef TARGET_PPC64 981ca241959SVíctor Colombo if (FIELD_EX64(env->msr, MSR, TS)) { 98280b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 98380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 98480b3f79bSAlexey Kardashevskiy } 98580b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 98680b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 98780b3f79bSAlexey Kardashevskiy } 98880b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 98980b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 99080b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 99180b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 99280b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 99380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 99480b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 99580b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 99680b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 99780b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 99880b3f79bSAlexey Kardashevskiy } 99980b3f79bSAlexey Kardashevskiy 10009b00ea49SDavid Gibson if (cap_papr) { 10019b00ea49SDavid Gibson if (kvm_put_vpa(cs) < 0) { 10028d83cbf1SGreg Kurz trace_kvm_failed_put_vpa(); 10039b00ea49SDavid Gibson } 10049b00ea49SDavid Gibson } 100598a8b524SAlexey Kardashevskiy 100698a8b524SAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 1007972bd576SAlexey Kardashevskiy 1008972bd576SAlexey Kardashevskiy if (level > KVM_PUT_RUNTIME_STATE) { 1009972bd576SAlexey Kardashevskiy kvm_put_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES); 1010972bd576SAlexey Kardashevskiy } 10119b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 1012f1af19d7SDavid Gibson } 1013f1af19d7SDavid Gibson 1014d76d1650Saurel32 return ret; 1015d76d1650Saurel32 } 1016d76d1650Saurel32 1017c371c2e3SBharat Bhushan static void kvm_sync_excp(CPUPPCState *env, int vector, int ivor) 1018c371c2e3SBharat Bhushan { 1019c371c2e3SBharat Bhushan env->excp_vectors[vector] = env->spr[ivor] + env->spr[SPR_BOOKE_IVPR]; 1020c371c2e3SBharat Bhushan } 1021c371c2e3SBharat Bhushan 1022a7a00a72SDavid Gibson static int kvmppc_get_booke_sregs(PowerPCCPU *cpu) 1023d76d1650Saurel32 { 102420d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1025ba5e5090SAlexander Graf struct kvm_sregs sregs; 1026a7a00a72SDavid Gibson int ret; 1027d76d1650Saurel32 1028a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 102990dc8812SScott Wood if (ret < 0) { 103090dc8812SScott Wood return ret; 103190dc8812SScott Wood } 103290dc8812SScott Wood 103390dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_BASE) { 103490dc8812SScott Wood env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0; 103590dc8812SScott Wood env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1; 103690dc8812SScott Wood env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr; 103790dc8812SScott Wood env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear; 103890dc8812SScott Wood env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr; 103990dc8812SScott Wood env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr; 104090dc8812SScott Wood env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr; 104190dc8812SScott Wood env->spr[SPR_DECR] = sregs.u.e.dec; 104290dc8812SScott Wood env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff; 104390dc8812SScott Wood env->spr[SPR_TBU] = sregs.u.e.tb >> 32; 104490dc8812SScott Wood env->spr[SPR_VRSAVE] = sregs.u.e.vrsave; 104590dc8812SScott Wood } 104690dc8812SScott Wood 104790dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206) { 104890dc8812SScott Wood env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir; 104990dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0; 105090dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1; 105190dc8812SScott Wood env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar; 105290dc8812SScott Wood env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr; 105390dc8812SScott Wood } 105490dc8812SScott Wood 105590dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_64) { 105690dc8812SScott Wood env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr; 105790dc8812SScott Wood } 105890dc8812SScott Wood 105990dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPRG8) { 106090dc8812SScott Wood env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8; 106190dc8812SScott Wood } 106290dc8812SScott Wood 106390dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_IVOR) { 106490dc8812SScott Wood env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0]; 1065c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_CRITICAL, SPR_BOOKE_IVOR0); 106690dc8812SScott Wood env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1]; 1067c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_MCHECK, SPR_BOOKE_IVOR1); 106890dc8812SScott Wood env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2]; 1069c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DSI, SPR_BOOKE_IVOR2); 107090dc8812SScott Wood env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3]; 1071c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ISI, SPR_BOOKE_IVOR3); 107290dc8812SScott Wood env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4]; 1073c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EXTERNAL, SPR_BOOKE_IVOR4); 107490dc8812SScott Wood env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5]; 1075c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ALIGN, SPR_BOOKE_IVOR5); 107690dc8812SScott Wood env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6]; 1077c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_PROGRAM, SPR_BOOKE_IVOR6); 107890dc8812SScott Wood env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7]; 1079c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FPU, SPR_BOOKE_IVOR7); 108090dc8812SScott Wood env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8]; 1081c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SYSCALL, SPR_BOOKE_IVOR8); 108290dc8812SScott Wood env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9]; 1083c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_APU, SPR_BOOKE_IVOR9); 108490dc8812SScott Wood env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10]; 1085c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DECR, SPR_BOOKE_IVOR10); 108690dc8812SScott Wood env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11]; 1087c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FIT, SPR_BOOKE_IVOR11); 108890dc8812SScott Wood env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12]; 1089c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_WDT, SPR_BOOKE_IVOR12); 109090dc8812SScott Wood env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13]; 1091c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DTLB, SPR_BOOKE_IVOR13); 109290dc8812SScott Wood env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14]; 1093c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ITLB, SPR_BOOKE_IVOR14); 109490dc8812SScott Wood env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15]; 1095c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DEBUG, SPR_BOOKE_IVOR15); 109690dc8812SScott Wood 109790dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPE) { 109890dc8812SScott Wood env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0]; 1099c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SPEU, SPR_BOOKE_IVOR32); 110090dc8812SScott Wood env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1]; 1101c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPDI, SPR_BOOKE_IVOR33); 110290dc8812SScott Wood env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2]; 1103c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPRI, SPR_BOOKE_IVOR34); 110490dc8812SScott Wood } 110590dc8812SScott Wood 110690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PM) { 110790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3]; 1108c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EPERFM, SPR_BOOKE_IVOR35); 110990dc8812SScott Wood } 111090dc8812SScott Wood 111190dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PC) { 111290dc8812SScott Wood env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4]; 1113c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORI, SPR_BOOKE_IVOR36); 111490dc8812SScott Wood env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5]; 1115c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORCI, SPR_BOOKE_IVOR37); 111690dc8812SScott Wood } 111790dc8812SScott Wood } 111890dc8812SScott Wood 111990dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) { 112090dc8812SScott Wood env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0; 112190dc8812SScott Wood env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1; 112290dc8812SScott Wood env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2; 112390dc8812SScott Wood env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff; 112490dc8812SScott Wood env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4; 112590dc8812SScott Wood env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6; 112690dc8812SScott Wood env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32; 112790dc8812SScott Wood env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg; 112890dc8812SScott Wood env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0]; 112990dc8812SScott Wood env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1]; 113090dc8812SScott Wood } 113190dc8812SScott Wood 113290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_EXP) { 113390dc8812SScott Wood env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr; 113490dc8812SScott Wood } 113590dc8812SScott Wood 113690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PD) { 113790dc8812SScott Wood env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc; 113890dc8812SScott Wood env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc; 113990dc8812SScott Wood } 114090dc8812SScott Wood 114190dc8812SScott Wood if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) { 114290dc8812SScott Wood env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr; 114390dc8812SScott Wood env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar; 114490dc8812SScott Wood env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0; 114590dc8812SScott Wood 114690dc8812SScott Wood if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) { 114790dc8812SScott Wood env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1; 114890dc8812SScott Wood env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2; 114990dc8812SScott Wood } 115090dc8812SScott Wood } 1151a7a00a72SDavid Gibson 1152a7a00a72SDavid Gibson return 0; 1153fafc0b6aSAlexander Graf } 115490dc8812SScott Wood 1155a7a00a72SDavid Gibson static int kvmppc_get_books_sregs(PowerPCCPU *cpu) 1156a7a00a72SDavid Gibson { 1157a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1158a7a00a72SDavid Gibson struct kvm_sregs sregs; 1159a7a00a72SDavid Gibson int ret; 1160a7a00a72SDavid Gibson int i; 1161a7a00a72SDavid Gibson 1162a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 116390dc8812SScott Wood if (ret < 0) { 116490dc8812SScott Wood return ret; 116590dc8812SScott Wood } 116690dc8812SScott Wood 1167e57ca75cSDavid Gibson if (!cpu->vhyp) { 1168bb593904SDavid Gibson ppc_store_sdr1(env, sregs.u.s.sdr1); 1169f3c75d42SAneesh Kumar K.V } 1170ba5e5090SAlexander Graf 1171ba5e5090SAlexander Graf /* Sync SLB */ 117282c09f2fSAlexander Graf #ifdef TARGET_PPC64 11734b4d4a21SAneesh Kumar K.V /* 11744b4d4a21SAneesh Kumar K.V * The packed SLB array we get from KVM_GET_SREGS only contains 1175a7a00a72SDavid Gibson * information about valid entries. So we flush our internal copy 1176a7a00a72SDavid Gibson * to get rid of stale ones, then put all valid SLB entries back 1177a7a00a72SDavid Gibson * in. 11784b4d4a21SAneesh Kumar K.V */ 11794b4d4a21SAneesh Kumar K.V memset(env->slb, 0, sizeof(env->slb)); 1180d83af167SAneesh Kumar K.V for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 11814b4d4a21SAneesh Kumar K.V target_ulong rb = sregs.u.s.ppc64.slb[i].slbe; 11824b4d4a21SAneesh Kumar K.V target_ulong rs = sregs.u.s.ppc64.slb[i].slbv; 11834b4d4a21SAneesh Kumar K.V /* 11844b4d4a21SAneesh Kumar K.V * Only restore valid entries 11854b4d4a21SAneesh Kumar K.V */ 11864b4d4a21SAneesh Kumar K.V if (rb & SLB_ESID_V) { 1187bcd81230SDavid Gibson ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs); 11884b4d4a21SAneesh Kumar K.V } 1189ba5e5090SAlexander Graf } 119082c09f2fSAlexander Graf #endif 1191ba5e5090SAlexander Graf 1192ba5e5090SAlexander Graf /* Sync SRs */ 1193ba5e5090SAlexander Graf for (i = 0; i < 16; i++) { 1194ba5e5090SAlexander Graf env->sr[i] = sregs.u.s.ppc32.sr[i]; 1195ba5e5090SAlexander Graf } 1196ba5e5090SAlexander Graf 1197ba5e5090SAlexander Graf /* Sync BATs */ 1198ba5e5090SAlexander Graf for (i = 0; i < 8; i++) { 1199ba5e5090SAlexander Graf env->DBAT[0][i] = sregs.u.s.ppc32.dbat[i] & 0xffffffff; 1200ba5e5090SAlexander Graf env->DBAT[1][i] = sregs.u.s.ppc32.dbat[i] >> 32; 1201ba5e5090SAlexander Graf env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff; 1202ba5e5090SAlexander Graf env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32; 1203ba5e5090SAlexander Graf } 1204a7a00a72SDavid Gibson 1205a7a00a72SDavid Gibson return 0; 1206a7a00a72SDavid Gibson } 1207a7a00a72SDavid Gibson 1208a1676bb3SJulia Suvorova int kvm_arch_get_registers(CPUState *cs, Error **errp) 1209a7a00a72SDavid Gibson { 1210a7a00a72SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 1211a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1212a7a00a72SDavid Gibson struct kvm_regs regs; 1213a7a00a72SDavid Gibson int i, ret; 1214a7a00a72SDavid Gibson 1215a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1216c995e942SDavid Gibson if (ret < 0) { 1217a7a00a72SDavid Gibson return ret; 1218c995e942SDavid Gibson } 1219a7a00a72SDavid Gibson 12202060436aSHarsh Prateek Bora ppc_set_cr(env, regs.cr); 1221a7a00a72SDavid Gibson env->ctr = regs.ctr; 1222a7a00a72SDavid Gibson env->lr = regs.lr; 1223a7a00a72SDavid Gibson cpu_write_xer(env, regs.xer); 1224a7a00a72SDavid Gibson env->msr = regs.msr; 1225a7a00a72SDavid Gibson env->nip = regs.pc; 1226a7a00a72SDavid Gibson 1227a7a00a72SDavid Gibson env->spr[SPR_SRR0] = regs.srr0; 1228a7a00a72SDavid Gibson env->spr[SPR_SRR1] = regs.srr1; 1229a7a00a72SDavid Gibson 1230a7a00a72SDavid Gibson env->spr[SPR_SPRG0] = regs.sprg0; 1231a7a00a72SDavid Gibson env->spr[SPR_SPRG1] = regs.sprg1; 1232a7a00a72SDavid Gibson env->spr[SPR_SPRG2] = regs.sprg2; 1233a7a00a72SDavid Gibson env->spr[SPR_SPRG3] = regs.sprg3; 1234a7a00a72SDavid Gibson env->spr[SPR_SPRG4] = regs.sprg4; 1235a7a00a72SDavid Gibson env->spr[SPR_SPRG5] = regs.sprg5; 1236a7a00a72SDavid Gibson env->spr[SPR_SPRG6] = regs.sprg6; 1237a7a00a72SDavid Gibson env->spr[SPR_SPRG7] = regs.sprg7; 1238a7a00a72SDavid Gibson 1239a7a00a72SDavid Gibson env->spr[SPR_BOOKE_PID] = regs.pid; 1240a7a00a72SDavid Gibson 1241c995e942SDavid Gibson for (i = 0; i < 32; i++) { 1242a7a00a72SDavid Gibson env->gpr[i] = regs.gpr[i]; 1243c995e942SDavid Gibson } 1244a7a00a72SDavid Gibson 1245a7a00a72SDavid Gibson kvm_get_fp(cs); 1246a7a00a72SDavid Gibson 1247a7a00a72SDavid Gibson if (cap_booke_sregs) { 1248a7a00a72SDavid Gibson ret = kvmppc_get_booke_sregs(cpu); 1249a7a00a72SDavid Gibson if (ret < 0) { 1250a7a00a72SDavid Gibson return ret; 1251a7a00a72SDavid Gibson } 1252a7a00a72SDavid Gibson } 1253a7a00a72SDavid Gibson 1254a7a00a72SDavid Gibson if (cap_segstate) { 1255a7a00a72SDavid Gibson ret = kvmppc_get_books_sregs(cpu); 1256a7a00a72SDavid Gibson if (ret < 0) { 1257a7a00a72SDavid Gibson return ret; 1258a7a00a72SDavid Gibson } 1259fafc0b6aSAlexander Graf } 1260ba5e5090SAlexander Graf 1261d67d40eaSDavid Gibson if (cap_hior) { 1262d67d40eaSDavid Gibson kvm_get_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 1263d67d40eaSDavid Gibson } 1264d67d40eaSDavid Gibson 1265d67d40eaSDavid Gibson if (cap_one_reg) { 1266c995e942SDavid Gibson /* 1267c995e942SDavid Gibson * We deliberately ignore errors here, for kernels which have 1268d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 1269d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 1270c995e942SDavid Gibson * work, at least until we try to migrate. 1271c995e942SDavid Gibson */ 1272d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 1273d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 1274d67d40eaSDavid Gibson 1275d67d40eaSDavid Gibson if (id != 0) { 1276d67d40eaSDavid Gibson kvm_get_one_spr(cs, id, i); 1277d67d40eaSDavid Gibson } 1278d67d40eaSDavid Gibson } 12799b00ea49SDavid Gibson 12809b00ea49SDavid Gibson #ifdef TARGET_PPC64 1281ca241959SVíctor Colombo if (FIELD_EX64(env->msr, MSR, TS)) { 128280b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 128380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 128480b3f79bSAlexey Kardashevskiy } 128580b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 128680b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 128780b3f79bSAlexey Kardashevskiy } 128880b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 128980b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 129080b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 129180b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 129280b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 129380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 129480b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 129580b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 129680b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 129780b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 129880b3f79bSAlexey Kardashevskiy } 129980b3f79bSAlexey Kardashevskiy 13009b00ea49SDavid Gibson if (cap_papr) { 13019b00ea49SDavid Gibson if (kvm_get_vpa(cs) < 0) { 13028d83cbf1SGreg Kurz trace_kvm_failed_get_vpa(); 13039b00ea49SDavid Gibson } 13049b00ea49SDavid Gibson } 130598a8b524SAlexey Kardashevskiy 130698a8b524SAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 1307972bd576SAlexey Kardashevskiy kvm_get_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES); 13089b00ea49SDavid Gibson #endif 1309d67d40eaSDavid Gibson } 1310d67d40eaSDavid Gibson 1311d76d1650Saurel32 return 0; 1312d76d1650Saurel32 } 1313d76d1650Saurel32 13141bc22652SAndreas Färber int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level) 1315fc87e185SAlexander Graf { 1316fc87e185SAlexander Graf unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET; 1317fc87e185SAlexander Graf 1318fc87e185SAlexander Graf if (irq != PPC_INTERRUPT_EXT) { 1319fc87e185SAlexander Graf return 0; 1320fc87e185SAlexander Graf } 1321fc87e185SAlexander Graf 132276d93e14Sjianchunfu if (!cap_interrupt_unset) { 1323fc87e185SAlexander Graf return 0; 1324fc87e185SAlexander Graf } 1325fc87e185SAlexander Graf 13261bc22652SAndreas Färber kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); 1327fc87e185SAlexander Graf 1328fc87e185SAlexander Graf return 0; 1329fc87e185SAlexander Graf } 1330fc87e185SAlexander Graf 133120d695a9SAndreas Färber void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 1332d76d1650Saurel32 { 13331e8f51e8SShivaprasad G Bhat return; 1334d76d1650Saurel32 } 1335d76d1650Saurel32 13364c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 1337d76d1650Saurel32 { 13384c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 1339d76d1650Saurel32 } 1340d76d1650Saurel32 134120d695a9SAndreas Färber int kvm_arch_process_async_events(CPUState *cs) 13420af691d7SMarcelo Tosatti { 1343259186a7SAndreas Färber return cs->halted; 13440af691d7SMarcelo Tosatti } 13450af691d7SMarcelo Tosatti 1346259186a7SAndreas Färber static int kvmppc_handle_halt(PowerPCCPU *cpu) 1347d76d1650Saurel32 { 1348259186a7SAndreas Färber CPUState *cs = CPU(cpu); 1349259186a7SAndreas Färber CPUPPCState *env = &cpu->env; 1350259186a7SAndreas Färber 13510939b8f8SVíctor Colombo if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && 13520939b8f8SVíctor Colombo FIELD_EX64(env->msr, MSR, EE)) { 1353259186a7SAndreas Färber cs->halted = 1; 135427103424SAndreas Färber cs->exception_index = EXCP_HLT; 1355d76d1650Saurel32 } 1356d76d1650Saurel32 1357bb4ea393SJan Kiszka return 0; 1358d76d1650Saurel32 } 1359d76d1650Saurel32 1360d76d1650Saurel32 /* map dcr access to existing qemu dcr emulation */ 1361c995e942SDavid Gibson static int kvmppc_handle_dcr_read(CPUPPCState *env, 1362c995e942SDavid Gibson uint32_t dcrn, uint32_t *data) 1363d76d1650Saurel32 { 1364c995e942SDavid Gibson if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) { 1365d76d1650Saurel32 fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn); 1366c995e942SDavid Gibson } 1367d76d1650Saurel32 1368bb4ea393SJan Kiszka return 0; 1369d76d1650Saurel32 } 1370d76d1650Saurel32 1371c995e942SDavid Gibson static int kvmppc_handle_dcr_write(CPUPPCState *env, 1372c995e942SDavid Gibson uint32_t dcrn, uint32_t data) 1373d76d1650Saurel32 { 1374c995e942SDavid Gibson if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) { 1375d76d1650Saurel32 fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn); 1376c995e942SDavid Gibson } 1377d76d1650Saurel32 1378bb4ea393SJan Kiszka return 0; 1379d76d1650Saurel32 } 1380d76d1650Saurel32 13818a0548f9SBharat Bhushan int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 13828a0548f9SBharat Bhushan { 13838a0548f9SBharat Bhushan /* Mixed endian case is not handled */ 13848a0548f9SBharat Bhushan uint32_t sc = debug_inst_opcode; 13858a0548f9SBharat Bhushan 13868a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 13878a0548f9SBharat Bhushan sizeof(sc), 0) || 13888a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 1)) { 13898a0548f9SBharat Bhushan return -EINVAL; 13908a0548f9SBharat Bhushan } 13918a0548f9SBharat Bhushan 13928a0548f9SBharat Bhushan return 0; 13938a0548f9SBharat Bhushan } 13948a0548f9SBharat Bhushan 13958a0548f9SBharat Bhushan int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 13968a0548f9SBharat Bhushan { 13978a0548f9SBharat Bhushan uint32_t sc; 13988a0548f9SBharat Bhushan 13998a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 0) || 14008a0548f9SBharat Bhushan sc != debug_inst_opcode || 14018a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 14028a0548f9SBharat Bhushan sizeof(sc), 1)) { 14038a0548f9SBharat Bhushan return -EINVAL; 14048a0548f9SBharat Bhushan } 14058a0548f9SBharat Bhushan 14068a0548f9SBharat Bhushan return 0; 14078a0548f9SBharat Bhushan } 14088a0548f9SBharat Bhushan 140988365d17SBharat Bhushan static int find_hw_breakpoint(target_ulong addr, int type) 141088365d17SBharat Bhushan { 141188365d17SBharat Bhushan int n; 141288365d17SBharat Bhushan 141388365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 141488365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 141588365d17SBharat Bhushan 141688365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 141788365d17SBharat Bhushan if (hw_debug_points[n].addr == addr && 141888365d17SBharat Bhushan hw_debug_points[n].type == type) { 141988365d17SBharat Bhushan return n; 142088365d17SBharat Bhushan } 142188365d17SBharat Bhushan } 142288365d17SBharat Bhushan 142388365d17SBharat Bhushan return -1; 142488365d17SBharat Bhushan } 142588365d17SBharat Bhushan 142688365d17SBharat Bhushan static int find_hw_watchpoint(target_ulong addr, int *flag) 142788365d17SBharat Bhushan { 142888365d17SBharat Bhushan int n; 142988365d17SBharat Bhushan 143088365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_ACCESS); 143188365d17SBharat Bhushan if (n >= 0) { 143288365d17SBharat Bhushan *flag = BP_MEM_ACCESS; 143388365d17SBharat Bhushan return n; 143488365d17SBharat Bhushan } 143588365d17SBharat Bhushan 143688365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_WRITE); 143788365d17SBharat Bhushan if (n >= 0) { 143888365d17SBharat Bhushan *flag = BP_MEM_WRITE; 143988365d17SBharat Bhushan return n; 144088365d17SBharat Bhushan } 144188365d17SBharat Bhushan 144288365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_READ); 144388365d17SBharat Bhushan if (n >= 0) { 144488365d17SBharat Bhushan *flag = BP_MEM_READ; 144588365d17SBharat Bhushan return n; 144688365d17SBharat Bhushan } 144788365d17SBharat Bhushan 144888365d17SBharat Bhushan return -1; 144988365d17SBharat Bhushan } 145088365d17SBharat Bhushan 1451b8a6eb18SAnton Johansson int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) 145288365d17SBharat Bhushan { 1453b8a6eb18SAnton Johansson const unsigned breakpoint_index = nb_hw_breakpoint + nb_hw_watchpoint; 1454b8a6eb18SAnton Johansson if (breakpoint_index >= ARRAY_SIZE(hw_debug_points)) { 145588365d17SBharat Bhushan return -ENOBUFS; 145688365d17SBharat Bhushan } 145788365d17SBharat Bhushan 1458b8a6eb18SAnton Johansson hw_debug_points[breakpoint_index].addr = addr; 1459b8a6eb18SAnton Johansson hw_debug_points[breakpoint_index].type = type; 146088365d17SBharat Bhushan 146188365d17SBharat Bhushan switch (type) { 146288365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 146388365d17SBharat Bhushan if (nb_hw_breakpoint >= max_hw_breakpoint) { 146488365d17SBharat Bhushan return -ENOBUFS; 146588365d17SBharat Bhushan } 146688365d17SBharat Bhushan 146788365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 146888365d17SBharat Bhushan return -EEXIST; 146988365d17SBharat Bhushan } 147088365d17SBharat Bhushan 147188365d17SBharat Bhushan nb_hw_breakpoint++; 147288365d17SBharat Bhushan break; 147388365d17SBharat Bhushan 147488365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 147588365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 147688365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 147788365d17SBharat Bhushan if (nb_hw_watchpoint >= max_hw_watchpoint) { 147888365d17SBharat Bhushan return -ENOBUFS; 147988365d17SBharat Bhushan } 148088365d17SBharat Bhushan 148188365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 148288365d17SBharat Bhushan return -EEXIST; 148388365d17SBharat Bhushan } 148488365d17SBharat Bhushan 148588365d17SBharat Bhushan nb_hw_watchpoint++; 148688365d17SBharat Bhushan break; 148788365d17SBharat Bhushan 148888365d17SBharat Bhushan default: 148988365d17SBharat Bhushan return -ENOSYS; 149088365d17SBharat Bhushan } 149188365d17SBharat Bhushan 149288365d17SBharat Bhushan return 0; 149388365d17SBharat Bhushan } 149488365d17SBharat Bhushan 1495b8a6eb18SAnton Johansson int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) 149688365d17SBharat Bhushan { 149788365d17SBharat Bhushan int n; 149888365d17SBharat Bhushan 149988365d17SBharat Bhushan n = find_hw_breakpoint(addr, type); 150088365d17SBharat Bhushan if (n < 0) { 150188365d17SBharat Bhushan return -ENOENT; 150288365d17SBharat Bhushan } 150388365d17SBharat Bhushan 150488365d17SBharat Bhushan switch (type) { 150588365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 150688365d17SBharat Bhushan nb_hw_breakpoint--; 150788365d17SBharat Bhushan break; 150888365d17SBharat Bhushan 150988365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 151088365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 151188365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 151288365d17SBharat Bhushan nb_hw_watchpoint--; 151388365d17SBharat Bhushan break; 151488365d17SBharat Bhushan 151588365d17SBharat Bhushan default: 151688365d17SBharat Bhushan return -ENOSYS; 151788365d17SBharat Bhushan } 151888365d17SBharat Bhushan hw_debug_points[n] = hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint]; 151988365d17SBharat Bhushan 152088365d17SBharat Bhushan return 0; 152188365d17SBharat Bhushan } 152288365d17SBharat Bhushan 152388365d17SBharat Bhushan void kvm_arch_remove_all_hw_breakpoints(void) 152488365d17SBharat Bhushan { 152588365d17SBharat Bhushan nb_hw_breakpoint = nb_hw_watchpoint = 0; 152688365d17SBharat Bhushan } 152788365d17SBharat Bhushan 15288a0548f9SBharat Bhushan void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 15298a0548f9SBharat Bhushan { 153088365d17SBharat Bhushan int n; 153188365d17SBharat Bhushan 15328a0548f9SBharat Bhushan /* Software Breakpoint updates */ 15338a0548f9SBharat Bhushan if (kvm_sw_breakpoints_active(cs)) { 15348a0548f9SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 15358a0548f9SBharat Bhushan } 153688365d17SBharat Bhushan 153788365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 153888365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 153988365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) <= ARRAY_SIZE(dbg->arch.bp)); 154088365d17SBharat Bhushan 154188365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 154288365d17SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; 154388365d17SBharat Bhushan memset(dbg->arch.bp, 0, sizeof(dbg->arch.bp)); 154488365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 154588365d17SBharat Bhushan switch (hw_debug_points[n].type) { 154688365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 154788365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_BREAKPOINT; 154888365d17SBharat Bhushan break; 154988365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 155088365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE; 155188365d17SBharat Bhushan break; 155288365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 155388365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_READ; 155488365d17SBharat Bhushan break; 155588365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 155688365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE | 155788365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_READ; 155888365d17SBharat Bhushan break; 155988365d17SBharat Bhushan default: 156088365d17SBharat Bhushan cpu_abort(cs, "Unsupported breakpoint type\n"); 156188365d17SBharat Bhushan } 156288365d17SBharat Bhushan dbg->arch.bp[n].addr = hw_debug_points[n].addr; 156388365d17SBharat Bhushan } 156488365d17SBharat Bhushan } 15658a0548f9SBharat Bhushan } 15668a0548f9SBharat Bhushan 15672cbd1581SFabiano Rosas static int kvm_handle_hw_breakpoint(CPUState *cs, 15682cbd1581SFabiano Rosas struct kvm_debug_exit_arch *arch_info) 15698a0548f9SBharat Bhushan { 15706e0552a3SFabiano Rosas int handle = DEBUG_RETURN_GUEST; 157188365d17SBharat Bhushan int n; 157288365d17SBharat Bhushan int flag = 0; 15738a0548f9SBharat Bhushan 157488365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 157588365d17SBharat Bhushan if (arch_info->status & KVMPPC_DEBUG_BREAKPOINT) { 157688365d17SBharat Bhushan n = find_hw_breakpoint(arch_info->address, GDB_BREAKPOINT_HW); 157788365d17SBharat Bhushan if (n >= 0) { 15786e0552a3SFabiano Rosas handle = DEBUG_RETURN_GDB; 157988365d17SBharat Bhushan } 158088365d17SBharat Bhushan } else if (arch_info->status & (KVMPPC_DEBUG_WATCH_READ | 158188365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_WRITE)) { 158288365d17SBharat Bhushan n = find_hw_watchpoint(arch_info->address, &flag); 158388365d17SBharat Bhushan if (n >= 0) { 15846e0552a3SFabiano Rosas handle = DEBUG_RETURN_GDB; 158588365d17SBharat Bhushan cs->watchpoint_hit = &hw_watchpoint; 158688365d17SBharat Bhushan hw_watchpoint.vaddr = hw_debug_points[n].addr; 158788365d17SBharat Bhushan hw_watchpoint.flags = flag; 158888365d17SBharat Bhushan } 158988365d17SBharat Bhushan } 159088365d17SBharat Bhushan } 15912cbd1581SFabiano Rosas return handle; 15922cbd1581SFabiano Rosas } 15932cbd1581SFabiano Rosas 1594468e3a1aSFabiano Rosas static int kvm_handle_singlestep(void) 1595468e3a1aSFabiano Rosas { 15966e0552a3SFabiano Rosas return DEBUG_RETURN_GDB; 1597468e3a1aSFabiano Rosas } 1598468e3a1aSFabiano Rosas 1599468e3a1aSFabiano Rosas static int kvm_handle_sw_breakpoint(void) 1600468e3a1aSFabiano Rosas { 16016e0552a3SFabiano Rosas return DEBUG_RETURN_GDB; 1602468e3a1aSFabiano Rosas } 1603468e3a1aSFabiano Rosas 16042cbd1581SFabiano Rosas static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) 16052cbd1581SFabiano Rosas { 16062cbd1581SFabiano Rosas CPUState *cs = CPU(cpu); 16072cbd1581SFabiano Rosas CPUPPCState *env = &cpu->env; 16082cbd1581SFabiano Rosas struct kvm_debug_exit_arch *arch_info = &run->debug.arch; 16092cbd1581SFabiano Rosas 16102cbd1581SFabiano Rosas if (cs->singlestep_enabled) { 1611468e3a1aSFabiano Rosas return kvm_handle_singlestep(); 1612468e3a1aSFabiano Rosas } 1613468e3a1aSFabiano Rosas 1614468e3a1aSFabiano Rosas if (arch_info->status) { 1615468e3a1aSFabiano Rosas return kvm_handle_hw_breakpoint(cs, arch_info); 1616468e3a1aSFabiano Rosas } 1617468e3a1aSFabiano Rosas 1618468e3a1aSFabiano Rosas if (kvm_find_sw_breakpoint(cs, arch_info->address)) { 1619468e3a1aSFabiano Rosas return kvm_handle_sw_breakpoint(); 1620468e3a1aSFabiano Rosas } 1621468e3a1aSFabiano Rosas 1622468e3a1aSFabiano Rosas /* 1623468e3a1aSFabiano Rosas * QEMU is not able to handle debug exception, so inject 16248a0548f9SBharat Bhushan * program exception to guest; 16258a0548f9SBharat Bhushan * Yes program exception NOT debug exception !! 162688365d17SBharat Bhushan * When QEMU is using debug resources then debug exception must 162788365d17SBharat Bhushan * be always set. To achieve this we set MSR_DE and also set 162888365d17SBharat Bhushan * MSRP_DEP so guest cannot change MSR_DE. 162988365d17SBharat Bhushan * When emulating debug resource for guest we want guest 163088365d17SBharat Bhushan * to control MSR_DE (enable/disable debug interrupt on need). 163188365d17SBharat Bhushan * Supporting both configurations are NOT possible. 163288365d17SBharat Bhushan * So the result is that we cannot share debug resources 163388365d17SBharat Bhushan * between QEMU and Guest on BOOKE architecture. 163488365d17SBharat Bhushan * In the current design QEMU gets the priority over guest, 163588365d17SBharat Bhushan * this means that if QEMU is using debug resources then guest 163688365d17SBharat Bhushan * cannot use them; 16378a0548f9SBharat Bhushan * For software breakpoint QEMU uses a privileged instruction; 16388a0548f9SBharat Bhushan * So there cannot be any reason that we are here for guest 16398a0548f9SBharat Bhushan * set debug exception, only possibility is guest executed a 16408a0548f9SBharat Bhushan * privileged / illegal instruction and that's why we are 16418a0548f9SBharat Bhushan * injecting a program interrupt. 16428a0548f9SBharat Bhushan */ 16438a0548f9SBharat Bhushan cpu_synchronize_state(cs); 1644468e3a1aSFabiano Rosas /* 1645468e3a1aSFabiano Rosas * env->nip is PC, so increment this by 4 to use 16468a0548f9SBharat Bhushan * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4. 16478a0548f9SBharat Bhushan */ 16488a0548f9SBharat Bhushan env->nip += 4; 16498a0548f9SBharat Bhushan cs->exception_index = POWERPC_EXCP_PROGRAM; 16508a0548f9SBharat Bhushan env->error_code = POWERPC_EXCP_INVAL; 16518a0548f9SBharat Bhushan ppc_cpu_do_interrupt(cs); 16528a0548f9SBharat Bhushan 16536e0552a3SFabiano Rosas return DEBUG_RETURN_GUEST; 16548a0548f9SBharat Bhushan } 16558a0548f9SBharat Bhushan 165620d695a9SAndreas Färber int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 1657d76d1650Saurel32 { 165820d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 165920d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1660bb4ea393SJan Kiszka int ret; 1661d76d1650Saurel32 1662195801d7SStefan Hajnoczi bql_lock(); 16634b8523eeSJan Kiszka 1664d76d1650Saurel32 switch (run->exit_reason) { 1665d76d1650Saurel32 case KVM_EXIT_DCR: 1666d76d1650Saurel32 if (run->dcr.is_write) { 16678d83cbf1SGreg Kurz trace_kvm_handle_dcr_write(); 1668d76d1650Saurel32 ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); 1669d76d1650Saurel32 } else { 1670228152c2SBoxuan Li trace_kvm_handle_dcr_read(); 1671d76d1650Saurel32 ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); 1672d76d1650Saurel32 } 1673d76d1650Saurel32 break; 1674d76d1650Saurel32 case KVM_EXIT_HLT: 16758d83cbf1SGreg Kurz trace_kvm_handle_halt(); 1676259186a7SAndreas Färber ret = kvmppc_handle_halt(cpu); 1677d76d1650Saurel32 break; 1678566abdb4SPaolo Bonzini #if defined(CONFIG_PSERIES) 1679f61b4bedSAlexander Graf case KVM_EXIT_PAPR_HCALL: 1680f290a238SFabiano Rosas trace_kvm_handle_papr_hcall(run->papr_hcall.nr); 168120d695a9SAndreas Färber run->papr_hcall.ret = spapr_hypercall(cpu, 1682aa100fa4SAndreas Färber run->papr_hcall.nr, 1683f61b4bedSAlexander Graf run->papr_hcall.args); 168478e8fde2SDavid Gibson ret = 0; 1685f61b4bedSAlexander Graf break; 1686f61b4bedSAlexander Graf #endif 16875b95b8b9SAlexander Graf case KVM_EXIT_EPR: 16888d83cbf1SGreg Kurz trace_kvm_handle_epr(); 1689933b19eaSAlexander Graf run->epr.epr = ldl_phys(cs->as, env->mpic_iack); 16905b95b8b9SAlexander Graf ret = 0; 16915b95b8b9SAlexander Graf break; 169231f2cb8fSBharat Bhushan case KVM_EXIT_WATCHDOG: 16938d83cbf1SGreg Kurz trace_kvm_handle_watchdog_expiry(); 169431f2cb8fSBharat Bhushan watchdog_perform_action(); 169531f2cb8fSBharat Bhushan ret = 0; 169631f2cb8fSBharat Bhushan break; 169731f2cb8fSBharat Bhushan 16988a0548f9SBharat Bhushan case KVM_EXIT_DEBUG: 16998d83cbf1SGreg Kurz trace_kvm_handle_debug_exception(); 17008a0548f9SBharat Bhushan if (kvm_handle_debug(cpu, run)) { 17018a0548f9SBharat Bhushan ret = EXCP_DEBUG; 17028a0548f9SBharat Bhushan break; 17038a0548f9SBharat Bhushan } 17048a0548f9SBharat Bhushan /* re-enter, this exception was guest-internal */ 17058a0548f9SBharat Bhushan ret = 0; 17068a0548f9SBharat Bhushan break; 17078a0548f9SBharat Bhushan 1708566abdb4SPaolo Bonzini #if defined(CONFIG_PSERIES) 17099ac703acSAravinda Prasad case KVM_EXIT_NMI: 17109ac703acSAravinda Prasad trace_kvm_handle_nmi_exception(); 17119ac703acSAravinda Prasad ret = kvm_handle_nmi(cpu, run); 17129ac703acSAravinda Prasad break; 17139ac703acSAravinda Prasad #endif 17149ac703acSAravinda Prasad 171573aaec4aSJan Kiszka default: 171673aaec4aSJan Kiszka fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); 171773aaec4aSJan Kiszka ret = -1; 171873aaec4aSJan Kiszka break; 1719d76d1650Saurel32 } 1720d76d1650Saurel32 1721195801d7SStefan Hajnoczi bql_unlock(); 1722d76d1650Saurel32 return ret; 1723d76d1650Saurel32 } 1724d76d1650Saurel32 172531f2cb8fSBharat Bhushan int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 172631f2cb8fSBharat Bhushan { 172731f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 172831f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 172931f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 173031f2cb8fSBharat Bhushan .id = KVM_REG_PPC_OR_TSR, 173131f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 173231f2cb8fSBharat Bhushan }; 173331f2cb8fSBharat Bhushan 1734c4550e6eSCédric Le Goater if (!kvm_enabled()) { 1735c4550e6eSCédric Le Goater return 0; 1736c4550e6eSCédric Le Goater } 1737c4550e6eSCédric Le Goater 173831f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 173931f2cb8fSBharat Bhushan } 174031f2cb8fSBharat Bhushan 174131f2cb8fSBharat Bhushan int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 174231f2cb8fSBharat Bhushan { 174331f2cb8fSBharat Bhushan 174431f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 174531f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 174631f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 174731f2cb8fSBharat Bhushan .id = KVM_REG_PPC_CLEAR_TSR, 174831f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 174931f2cb8fSBharat Bhushan }; 175031f2cb8fSBharat Bhushan 1751c4550e6eSCédric Le Goater if (!kvm_enabled()) { 1752c4550e6eSCédric Le Goater return 0; 1753c4550e6eSCédric Le Goater } 1754c4550e6eSCédric Le Goater 175531f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 175631f2cb8fSBharat Bhushan } 175731f2cb8fSBharat Bhushan 175831f2cb8fSBharat Bhushan int kvmppc_set_tcr(PowerPCCPU *cpu) 175931f2cb8fSBharat Bhushan { 176031f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 176131f2cb8fSBharat Bhushan CPUPPCState *env = &cpu->env; 176231f2cb8fSBharat Bhushan uint32_t tcr = env->spr[SPR_BOOKE_TCR]; 176331f2cb8fSBharat Bhushan 176431f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 176531f2cb8fSBharat Bhushan .id = KVM_REG_PPC_TCR, 176631f2cb8fSBharat Bhushan .addr = (uintptr_t) &tcr, 176731f2cb8fSBharat Bhushan }; 176831f2cb8fSBharat Bhushan 1769c4550e6eSCédric Le Goater if (!kvm_enabled()) { 1770c4550e6eSCédric Le Goater return 0; 1771c4550e6eSCédric Le Goater } 1772c4550e6eSCédric Le Goater 177331f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 177431f2cb8fSBharat Bhushan } 177531f2cb8fSBharat Bhushan 177631f2cb8fSBharat Bhushan int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu) 177731f2cb8fSBharat Bhushan { 177831f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 177931f2cb8fSBharat Bhushan int ret; 178031f2cb8fSBharat Bhushan 178131f2cb8fSBharat Bhushan if (!kvm_enabled()) { 178231f2cb8fSBharat Bhushan return -1; 178331f2cb8fSBharat Bhushan } 178431f2cb8fSBharat Bhushan 178531f2cb8fSBharat Bhushan if (!cap_ppc_watchdog) { 178631f2cb8fSBharat Bhushan printf("warning: KVM does not support watchdog"); 178731f2cb8fSBharat Bhushan return -1; 178831f2cb8fSBharat Bhushan } 178931f2cb8fSBharat Bhushan 179048add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_BOOKE_WATCHDOG, 0); 179131f2cb8fSBharat Bhushan if (ret < 0) { 179231f2cb8fSBharat Bhushan fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n", 179331f2cb8fSBharat Bhushan __func__, strerror(-ret)); 179431f2cb8fSBharat Bhushan return ret; 179531f2cb8fSBharat Bhushan } 179631f2cb8fSBharat Bhushan 179731f2cb8fSBharat Bhushan return ret; 179831f2cb8fSBharat Bhushan } 179931f2cb8fSBharat Bhushan 1800dc333cd6SAlexander Graf static int read_cpuinfo(const char *field, char *value, int len) 1801dc333cd6SAlexander Graf { 1802dc333cd6SAlexander Graf FILE *f; 1803dc333cd6SAlexander Graf int ret = -1; 1804dc333cd6SAlexander Graf int field_len = strlen(field); 1805dc333cd6SAlexander Graf char line[512]; 1806dc333cd6SAlexander Graf 1807dc333cd6SAlexander Graf f = fopen("/proc/cpuinfo", "r"); 1808dc333cd6SAlexander Graf if (!f) { 1809dc333cd6SAlexander Graf return -1; 1810dc333cd6SAlexander Graf } 1811dc333cd6SAlexander Graf 1812dc333cd6SAlexander Graf do { 1813dc333cd6SAlexander Graf if (!fgets(line, sizeof(line), f)) { 1814dc333cd6SAlexander Graf break; 1815dc333cd6SAlexander Graf } 1816dc333cd6SAlexander Graf if (!strncmp(line, field, field_len)) { 1817ae215068SJim Meyering pstrcpy(value, len, line); 1818dc333cd6SAlexander Graf ret = 0; 1819dc333cd6SAlexander Graf break; 1820dc333cd6SAlexander Graf } 1821dc333cd6SAlexander Graf } while (*line); 1822dc333cd6SAlexander Graf 1823dc333cd6SAlexander Graf fclose(f); 1824dc333cd6SAlexander Graf 1825dc333cd6SAlexander Graf return ret; 1826dc333cd6SAlexander Graf } 1827dc333cd6SAlexander Graf 18289cbcfb59SGreg Kurz static uint32_t kvmppc_get_tbfreq_procfs(void) 1829dc333cd6SAlexander Graf { 1830dc333cd6SAlexander Graf char line[512]; 1831dc333cd6SAlexander Graf char *ns; 18329cbcfb59SGreg Kurz uint32_t tbfreq_fallback = NANOSECONDS_PER_SECOND; 18339cbcfb59SGreg Kurz uint32_t tbfreq_procfs; 1834dc333cd6SAlexander Graf 1835dc333cd6SAlexander Graf if (read_cpuinfo("timebase", line, sizeof(line))) { 18369cbcfb59SGreg Kurz return tbfreq_fallback; 1837dc333cd6SAlexander Graf } 1838dc333cd6SAlexander Graf 1839c995e942SDavid Gibson ns = strchr(line, ':'); 1840c995e942SDavid Gibson if (!ns) { 18419cbcfb59SGreg Kurz return tbfreq_fallback; 1842dc333cd6SAlexander Graf } 1843dc333cd6SAlexander Graf 18449cbcfb59SGreg Kurz tbfreq_procfs = atoi(++ns); 1845dc333cd6SAlexander Graf 18469cbcfb59SGreg Kurz /* 0 is certainly not acceptable by the guest, return fallback value */ 18479cbcfb59SGreg Kurz return tbfreq_procfs ? tbfreq_procfs : tbfreq_fallback; 18489cbcfb59SGreg Kurz } 18499cbcfb59SGreg Kurz 18509cbcfb59SGreg Kurz uint32_t kvmppc_get_tbfreq(void) 18519cbcfb59SGreg Kurz { 18529cbcfb59SGreg Kurz static uint32_t cached_tbfreq; 18539cbcfb59SGreg Kurz 18549cbcfb59SGreg Kurz if (!cached_tbfreq) { 18559cbcfb59SGreg Kurz cached_tbfreq = kvmppc_get_tbfreq_procfs(); 18569cbcfb59SGreg Kurz } 18579cbcfb59SGreg Kurz 18589cbcfb59SGreg Kurz return cached_tbfreq; 1859ef951443SNikunj A Dadhania } 1860ef951443SNikunj A Dadhania 1861ef951443SNikunj A Dadhania bool kvmppc_get_host_serial(char **value) 1862ef951443SNikunj A Dadhania { 1863ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/system-id", value, NULL, 1864ef951443SNikunj A Dadhania NULL); 1865ef951443SNikunj A Dadhania } 1866ef951443SNikunj A Dadhania 1867ef951443SNikunj A Dadhania bool kvmppc_get_host_model(char **value) 1868ef951443SNikunj A Dadhania { 1869ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/model", value, NULL, NULL); 1870dc333cd6SAlexander Graf } 18714513d923SGleb Natapov 1872eadaada1SAlexander Graf /* Try to find a device tree node for a CPU with clock-frequency property */ 1873eadaada1SAlexander Graf static int kvmppc_find_cpu_dt(char *buf, int buf_len) 1874eadaada1SAlexander Graf { 1875eadaada1SAlexander Graf struct dirent *dirp; 1876eadaada1SAlexander Graf DIR *dp; 1877eadaada1SAlexander Graf 1878c995e942SDavid Gibson dp = opendir(PROC_DEVTREE_CPU); 1879c995e942SDavid Gibson if (!dp) { 1880eadaada1SAlexander Graf printf("Can't open directory " PROC_DEVTREE_CPU "\n"); 1881eadaada1SAlexander Graf return -1; 1882eadaada1SAlexander Graf } 1883eadaada1SAlexander Graf 1884eadaada1SAlexander Graf buf[0] = '\0'; 1885eadaada1SAlexander Graf while ((dirp = readdir(dp)) != NULL) { 1886eadaada1SAlexander Graf FILE *f; 18871a42c692SMurilo Opsfelder Araujo 18881a42c692SMurilo Opsfelder Araujo /* Don't accidentally read from the current and parent directories */ 18891a42c692SMurilo Opsfelder Araujo if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { 18901a42c692SMurilo Opsfelder Araujo continue; 18911a42c692SMurilo Opsfelder Araujo } 18921a42c692SMurilo Opsfelder Araujo 1893eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s/clock-frequency", PROC_DEVTREE_CPU, 1894eadaada1SAlexander Graf dirp->d_name); 1895eadaada1SAlexander Graf f = fopen(buf, "r"); 1896eadaada1SAlexander Graf if (f) { 1897eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s", PROC_DEVTREE_CPU, dirp->d_name); 1898eadaada1SAlexander Graf fclose(f); 1899eadaada1SAlexander Graf break; 1900eadaada1SAlexander Graf } 1901eadaada1SAlexander Graf buf[0] = '\0'; 1902eadaada1SAlexander Graf } 1903eadaada1SAlexander Graf closedir(dp); 1904eadaada1SAlexander Graf if (buf[0] == '\0') { 1905eadaada1SAlexander Graf printf("Unknown host!\n"); 1906eadaada1SAlexander Graf return -1; 1907eadaada1SAlexander Graf } 1908eadaada1SAlexander Graf 1909eadaada1SAlexander Graf return 0; 1910eadaada1SAlexander Graf } 1911eadaada1SAlexander Graf 19127d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_dt(const char *filename) 1913eadaada1SAlexander Graf { 19149bc884b7SDavid Gibson union { 19159bc884b7SDavid Gibson uint32_t v32; 19169bc884b7SDavid Gibson uint64_t v64; 19179bc884b7SDavid Gibson } u; 1918eadaada1SAlexander Graf FILE *f; 1919eadaada1SAlexander Graf int len; 1920eadaada1SAlexander Graf 19217d94a30bSSukadev Bhattiprolu f = fopen(filename, "rb"); 1922eadaada1SAlexander Graf if (!f) { 1923eadaada1SAlexander Graf return -1; 1924eadaada1SAlexander Graf } 1925eadaada1SAlexander Graf 19269bc884b7SDavid Gibson len = fread(&u, 1, sizeof(u), f); 1927eadaada1SAlexander Graf fclose(f); 1928eadaada1SAlexander Graf switch (len) { 19299bc884b7SDavid Gibson case 4: 19309bc884b7SDavid Gibson /* property is a 32-bit quantity */ 19319bc884b7SDavid Gibson return be32_to_cpu(u.v32); 19329bc884b7SDavid Gibson case 8: 19339bc884b7SDavid Gibson return be64_to_cpu(u.v64); 1934eadaada1SAlexander Graf } 1935eadaada1SAlexander Graf 1936eadaada1SAlexander Graf return 0; 1937eadaada1SAlexander Graf } 1938eadaada1SAlexander Graf 1939c995e942SDavid Gibson /* 1940c995e942SDavid Gibson * Read a CPU node property from the host device tree that's a single 19417d94a30bSSukadev Bhattiprolu * integer (32-bit or 64-bit). Returns 0 if anything goes wrong 1942c995e942SDavid Gibson * (can't find or open the property, or doesn't understand the format) 1943c995e942SDavid Gibson */ 19447d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_cpu_dt(const char *propname) 19457d94a30bSSukadev Bhattiprolu { 19467d94a30bSSukadev Bhattiprolu char buf[PATH_MAX], *tmp; 19477d94a30bSSukadev Bhattiprolu uint64_t val; 19487d94a30bSSukadev Bhattiprolu 19497d94a30bSSukadev Bhattiprolu if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { 19507d94a30bSSukadev Bhattiprolu return -1; 19517d94a30bSSukadev Bhattiprolu } 19527d94a30bSSukadev Bhattiprolu 19537d94a30bSSukadev Bhattiprolu tmp = g_strdup_printf("%s/%s", buf, propname); 19547d94a30bSSukadev Bhattiprolu val = kvmppc_read_int_dt(tmp); 19557d94a30bSSukadev Bhattiprolu g_free(tmp); 19567d94a30bSSukadev Bhattiprolu 19577d94a30bSSukadev Bhattiprolu return val; 19587d94a30bSSukadev Bhattiprolu } 19597d94a30bSSukadev Bhattiprolu 19609bc884b7SDavid Gibson uint64_t kvmppc_get_clockfreq(void) 19619bc884b7SDavid Gibson { 19629bc884b7SDavid Gibson return kvmppc_read_int_cpu_dt("clock-frequency"); 19639bc884b7SDavid Gibson } 19649bc884b7SDavid Gibson 19657d050527SSuraj Jitindar Singh static int kvmppc_get_dec_bits(void) 19667d050527SSuraj Jitindar Singh { 19677d050527SSuraj Jitindar Singh int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits"); 19687d050527SSuraj Jitindar Singh 19697d050527SSuraj Jitindar Singh if (nr_bits > 0) { 19707d050527SSuraj Jitindar Singh return nr_bits; 19717d050527SSuraj Jitindar Singh } 19727d050527SSuraj Jitindar Singh return 0; 19737d050527SSuraj Jitindar Singh } 19747d050527SSuraj Jitindar Singh 19751a61a9aeSStuart Yoder static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo) 197645024f09SAlexander Graf { 1977db70b311SRichard Henderson CPUState *cs = env_cpu(env); 197845024f09SAlexander Graf 19796fd33a75SAlexander Graf if (kvm_vm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) && 19801a61a9aeSStuart Yoder !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) { 19811a61a9aeSStuart Yoder return 0; 19821a61a9aeSStuart Yoder } 198345024f09SAlexander Graf 19841a61a9aeSStuart Yoder return 1; 19851a61a9aeSStuart Yoder } 19861a61a9aeSStuart Yoder 19871a61a9aeSStuart Yoder int kvmppc_get_hasidle(CPUPPCState *env) 19881a61a9aeSStuart Yoder { 19891a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 19901a61a9aeSStuart Yoder 19911a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo) && 19921a61a9aeSStuart Yoder (pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) { 19931a61a9aeSStuart Yoder return 1; 19941a61a9aeSStuart Yoder } 19951a61a9aeSStuart Yoder 19961a61a9aeSStuart Yoder return 0; 19971a61a9aeSStuart Yoder } 19981a61a9aeSStuart Yoder 19991a61a9aeSStuart Yoder int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) 20001a61a9aeSStuart Yoder { 20011a61a9aeSStuart Yoder uint32_t *hc = (uint32_t *)buf; 20021a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 20031a61a9aeSStuart Yoder 20041a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo)) { 20051a61a9aeSStuart Yoder memcpy(buf, pvinfo.hcall, buf_len); 200645024f09SAlexander Graf return 0; 200745024f09SAlexander Graf } 200845024f09SAlexander Graf 200945024f09SAlexander Graf /* 2010d13fc32eSAlexander Graf * Fallback to always fail hypercalls regardless of endianness: 201145024f09SAlexander Graf * 2012d13fc32eSAlexander Graf * tdi 0,r0,72 (becomes b .+8 in wrong endian, nop in good endian) 201345024f09SAlexander Graf * li r3, -1 2014d13fc32eSAlexander Graf * b .+8 (becomes nop in wrong endian) 2015d13fc32eSAlexander Graf * bswap32(li r3, -1) 201645024f09SAlexander Graf */ 201745024f09SAlexander Graf 2018d13fc32eSAlexander Graf hc[0] = cpu_to_be32(0x08000048); 2019d13fc32eSAlexander Graf hc[1] = cpu_to_be32(0x3860ffff); 2020d13fc32eSAlexander Graf hc[2] = cpu_to_be32(0x48000008); 2021d13fc32eSAlexander Graf hc[3] = cpu_to_be32(bswap32(0x3860ffff)); 202245024f09SAlexander Graf 20230ddbd053SAlexey Kardashevskiy return 1; 202445024f09SAlexander Graf } 202545024f09SAlexander Graf 2026026bfd89SDavid Gibson static inline int kvmppc_enable_hcall(KVMState *s, target_ulong hcall) 2027026bfd89SDavid Gibson { 2028026bfd89SDavid Gibson return kvm_vm_enable_cap(s, KVM_CAP_PPC_ENABLE_HCALL, 0, hcall, 1); 2029026bfd89SDavid Gibson } 2030026bfd89SDavid Gibson 2031026bfd89SDavid Gibson void kvmppc_enable_logical_ci_hcalls(void) 2032026bfd89SDavid Gibson { 2033026bfd89SDavid Gibson /* 2034026bfd89SDavid Gibson * FIXME: it would be nice if we could detect the cases where 2035026bfd89SDavid Gibson * we're using a device which requires the in kernel 2036026bfd89SDavid Gibson * implementation of these hcalls, but the kernel lacks them and 2037026bfd89SDavid Gibson * produce a warning. 2038026bfd89SDavid Gibson */ 2039026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_LOAD); 2040026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_STORE); 2041026bfd89SDavid Gibson } 2042026bfd89SDavid Gibson 2043ef9971ddSAlexey Kardashevskiy void kvmppc_enable_set_mode_hcall(void) 2044ef9971ddSAlexey Kardashevskiy { 2045ef9971ddSAlexey Kardashevskiy kvmppc_enable_hcall(kvm_state, H_SET_MODE); 2046ef9971ddSAlexey Kardashevskiy } 2047ef9971ddSAlexey Kardashevskiy 20485145ad4fSNathan Whitehorn void kvmppc_enable_clear_ref_mod_hcalls(void) 20495145ad4fSNathan Whitehorn { 20505145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_REF); 20515145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD); 20525145ad4fSNathan Whitehorn } 20535145ad4fSNathan Whitehorn 205468f9f708SSuraj Jitindar Singh void kvmppc_enable_h_page_init(void) 205568f9f708SSuraj Jitindar Singh { 205668f9f708SSuraj Jitindar Singh kvmppc_enable_hcall(kvm_state, H_PAGE_INIT); 205768f9f708SSuraj Jitindar Singh } 205868f9f708SSuraj Jitindar Singh 205982123b75SBharata B Rao void kvmppc_enable_h_rpt_invalidate(void) 206082123b75SBharata B Rao { 206182123b75SBharata B Rao kvmppc_enable_hcall(kvm_state, H_RPT_INVALIDATE); 206282123b75SBharata B Rao } 206382123b75SBharata B Rao 2064566abdb4SPaolo Bonzini #ifdef CONFIG_PSERIES 20651bc22652SAndreas Färber void kvmppc_set_papr(PowerPCCPU *cpu) 2066f61b4bedSAlexander Graf { 20671bc22652SAndreas Färber CPUState *cs = CPU(cpu); 2068f61b4bedSAlexander Graf int ret; 2069f61b4bedSAlexander Graf 2070da20aed1SDavid Gibson if (!kvm_enabled()) { 2071da20aed1SDavid Gibson return; 2072da20aed1SDavid Gibson } 2073da20aed1SDavid Gibson 207448add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0); 2075f61b4bedSAlexander Graf if (ret) { 2076072ed5f2SThomas Huth error_report("This vCPU type or KVM version does not support PAPR"); 2077072ed5f2SThomas Huth exit(1); 2078f61b4bedSAlexander Graf } 20799b00ea49SDavid Gibson 2080c995e942SDavid Gibson /* 2081c995e942SDavid Gibson * Update the capability flag so we sync the right information 2082c995e942SDavid Gibson * with kvm 2083c995e942SDavid Gibson */ 20849b00ea49SDavid Gibson cap_papr = 1; 2085f1af19d7SDavid Gibson } 2086566abdb4SPaolo Bonzini #endif 2087f61b4bedSAlexander Graf 2088d6e166c0SDavid Gibson int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr) 20896db5bb0fSAlexey Kardashevskiy { 2090d6e166c0SDavid Gibson return kvm_set_one_reg(CPU(cpu), KVM_REG_PPC_ARCH_COMPAT, &compat_pvr); 20916db5bb0fSAlexey Kardashevskiy } 20926db5bb0fSAlexey Kardashevskiy 20935b95b8b9SAlexander Graf void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy) 20945b95b8b9SAlexander Graf { 20955b95b8b9SAlexander Graf CPUState *cs = CPU(cpu); 20965b95b8b9SAlexander Graf int ret; 20975b95b8b9SAlexander Graf 209848add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_EPR, 0, mpic_proxy); 20995b95b8b9SAlexander Graf if (ret && mpic_proxy) { 2100072ed5f2SThomas Huth error_report("This KVM version does not support EPR"); 2101072ed5f2SThomas Huth exit(1); 21025b95b8b9SAlexander Graf } 21035b95b8b9SAlexander Graf } 21045b95b8b9SAlexander Graf 2105ec010c00SNicholas Piggin bool kvmppc_get_fwnmi(void) 2106ec010c00SNicholas Piggin { 2107ec010c00SNicholas Piggin return cap_fwnmi; 2108ec010c00SNicholas Piggin } 2109ec010c00SNicholas Piggin 2110aef92d87SLaurent Vivier int kvmppc_set_fwnmi(PowerPCCPU *cpu) 21119d953ce4SAravinda Prasad { 21129d953ce4SAravinda Prasad CPUState *cs = CPU(cpu); 21139d953ce4SAravinda Prasad 21149d953ce4SAravinda Prasad return kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_FWNMI, 0); 21159d953ce4SAravinda Prasad } 21169d953ce4SAravinda Prasad 2117e97c3636SDavid Gibson int kvmppc_smt_threads(void) 2118e97c3636SDavid Gibson { 2119e97c3636SDavid Gibson return cap_ppc_smt ? cap_ppc_smt : 1; 2120e97c3636SDavid Gibson } 2121e97c3636SDavid Gibson 2122fa98fbfcSSam Bobroff int kvmppc_set_smt_threads(int smt) 2123fa98fbfcSSam Bobroff { 2124fa98fbfcSSam Bobroff int ret; 2125fa98fbfcSSam Bobroff 2126fa98fbfcSSam Bobroff ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SMT, 0, smt, 0); 2127fa98fbfcSSam Bobroff if (!ret) { 2128fa98fbfcSSam Bobroff cap_ppc_smt = smt; 2129fa98fbfcSSam Bobroff } 2130fa98fbfcSSam Bobroff return ret; 2131fa98fbfcSSam Bobroff } 2132fa98fbfcSSam Bobroff 21330c115681SVladimir Sementsov-Ogievskiy void kvmppc_error_append_smt_possible_hint(Error *const *errp) 2134fa98fbfcSSam Bobroff { 2135fa98fbfcSSam Bobroff int i; 2136fa98fbfcSSam Bobroff GString *g; 2137fa98fbfcSSam Bobroff char *s; 2138fa98fbfcSSam Bobroff 2139fa98fbfcSSam Bobroff assert(kvm_enabled()); 2140fa98fbfcSSam Bobroff if (cap_ppc_smt_possible) { 2141fa98fbfcSSam Bobroff g = g_string_new("Available VSMT modes:"); 2142fa98fbfcSSam Bobroff for (i = 63; i >= 0; i--) { 2143fa98fbfcSSam Bobroff if ((1UL << i) & cap_ppc_smt_possible) { 2144fa98fbfcSSam Bobroff g_string_append_printf(g, " %lu", (1UL << i)); 2145fa98fbfcSSam Bobroff } 2146fa98fbfcSSam Bobroff } 2147fa98fbfcSSam Bobroff s = g_string_free(g, false); 21481a639fdfSMarkus Armbruster error_append_hint(errp, "%s.\n", s); 2149fa98fbfcSSam Bobroff g_free(s); 2150fa98fbfcSSam Bobroff } else { 21511a639fdfSMarkus Armbruster error_append_hint(errp, 2152fa98fbfcSSam Bobroff "This KVM seems to be too old to support VSMT.\n"); 2153fa98fbfcSSam Bobroff } 2154fa98fbfcSSam Bobroff } 2155fa98fbfcSSam Bobroff 2156fa98fbfcSSam Bobroff 21577f763a5dSDavid Gibson #ifdef TARGET_PPC64 21586a84737cSDavid Gibson uint64_t kvmppc_vrma_limit(unsigned int hash_shift) 21597f763a5dSDavid Gibson { 2160f36951c1SDavid Gibson struct kvm_ppc_smmu_info info; 2161f36951c1SDavid Gibson long rampagesize, best_page_shift; 2162f36951c1SDavid Gibson int i; 2163f36951c1SDavid Gibson 2164c995e942SDavid Gibson /* 2165c995e942SDavid Gibson * Find the largest hardware supported page size that's less than 2166c995e942SDavid Gibson * or equal to the (logical) backing page size of guest RAM 2167c995e942SDavid Gibson */ 2168ab256960SGreg Kurz kvm_get_smmu_info(&info, &error_fatal); 2169905b7ee4SDavid Hildenbrand rampagesize = qemu_minrampagesize(); 2170f36951c1SDavid Gibson best_page_shift = 0; 2171f36951c1SDavid Gibson 2172f36951c1SDavid Gibson for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) { 2173f36951c1SDavid Gibson struct kvm_ppc_one_seg_page_size *sps = &info.sps[i]; 2174f36951c1SDavid Gibson 2175f36951c1SDavid Gibson if (!sps->page_shift) { 2176f36951c1SDavid Gibson continue; 2177f36951c1SDavid Gibson } 2178f36951c1SDavid Gibson 2179f36951c1SDavid Gibson if ((sps->page_shift > best_page_shift) 2180f36951c1SDavid Gibson && ((1UL << sps->page_shift) <= rampagesize)) { 2181f36951c1SDavid Gibson best_page_shift = sps->page_shift; 2182f36951c1SDavid Gibson } 2183f36951c1SDavid Gibson } 2184f36951c1SDavid Gibson 21856a84737cSDavid Gibson return 1ULL << (best_page_shift + hash_shift - 7); 21867f763a5dSDavid Gibson } 21877f763a5dSDavid Gibson #endif 21887f763a5dSDavid Gibson 2189da95324eSAlexey Kardashevskiy bool kvmppc_spapr_use_multitce(void) 2190da95324eSAlexey Kardashevskiy { 2191da95324eSAlexey Kardashevskiy return cap_spapr_multitce; 2192da95324eSAlexey Kardashevskiy } 2193da95324eSAlexey Kardashevskiy 21943dc410aeSAlexey Kardashevskiy int kvmppc_spapr_enable_inkernel_multitce(void) 21953dc410aeSAlexey Kardashevskiy { 21963dc410aeSAlexey Kardashevskiy int ret; 21973dc410aeSAlexey Kardashevskiy 21983dc410aeSAlexey Kardashevskiy ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_ENABLE_HCALL, 0, 21993dc410aeSAlexey Kardashevskiy H_PUT_TCE_INDIRECT, 1); 22003dc410aeSAlexey Kardashevskiy if (!ret) { 22013dc410aeSAlexey Kardashevskiy ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_ENABLE_HCALL, 0, 22023dc410aeSAlexey Kardashevskiy H_STUFF_TCE, 1); 22033dc410aeSAlexey Kardashevskiy } 22043dc410aeSAlexey Kardashevskiy 22053dc410aeSAlexey Kardashevskiy return ret; 22063dc410aeSAlexey Kardashevskiy } 22073dc410aeSAlexey Kardashevskiy 2208d6ee2a7cSAlexey Kardashevskiy void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift, 2209d6ee2a7cSAlexey Kardashevskiy uint64_t bus_offset, uint32_t nb_table, 2210d6ee2a7cSAlexey Kardashevskiy int *pfd, bool need_vfio) 22110f5cb298SDavid Gibson { 22120f5cb298SDavid Gibson long len; 22130f5cb298SDavid Gibson int fd; 22140f5cb298SDavid Gibson void *table; 22150f5cb298SDavid Gibson 2216c995e942SDavid Gibson /* 2217c995e942SDavid Gibson * Must set fd to -1 so we don't try to munmap when called for 2218b5aec396SDavid Gibson * destroying the table, which the upper layers -will- do 2219b5aec396SDavid Gibson */ 2220b5aec396SDavid Gibson *pfd = -1; 22216a81dd17SDavid Gibson if (!cap_spapr_tce || (need_vfio && !cap_spapr_vfio)) { 22220f5cb298SDavid Gibson return NULL; 22230f5cb298SDavid Gibson } 22240f5cb298SDavid Gibson 2225d6ee2a7cSAlexey Kardashevskiy if (cap_spapr_tce_64) { 2226d6ee2a7cSAlexey Kardashevskiy struct kvm_create_spapr_tce_64 args = { 2227d6ee2a7cSAlexey Kardashevskiy .liobn = liobn, 2228d6ee2a7cSAlexey Kardashevskiy .page_shift = page_shift, 2229d6ee2a7cSAlexey Kardashevskiy .offset = bus_offset >> page_shift, 2230d6ee2a7cSAlexey Kardashevskiy .size = nb_table, 2231d6ee2a7cSAlexey Kardashevskiy .flags = 0 2232d6ee2a7cSAlexey Kardashevskiy }; 2233d6ee2a7cSAlexey Kardashevskiy fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE_64, &args); 2234d6ee2a7cSAlexey Kardashevskiy if (fd < 0) { 2235d6ee2a7cSAlexey Kardashevskiy fprintf(stderr, 2236d6ee2a7cSAlexey Kardashevskiy "KVM: Failed to create TCE64 table for liobn 0x%x\n", 2237d6ee2a7cSAlexey Kardashevskiy liobn); 2238d6ee2a7cSAlexey Kardashevskiy return NULL; 2239d6ee2a7cSAlexey Kardashevskiy } 2240d6ee2a7cSAlexey Kardashevskiy } else if (cap_spapr_tce) { 2241d6ee2a7cSAlexey Kardashevskiy uint64_t window_size = (uint64_t) nb_table << page_shift; 2242d6ee2a7cSAlexey Kardashevskiy struct kvm_create_spapr_tce args = { 2243d6ee2a7cSAlexey Kardashevskiy .liobn = liobn, 2244d6ee2a7cSAlexey Kardashevskiy .window_size = window_size, 2245d6ee2a7cSAlexey Kardashevskiy }; 2246d6ee2a7cSAlexey Kardashevskiy if ((window_size != args.window_size) || bus_offset) { 2247d6ee2a7cSAlexey Kardashevskiy return NULL; 2248d6ee2a7cSAlexey Kardashevskiy } 22490f5cb298SDavid Gibson fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); 22500f5cb298SDavid Gibson if (fd < 0) { 2251b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", 2252b5aec396SDavid Gibson liobn); 22530f5cb298SDavid Gibson return NULL; 22540f5cb298SDavid Gibson } 2255d6ee2a7cSAlexey Kardashevskiy } else { 2256d6ee2a7cSAlexey Kardashevskiy return NULL; 2257d6ee2a7cSAlexey Kardashevskiy } 22580f5cb298SDavid Gibson 2259d6ee2a7cSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22600f5cb298SDavid Gibson /* FIXME: round this up to page size */ 22610f5cb298SDavid Gibson 226274b41e56SDavid Gibson table = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 22630f5cb298SDavid Gibson if (table == MAP_FAILED) { 2264b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n", 2265b5aec396SDavid Gibson liobn); 22660f5cb298SDavid Gibson close(fd); 22670f5cb298SDavid Gibson return NULL; 22680f5cb298SDavid Gibson } 22690f5cb298SDavid Gibson 22700f5cb298SDavid Gibson *pfd = fd; 22710f5cb298SDavid Gibson return table; 22720f5cb298SDavid Gibson } 22730f5cb298SDavid Gibson 2274523e7b8aSAlexey Kardashevskiy int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t nb_table) 22750f5cb298SDavid Gibson { 22760f5cb298SDavid Gibson long len; 22770f5cb298SDavid Gibson 22780f5cb298SDavid Gibson if (fd < 0) { 22790f5cb298SDavid Gibson return -1; 22800f5cb298SDavid Gibson } 22810f5cb298SDavid Gibson 2282523e7b8aSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22830f5cb298SDavid Gibson if ((munmap(table, len) < 0) || 22840f5cb298SDavid Gibson (close(fd) < 0)) { 2285b5aec396SDavid Gibson fprintf(stderr, "KVM: Unexpected error removing TCE table: %s", 2286b5aec396SDavid Gibson strerror(errno)); 22870f5cb298SDavid Gibson /* Leak the table */ 22880f5cb298SDavid Gibson } 22890f5cb298SDavid Gibson 22900f5cb298SDavid Gibson return 0; 22910f5cb298SDavid Gibson } 22920f5cb298SDavid Gibson 22937f763a5dSDavid Gibson int kvmppc_reset_htab(int shift_hint) 22947f763a5dSDavid Gibson { 22957f763a5dSDavid Gibson uint32_t shift = shift_hint; 22967f763a5dSDavid Gibson 2297ace9a2cbSDavid Gibson if (!kvm_enabled()) { 2298ace9a2cbSDavid Gibson /* Full emulation, tell caller to allocate htab itself */ 2299ace9a2cbSDavid Gibson return 0; 2300ace9a2cbSDavid Gibson } 23016977afdaSGreg Kurz if (kvm_vm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { 23027f763a5dSDavid Gibson int ret; 23037f763a5dSDavid Gibson ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift); 2304ace9a2cbSDavid Gibson if (ret == -ENOTTY) { 2305c995e942SDavid Gibson /* 2306c995e942SDavid Gibson * At least some versions of PR KVM advertise the 2307ace9a2cbSDavid Gibson * capability, but don't implement the ioctl(). Oops. 2308ace9a2cbSDavid Gibson * Return 0 so that we allocate the htab in qemu, as is 2309c995e942SDavid Gibson * correct for PR. 2310c995e942SDavid Gibson */ 2311ace9a2cbSDavid Gibson return 0; 2312ace9a2cbSDavid Gibson } else if (ret < 0) { 23137f763a5dSDavid Gibson return ret; 23147f763a5dSDavid Gibson } 23157f763a5dSDavid Gibson return shift; 23167f763a5dSDavid Gibson } 23177f763a5dSDavid Gibson 2318c995e942SDavid Gibson /* 2319c995e942SDavid Gibson * We have a kernel that predates the htab reset calls. For PR 2320ace9a2cbSDavid Gibson * KVM, we need to allocate the htab ourselves, for an HV KVM of 2321c995e942SDavid Gibson * this era, it has allocated a 16MB fixed size hash table 2322c995e942SDavid Gibson * already. 2323c995e942SDavid Gibson */ 232496c9cff0SThomas Huth if (kvmppc_is_pr(kvm_state)) { 2325ace9a2cbSDavid Gibson /* PR - tell caller to allocate htab */ 23267f763a5dSDavid Gibson return 0; 2327ace9a2cbSDavid Gibson } else { 2328ace9a2cbSDavid Gibson /* HV - assume 16MB kernel allocated htab */ 2329ace9a2cbSDavid Gibson return 24; 2330ace9a2cbSDavid Gibson } 23317f763a5dSDavid Gibson } 23327f763a5dSDavid Gibson 2333a1e98583SDavid Gibson static inline uint32_t mfpvr(void) 2334a1e98583SDavid Gibson { 2335a1e98583SDavid Gibson uint32_t pvr; 2336a1e98583SDavid Gibson 2337a1e98583SDavid Gibson asm ("mfpvr %0" 2338a1e98583SDavid Gibson : "=r"(pvr)); 2339a1e98583SDavid Gibson return pvr; 2340a1e98583SDavid Gibson } 2341a1e98583SDavid Gibson 2342a7342588SDavid Gibson static void alter_insns(uint64_t *word, uint64_t flags, bool on) 2343a7342588SDavid Gibson { 2344a7342588SDavid Gibson if (on) { 2345a7342588SDavid Gibson *word |= flags; 2346a7342588SDavid Gibson } else { 2347a7342588SDavid Gibson *word &= ~flags; 2348a7342588SDavid Gibson } 2349a7342588SDavid Gibson } 2350a7342588SDavid Gibson 2351cfb52d07SHarsh Prateek Bora static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) 2352cfb52d07SHarsh Prateek Bora { 2353cfb52d07SHarsh Prateek Bora int ret; 2354cfb52d07SHarsh Prateek Bora const char *vcpu_str = (cs->parent_obj.hotplugged == true) ? 2355cfb52d07SHarsh Prateek Bora "hotplug" : "create"; 2356cfb52d07SHarsh Prateek Bora cs->cpu_index = cpu_get_free_index(); 2357cfb52d07SHarsh Prateek Bora 2358cfb52d07SHarsh Prateek Bora POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; 2359cfb52d07SHarsh Prateek Bora 2360cfb52d07SHarsh Prateek Bora /* create and park to fail gracefully in case vcpu hotplug fails */ 2361cfb52d07SHarsh Prateek Bora ret = kvm_create_and_park_vcpu(cs); 2362cfb52d07SHarsh Prateek Bora if (ret) { 2363cfb52d07SHarsh Prateek Bora /* 2364cfb52d07SHarsh Prateek Bora * This causes QEMU to terminate if initial CPU creation 2365cfb52d07SHarsh Prateek Bora * fails, and only CPU hotplug failure if the error happens 2366cfb52d07SHarsh Prateek Bora * there. 2367cfb52d07SHarsh Prateek Bora */ 2368cfb52d07SHarsh Prateek Bora error_setg(errp, "%s: vcpu %s failed with %d", 2369cfb52d07SHarsh Prateek Bora __func__, vcpu_str, ret); 2370cfb52d07SHarsh Prateek Bora return false; 2371cfb52d07SHarsh Prateek Bora } 2372cfb52d07SHarsh Prateek Bora return true; 2373cfb52d07SHarsh Prateek Bora } 2374cfb52d07SHarsh Prateek Bora 23752985b86bSAndreas Färber static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) 23762985b86bSAndreas Färber { 23772985b86bSAndreas Färber PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); 23780cbad81fSDavid Gibson uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size"); 23790cbad81fSDavid Gibson uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); 2380a1e98583SDavid Gibson 2381cfe34f44SAndreas Färber /* Now fix up the class with information we can query from the host */ 23823bc9ccc0SAlexey Kardashevskiy pcc->pvr = mfpvr(); 2383a7342588SDavid Gibson 23843f2ca480SDavid Gibson alter_insns(&pcc->insns_flags, PPC_ALTIVEC, 23853f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); 23863f2ca480SDavid Gibson alter_insns(&pcc->insns_flags2, PPC2_VSX, 23873f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_VSX); 23883f2ca480SDavid Gibson alter_insns(&pcc->insns_flags2, PPC2_DFP, 23893f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_DFP); 23900cbad81fSDavid Gibson 23910cbad81fSDavid Gibson if (dcache_size != -1) { 23920cbad81fSDavid Gibson pcc->l1_dcache_size = dcache_size; 23930cbad81fSDavid Gibson } 23940cbad81fSDavid Gibson 23950cbad81fSDavid Gibson if (icache_size != -1) { 23960cbad81fSDavid Gibson pcc->l1_icache_size = icache_size; 23970cbad81fSDavid Gibson } 2398c64abd1fSSam Bobroff 2399c64abd1fSSam Bobroff #if defined(TARGET_PPC64) 2400aa6edf97SPhilippe Mathieu-Daudé pcc->radix_page_info = kvmppc_get_radix_page_info(); 2401c64abd1fSSam Bobroff #endif /* defined(TARGET_PPC64) */ 2402a1e98583SDavid Gibson } 2403a1e98583SDavid Gibson 24043b961124SStuart Yoder bool kvmppc_has_cap_epr(void) 24053b961124SStuart Yoder { 24063b961124SStuart Yoder return cap_epr; 24073b961124SStuart Yoder } 24083b961124SStuart Yoder 240987a91de6SAlexander Graf bool kvmppc_has_cap_fixup_hcalls(void) 241087a91de6SAlexander Graf { 241187a91de6SAlexander Graf return cap_fixup_hcalls; 241287a91de6SAlexander Graf } 241387a91de6SAlexander Graf 2414bac3bf28SThomas Huth bool kvmppc_has_cap_htm(void) 2415bac3bf28SThomas Huth { 2416bac3bf28SThomas Huth return cap_htm; 2417bac3bf28SThomas Huth } 2418bac3bf28SThomas Huth 2419cf1c4cceSSam Bobroff bool kvmppc_has_cap_mmu_radix(void) 2420cf1c4cceSSam Bobroff { 2421cf1c4cceSSam Bobroff return cap_mmu_radix; 2422cf1c4cceSSam Bobroff } 2423cf1c4cceSSam Bobroff 2424cf1c4cceSSam Bobroff bool kvmppc_has_cap_mmu_hash_v3(void) 2425cf1c4cceSSam Bobroff { 2426cf1c4cceSSam Bobroff return cap_mmu_hash_v3; 2427cf1c4cceSSam Bobroff } 2428cf1c4cceSSam Bobroff 2429072f416aSSuraj Jitindar Singh static bool kvmppc_power8_host(void) 2430072f416aSSuraj Jitindar Singh { 2431072f416aSSuraj Jitindar Singh bool ret = false; 2432072f416aSSuraj Jitindar Singh #ifdef TARGET_PPC64 2433072f416aSSuraj Jitindar Singh { 2434072f416aSSuraj Jitindar Singh uint32_t base_pvr = CPU_POWERPC_POWER_SERVER_MASK & mfpvr(); 2435072f416aSSuraj Jitindar Singh ret = (base_pvr == CPU_POWERPC_POWER8E_BASE) || 2436072f416aSSuraj Jitindar Singh (base_pvr == CPU_POWERPC_POWER8NVL_BASE) || 2437072f416aSSuraj Jitindar Singh (base_pvr == CPU_POWERPC_POWER8_BASE); 2438072f416aSSuraj Jitindar Singh } 2439072f416aSSuraj Jitindar Singh #endif /* TARGET_PPC64 */ 2440072f416aSSuraj Jitindar Singh return ret; 2441072f416aSSuraj Jitindar Singh } 2442072f416aSSuraj Jitindar Singh 24438fea7044SSuraj Jitindar Singh static int parse_cap_ppc_safe_cache(struct kvm_ppc_cpu_char c) 24448fea7044SSuraj Jitindar Singh { 2445072f416aSSuraj Jitindar Singh bool l1d_thread_priv_req = !kvmppc_power8_host(); 2446072f416aSSuraj Jitindar Singh 24478fea7044SSuraj Jitindar Singh if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) { 24488fea7044SSuraj Jitindar Singh return 2; 2449072f416aSSuraj Jitindar Singh } else if ((!l1d_thread_priv_req || 2450072f416aSSuraj Jitindar Singh c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) && 24518fea7044SSuraj Jitindar Singh (c.character & c.character_mask 24528fea7044SSuraj Jitindar Singh & (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) { 24538fea7044SSuraj Jitindar Singh return 1; 24548fea7044SSuraj Jitindar Singh } 24558fea7044SSuraj Jitindar Singh 24568fea7044SSuraj Jitindar Singh return 0; 24578fea7044SSuraj Jitindar Singh } 24588fea7044SSuraj Jitindar Singh 24598fea7044SSuraj Jitindar Singh static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c) 24608fea7044SSuraj Jitindar Singh { 24618fea7044SSuraj Jitindar Singh if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) { 24628fea7044SSuraj Jitindar Singh return 2; 24638fea7044SSuraj Jitindar Singh } else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) { 24648fea7044SSuraj Jitindar Singh return 1; 24658fea7044SSuraj Jitindar Singh } 24668fea7044SSuraj Jitindar Singh 24678fea7044SSuraj Jitindar Singh return 0; 24688fea7044SSuraj Jitindar Singh } 24698fea7044SSuraj Jitindar Singh 24708fea7044SSuraj Jitindar Singh static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) 24718fea7044SSuraj Jitindar Singh { 2472399b2896SSuraj Jitindar Singh if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) && 2473399b2896SSuraj Jitindar Singh (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) && 2474399b2896SSuraj Jitindar Singh (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) { 2475399b2896SSuraj Jitindar Singh return SPAPR_CAP_FIXED_NA; 2476399b2896SSuraj Jitindar Singh } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) { 2477399b2896SSuraj Jitindar Singh return SPAPR_CAP_WORKAROUND; 2478399b2896SSuraj Jitindar Singh } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { 24798fea7044SSuraj Jitindar Singh return SPAPR_CAP_FIXED_CCD; 24808fea7044SSuraj Jitindar Singh } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { 24818fea7044SSuraj Jitindar Singh return SPAPR_CAP_FIXED_IBS; 24828fea7044SSuraj Jitindar Singh } 24838fea7044SSuraj Jitindar Singh 24848fea7044SSuraj Jitindar Singh return 0; 24858fea7044SSuraj Jitindar Singh } 24868fea7044SSuraj Jitindar Singh 24878ff43ee4SSuraj Jitindar Singh static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) 24888ff43ee4SSuraj Jitindar Singh { 24898ff43ee4SSuraj Jitindar Singh if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) { 24908ff43ee4SSuraj Jitindar Singh return 1; 24918ff43ee4SSuraj Jitindar Singh } 24928ff43ee4SSuraj Jitindar Singh return 0; 24938ff43ee4SSuraj Jitindar Singh } 24948ff43ee4SSuraj Jitindar Singh 249538afd772SCédric Le Goater bool kvmppc_has_cap_xive(void) 249638afd772SCédric Le Goater { 249738afd772SCédric Le Goater return cap_xive; 249838afd772SCédric Le Goater } 249938afd772SCédric Le Goater 25008acc2ae5SSuraj Jitindar Singh static void kvmppc_get_cpu_characteristics(KVMState *s) 25018acc2ae5SSuraj Jitindar Singh { 25028acc2ae5SSuraj Jitindar Singh struct kvm_ppc_cpu_char c; 25038acc2ae5SSuraj Jitindar Singh int ret; 25048acc2ae5SSuraj Jitindar Singh 25058acc2ae5SSuraj Jitindar Singh /* Assume broken */ 25068acc2ae5SSuraj Jitindar Singh cap_ppc_safe_cache = 0; 25078acc2ae5SSuraj Jitindar Singh cap_ppc_safe_bounds_check = 0; 25088acc2ae5SSuraj Jitindar Singh cap_ppc_safe_indirect_branch = 0; 25098acc2ae5SSuraj Jitindar Singh 25108acc2ae5SSuraj Jitindar Singh ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR); 25118acc2ae5SSuraj Jitindar Singh if (!ret) { 25128acc2ae5SSuraj Jitindar Singh return; 25138acc2ae5SSuraj Jitindar Singh } 25148acc2ae5SSuraj Jitindar Singh ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c); 25158acc2ae5SSuraj Jitindar Singh if (ret < 0) { 25168acc2ae5SSuraj Jitindar Singh return; 25178acc2ae5SSuraj Jitindar Singh } 25188fea7044SSuraj Jitindar Singh 25198fea7044SSuraj Jitindar Singh cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); 25208fea7044SSuraj Jitindar Singh cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); 25218fea7044SSuraj Jitindar Singh cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); 25228ff43ee4SSuraj Jitindar Singh cap_ppc_count_cache_flush_assist = 25238ff43ee4SSuraj Jitindar Singh parse_cap_ppc_count_cache_flush_assist(c); 25248acc2ae5SSuraj Jitindar Singh } 25258acc2ae5SSuraj Jitindar Singh 25268acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_cache(void) 25278acc2ae5SSuraj Jitindar Singh { 25288acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_cache; 25298acc2ae5SSuraj Jitindar Singh } 25308acc2ae5SSuraj Jitindar Singh 25318acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_bounds_check(void) 25328acc2ae5SSuraj Jitindar Singh { 25338acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_bounds_check; 25348acc2ae5SSuraj Jitindar Singh } 25358acc2ae5SSuraj Jitindar Singh 25368acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_indirect_branch(void) 25378acc2ae5SSuraj Jitindar Singh { 25388acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_indirect_branch; 25398acc2ae5SSuraj Jitindar Singh } 25408acc2ae5SSuraj Jitindar Singh 25418ff43ee4SSuraj Jitindar Singh int kvmppc_get_cap_count_cache_flush_assist(void) 25428ff43ee4SSuraj Jitindar Singh { 25438ff43ee4SSuraj Jitindar Singh return cap_ppc_count_cache_flush_assist; 25448ff43ee4SSuraj Jitindar Singh } 25458ff43ee4SSuraj Jitindar Singh 2546b9a477b7SSuraj Jitindar Singh bool kvmppc_has_cap_nested_kvm_hv(void) 2547b9a477b7SSuraj Jitindar Singh { 2548b9a477b7SSuraj Jitindar Singh return !!cap_ppc_nested_kvm_hv; 2549b9a477b7SSuraj Jitindar Singh } 2550b9a477b7SSuraj Jitindar Singh 2551b9a477b7SSuraj Jitindar Singh int kvmppc_set_cap_nested_kvm_hv(int enable) 2552b9a477b7SSuraj Jitindar Singh { 2553b9a477b7SSuraj Jitindar Singh return kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_NESTED_HV, 0, enable); 2554b9a477b7SSuraj Jitindar Singh } 2555b9a477b7SSuraj Jitindar Singh 25569ded780cSAlexey Kardashevskiy bool kvmppc_has_cap_spapr_vfio(void) 25579ded780cSAlexey Kardashevskiy { 25589ded780cSAlexey Kardashevskiy return cap_spapr_vfio; 25599ded780cSAlexey Kardashevskiy } 25609ded780cSAlexey Kardashevskiy 25617d050527SSuraj Jitindar Singh int kvmppc_get_cap_large_decr(void) 25627d050527SSuraj Jitindar Singh { 25637d050527SSuraj Jitindar Singh return cap_large_decr; 25647d050527SSuraj Jitindar Singh } 25657d050527SSuraj Jitindar Singh 25667d050527SSuraj Jitindar Singh int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable) 25677d050527SSuraj Jitindar Singh { 25687d050527SSuraj Jitindar Singh CPUState *cs = CPU(cpu); 256959411579SDaniel Henrique Barboza uint64_t lpcr = 0; 25707d050527SSuraj Jitindar Singh 25717d050527SSuraj Jitindar Singh kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25727d050527SSuraj Jitindar Singh /* Do we need to modify the LPCR? */ 25737d050527SSuraj Jitindar Singh if (!!(lpcr & LPCR_LD) != !!enable) { 25747d050527SSuraj Jitindar Singh if (enable) { 25757d050527SSuraj Jitindar Singh lpcr |= LPCR_LD; 25767d050527SSuraj Jitindar Singh } else { 25777d050527SSuraj Jitindar Singh lpcr &= ~LPCR_LD; 25787d050527SSuraj Jitindar Singh } 25797d050527SSuraj Jitindar Singh kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25807d050527SSuraj Jitindar Singh kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25817d050527SSuraj Jitindar Singh 25827d050527SSuraj Jitindar Singh if (!!(lpcr & LPCR_LD) != !!enable) { 25837d050527SSuraj Jitindar Singh return -1; 25847d050527SSuraj Jitindar Singh } 25857d050527SSuraj Jitindar Singh } 25867d050527SSuraj Jitindar Singh 25877d050527SSuraj Jitindar Singh return 0; 25887d050527SSuraj Jitindar Singh } 25897d050527SSuraj Jitindar Singh 259082123b75SBharata B Rao int kvmppc_has_cap_rpt_invalidate(void) 259182123b75SBharata B Rao { 259282123b75SBharata B Rao return cap_rpt_invalidate; 259382123b75SBharata B Rao } 259482123b75SBharata B Rao 2595ccc5a4c5SNicholas Piggin bool kvmppc_supports_ail_3(void) 2596ccc5a4c5SNicholas Piggin { 2597ccc5a4c5SNicholas Piggin return cap_ail_mode_3; 2598ccc5a4c5SNicholas Piggin } 2599ccc5a4c5SNicholas Piggin 260052b2519cSThomas Huth PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) 260152b2519cSThomas Huth { 260252b2519cSThomas Huth uint32_t host_pvr = mfpvr(); 260352b2519cSThomas Huth PowerPCCPUClass *pvr_pcc; 260452b2519cSThomas Huth 260552b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr(host_pvr); 260652b2519cSThomas Huth if (pvr_pcc == NULL) { 260752b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr); 260852b2519cSThomas Huth } 260952b2519cSThomas Huth 261052b2519cSThomas Huth return pvr_pcc; 261152b2519cSThomas Huth } 261252b2519cSThomas Huth 2613165dc3edSDavid Gibson static void pseries_machine_class_fixup(ObjectClass *oc, void *opaque) 2614165dc3edSDavid Gibson { 2615165dc3edSDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); 2616165dc3edSDavid Gibson 2617165dc3edSDavid Gibson mc->default_cpu_type = TYPE_HOST_POWERPC_CPU; 2618165dc3edSDavid Gibson } 2619165dc3edSDavid Gibson 2620165dc3edSDavid Gibson static int kvm_ppc_register_host_cpu_type(void) 26215ba4576bSAndreas Färber { 26225ba4576bSAndreas Färber TypeInfo type_info = { 26235ba4576bSAndreas Färber .name = TYPE_HOST_POWERPC_CPU, 26245ba4576bSAndreas Färber .class_init = kvmppc_host_cpu_class_init, 26255ba4576bSAndreas Färber }; 26265ba4576bSAndreas Färber PowerPCCPUClass *pvr_pcc; 262792e926e1SGreg Kurz ObjectClass *oc; 26285b79b1caSAlexey Kardashevskiy DeviceClass *dc; 2629715d4b96SThomas Huth int i; 26305ba4576bSAndreas Färber 263152b2519cSThomas Huth pvr_pcc = kvm_ppc_get_host_cpu_class(); 26323bc9ccc0SAlexey Kardashevskiy if (pvr_pcc == NULL) { 26335ba4576bSAndreas Färber return -1; 26345ba4576bSAndreas Färber } 26355ba4576bSAndreas Färber type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); 26366e0a8883SZhao Liu type_register_static(&type_info); 26372e9c10ebSIgor Mammedov /* override TCG default cpu type with 'host' cpu model */ 2638165dc3edSDavid Gibson object_class_foreach(pseries_machine_class_fixup, TYPE_SPAPR_MACHINE, 2639165dc3edSDavid Gibson false, NULL); 26405b79b1caSAlexey Kardashevskiy 264192e926e1SGreg Kurz oc = object_class_by_name(type_info.name); 264292e926e1SGreg Kurz g_assert(oc); 264392e926e1SGreg Kurz 2644715d4b96SThomas Huth /* 2645715d4b96SThomas Huth * Update generic CPU family class alias (e.g. on a POWER8NVL host, 2646715d4b96SThomas Huth * we want "POWER8" to be a "family" alias that points to the current 2647715d4b96SThomas Huth * host CPU type, too) 2648715d4b96SThomas Huth */ 2649715d4b96SThomas Huth dc = DEVICE_CLASS(ppc_cpu_get_family_class(pvr_pcc)); 2650715d4b96SThomas Huth for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { 2651c5354f54SIgor Mammedov if (strcasecmp(ppc_cpu_aliases[i].alias, dc->desc) == 0) { 2652715d4b96SThomas Huth char *suffix; 2653715d4b96SThomas Huth 2654715d4b96SThomas Huth ppc_cpu_aliases[i].model = g_strdup(object_class_get_name(oc)); 2655c9137065SIgor Mammedov suffix = strstr(ppc_cpu_aliases[i].model, POWERPC_CPU_TYPE_SUFFIX); 2656715d4b96SThomas Huth if (suffix) { 2657715d4b96SThomas Huth *suffix = 0; 2658715d4b96SThomas Huth } 2659715d4b96SThomas Huth break; 2660715d4b96SThomas Huth } 2661715d4b96SThomas Huth } 2662715d4b96SThomas Huth 26635ba4576bSAndreas Färber return 0; 26645ba4576bSAndreas Färber } 26655ba4576bSAndreas Färber 2666feaa64c4SDavid Gibson int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function) 2667feaa64c4SDavid Gibson { 2668feaa64c4SDavid Gibson struct kvm_rtas_token_args args = { 2669feaa64c4SDavid Gibson .token = token, 2670feaa64c4SDavid Gibson }; 2671feaa64c4SDavid Gibson 2672feaa64c4SDavid Gibson if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_RTAS)) { 2673feaa64c4SDavid Gibson return -ENOENT; 2674feaa64c4SDavid Gibson } 2675feaa64c4SDavid Gibson 26767701aeedSCédric Le Goater strncpy(args.name, function, sizeof(args.name) - 1); 2677feaa64c4SDavid Gibson 2678feaa64c4SDavid Gibson return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args); 2679feaa64c4SDavid Gibson } 268012b1143bSDavid Gibson 268114b0d748SGreg Kurz int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp) 2682e68cb8b4SAlexey Kardashevskiy { 2683e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_fd s = { 2684e68cb8b4SAlexey Kardashevskiy .flags = write ? KVM_GET_HTAB_WRITE : 0, 268514b0d748SGreg Kurz .start_index = index, 2686e68cb8b4SAlexey Kardashevskiy }; 268782be8e73SGreg Kurz int ret; 2688e68cb8b4SAlexey Kardashevskiy 2689e68cb8b4SAlexey Kardashevskiy if (!cap_htab_fd) { 269014b0d748SGreg Kurz error_setg(errp, "KVM version doesn't support %s the HPT", 269114b0d748SGreg Kurz write ? "writing" : "reading"); 269282be8e73SGreg Kurz return -ENOTSUP; 2693e68cb8b4SAlexey Kardashevskiy } 2694e68cb8b4SAlexey Kardashevskiy 269582be8e73SGreg Kurz ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s); 269682be8e73SGreg Kurz if (ret < 0) { 269714b0d748SGreg Kurz error_setg(errp, "Unable to open fd for %s HPT %s KVM: %s", 269814b0d748SGreg Kurz write ? "writing" : "reading", write ? "to" : "from", 269914b0d748SGreg Kurz strerror(errno)); 270082be8e73SGreg Kurz return -errno; 270182be8e73SGreg Kurz } 270282be8e73SGreg Kurz 270382be8e73SGreg Kurz return ret; 2704e68cb8b4SAlexey Kardashevskiy } 2705e68cb8b4SAlexey Kardashevskiy 2706e68cb8b4SAlexey Kardashevskiy int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) 2707e68cb8b4SAlexey Kardashevskiy { 2708bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 2709aba594daSThomas Huth g_autofree uint8_t *buf = g_malloc(bufsize); 2710e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2711e68cb8b4SAlexey Kardashevskiy 2712e68cb8b4SAlexey Kardashevskiy do { 2713e68cb8b4SAlexey Kardashevskiy rc = read(fd, buf, bufsize); 2714e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2715e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error reading data from KVM HTAB fd: %s\n", 2716e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2717e68cb8b4SAlexey Kardashevskiy return rc; 2718e68cb8b4SAlexey Kardashevskiy } else if (rc) { 2719e094c4c1SCédric Le Goater uint8_t *buffer = buf; 2720e094c4c1SCédric Le Goater ssize_t n = rc; 2721e094c4c1SCédric Le Goater while (n) { 2722e094c4c1SCédric Le Goater struct kvm_get_htab_header *head = 2723e094c4c1SCédric Le Goater (struct kvm_get_htab_header *) buffer; 2724e094c4c1SCédric Le Goater size_t chunksize = sizeof(*head) + 2725e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid; 2726e094c4c1SCédric Le Goater 2727e094c4c1SCédric Le Goater qemu_put_be32(f, head->index); 2728e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_valid); 2729e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_invalid); 2730e094c4c1SCédric Le Goater qemu_put_buffer(f, (void *)(head + 1), 2731e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid); 2732e094c4c1SCédric Le Goater 2733e094c4c1SCédric Le Goater buffer += chunksize; 2734e094c4c1SCédric Le Goater n -= chunksize; 2735e094c4c1SCédric Le Goater } 2736e68cb8b4SAlexey Kardashevskiy } 2737e68cb8b4SAlexey Kardashevskiy } while ((rc != 0) 2738c995e942SDavid Gibson && ((max_ns < 0) || 2739c995e942SDavid Gibson ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns))); 2740e68cb8b4SAlexey Kardashevskiy 2741e68cb8b4SAlexey Kardashevskiy return (rc == 0) ? 1 : 0; 2742e68cb8b4SAlexey Kardashevskiy } 2743e68cb8b4SAlexey Kardashevskiy 2744e68cb8b4SAlexey Kardashevskiy int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, 27450a06e4d6SGreg Kurz uint16_t n_valid, uint16_t n_invalid, Error **errp) 2746e68cb8b4SAlexey Kardashevskiy { 2747e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_header *buf; 2748e68cb8b4SAlexey Kardashevskiy size_t chunksize = sizeof(*buf) + n_valid * HASH_PTE_SIZE_64; 2749e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2750e68cb8b4SAlexey Kardashevskiy 2751e68cb8b4SAlexey Kardashevskiy buf = alloca(chunksize); 2752e68cb8b4SAlexey Kardashevskiy buf->index = index; 2753e68cb8b4SAlexey Kardashevskiy buf->n_valid = n_valid; 2754e68cb8b4SAlexey Kardashevskiy buf->n_invalid = n_invalid; 2755e68cb8b4SAlexey Kardashevskiy 2756e68cb8b4SAlexey Kardashevskiy qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64 * n_valid); 2757e68cb8b4SAlexey Kardashevskiy 2758e68cb8b4SAlexey Kardashevskiy rc = write(fd, buf, chunksize); 2759e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 27600a06e4d6SGreg Kurz error_setg_errno(errp, errno, "Error writing the KVM hash table"); 27610a06e4d6SGreg Kurz return -errno; 2762e68cb8b4SAlexey Kardashevskiy } 2763e68cb8b4SAlexey Kardashevskiy if (rc != chunksize) { 2764e68cb8b4SAlexey Kardashevskiy /* We should never get a short write on a single chunk */ 27650a06e4d6SGreg Kurz error_setg(errp, "Short write while restoring the KVM hash table"); 27660a06e4d6SGreg Kurz return -ENOSPC; 2767e68cb8b4SAlexey Kardashevskiy } 2768e68cb8b4SAlexey Kardashevskiy return 0; 2769e68cb8b4SAlexey Kardashevskiy } 2770e68cb8b4SAlexey Kardashevskiy 277120d695a9SAndreas Färber bool kvm_arch_stop_on_emulation_error(CPUState *cpu) 27724513d923SGleb Natapov { 27734513d923SGleb Natapov return true; 27744513d923SGleb Natapov } 2775a1b87fe0SJan Kiszka 277682169660SScott Wood void kvm_arch_init_irq_routing(KVMState *s) 277782169660SScott Wood { 277882169660SScott Wood } 2779c65f9a07SGreg Kurz 27801ad9f0a4SDavid Gibson void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr ptex, int n) 27811ad9f0a4SDavid Gibson { 27821ad9f0a4SDavid Gibson int fd, rc; 27831ad9f0a4SDavid Gibson int i; 27847c43bca0SAneesh Kumar K.V 278514b0d748SGreg Kurz fd = kvmppc_get_htab_fd(false, ptex, &error_abort); 27861ad9f0a4SDavid Gibson 27871ad9f0a4SDavid Gibson i = 0; 27881ad9f0a4SDavid Gibson while (i < n) { 27891ad9f0a4SDavid Gibson struct kvm_get_htab_header *hdr; 27901ad9f0a4SDavid Gibson int m = n < HPTES_PER_GROUP ? n : HPTES_PER_GROUP; 279197c2fc50SThomas Huth char buf[sizeof(*hdr) + HPTES_PER_GROUP * HASH_PTE_SIZE_64]; 27921ad9f0a4SDavid Gibson 279397c2fc50SThomas Huth rc = read(fd, buf, sizeof(*hdr) + m * HASH_PTE_SIZE_64); 27941ad9f0a4SDavid Gibson if (rc < 0) { 27951ad9f0a4SDavid Gibson hw_error("kvmppc_read_hptes: Unable to read HPTEs"); 27961ad9f0a4SDavid Gibson } 27971ad9f0a4SDavid Gibson 27981ad9f0a4SDavid Gibson hdr = (struct kvm_get_htab_header *)buf; 27991ad9f0a4SDavid Gibson while ((i < n) && ((char *)hdr < (buf + rc))) { 2800a36593e1SAlexey Kardashevskiy int invalid = hdr->n_invalid, valid = hdr->n_valid; 28011ad9f0a4SDavid Gibson 28021ad9f0a4SDavid Gibson if (hdr->index != (ptex + i)) { 28031ad9f0a4SDavid Gibson hw_error("kvmppc_read_hptes: Unexpected HPTE index %"PRIu32 28041ad9f0a4SDavid Gibson " != (%"HWADDR_PRIu" + %d", hdr->index, ptex, i); 28051ad9f0a4SDavid Gibson } 28061ad9f0a4SDavid Gibson 2807a36593e1SAlexey Kardashevskiy if (n - i < valid) { 2808a36593e1SAlexey Kardashevskiy valid = n - i; 2809a36593e1SAlexey Kardashevskiy } 2810a36593e1SAlexey Kardashevskiy memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * valid); 2811a36593e1SAlexey Kardashevskiy i += valid; 28121ad9f0a4SDavid Gibson 28131ad9f0a4SDavid Gibson if ((n - i) < invalid) { 28141ad9f0a4SDavid Gibson invalid = n - i; 28151ad9f0a4SDavid Gibson } 28161ad9f0a4SDavid Gibson memset(hptes + i, 0, invalid * HASH_PTE_SIZE_64); 2817a36593e1SAlexey Kardashevskiy i += invalid; 28181ad9f0a4SDavid Gibson 28191ad9f0a4SDavid Gibson hdr = (struct kvm_get_htab_header *) 28201ad9f0a4SDavid Gibson ((char *)(hdr + 1) + HASH_PTE_SIZE_64 * hdr->n_valid); 28211ad9f0a4SDavid Gibson } 28221ad9f0a4SDavid Gibson } 28231ad9f0a4SDavid Gibson 28241ad9f0a4SDavid Gibson close(fd); 28251ad9f0a4SDavid Gibson } 28261ad9f0a4SDavid Gibson 28271ad9f0a4SDavid Gibson void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) 28287c43bca0SAneesh Kumar K.V { 28291ad9f0a4SDavid Gibson int fd, rc; 28301ad9f0a4SDavid Gibson struct { 28311ad9f0a4SDavid Gibson struct kvm_get_htab_header hdr; 28321ad9f0a4SDavid Gibson uint64_t pte0; 28331ad9f0a4SDavid Gibson uint64_t pte1; 28341ad9f0a4SDavid Gibson } buf; 2835c1385933SAneesh Kumar K.V 283614b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0 /* Ignored */, &error_abort); 2837c1385933SAneesh Kumar K.V 28381ad9f0a4SDavid Gibson buf.hdr.n_valid = 1; 28391ad9f0a4SDavid Gibson buf.hdr.n_invalid = 0; 28401ad9f0a4SDavid Gibson buf.hdr.index = ptex; 28411ad9f0a4SDavid Gibson buf.pte0 = cpu_to_be64(pte0); 28421ad9f0a4SDavid Gibson buf.pte1 = cpu_to_be64(pte1); 28431ad9f0a4SDavid Gibson 28441ad9f0a4SDavid Gibson rc = write(fd, &buf, sizeof(buf)); 28451ad9f0a4SDavid Gibson if (rc != sizeof(buf)) { 28461ad9f0a4SDavid Gibson hw_error("kvmppc_write_hpte: Unable to update KVM HPT"); 2847c1385933SAneesh Kumar K.V } 28481ad9f0a4SDavid Gibson close(fd); 2849c1385933SAneesh Kumar K.V } 28509e03a040SFrank Blaschka 28519e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 2852dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 28539e03a040SFrank Blaschka { 28549e03a040SFrank Blaschka return 0; 28559e03a040SFrank Blaschka } 28561850b6b7SEric Auger 285738d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 285838d87493SPeter Xu int vector, PCIDevice *dev) 285938d87493SPeter Xu { 286038d87493SPeter Xu return 0; 286138d87493SPeter Xu } 286238d87493SPeter Xu 286338d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 286438d87493SPeter Xu { 286538d87493SPeter Xu return 0; 286638d87493SPeter Xu } 286738d87493SPeter Xu 28681850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 28691850b6b7SEric Auger { 28701850b6b7SEric Auger return data & 0xffff; 28711850b6b7SEric Auger } 28724d9392beSThomas Huth 2873566abdb4SPaolo Bonzini #if defined(CONFIG_PSERIES) 28749ac703acSAravinda Prasad int kvm_handle_nmi(PowerPCCPU *cpu, struct kvm_run *run) 28759ac703acSAravinda Prasad { 2876211a7784SGanesh Goudar uint16_t flags = run->flags & KVM_RUN_PPC_NMI_DISP_MASK; 287781fe70e4SAravinda Prasad 28789ac703acSAravinda Prasad cpu_synchronize_state(CPU(cpu)); 28799ac703acSAravinda Prasad 2880211a7784SGanesh Goudar spapr_mce_req_event(cpu, flags == KVM_RUN_PPC_NMI_DISP_FULLY_RECOV); 28819ac703acSAravinda Prasad 28829ac703acSAravinda Prasad return 0; 28839ac703acSAravinda Prasad } 28849ac703acSAravinda Prasad #endif 28859ac703acSAravinda Prasad 28864d9392beSThomas Huth int kvmppc_enable_hwrng(void) 28874d9392beSThomas Huth { 28884d9392beSThomas Huth if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG)) { 28894d9392beSThomas Huth return -1; 28904d9392beSThomas Huth } 28914d9392beSThomas Huth 28924d9392beSThomas Huth return kvmppc_enable_hcall(kvm_state, H_RANDOM); 28934d9392beSThomas Huth } 289430f4b05bSDavid Gibson 289530f4b05bSDavid Gibson void kvmppc_check_papr_resize_hpt(Error **errp) 289630f4b05bSDavid Gibson { 289730f4b05bSDavid Gibson if (!kvm_enabled()) { 2898b55d295eSDavid Gibson return; /* No KVM, we're good */ 2899b55d295eSDavid Gibson } 2900b55d295eSDavid Gibson 2901b55d295eSDavid Gibson if (cap_resize_hpt) { 2902b55d295eSDavid Gibson return; /* Kernel has explicit support, we're good */ 2903b55d295eSDavid Gibson } 2904b55d295eSDavid Gibson 2905b55d295eSDavid Gibson /* Otherwise fallback on looking for PR KVM */ 2906b55d295eSDavid Gibson if (kvmppc_is_pr(kvm_state)) { 290730f4b05bSDavid Gibson return; 290830f4b05bSDavid Gibson } 290930f4b05bSDavid Gibson 291030f4b05bSDavid Gibson error_setg(errp, 291130f4b05bSDavid Gibson "Hash page table resizing not available with this KVM version"); 291230f4b05bSDavid Gibson } 2913b55d295eSDavid Gibson 2914b55d295eSDavid Gibson int kvmppc_resize_hpt_prepare(PowerPCCPU *cpu, target_ulong flags, int shift) 2915b55d295eSDavid Gibson { 2916b55d295eSDavid Gibson CPUState *cs = CPU(cpu); 2917b55d295eSDavid Gibson struct kvm_ppc_resize_hpt rhpt = { 2918b55d295eSDavid Gibson .flags = flags, 2919b55d295eSDavid Gibson .shift = shift, 2920b55d295eSDavid Gibson }; 2921b55d295eSDavid Gibson 2922b55d295eSDavid Gibson if (!cap_resize_hpt) { 2923b55d295eSDavid Gibson return -ENOSYS; 2924b55d295eSDavid Gibson } 2925b55d295eSDavid Gibson 2926b55d295eSDavid Gibson return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_PREPARE, &rhpt); 2927b55d295eSDavid Gibson } 2928b55d295eSDavid Gibson 2929b55d295eSDavid Gibson int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, target_ulong flags, int shift) 2930b55d295eSDavid Gibson { 2931b55d295eSDavid Gibson CPUState *cs = CPU(cpu); 2932b55d295eSDavid Gibson struct kvm_ppc_resize_hpt rhpt = { 2933b55d295eSDavid Gibson .flags = flags, 2934b55d295eSDavid Gibson .shift = shift, 2935b55d295eSDavid Gibson }; 2936b55d295eSDavid Gibson 2937b55d295eSDavid Gibson if (!cap_resize_hpt) { 2938b55d295eSDavid Gibson return -ENOSYS; 2939b55d295eSDavid Gibson } 2940b55d295eSDavid Gibson 2941b55d295eSDavid Gibson return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_COMMIT, &rhpt); 2942b55d295eSDavid Gibson } 2943b55d295eSDavid Gibson 2944c363a37aSDaniel Henrique Barboza /* 2945c363a37aSDaniel Henrique Barboza * This is a helper function to detect a post migration scenario 2946c363a37aSDaniel Henrique Barboza * in which a guest, running as KVM-HV, freezes in cpu_post_load because 2947c363a37aSDaniel Henrique Barboza * the guest kernel can't handle a PVR value other than the actual host 2948c363a37aSDaniel Henrique Barboza * PVR in KVM_SET_SREGS, even if pvr_match() returns true. 2949c363a37aSDaniel Henrique Barboza * 2950c363a37aSDaniel Henrique Barboza * If we don't have cap_ppc_pvr_compat and we're not running in PR 2951c363a37aSDaniel Henrique Barboza * (so, we're HV), return true. The workaround itself is done in 2952c363a37aSDaniel Henrique Barboza * cpu_post_load. 2953c363a37aSDaniel Henrique Barboza * 2954c363a37aSDaniel Henrique Barboza * The order here is important: we'll only check for KVM PR as a 2955c363a37aSDaniel Henrique Barboza * fallback if the guest kernel can't handle the situation itself. 2956c363a37aSDaniel Henrique Barboza * We need to avoid as much as possible querying the running KVM type 2957c363a37aSDaniel Henrique Barboza * in QEMU level. 2958c363a37aSDaniel Henrique Barboza */ 2959c363a37aSDaniel Henrique Barboza bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu) 2960c363a37aSDaniel Henrique Barboza { 2961c363a37aSDaniel Henrique Barboza CPUState *cs = CPU(cpu); 2962c363a37aSDaniel Henrique Barboza 2963c363a37aSDaniel Henrique Barboza if (!kvm_enabled()) { 2964c363a37aSDaniel Henrique Barboza return false; 2965c363a37aSDaniel Henrique Barboza } 2966c363a37aSDaniel Henrique Barboza 2967c363a37aSDaniel Henrique Barboza if (cap_ppc_pvr_compat) { 2968c363a37aSDaniel Henrique Barboza return false; 2969c363a37aSDaniel Henrique Barboza } 2970c363a37aSDaniel Henrique Barboza 2971c363a37aSDaniel Henrique Barboza return !kvmppc_is_pr(cs->kvm_state); 2972c363a37aSDaniel Henrique Barboza } 2973a84f7179SNikunj A Dadhania 2974a84f7179SNikunj A Dadhania void kvmppc_set_reg_ppc_online(PowerPCCPU *cpu, unsigned int online) 2975a84f7179SNikunj A Dadhania { 2976a84f7179SNikunj A Dadhania CPUState *cs = CPU(cpu); 2977a84f7179SNikunj A Dadhania 2978a84f7179SNikunj A Dadhania if (kvm_enabled()) { 2979a84f7179SNikunj A Dadhania kvm_set_one_reg(cs, KVM_REG_PPC_ONLINE, &online); 2980a84f7179SNikunj A Dadhania } 2981a84f7179SNikunj A Dadhania } 29829723295aSGreg Kurz 29839723295aSGreg Kurz void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) 29849723295aSGreg Kurz { 29859723295aSGreg Kurz CPUState *cs = CPU(cpu); 29869723295aSGreg Kurz 29879723295aSGreg Kurz if (kvm_enabled()) { 29889723295aSGreg Kurz kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &tb_offset); 29899723295aSGreg Kurz } 29909723295aSGreg Kurz } 299192a5199bSTom Lendacky 29923dba0a33SPaolo Bonzini void kvm_arch_accel_class_init(ObjectClass *oc) 29933dba0a33SPaolo Bonzini { 29943dba0a33SPaolo Bonzini } 2995cfb52d07SHarsh Prateek Bora 2996cfb52d07SHarsh Prateek Bora static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) 2997cfb52d07SHarsh Prateek Bora { 2998cfb52d07SHarsh Prateek Bora AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); 2999cfb52d07SHarsh Prateek Bora 3000cfb52d07SHarsh Prateek Bora acc->cpu_target_realize = kvmppc_cpu_realize; 3001cfb52d07SHarsh Prateek Bora } 3002cfb52d07SHarsh Prateek Bora 3003cfb52d07SHarsh Prateek Bora static const TypeInfo kvm_cpu_accel_type_info = { 3004cfb52d07SHarsh Prateek Bora .name = ACCEL_CPU_NAME("kvm"), 3005cfb52d07SHarsh Prateek Bora 3006cfb52d07SHarsh Prateek Bora .parent = TYPE_ACCEL_CPU, 3007cfb52d07SHarsh Prateek Bora .class_init = kvm_cpu_accel_class_init, 3008cfb52d07SHarsh Prateek Bora .abstract = true, 3009cfb52d07SHarsh Prateek Bora }; 3010cfb52d07SHarsh Prateek Bora static void kvm_cpu_accel_register_types(void) 3011cfb52d07SHarsh Prateek Bora { 3012cfb52d07SHarsh Prateek Bora type_register_static(&kvm_cpu_accel_type_info); 3013cfb52d07SHarsh Prateek Bora } 3014cfb52d07SHarsh Prateek Bora type_init(kvm_cpu_accel_register_types); 3015