1d76d1650Saurel32 /* 2d76d1650Saurel32 * PowerPC implementation of KVM hooks 3d76d1650Saurel32 * 4d76d1650Saurel32 * Copyright IBM Corp. 2007 590dc8812SScott Wood * Copyright (C) 2011 Freescale Semiconductor, Inc. 6d76d1650Saurel32 * 7d76d1650Saurel32 * Authors: 8d76d1650Saurel32 * Jerone Young <jyoung5@us.ibm.com> 9d76d1650Saurel32 * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> 10d76d1650Saurel32 * Hollis Blanchard <hollisb@us.ibm.com> 11d76d1650Saurel32 * 12d76d1650Saurel32 * This work is licensed under the terms of the GNU GPL, version 2 or later. 13d76d1650Saurel32 * See the COPYING file in the top-level directory. 14d76d1650Saurel32 * 15d76d1650Saurel32 */ 16d76d1650Saurel32 170d75590dSPeter Maydell #include "qemu/osdep.h" 18eadaada1SAlexander Graf #include <dirent.h> 19d76d1650Saurel32 #include <sys/ioctl.h> 204656e1f0SBenjamin Herrenschmidt #include <sys/vfs.h> 21d76d1650Saurel32 22d76d1650Saurel32 #include <linux/kvm.h> 23d76d1650Saurel32 24d76d1650Saurel32 #include "qemu-common.h" 2530f4b05bSDavid Gibson #include "qapi/error.h" 26072ed5f2SThomas Huth #include "qemu/error-report.h" 2733c11879SPaolo Bonzini #include "cpu.h" 28715d4b96SThomas Huth #include "cpu-models.h" 291de7afc9SPaolo Bonzini #include "qemu/timer.h" 309c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 31b3946626SVincent Palatin #include "sysemu/hw_accel.h" 32d76d1650Saurel32 #include "kvm_ppc.h" 339c17d615SPaolo Bonzini #include "sysemu/cpus.h" 349c17d615SPaolo Bonzini #include "sysemu/device_tree.h" 35d5aea6f3SDavid Gibson #include "mmu-hash64.h" 36d76d1650Saurel32 37f61b4bedSAlexander Graf #include "hw/sysbus.h" 380d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 397ebaf795SBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 4098a8b524SAlexey Kardashevskiy #include "hw/ppc/ppc.h" 4131f2cb8fSBharat Bhushan #include "sysemu/watchdog.h" 42b36f100eSAlexey Kardashevskiy #include "trace.h" 4388365d17SBharat Bhushan #include "exec/gdbstub.h" 444c663752SPaolo Bonzini #include "exec/memattrs.h" 459c607668SAlexey Kardashevskiy #include "exec/ram_addr.h" 462d103aaeSMichael Roth #include "sysemu/hostmem.h" 47f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 489c607668SAlexey Kardashevskiy #include "qemu/mmap-alloc.h" 49f3d9f303SSam Bobroff #include "elf.h" 50c64abd1fSSam Bobroff #include "sysemu/kvm_int.h" 51f61b4bedSAlexander Graf 52*c995e942SDavid Gibson /* #define DEBUG_KVM */ 53d76d1650Saurel32 54d76d1650Saurel32 #ifdef DEBUG_KVM 55da56ff91SPeter Maydell #define DPRINTF(fmt, ...) \ 56d76d1650Saurel32 do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 57d76d1650Saurel32 #else 58da56ff91SPeter Maydell #define DPRINTF(fmt, ...) \ 59d76d1650Saurel32 do { } while (0) 60d76d1650Saurel32 #endif 61d76d1650Saurel32 62eadaada1SAlexander Graf #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" 63eadaada1SAlexander Graf 6494a8d39aSJan Kiszka const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 6594a8d39aSJan Kiszka KVM_CAP_LAST_INFO 6694a8d39aSJan Kiszka }; 6794a8d39aSJan Kiszka 68*c995e942SDavid Gibson static int cap_interrupt_unset; 69*c995e942SDavid Gibson static int cap_interrupt_level; 7090dc8812SScott Wood static int cap_segstate; 7190dc8812SScott Wood static int cap_booke_sregs; 72e97c3636SDavid Gibson static int cap_ppc_smt; 73fa98fbfcSSam Bobroff static int cap_ppc_smt_possible; 740f5cb298SDavid Gibson static int cap_spapr_tce; 75d6ee2a7cSAlexey Kardashevskiy static int cap_spapr_tce_64; 76da95324eSAlexey Kardashevskiy static int cap_spapr_multitce; 779bb62a07SAlexey Kardashevskiy static int cap_spapr_vfio; 78f1af19d7SDavid Gibson static int cap_hior; 79d67d40eaSDavid Gibson static int cap_one_reg; 803b961124SStuart Yoder static int cap_epr; 8131f2cb8fSBharat Bhushan static int cap_ppc_watchdog; 829b00ea49SDavid Gibson static int cap_papr; 83e68cb8b4SAlexey Kardashevskiy static int cap_htab_fd; 8487a91de6SAlexander Graf static int cap_fixup_hcalls; 85bac3bf28SThomas Huth static int cap_htm; /* Hardware transactional memory support */ 86cf1c4cceSSam Bobroff static int cap_mmu_radix; 87cf1c4cceSSam Bobroff static int cap_mmu_hash_v3; 88b55d295eSDavid Gibson static int cap_resize_hpt; 89c363a37aSDaniel Henrique Barboza static int cap_ppc_pvr_compat; 908acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_cache; 918acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_bounds_check; 928acc2ae5SSuraj Jitindar Singh static int cap_ppc_safe_indirect_branch; 938ff43ee4SSuraj Jitindar Singh static int cap_ppc_count_cache_flush_assist; 94b9a477b7SSuraj Jitindar Singh static int cap_ppc_nested_kvm_hv; 957d050527SSuraj Jitindar Singh static int cap_large_decr; 96fc87e185SAlexander Graf 973c902d44SBharat Bhushan static uint32_t debug_inst_opcode; 983c902d44SBharat Bhushan 99*c995e942SDavid Gibson /* 100*c995e942SDavid Gibson * XXX We have a race condition where we actually have a level triggered 101c821c2bdSAlexander Graf * interrupt, but the infrastructure can't expose that yet, so the guest 102c821c2bdSAlexander Graf * takes but ignores it, goes to sleep and never gets notified that there's 103c821c2bdSAlexander Graf * still an interrupt pending. 104c6a94ba5SAlexander Graf * 105c821c2bdSAlexander Graf * As a quick workaround, let's just wake up again 20 ms after we injected 106c821c2bdSAlexander Graf * an interrupt. That way we can assure that we're always reinjecting 107c821c2bdSAlexander Graf * interrupts in case the guest swallowed them. 108c6a94ba5SAlexander Graf */ 109c6a94ba5SAlexander Graf static QEMUTimer *idle_timer; 110c6a94ba5SAlexander Graf 111d5a68146SAndreas Färber static void kvm_kick_cpu(void *opaque) 112c6a94ba5SAlexander Graf { 113d5a68146SAndreas Färber PowerPCCPU *cpu = opaque; 114d5a68146SAndreas Färber 115c08d7424SAndreas Färber qemu_cpu_kick(CPU(cpu)); 116c6a94ba5SAlexander Graf } 117c6a94ba5SAlexander Graf 118*c995e942SDavid Gibson /* 119*c995e942SDavid Gibson * Check whether we are running with KVM-PR (instead of KVM-HV). This 12096c9cff0SThomas Huth * should only be used for fallback tests - generally we should use 12196c9cff0SThomas Huth * explicit capabilities for the features we want, rather than 122*c995e942SDavid Gibson * assuming what is/isn't available depending on the KVM variant. 123*c995e942SDavid Gibson */ 12496c9cff0SThomas Huth static bool kvmppc_is_pr(KVMState *ks) 12596c9cff0SThomas Huth { 12696c9cff0SThomas Huth /* Assume KVM-PR if the GET_PVINFO capability is available */ 12770a0c19eSGreg Kurz return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; 12896c9cff0SThomas Huth } 12996c9cff0SThomas Huth 1302e9c10ebSIgor Mammedov static int kvm_ppc_register_host_cpu_type(MachineState *ms); 1318acc2ae5SSuraj Jitindar Singh static void kvmppc_get_cpu_characteristics(KVMState *s); 1327d050527SSuraj Jitindar Singh static int kvmppc_get_dec_bits(void); 1335ba4576bSAndreas Färber 134b16565b3SMarcel Apfelbaum int kvm_arch_init(MachineState *ms, KVMState *s) 135d76d1650Saurel32 { 136fc87e185SAlexander Graf cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ); 137fc87e185SAlexander Graf cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL); 13890dc8812SScott Wood cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE); 13990dc8812SScott Wood cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS); 1406977afdaSGreg Kurz cap_ppc_smt_possible = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE); 1410f5cb298SDavid Gibson cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE); 142d6ee2a7cSAlexey Kardashevskiy cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64); 143da95324eSAlexey Kardashevskiy cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE); 1449ded780cSAlexey Kardashevskiy cap_spapr_vfio = kvm_vm_check_extension(s, KVM_CAP_SPAPR_TCE_VFIO); 145d67d40eaSDavid Gibson cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG); 146f1af19d7SDavid Gibson cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR); 1473b961124SStuart Yoder cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR); 14831f2cb8fSBharat Bhushan cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG); 149*c995e942SDavid Gibson /* 150*c995e942SDavid Gibson * Note: we don't set cap_papr here, because this capability is 151*c995e942SDavid Gibson * only activated after this by kvmppc_set_papr() 152*c995e942SDavid Gibson */ 1536977afdaSGreg Kurz cap_htab_fd = kvm_vm_check_extension(s, KVM_CAP_PPC_HTAB_FD); 15487a91de6SAlexander Graf cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL); 155fa98fbfcSSam Bobroff cap_ppc_smt = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT); 156bac3bf28SThomas Huth cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM); 157cf1c4cceSSam Bobroff cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX); 158cf1c4cceSSam Bobroff cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3); 159b55d295eSDavid Gibson cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT); 1608acc2ae5SSuraj Jitindar Singh kvmppc_get_cpu_characteristics(s); 161b9a477b7SSuraj Jitindar Singh cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV); 1627d050527SSuraj Jitindar Singh cap_large_decr = kvmppc_get_dec_bits(); 163c363a37aSDaniel Henrique Barboza /* 164c363a37aSDaniel Henrique Barboza * Note: setting it to false because there is not such capability 165c363a37aSDaniel Henrique Barboza * in KVM at this moment. 166c363a37aSDaniel Henrique Barboza * 167c363a37aSDaniel Henrique Barboza * TODO: call kvm_vm_check_extension() with the right capability 168*c995e942SDavid Gibson * after the kernel starts implementing it. 169*c995e942SDavid Gibson */ 170c363a37aSDaniel Henrique Barboza cap_ppc_pvr_compat = false; 171fc87e185SAlexander Graf 172fc87e185SAlexander Graf if (!cap_interrupt_level) { 173fc87e185SAlexander Graf fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the " 174fc87e185SAlexander Graf "VM to stall at times!\n"); 175fc87e185SAlexander Graf } 176fc87e185SAlexander Graf 1772e9c10ebSIgor Mammedov kvm_ppc_register_host_cpu_type(ms); 1785ba4576bSAndreas Färber 179d76d1650Saurel32 return 0; 180d76d1650Saurel32 } 181d76d1650Saurel32 182d525ffabSPaolo Bonzini int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) 183d525ffabSPaolo Bonzini { 184d525ffabSPaolo Bonzini return 0; 185d525ffabSPaolo Bonzini } 186d525ffabSPaolo Bonzini 1871bc22652SAndreas Färber static int kvm_arch_sync_sregs(PowerPCCPU *cpu) 188d76d1650Saurel32 { 1891bc22652SAndreas Färber CPUPPCState *cenv = &cpu->env; 1901bc22652SAndreas Färber CPUState *cs = CPU(cpu); 191861bbc80SAlexander Graf struct kvm_sregs sregs; 1925666ca4aSScott Wood int ret; 1935666ca4aSScott Wood 1945666ca4aSScott Wood if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 195*c995e942SDavid Gibson /* 196*c995e942SDavid Gibson * What we're really trying to say is "if we're on BookE, we 197*c995e942SDavid Gibson * use the native PVR for now". This is the only sane way to 198*c995e942SDavid Gibson * check it though, so we potentially confuse users that they 199*c995e942SDavid Gibson * can run BookE guests on BookS. Let's hope nobody dares 200*c995e942SDavid Gibson * enough :) 201*c995e942SDavid Gibson */ 2025666ca4aSScott Wood return 0; 2035666ca4aSScott Wood } else { 20490dc8812SScott Wood if (!cap_segstate) { 20564e07be5SAlexander Graf fprintf(stderr, "kvm error: missing PVR setting capability\n"); 20664e07be5SAlexander Graf return -ENOSYS; 2075666ca4aSScott Wood } 2085666ca4aSScott Wood } 2095666ca4aSScott Wood 2101bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); 2115666ca4aSScott Wood if (ret) { 2125666ca4aSScott Wood return ret; 2135666ca4aSScott Wood } 214861bbc80SAlexander Graf 215861bbc80SAlexander Graf sregs.pvr = cenv->spr[SPR_PVR]; 2161bc22652SAndreas Färber return kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); 2175666ca4aSScott Wood } 2185666ca4aSScott Wood 21993dd5e85SScott Wood /* Set up a shared TLB array with KVM */ 2201bc22652SAndreas Färber static int kvm_booke206_tlb_init(PowerPCCPU *cpu) 22193dd5e85SScott Wood { 2221bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 2231bc22652SAndreas Färber CPUState *cs = CPU(cpu); 22493dd5e85SScott Wood struct kvm_book3e_206_tlb_params params = {}; 22593dd5e85SScott Wood struct kvm_config_tlb cfg = {}; 22693dd5e85SScott Wood unsigned int entries = 0; 22793dd5e85SScott Wood int ret, i; 22893dd5e85SScott Wood 22993dd5e85SScott Wood if (!kvm_enabled() || 230a60f24b5SAndreas Färber !kvm_check_extension(cs->kvm_state, KVM_CAP_SW_TLB)) { 23193dd5e85SScott Wood return 0; 23293dd5e85SScott Wood } 23393dd5e85SScott Wood 23493dd5e85SScott Wood assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN); 23593dd5e85SScott Wood 23693dd5e85SScott Wood for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 23793dd5e85SScott Wood params.tlb_sizes[i] = booke206_tlb_size(env, i); 23893dd5e85SScott Wood params.tlb_ways[i] = booke206_tlb_ways(env, i); 23993dd5e85SScott Wood entries += params.tlb_sizes[i]; 24093dd5e85SScott Wood } 24193dd5e85SScott Wood 24293dd5e85SScott Wood assert(entries == env->nb_tlb); 24393dd5e85SScott Wood assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t)); 24493dd5e85SScott Wood 24593dd5e85SScott Wood env->tlb_dirty = true; 24693dd5e85SScott Wood 24793dd5e85SScott Wood cfg.array = (uintptr_t)env->tlb.tlbm; 24893dd5e85SScott Wood cfg.array_len = sizeof(ppcmas_tlb_t) * entries; 24993dd5e85SScott Wood cfg.params = (uintptr_t)¶ms; 25093dd5e85SScott Wood cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV; 25193dd5e85SScott Wood 25248add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_SW_TLB, 0, (uintptr_t)&cfg); 25393dd5e85SScott Wood if (ret < 0) { 25493dd5e85SScott Wood fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n", 25593dd5e85SScott Wood __func__, strerror(-ret)); 25693dd5e85SScott Wood return ret; 25793dd5e85SScott Wood } 25893dd5e85SScott Wood 25993dd5e85SScott Wood env->kvm_sw_tlb = true; 26093dd5e85SScott Wood return 0; 26193dd5e85SScott Wood } 26293dd5e85SScott Wood 2634656e1f0SBenjamin Herrenschmidt 2644656e1f0SBenjamin Herrenschmidt #if defined(TARGET_PPC64) 265ab256960SGreg Kurz static void kvm_get_smmu_info(struct kvm_ppc_smmu_info *info, Error **errp) 2664656e1f0SBenjamin Herrenschmidt { 2674656e1f0SBenjamin Herrenschmidt int ret; 2684656e1f0SBenjamin Herrenschmidt 269ab256960SGreg Kurz assert(kvm_state != NULL); 270ab256960SGreg Kurz 271ab256960SGreg Kurz if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { 27271d0f1eaSGreg Kurz error_setg(errp, "KVM doesn't expose the MMU features it supports"); 27371d0f1eaSGreg Kurz error_append_hint(errp, "Consider switching to a newer KVM\n"); 27471d0f1eaSGreg Kurz return; 27571d0f1eaSGreg Kurz } 27671d0f1eaSGreg Kurz 277ab256960SGreg Kurz ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_SMMU_INFO, info); 2784656e1f0SBenjamin Herrenschmidt if (ret == 0) { 2794656e1f0SBenjamin Herrenschmidt return; 2804656e1f0SBenjamin Herrenschmidt } 2814656e1f0SBenjamin Herrenschmidt 28271d0f1eaSGreg Kurz error_setg_errno(errp, -ret, 28371d0f1eaSGreg Kurz "KVM failed to provide the MMU features it supports"); 2844656e1f0SBenjamin Herrenschmidt } 2854656e1f0SBenjamin Herrenschmidt 286c64abd1fSSam Bobroff struct ppc_radix_page_info *kvm_get_radix_page_info(void) 287c64abd1fSSam Bobroff { 288c64abd1fSSam Bobroff KVMState *s = KVM_STATE(current_machine->accelerator); 289c64abd1fSSam Bobroff struct ppc_radix_page_info *radix_page_info; 290c64abd1fSSam Bobroff struct kvm_ppc_rmmu_info rmmu_info; 291c64abd1fSSam Bobroff int i; 292c64abd1fSSam Bobroff 293c64abd1fSSam Bobroff if (!kvm_check_extension(s, KVM_CAP_PPC_MMU_RADIX)) { 294c64abd1fSSam Bobroff return NULL; 295c64abd1fSSam Bobroff } 296c64abd1fSSam Bobroff if (kvm_vm_ioctl(s, KVM_PPC_GET_RMMU_INFO, &rmmu_info)) { 297c64abd1fSSam Bobroff return NULL; 298c64abd1fSSam Bobroff } 299c64abd1fSSam Bobroff radix_page_info = g_malloc0(sizeof(*radix_page_info)); 300c64abd1fSSam Bobroff radix_page_info->count = 0; 301c64abd1fSSam Bobroff for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { 302c64abd1fSSam Bobroff if (rmmu_info.ap_encodings[i]) { 303c64abd1fSSam Bobroff radix_page_info->entries[i] = rmmu_info.ap_encodings[i]; 304c64abd1fSSam Bobroff radix_page_info->count++; 305c64abd1fSSam Bobroff } 306c64abd1fSSam Bobroff } 307c64abd1fSSam Bobroff return radix_page_info; 308c64abd1fSSam Bobroff } 309c64abd1fSSam Bobroff 310b4db5413SSuraj Jitindar Singh target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu, 311b4db5413SSuraj Jitindar Singh bool radix, bool gtse, 312b4db5413SSuraj Jitindar Singh uint64_t proc_tbl) 313b4db5413SSuraj Jitindar Singh { 314b4db5413SSuraj Jitindar Singh CPUState *cs = CPU(cpu); 315b4db5413SSuraj Jitindar Singh int ret; 316b4db5413SSuraj Jitindar Singh uint64_t flags = 0; 317b4db5413SSuraj Jitindar Singh struct kvm_ppc_mmuv3_cfg cfg = { 318b4db5413SSuraj Jitindar Singh .process_table = proc_tbl, 319b4db5413SSuraj Jitindar Singh }; 320b4db5413SSuraj Jitindar Singh 321b4db5413SSuraj Jitindar Singh if (radix) { 322b4db5413SSuraj Jitindar Singh flags |= KVM_PPC_MMUV3_RADIX; 323b4db5413SSuraj Jitindar Singh } 324b4db5413SSuraj Jitindar Singh if (gtse) { 325b4db5413SSuraj Jitindar Singh flags |= KVM_PPC_MMUV3_GTSE; 326b4db5413SSuraj Jitindar Singh } 327b4db5413SSuraj Jitindar Singh cfg.flags = flags; 328b4db5413SSuraj Jitindar Singh ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_CONFIGURE_V3_MMU, &cfg); 329b4db5413SSuraj Jitindar Singh switch (ret) { 330b4db5413SSuraj Jitindar Singh case 0: 331b4db5413SSuraj Jitindar Singh return H_SUCCESS; 332b4db5413SSuraj Jitindar Singh case -EINVAL: 333b4db5413SSuraj Jitindar Singh return H_PARAMETER; 334b4db5413SSuraj Jitindar Singh case -ENODEV: 335b4db5413SSuraj Jitindar Singh return H_NOT_AVAILABLE; 336b4db5413SSuraj Jitindar Singh default: 337b4db5413SSuraj Jitindar Singh return H_HARDWARE; 338b4db5413SSuraj Jitindar Singh } 339b4db5413SSuraj Jitindar Singh } 340b4db5413SSuraj Jitindar Singh 34124c6863cSDavid Gibson bool kvmppc_hpt_needs_host_contiguous_pages(void) 34224c6863cSDavid Gibson { 34324c6863cSDavid Gibson static struct kvm_ppc_smmu_info smmu_info; 34424c6863cSDavid Gibson 34524c6863cSDavid Gibson if (!kvm_enabled()) { 34624c6863cSDavid Gibson return false; 34724c6863cSDavid Gibson } 34824c6863cSDavid Gibson 349ab256960SGreg Kurz kvm_get_smmu_info(&smmu_info, &error_fatal); 35024c6863cSDavid Gibson return !!(smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL); 35124c6863cSDavid Gibson } 35224c6863cSDavid Gibson 353e5ca28ecSDavid Gibson void kvm_check_mmu(PowerPCCPU *cpu, Error **errp) 3544656e1f0SBenjamin Herrenschmidt { 355e5ca28ecSDavid Gibson struct kvm_ppc_smmu_info smmu_info; 3564656e1f0SBenjamin Herrenschmidt int iq, ik, jq, jk; 35771d0f1eaSGreg Kurz Error *local_err = NULL; 3584656e1f0SBenjamin Herrenschmidt 359e5ca28ecSDavid Gibson /* For now, we only have anything to check on hash64 MMUs */ 360e5ca28ecSDavid Gibson if (!cpu->hash64_opts || !kvm_enabled()) { 3614656e1f0SBenjamin Herrenschmidt return; 3624656e1f0SBenjamin Herrenschmidt } 3634656e1f0SBenjamin Herrenschmidt 364ab256960SGreg Kurz kvm_get_smmu_info(&smmu_info, &local_err); 36571d0f1eaSGreg Kurz if (local_err) { 36671d0f1eaSGreg Kurz error_propagate(errp, local_err); 36771d0f1eaSGreg Kurz return; 36871d0f1eaSGreg Kurz } 369e5ca28ecSDavid Gibson 370e5ca28ecSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG) 371e5ca28ecSDavid Gibson && !(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { 372e5ca28ecSDavid Gibson error_setg(errp, 373e5ca28ecSDavid Gibson "KVM does not support 1TiB segments which guest expects"); 374e5ca28ecSDavid Gibson return; 3754656e1f0SBenjamin Herrenschmidt } 3764656e1f0SBenjamin Herrenschmidt 377e5ca28ecSDavid Gibson if (smmu_info.slb_size < cpu->hash64_opts->slb_size) { 378e5ca28ecSDavid Gibson error_setg(errp, "KVM only supports %u SLB entries, but guest needs %u", 379e5ca28ecSDavid Gibson smmu_info.slb_size, cpu->hash64_opts->slb_size); 380e5ca28ecSDavid Gibson return; 38190da0d5aSBenjamin Herrenschmidt } 38290da0d5aSBenjamin Herrenschmidt 38308215d8fSAlexander Graf /* 384e5ca28ecSDavid Gibson * Verify that every pagesize supported by the cpu model is 385e5ca28ecSDavid Gibson * supported by KVM with the same encodings 38608215d8fSAlexander Graf */ 387e5ca28ecSDavid Gibson for (iq = 0; iq < ARRAY_SIZE(cpu->hash64_opts->sps); iq++) { 388b07c59f7SDavid Gibson PPCHash64SegmentPageSizes *qsps = &cpu->hash64_opts->sps[iq]; 389e5ca28ecSDavid Gibson struct kvm_ppc_one_seg_page_size *ksps; 3904656e1f0SBenjamin Herrenschmidt 391e5ca28ecSDavid Gibson for (ik = 0; ik < ARRAY_SIZE(smmu_info.sps); ik++) { 392e5ca28ecSDavid Gibson if (qsps->page_shift == smmu_info.sps[ik].page_shift) { 3934656e1f0SBenjamin Herrenschmidt break; 3944656e1f0SBenjamin Herrenschmidt } 3954656e1f0SBenjamin Herrenschmidt } 396e5ca28ecSDavid Gibson if (ik >= ARRAY_SIZE(smmu_info.sps)) { 397e5ca28ecSDavid Gibson error_setg(errp, "KVM doesn't support for base page shift %u", 398e5ca28ecSDavid Gibson qsps->page_shift); 399e5ca28ecSDavid Gibson return; 400e5ca28ecSDavid Gibson } 401e5ca28ecSDavid Gibson 402e5ca28ecSDavid Gibson ksps = &smmu_info.sps[ik]; 403e5ca28ecSDavid Gibson if (ksps->slb_enc != qsps->slb_enc) { 404e5ca28ecSDavid Gibson error_setg(errp, 405e5ca28ecSDavid Gibson "KVM uses SLB encoding 0x%x for page shift %u, but guest expects 0x%x", 406e5ca28ecSDavid Gibson ksps->slb_enc, ksps->page_shift, qsps->slb_enc); 407e5ca28ecSDavid Gibson return; 408e5ca28ecSDavid Gibson } 409e5ca28ecSDavid Gibson 410e5ca28ecSDavid Gibson for (jq = 0; jq < ARRAY_SIZE(qsps->enc); jq++) { 411e5ca28ecSDavid Gibson for (jk = 0; jk < ARRAY_SIZE(ksps->enc); jk++) { 412e5ca28ecSDavid Gibson if (qsps->enc[jq].page_shift == ksps->enc[jk].page_shift) { 4134656e1f0SBenjamin Herrenschmidt break; 4144656e1f0SBenjamin Herrenschmidt } 4154656e1f0SBenjamin Herrenschmidt } 4164656e1f0SBenjamin Herrenschmidt 417e5ca28ecSDavid Gibson if (jk >= ARRAY_SIZE(ksps->enc)) { 418e5ca28ecSDavid Gibson error_setg(errp, "KVM doesn't support page shift %u/%u", 419e5ca28ecSDavid Gibson qsps->enc[jq].page_shift, qsps->page_shift); 420e5ca28ecSDavid Gibson return; 421e5ca28ecSDavid Gibson } 422e5ca28ecSDavid Gibson if (qsps->enc[jq].pte_enc != ksps->enc[jk].pte_enc) { 423e5ca28ecSDavid Gibson error_setg(errp, 424e5ca28ecSDavid Gibson "KVM uses PTE encoding 0x%x for page shift %u/%u, but guest expects 0x%x", 425e5ca28ecSDavid Gibson ksps->enc[jk].pte_enc, qsps->enc[jq].page_shift, 426e5ca28ecSDavid Gibson qsps->page_shift, qsps->enc[jq].pte_enc); 427e5ca28ecSDavid Gibson return; 428e5ca28ecSDavid Gibson } 429e5ca28ecSDavid Gibson } 4304656e1f0SBenjamin Herrenschmidt } 4314656e1f0SBenjamin Herrenschmidt 432e5ca28ecSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) { 433*c995e942SDavid Gibson /* 434*c995e942SDavid Gibson * Mostly what guest pagesizes we can use are related to the 435e5ca28ecSDavid Gibson * host pages used to map guest RAM, which is handled in the 436e5ca28ecSDavid Gibson * platform code. Cache-Inhibited largepages (64k) however are 437e5ca28ecSDavid Gibson * used for I/O, so if they're mapped to the host at all it 438e5ca28ecSDavid Gibson * will be a normal mapping, not a special hugepage one used 439*c995e942SDavid Gibson * for RAM. 440*c995e942SDavid Gibson */ 441e5ca28ecSDavid Gibson if (getpagesize() < 0x10000) { 442e5ca28ecSDavid Gibson error_setg(errp, 443e5ca28ecSDavid Gibson "KVM can't supply 64kiB CI pages, which guest expects"); 444e5ca28ecSDavid Gibson } 445e5ca28ecSDavid Gibson } 446e5ca28ecSDavid Gibson } 4474656e1f0SBenjamin Herrenschmidt #endif /* !defined (TARGET_PPC64) */ 4484656e1f0SBenjamin Herrenschmidt 449b164e48eSEduardo Habkost unsigned long kvm_arch_vcpu_id(CPUState *cpu) 450b164e48eSEduardo Habkost { 4512e886fb3SSam Bobroff return POWERPC_CPU(cpu)->vcpu_id; 452b164e48eSEduardo Habkost } 453b164e48eSEduardo Habkost 454*c995e942SDavid Gibson /* 455*c995e942SDavid Gibson * e500 supports 2 h/w breakpoint and 2 watchpoint. book3s supports 456*c995e942SDavid Gibson * only 1 watchpoint, so array size of 4 is sufficient for now. 45788365d17SBharat Bhushan */ 45888365d17SBharat Bhushan #define MAX_HW_BKPTS 4 45988365d17SBharat Bhushan 46088365d17SBharat Bhushan static struct HWBreakpoint { 46188365d17SBharat Bhushan target_ulong addr; 46288365d17SBharat Bhushan int type; 46388365d17SBharat Bhushan } hw_debug_points[MAX_HW_BKPTS]; 46488365d17SBharat Bhushan 46588365d17SBharat Bhushan static CPUWatchpoint hw_watchpoint; 46688365d17SBharat Bhushan 46788365d17SBharat Bhushan /* Default there is no breakpoint and watchpoint supported */ 46888365d17SBharat Bhushan static int max_hw_breakpoint; 46988365d17SBharat Bhushan static int max_hw_watchpoint; 47088365d17SBharat Bhushan static int nb_hw_breakpoint; 47188365d17SBharat Bhushan static int nb_hw_watchpoint; 47288365d17SBharat Bhushan 47388365d17SBharat Bhushan static void kvmppc_hw_debug_points_init(CPUPPCState *cenv) 47488365d17SBharat Bhushan { 47588365d17SBharat Bhushan if (cenv->excp_model == POWERPC_EXCP_BOOKE) { 47688365d17SBharat Bhushan max_hw_breakpoint = 2; 47788365d17SBharat Bhushan max_hw_watchpoint = 2; 47888365d17SBharat Bhushan } 47988365d17SBharat Bhushan 48088365d17SBharat Bhushan if ((max_hw_breakpoint + max_hw_watchpoint) > MAX_HW_BKPTS) { 48188365d17SBharat Bhushan fprintf(stderr, "Error initializing h/w breakpoints\n"); 48288365d17SBharat Bhushan return; 48388365d17SBharat Bhushan } 48488365d17SBharat Bhushan } 48588365d17SBharat Bhushan 48620d695a9SAndreas Färber int kvm_arch_init_vcpu(CPUState *cs) 4875666ca4aSScott Wood { 48820d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 48920d695a9SAndreas Färber CPUPPCState *cenv = &cpu->env; 4905666ca4aSScott Wood int ret; 4915666ca4aSScott Wood 4924656e1f0SBenjamin Herrenschmidt /* Synchronize sregs with kvm */ 4931bc22652SAndreas Färber ret = kvm_arch_sync_sregs(cpu); 4945666ca4aSScott Wood if (ret) { 495388e47c7SThomas Huth if (ret == -EINVAL) { 496388e47c7SThomas Huth error_report("Register sync failed... If you're using kvm-hv.ko," 497388e47c7SThomas Huth " only \"-cpu host\" is possible"); 498388e47c7SThomas Huth } 4995666ca4aSScott Wood return ret; 5005666ca4aSScott Wood } 501861bbc80SAlexander Graf 502bc72ad67SAlex Bligh idle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kvm_kick_cpu, cpu); 503c821c2bdSAlexander Graf 50493dd5e85SScott Wood switch (cenv->mmu_model) { 50593dd5e85SScott Wood case POWERPC_MMU_BOOKE206: 5067f516c96SThomas Huth /* This target supports access to KVM's guest TLB */ 5071bc22652SAndreas Färber ret = kvm_booke206_tlb_init(cpu); 50893dd5e85SScott Wood break; 5097f516c96SThomas Huth case POWERPC_MMU_2_07: 5107f516c96SThomas Huth if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) { 511*c995e942SDavid Gibson /* 512*c995e942SDavid Gibson * KVM-HV has transactional memory on POWER8 also without 513*c995e942SDavid Gibson * the KVM_CAP_PPC_HTM extension, so enable it here 514*c995e942SDavid Gibson * instead as long as it's availble to userspace on the 515*c995e942SDavid Gibson * host. 516*c995e942SDavid Gibson */ 517f3d9f303SSam Bobroff if (qemu_getauxval(AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) { 5187f516c96SThomas Huth cap_htm = true; 5197f516c96SThomas Huth } 520f3d9f303SSam Bobroff } 5217f516c96SThomas Huth break; 52293dd5e85SScott Wood default: 52393dd5e85SScott Wood break; 52493dd5e85SScott Wood } 52593dd5e85SScott Wood 5263c902d44SBharat Bhushan kvm_get_one_reg(cs, KVM_REG_PPC_DEBUG_INST, &debug_inst_opcode); 52788365d17SBharat Bhushan kvmppc_hw_debug_points_init(cenv); 5283c902d44SBharat Bhushan 529861bbc80SAlexander Graf return ret; 530d76d1650Saurel32 } 531d76d1650Saurel32 5321bc22652SAndreas Färber static void kvm_sw_tlb_put(PowerPCCPU *cpu) 53393dd5e85SScott Wood { 5341bc22652SAndreas Färber CPUPPCState *env = &cpu->env; 5351bc22652SAndreas Färber CPUState *cs = CPU(cpu); 53693dd5e85SScott Wood struct kvm_dirty_tlb dirty_tlb; 53793dd5e85SScott Wood unsigned char *bitmap; 53893dd5e85SScott Wood int ret; 53993dd5e85SScott Wood 54093dd5e85SScott Wood if (!env->kvm_sw_tlb) { 54193dd5e85SScott Wood return; 54293dd5e85SScott Wood } 54393dd5e85SScott Wood 54493dd5e85SScott Wood bitmap = g_malloc((env->nb_tlb + 7) / 8); 54593dd5e85SScott Wood memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8); 54693dd5e85SScott Wood 54793dd5e85SScott Wood dirty_tlb.bitmap = (uintptr_t)bitmap; 54893dd5e85SScott Wood dirty_tlb.num_dirty = env->nb_tlb; 54993dd5e85SScott Wood 5501bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_DIRTY_TLB, &dirty_tlb); 55193dd5e85SScott Wood if (ret) { 55293dd5e85SScott Wood fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n", 55393dd5e85SScott Wood __func__, strerror(-ret)); 55493dd5e85SScott Wood } 55593dd5e85SScott Wood 55693dd5e85SScott Wood g_free(bitmap); 55793dd5e85SScott Wood } 55893dd5e85SScott Wood 559d67d40eaSDavid Gibson static void kvm_get_one_spr(CPUState *cs, uint64_t id, int spr) 560d67d40eaSDavid Gibson { 561d67d40eaSDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 562d67d40eaSDavid Gibson CPUPPCState *env = &cpu->env; 563d67d40eaSDavid Gibson union { 564d67d40eaSDavid Gibson uint32_t u32; 565d67d40eaSDavid Gibson uint64_t u64; 566d67d40eaSDavid Gibson } val; 567d67d40eaSDavid Gibson struct kvm_one_reg reg = { 568d67d40eaSDavid Gibson .id = id, 569d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 570d67d40eaSDavid Gibson }; 571d67d40eaSDavid Gibson int ret; 572d67d40eaSDavid Gibson 573d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 574d67d40eaSDavid Gibson if (ret != 0) { 575b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_get(spr, strerror(errno)); 576d67d40eaSDavid Gibson } else { 577d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 578d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 579d67d40eaSDavid Gibson env->spr[spr] = val.u32; 580d67d40eaSDavid Gibson break; 581d67d40eaSDavid Gibson 582d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 583d67d40eaSDavid Gibson env->spr[spr] = val.u64; 584d67d40eaSDavid Gibson break; 585d67d40eaSDavid Gibson 586d67d40eaSDavid Gibson default: 587d67d40eaSDavid Gibson /* Don't handle this size yet */ 588d67d40eaSDavid Gibson abort(); 589d67d40eaSDavid Gibson } 590d67d40eaSDavid Gibson } 591d67d40eaSDavid Gibson } 592d67d40eaSDavid Gibson 593d67d40eaSDavid Gibson static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr) 594d67d40eaSDavid Gibson { 595d67d40eaSDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 596d67d40eaSDavid Gibson CPUPPCState *env = &cpu->env; 597d67d40eaSDavid Gibson union { 598d67d40eaSDavid Gibson uint32_t u32; 599d67d40eaSDavid Gibson uint64_t u64; 600d67d40eaSDavid Gibson } val; 601d67d40eaSDavid Gibson struct kvm_one_reg reg = { 602d67d40eaSDavid Gibson .id = id, 603d67d40eaSDavid Gibson .addr = (uintptr_t) &val, 604d67d40eaSDavid Gibson }; 605d67d40eaSDavid Gibson int ret; 606d67d40eaSDavid Gibson 607d67d40eaSDavid Gibson switch (id & KVM_REG_SIZE_MASK) { 608d67d40eaSDavid Gibson case KVM_REG_SIZE_U32: 609d67d40eaSDavid Gibson val.u32 = env->spr[spr]; 610d67d40eaSDavid Gibson break; 611d67d40eaSDavid Gibson 612d67d40eaSDavid Gibson case KVM_REG_SIZE_U64: 613d67d40eaSDavid Gibson val.u64 = env->spr[spr]; 614d67d40eaSDavid Gibson break; 615d67d40eaSDavid Gibson 616d67d40eaSDavid Gibson default: 617d67d40eaSDavid Gibson /* Don't handle this size yet */ 618d67d40eaSDavid Gibson abort(); 619d67d40eaSDavid Gibson } 620d67d40eaSDavid Gibson 621d67d40eaSDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 622d67d40eaSDavid Gibson if (ret != 0) { 623b36f100eSAlexey Kardashevskiy trace_kvm_failed_spr_set(spr, strerror(errno)); 624d67d40eaSDavid Gibson } 625d67d40eaSDavid Gibson } 626d67d40eaSDavid Gibson 62770b79849SDavid Gibson static int kvm_put_fp(CPUState *cs) 62870b79849SDavid Gibson { 62970b79849SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 63070b79849SDavid Gibson CPUPPCState *env = &cpu->env; 63170b79849SDavid Gibson struct kvm_one_reg reg; 63270b79849SDavid Gibson int i; 63370b79849SDavid Gibson int ret; 63470b79849SDavid Gibson 63570b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 63670b79849SDavid Gibson uint64_t fpscr = env->fpscr; 63770b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 63870b79849SDavid Gibson 63970b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 64070b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 64170b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 64270b79849SDavid Gibson if (ret < 0) { 643da56ff91SPeter Maydell DPRINTF("Unable to set FPSCR to KVM: %s\n", strerror(errno)); 64470b79849SDavid Gibson return ret; 64570b79849SDavid Gibson } 64670b79849SDavid Gibson 64770b79849SDavid Gibson for (i = 0; i < 32; i++) { 64870b79849SDavid Gibson uint64_t vsr[2]; 649ef96e3aeSMark Cave-Ayland uint64_t *fpr = cpu_fpr_ptr(&cpu->env, i); 650ef96e3aeSMark Cave-Ayland uint64_t *vsrl = cpu_vsrl_ptr(&cpu->env, i); 65170b79849SDavid Gibson 6523a4b791bSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 653ef96e3aeSMark Cave-Ayland vsr[0] = float64_val(*fpr); 654ef96e3aeSMark Cave-Ayland vsr[1] = *vsrl; 6553a4b791bSGreg Kurz #else 656ef96e3aeSMark Cave-Ayland vsr[0] = *vsrl; 657ef96e3aeSMark Cave-Ayland vsr[1] = float64_val(*fpr); 6583a4b791bSGreg Kurz #endif 65970b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 66070b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 66170b79849SDavid Gibson 66270b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 66370b79849SDavid Gibson if (ret < 0) { 664da56ff91SPeter Maydell DPRINTF("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR", 66570b79849SDavid Gibson i, strerror(errno)); 66670b79849SDavid Gibson return ret; 66770b79849SDavid Gibson } 66870b79849SDavid Gibson } 66970b79849SDavid Gibson } 67070b79849SDavid Gibson 67170b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 67270b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 67370b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 67470b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 67570b79849SDavid Gibson if (ret < 0) { 676da56ff91SPeter Maydell DPRINTF("Unable to set VSCR to KVM: %s\n", strerror(errno)); 67770b79849SDavid Gibson return ret; 67870b79849SDavid Gibson } 67970b79849SDavid Gibson 68070b79849SDavid Gibson for (i = 0; i < 32; i++) { 68170b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 682ef96e3aeSMark Cave-Ayland reg.addr = (uintptr_t)cpu_avr_ptr(env, i); 68370b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 68470b79849SDavid Gibson if (ret < 0) { 685da56ff91SPeter Maydell DPRINTF("Unable to set VR%d to KVM: %s\n", i, strerror(errno)); 68670b79849SDavid Gibson return ret; 68770b79849SDavid Gibson } 68870b79849SDavid Gibson } 68970b79849SDavid Gibson } 69070b79849SDavid Gibson 69170b79849SDavid Gibson return 0; 69270b79849SDavid Gibson } 69370b79849SDavid Gibson 69470b79849SDavid Gibson static int kvm_get_fp(CPUState *cs) 69570b79849SDavid Gibson { 69670b79849SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 69770b79849SDavid Gibson CPUPPCState *env = &cpu->env; 69870b79849SDavid Gibson struct kvm_one_reg reg; 69970b79849SDavid Gibson int i; 70070b79849SDavid Gibson int ret; 70170b79849SDavid Gibson 70270b79849SDavid Gibson if (env->insns_flags & PPC_FLOAT) { 70370b79849SDavid Gibson uint64_t fpscr; 70470b79849SDavid Gibson bool vsx = !!(env->insns_flags2 & PPC2_VSX); 70570b79849SDavid Gibson 70670b79849SDavid Gibson reg.id = KVM_REG_PPC_FPSCR; 70770b79849SDavid Gibson reg.addr = (uintptr_t)&fpscr; 70870b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 70970b79849SDavid Gibson if (ret < 0) { 710da56ff91SPeter Maydell DPRINTF("Unable to get FPSCR from KVM: %s\n", strerror(errno)); 71170b79849SDavid Gibson return ret; 71270b79849SDavid Gibson } else { 71370b79849SDavid Gibson env->fpscr = fpscr; 71470b79849SDavid Gibson } 71570b79849SDavid Gibson 71670b79849SDavid Gibson for (i = 0; i < 32; i++) { 71770b79849SDavid Gibson uint64_t vsr[2]; 718ef96e3aeSMark Cave-Ayland uint64_t *fpr = cpu_fpr_ptr(&cpu->env, i); 719ef96e3aeSMark Cave-Ayland uint64_t *vsrl = cpu_vsrl_ptr(&cpu->env, i); 72070b79849SDavid Gibson 72170b79849SDavid Gibson reg.addr = (uintptr_t) &vsr; 72270b79849SDavid Gibson reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i); 72370b79849SDavid Gibson 72470b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 72570b79849SDavid Gibson if (ret < 0) { 726da56ff91SPeter Maydell DPRINTF("Unable to get %s%d from KVM: %s\n", 72770b79849SDavid Gibson vsx ? "VSR" : "FPR", i, strerror(errno)); 72870b79849SDavid Gibson return ret; 72970b79849SDavid Gibson } else { 7303a4b791bSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 731ef96e3aeSMark Cave-Ayland *fpr = vsr[0]; 73270b79849SDavid Gibson if (vsx) { 733ef96e3aeSMark Cave-Ayland *vsrl = vsr[1]; 73470b79849SDavid Gibson } 7353a4b791bSGreg Kurz #else 736ef96e3aeSMark Cave-Ayland *fpr = vsr[1]; 7373a4b791bSGreg Kurz if (vsx) { 738ef96e3aeSMark Cave-Ayland *vsrl = vsr[0]; 7393a4b791bSGreg Kurz } 7403a4b791bSGreg Kurz #endif 74170b79849SDavid Gibson } 74270b79849SDavid Gibson } 74370b79849SDavid Gibson } 74470b79849SDavid Gibson 74570b79849SDavid Gibson if (env->insns_flags & PPC_ALTIVEC) { 74670b79849SDavid Gibson reg.id = KVM_REG_PPC_VSCR; 74770b79849SDavid Gibson reg.addr = (uintptr_t)&env->vscr; 74870b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 74970b79849SDavid Gibson if (ret < 0) { 750da56ff91SPeter Maydell DPRINTF("Unable to get VSCR from KVM: %s\n", strerror(errno)); 75170b79849SDavid Gibson return ret; 75270b79849SDavid Gibson } 75370b79849SDavid Gibson 75470b79849SDavid Gibson for (i = 0; i < 32; i++) { 75570b79849SDavid Gibson reg.id = KVM_REG_PPC_VR(i); 756ef96e3aeSMark Cave-Ayland reg.addr = (uintptr_t)cpu_avr_ptr(env, i); 75770b79849SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 75870b79849SDavid Gibson if (ret < 0) { 759da56ff91SPeter Maydell DPRINTF("Unable to get VR%d from KVM: %s\n", 76070b79849SDavid Gibson i, strerror(errno)); 76170b79849SDavid Gibson return ret; 76270b79849SDavid Gibson } 76370b79849SDavid Gibson } 76470b79849SDavid Gibson } 76570b79849SDavid Gibson 76670b79849SDavid Gibson return 0; 76770b79849SDavid Gibson } 76870b79849SDavid Gibson 7699b00ea49SDavid Gibson #if defined(TARGET_PPC64) 7709b00ea49SDavid Gibson static int kvm_get_vpa(CPUState *cs) 7719b00ea49SDavid Gibson { 7729b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 773ce2918cbSDavid Gibson SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 7749b00ea49SDavid Gibson struct kvm_one_reg reg; 7759b00ea49SDavid Gibson int ret; 7769b00ea49SDavid Gibson 7779b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 7787388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 7799b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7809b00ea49SDavid Gibson if (ret < 0) { 781da56ff91SPeter Maydell DPRINTF("Unable to get VPA address from KVM: %s\n", strerror(errno)); 7829b00ea49SDavid Gibson return ret; 7839b00ea49SDavid Gibson } 7849b00ea49SDavid Gibson 7857388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->slb_shadow_size 7867388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->slb_shadow_addr + 8)); 7879b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 7887388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr; 7899b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 7909b00ea49SDavid Gibson if (ret < 0) { 791da56ff91SPeter Maydell DPRINTF("Unable to get SLB shadow state from KVM: %s\n", 7929b00ea49SDavid Gibson strerror(errno)); 7939b00ea49SDavid Gibson return ret; 7949b00ea49SDavid Gibson } 7959b00ea49SDavid Gibson 7967388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->dtl_size 7977388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->dtl_addr + 8)); 7989b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 7997388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->dtl_addr; 8009b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 8019b00ea49SDavid Gibson if (ret < 0) { 802da56ff91SPeter Maydell DPRINTF("Unable to get dispatch trace log state from KVM: %s\n", 8039b00ea49SDavid Gibson strerror(errno)); 8049b00ea49SDavid Gibson return ret; 8059b00ea49SDavid Gibson } 8069b00ea49SDavid Gibson 8079b00ea49SDavid Gibson return 0; 8089b00ea49SDavid Gibson } 8099b00ea49SDavid Gibson 8109b00ea49SDavid Gibson static int kvm_put_vpa(CPUState *cs) 8119b00ea49SDavid Gibson { 8129b00ea49SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 813ce2918cbSDavid Gibson SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 8149b00ea49SDavid Gibson struct kvm_one_reg reg; 8159b00ea49SDavid Gibson int ret; 8169b00ea49SDavid Gibson 817*c995e942SDavid Gibson /* 818*c995e942SDavid Gibson * SLB shadow or DTL can't be registered unless a master VPA is 8199b00ea49SDavid Gibson * registered. That means when restoring state, if a VPA *is* 8209b00ea49SDavid Gibson * registered, we need to set that up first. If not, we need to 821*c995e942SDavid Gibson * deregister the others before deregistering the master VPA 822*c995e942SDavid Gibson */ 8237388efafSDavid Gibson assert(spapr_cpu->vpa_addr 8247388efafSDavid Gibson || !(spapr_cpu->slb_shadow_addr || spapr_cpu->dtl_addr)); 8259b00ea49SDavid Gibson 8267388efafSDavid Gibson if (spapr_cpu->vpa_addr) { 8279b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8287388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 8299b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8309b00ea49SDavid Gibson if (ret < 0) { 831da56ff91SPeter Maydell DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno)); 8329b00ea49SDavid Gibson return ret; 8339b00ea49SDavid Gibson } 8349b00ea49SDavid Gibson } 8359b00ea49SDavid Gibson 8367388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->slb_shadow_size 8377388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->slb_shadow_addr + 8)); 8389b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_SLB; 8397388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr; 8409b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8419b00ea49SDavid Gibson if (ret < 0) { 842da56ff91SPeter Maydell DPRINTF("Unable to set SLB shadow state to KVM: %s\n", strerror(errno)); 8439b00ea49SDavid Gibson return ret; 8449b00ea49SDavid Gibson } 8459b00ea49SDavid Gibson 8467388efafSDavid Gibson assert((uintptr_t)&spapr_cpu->dtl_size 8477388efafSDavid Gibson == ((uintptr_t)&spapr_cpu->dtl_addr + 8)); 8489b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_DTL; 8497388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->dtl_addr; 8509b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8519b00ea49SDavid Gibson if (ret < 0) { 852da56ff91SPeter Maydell DPRINTF("Unable to set dispatch trace log state to KVM: %s\n", 8539b00ea49SDavid Gibson strerror(errno)); 8549b00ea49SDavid Gibson return ret; 8559b00ea49SDavid Gibson } 8569b00ea49SDavid Gibson 8577388efafSDavid Gibson if (!spapr_cpu->vpa_addr) { 8589b00ea49SDavid Gibson reg.id = KVM_REG_PPC_VPA_ADDR; 8597388efafSDavid Gibson reg.addr = (uintptr_t)&spapr_cpu->vpa_addr; 8609b00ea49SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 8619b00ea49SDavid Gibson if (ret < 0) { 862da56ff91SPeter Maydell DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno)); 8639b00ea49SDavid Gibson return ret; 8649b00ea49SDavid Gibson } 8659b00ea49SDavid Gibson } 8669b00ea49SDavid Gibson 8679b00ea49SDavid Gibson return 0; 8689b00ea49SDavid Gibson } 8699b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 8709b00ea49SDavid Gibson 871e5c0d3ceSDavid Gibson int kvmppc_put_books_sregs(PowerPCCPU *cpu) 872a7a00a72SDavid Gibson { 873a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 874a7a00a72SDavid Gibson struct kvm_sregs sregs; 875a7a00a72SDavid Gibson int i; 876a7a00a72SDavid Gibson 877a7a00a72SDavid Gibson sregs.pvr = env->spr[SPR_PVR]; 878a7a00a72SDavid Gibson 8791ec26c75SGreg Kurz if (cpu->vhyp) { 8801ec26c75SGreg Kurz PPCVirtualHypervisorClass *vhc = 8811ec26c75SGreg Kurz PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 8821ec26c75SGreg Kurz sregs.u.s.sdr1 = vhc->encode_hpt_for_kvm_pr(cpu->vhyp); 8831ec26c75SGreg Kurz } else { 884a7a00a72SDavid Gibson sregs.u.s.sdr1 = env->spr[SPR_SDR1]; 8851ec26c75SGreg Kurz } 886a7a00a72SDavid Gibson 887a7a00a72SDavid Gibson /* Sync SLB */ 888a7a00a72SDavid Gibson #ifdef TARGET_PPC64 889a7a00a72SDavid Gibson for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 890a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; 891a7a00a72SDavid Gibson if (env->slb[i].esid & SLB_ESID_V) { 892a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbe |= i; 893a7a00a72SDavid Gibson } 894a7a00a72SDavid Gibson sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; 895a7a00a72SDavid Gibson } 896a7a00a72SDavid Gibson #endif 897a7a00a72SDavid Gibson 898a7a00a72SDavid Gibson /* Sync SRs */ 899a7a00a72SDavid Gibson for (i = 0; i < 16; i++) { 900a7a00a72SDavid Gibson sregs.u.s.ppc32.sr[i] = env->sr[i]; 901a7a00a72SDavid Gibson } 902a7a00a72SDavid Gibson 903a7a00a72SDavid Gibson /* Sync BATs */ 904a7a00a72SDavid Gibson for (i = 0; i < 8; i++) { 905a7a00a72SDavid Gibson /* Beware. We have to swap upper and lower bits here */ 906a7a00a72SDavid Gibson sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) 907a7a00a72SDavid Gibson | env->DBAT[1][i]; 908a7a00a72SDavid Gibson sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) 909a7a00a72SDavid Gibson | env->IBAT[1][i]; 910a7a00a72SDavid Gibson } 911a7a00a72SDavid Gibson 912a7a00a72SDavid Gibson return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); 913a7a00a72SDavid Gibson } 914a7a00a72SDavid Gibson 91520d695a9SAndreas Färber int kvm_arch_put_registers(CPUState *cs, int level) 916d76d1650Saurel32 { 91720d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 91820d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 919d76d1650Saurel32 struct kvm_regs regs; 920d76d1650Saurel32 int ret; 921d76d1650Saurel32 int i; 922d76d1650Saurel32 9231bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 9241bc22652SAndreas Färber if (ret < 0) { 925d76d1650Saurel32 return ret; 9261bc22652SAndreas Färber } 927d76d1650Saurel32 928d76d1650Saurel32 regs.ctr = env->ctr; 929d76d1650Saurel32 regs.lr = env->lr; 930da91a00fSRichard Henderson regs.xer = cpu_read_xer(env); 931d76d1650Saurel32 regs.msr = env->msr; 932d76d1650Saurel32 regs.pc = env->nip; 933d76d1650Saurel32 934d76d1650Saurel32 regs.srr0 = env->spr[SPR_SRR0]; 935d76d1650Saurel32 regs.srr1 = env->spr[SPR_SRR1]; 936d76d1650Saurel32 937d76d1650Saurel32 regs.sprg0 = env->spr[SPR_SPRG0]; 938d76d1650Saurel32 regs.sprg1 = env->spr[SPR_SPRG1]; 939d76d1650Saurel32 regs.sprg2 = env->spr[SPR_SPRG2]; 940d76d1650Saurel32 regs.sprg3 = env->spr[SPR_SPRG3]; 941d76d1650Saurel32 regs.sprg4 = env->spr[SPR_SPRG4]; 942d76d1650Saurel32 regs.sprg5 = env->spr[SPR_SPRG5]; 943d76d1650Saurel32 regs.sprg6 = env->spr[SPR_SPRG6]; 944d76d1650Saurel32 regs.sprg7 = env->spr[SPR_SPRG7]; 945d76d1650Saurel32 94690dc8812SScott Wood regs.pid = env->spr[SPR_BOOKE_PID]; 94790dc8812SScott Wood 948*c995e942SDavid Gibson for (i = 0; i < 32; i++) { 949d76d1650Saurel32 regs.gpr[i] = env->gpr[i]; 950*c995e942SDavid Gibson } 951d76d1650Saurel32 9524bddaf55SAlexey Kardashevskiy regs.cr = 0; 9534bddaf55SAlexey Kardashevskiy for (i = 0; i < 8; i++) { 9544bddaf55SAlexey Kardashevskiy regs.cr |= (env->crf[i] & 15) << (4 * (7 - i)); 9554bddaf55SAlexey Kardashevskiy } 9564bddaf55SAlexey Kardashevskiy 9571bc22652SAndreas Färber ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 958*c995e942SDavid Gibson if (ret < 0) { 959d76d1650Saurel32 return ret; 960*c995e942SDavid Gibson } 961d76d1650Saurel32 96270b79849SDavid Gibson kvm_put_fp(cs); 96370b79849SDavid Gibson 96493dd5e85SScott Wood if (env->tlb_dirty) { 9651bc22652SAndreas Färber kvm_sw_tlb_put(cpu); 96693dd5e85SScott Wood env->tlb_dirty = false; 96793dd5e85SScott Wood } 96893dd5e85SScott Wood 969f1af19d7SDavid Gibson if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) { 970a7a00a72SDavid Gibson ret = kvmppc_put_books_sregs(cpu); 971a7a00a72SDavid Gibson if (ret < 0) { 972f1af19d7SDavid Gibson return ret; 973f1af19d7SDavid Gibson } 974f1af19d7SDavid Gibson } 975f1af19d7SDavid Gibson 976f1af19d7SDavid Gibson if (cap_hior && (level >= KVM_PUT_RESET_STATE)) { 977d67d40eaSDavid Gibson kvm_put_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 978d67d40eaSDavid Gibson } 979f1af19d7SDavid Gibson 980d67d40eaSDavid Gibson if (cap_one_reg) { 981d67d40eaSDavid Gibson int i; 982d67d40eaSDavid Gibson 983*c995e942SDavid Gibson /* 984*c995e942SDavid Gibson * We deliberately ignore errors here, for kernels which have 985d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 986d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 987*c995e942SDavid Gibson * work, at least until we try to migrate. 988*c995e942SDavid Gibson */ 989d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 990d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 991d67d40eaSDavid Gibson 992d67d40eaSDavid Gibson if (id != 0) { 993d67d40eaSDavid Gibson kvm_put_one_spr(cs, id, i); 994d67d40eaSDavid Gibson } 995f1af19d7SDavid Gibson } 9969b00ea49SDavid Gibson 9979b00ea49SDavid Gibson #ifdef TARGET_PPC64 99880b3f79bSAlexey Kardashevskiy if (msr_ts) { 99980b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 100080b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 100180b3f79bSAlexey Kardashevskiy } 100280b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 100380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 100480b3f79bSAlexey Kardashevskiy } 100580b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 100680b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 100780b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 100880b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 100980b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 101080b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 101180b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 101280b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 101380b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 101480b3f79bSAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 101580b3f79bSAlexey Kardashevskiy } 101680b3f79bSAlexey Kardashevskiy 10179b00ea49SDavid Gibson if (cap_papr) { 10189b00ea49SDavid Gibson if (kvm_put_vpa(cs) < 0) { 1019da56ff91SPeter Maydell DPRINTF("Warning: Unable to set VPA information to KVM\n"); 10209b00ea49SDavid Gibson } 10219b00ea49SDavid Gibson } 102298a8b524SAlexey Kardashevskiy 102398a8b524SAlexey Kardashevskiy kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 10249b00ea49SDavid Gibson #endif /* TARGET_PPC64 */ 1025f1af19d7SDavid Gibson } 1026f1af19d7SDavid Gibson 1027d76d1650Saurel32 return ret; 1028d76d1650Saurel32 } 1029d76d1650Saurel32 1030c371c2e3SBharat Bhushan static void kvm_sync_excp(CPUPPCState *env, int vector, int ivor) 1031c371c2e3SBharat Bhushan { 1032c371c2e3SBharat Bhushan env->excp_vectors[vector] = env->spr[ivor] + env->spr[SPR_BOOKE_IVPR]; 1033c371c2e3SBharat Bhushan } 1034c371c2e3SBharat Bhushan 1035a7a00a72SDavid Gibson static int kvmppc_get_booke_sregs(PowerPCCPU *cpu) 1036d76d1650Saurel32 { 103720d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1038ba5e5090SAlexander Graf struct kvm_sregs sregs; 1039a7a00a72SDavid Gibson int ret; 1040d76d1650Saurel32 1041a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 104290dc8812SScott Wood if (ret < 0) { 104390dc8812SScott Wood return ret; 104490dc8812SScott Wood } 104590dc8812SScott Wood 104690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_BASE) { 104790dc8812SScott Wood env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0; 104890dc8812SScott Wood env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1; 104990dc8812SScott Wood env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr; 105090dc8812SScott Wood env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear; 105190dc8812SScott Wood env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr; 105290dc8812SScott Wood env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr; 105390dc8812SScott Wood env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr; 105490dc8812SScott Wood env->spr[SPR_DECR] = sregs.u.e.dec; 105590dc8812SScott Wood env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff; 105690dc8812SScott Wood env->spr[SPR_TBU] = sregs.u.e.tb >> 32; 105790dc8812SScott Wood env->spr[SPR_VRSAVE] = sregs.u.e.vrsave; 105890dc8812SScott Wood } 105990dc8812SScott Wood 106090dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206) { 106190dc8812SScott Wood env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir; 106290dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0; 106390dc8812SScott Wood env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1; 106490dc8812SScott Wood env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar; 106590dc8812SScott Wood env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr; 106690dc8812SScott Wood } 106790dc8812SScott Wood 106890dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_64) { 106990dc8812SScott Wood env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr; 107090dc8812SScott Wood } 107190dc8812SScott Wood 107290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPRG8) { 107390dc8812SScott Wood env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8; 107490dc8812SScott Wood } 107590dc8812SScott Wood 107690dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_IVOR) { 107790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0]; 1078c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_CRITICAL, SPR_BOOKE_IVOR0); 107990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1]; 1080c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_MCHECK, SPR_BOOKE_IVOR1); 108190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2]; 1082c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DSI, SPR_BOOKE_IVOR2); 108390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3]; 1084c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ISI, SPR_BOOKE_IVOR3); 108590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4]; 1086c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EXTERNAL, SPR_BOOKE_IVOR4); 108790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5]; 1088c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ALIGN, SPR_BOOKE_IVOR5); 108990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6]; 1090c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_PROGRAM, SPR_BOOKE_IVOR6); 109190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7]; 1092c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FPU, SPR_BOOKE_IVOR7); 109390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8]; 1094c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SYSCALL, SPR_BOOKE_IVOR8); 109590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9]; 1096c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_APU, SPR_BOOKE_IVOR9); 109790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10]; 1098c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DECR, SPR_BOOKE_IVOR10); 109990dc8812SScott Wood env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11]; 1100c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_FIT, SPR_BOOKE_IVOR11); 110190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12]; 1102c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_WDT, SPR_BOOKE_IVOR12); 110390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13]; 1104c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DTLB, SPR_BOOKE_IVOR13); 110590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14]; 1106c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_ITLB, SPR_BOOKE_IVOR14); 110790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15]; 1108c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DEBUG, SPR_BOOKE_IVOR15); 110990dc8812SScott Wood 111090dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_SPE) { 111190dc8812SScott Wood env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0]; 1112c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_SPEU, SPR_BOOKE_IVOR32); 111390dc8812SScott Wood env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1]; 1114c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPDI, SPR_BOOKE_IVOR33); 111590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2]; 1116c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EFPRI, SPR_BOOKE_IVOR34); 111790dc8812SScott Wood } 111890dc8812SScott Wood 111990dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PM) { 112090dc8812SScott Wood env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3]; 1121c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_EPERFM, SPR_BOOKE_IVOR35); 112290dc8812SScott Wood } 112390dc8812SScott Wood 112490dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PC) { 112590dc8812SScott Wood env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4]; 1126c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORI, SPR_BOOKE_IVOR36); 112790dc8812SScott Wood env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5]; 1128c371c2e3SBharat Bhushan kvm_sync_excp(env, POWERPC_EXCP_DOORCI, SPR_BOOKE_IVOR37); 112990dc8812SScott Wood } 113090dc8812SScott Wood } 113190dc8812SScott Wood 113290dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) { 113390dc8812SScott Wood env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0; 113490dc8812SScott Wood env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1; 113590dc8812SScott Wood env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2; 113690dc8812SScott Wood env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff; 113790dc8812SScott Wood env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4; 113890dc8812SScott Wood env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6; 113990dc8812SScott Wood env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32; 114090dc8812SScott Wood env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg; 114190dc8812SScott Wood env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0]; 114290dc8812SScott Wood env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1]; 114390dc8812SScott Wood } 114490dc8812SScott Wood 114590dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_EXP) { 114690dc8812SScott Wood env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr; 114790dc8812SScott Wood } 114890dc8812SScott Wood 114990dc8812SScott Wood if (sregs.u.e.features & KVM_SREGS_E_PD) { 115090dc8812SScott Wood env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc; 115190dc8812SScott Wood env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc; 115290dc8812SScott Wood } 115390dc8812SScott Wood 115490dc8812SScott Wood if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) { 115590dc8812SScott Wood env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr; 115690dc8812SScott Wood env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar; 115790dc8812SScott Wood env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0; 115890dc8812SScott Wood 115990dc8812SScott Wood if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) { 116090dc8812SScott Wood env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1; 116190dc8812SScott Wood env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2; 116290dc8812SScott Wood } 116390dc8812SScott Wood } 1164a7a00a72SDavid Gibson 1165a7a00a72SDavid Gibson return 0; 1166fafc0b6aSAlexander Graf } 116790dc8812SScott Wood 1168a7a00a72SDavid Gibson static int kvmppc_get_books_sregs(PowerPCCPU *cpu) 1169a7a00a72SDavid Gibson { 1170a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1171a7a00a72SDavid Gibson struct kvm_sregs sregs; 1172a7a00a72SDavid Gibson int ret; 1173a7a00a72SDavid Gibson int i; 1174a7a00a72SDavid Gibson 1175a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); 117690dc8812SScott Wood if (ret < 0) { 117790dc8812SScott Wood return ret; 117890dc8812SScott Wood } 117990dc8812SScott Wood 1180e57ca75cSDavid Gibson if (!cpu->vhyp) { 1181bb593904SDavid Gibson ppc_store_sdr1(env, sregs.u.s.sdr1); 1182f3c75d42SAneesh Kumar K.V } 1183ba5e5090SAlexander Graf 1184ba5e5090SAlexander Graf /* Sync SLB */ 118582c09f2fSAlexander Graf #ifdef TARGET_PPC64 11864b4d4a21SAneesh Kumar K.V /* 11874b4d4a21SAneesh Kumar K.V * The packed SLB array we get from KVM_GET_SREGS only contains 1188a7a00a72SDavid Gibson * information about valid entries. So we flush our internal copy 1189a7a00a72SDavid Gibson * to get rid of stale ones, then put all valid SLB entries back 1190a7a00a72SDavid Gibson * in. 11914b4d4a21SAneesh Kumar K.V */ 11924b4d4a21SAneesh Kumar K.V memset(env->slb, 0, sizeof(env->slb)); 1193d83af167SAneesh Kumar K.V for (i = 0; i < ARRAY_SIZE(env->slb); i++) { 11944b4d4a21SAneesh Kumar K.V target_ulong rb = sregs.u.s.ppc64.slb[i].slbe; 11954b4d4a21SAneesh Kumar K.V target_ulong rs = sregs.u.s.ppc64.slb[i].slbv; 11964b4d4a21SAneesh Kumar K.V /* 11974b4d4a21SAneesh Kumar K.V * Only restore valid entries 11984b4d4a21SAneesh Kumar K.V */ 11994b4d4a21SAneesh Kumar K.V if (rb & SLB_ESID_V) { 1200bcd81230SDavid Gibson ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs); 12014b4d4a21SAneesh Kumar K.V } 1202ba5e5090SAlexander Graf } 120382c09f2fSAlexander Graf #endif 1204ba5e5090SAlexander Graf 1205ba5e5090SAlexander Graf /* Sync SRs */ 1206ba5e5090SAlexander Graf for (i = 0; i < 16; i++) { 1207ba5e5090SAlexander Graf env->sr[i] = sregs.u.s.ppc32.sr[i]; 1208ba5e5090SAlexander Graf } 1209ba5e5090SAlexander Graf 1210ba5e5090SAlexander Graf /* Sync BATs */ 1211ba5e5090SAlexander Graf for (i = 0; i < 8; i++) { 1212ba5e5090SAlexander Graf env->DBAT[0][i] = sregs.u.s.ppc32.dbat[i] & 0xffffffff; 1213ba5e5090SAlexander Graf env->DBAT[1][i] = sregs.u.s.ppc32.dbat[i] >> 32; 1214ba5e5090SAlexander Graf env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff; 1215ba5e5090SAlexander Graf env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32; 1216ba5e5090SAlexander Graf } 1217a7a00a72SDavid Gibson 1218a7a00a72SDavid Gibson return 0; 1219a7a00a72SDavid Gibson } 1220a7a00a72SDavid Gibson 1221a7a00a72SDavid Gibson int kvm_arch_get_registers(CPUState *cs) 1222a7a00a72SDavid Gibson { 1223a7a00a72SDavid Gibson PowerPCCPU *cpu = POWERPC_CPU(cs); 1224a7a00a72SDavid Gibson CPUPPCState *env = &cpu->env; 1225a7a00a72SDavid Gibson struct kvm_regs regs; 1226a7a00a72SDavid Gibson uint32_t cr; 1227a7a00a72SDavid Gibson int i, ret; 1228a7a00a72SDavid Gibson 1229a7a00a72SDavid Gibson ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1230*c995e942SDavid Gibson if (ret < 0) { 1231a7a00a72SDavid Gibson return ret; 1232*c995e942SDavid Gibson } 1233a7a00a72SDavid Gibson 1234a7a00a72SDavid Gibson cr = regs.cr; 1235a7a00a72SDavid Gibson for (i = 7; i >= 0; i--) { 1236a7a00a72SDavid Gibson env->crf[i] = cr & 15; 1237a7a00a72SDavid Gibson cr >>= 4; 1238a7a00a72SDavid Gibson } 1239a7a00a72SDavid Gibson 1240a7a00a72SDavid Gibson env->ctr = regs.ctr; 1241a7a00a72SDavid Gibson env->lr = regs.lr; 1242a7a00a72SDavid Gibson cpu_write_xer(env, regs.xer); 1243a7a00a72SDavid Gibson env->msr = regs.msr; 1244a7a00a72SDavid Gibson env->nip = regs.pc; 1245a7a00a72SDavid Gibson 1246a7a00a72SDavid Gibson env->spr[SPR_SRR0] = regs.srr0; 1247a7a00a72SDavid Gibson env->spr[SPR_SRR1] = regs.srr1; 1248a7a00a72SDavid Gibson 1249a7a00a72SDavid Gibson env->spr[SPR_SPRG0] = regs.sprg0; 1250a7a00a72SDavid Gibson env->spr[SPR_SPRG1] = regs.sprg1; 1251a7a00a72SDavid Gibson env->spr[SPR_SPRG2] = regs.sprg2; 1252a7a00a72SDavid Gibson env->spr[SPR_SPRG3] = regs.sprg3; 1253a7a00a72SDavid Gibson env->spr[SPR_SPRG4] = regs.sprg4; 1254a7a00a72SDavid Gibson env->spr[SPR_SPRG5] = regs.sprg5; 1255a7a00a72SDavid Gibson env->spr[SPR_SPRG6] = regs.sprg6; 1256a7a00a72SDavid Gibson env->spr[SPR_SPRG7] = regs.sprg7; 1257a7a00a72SDavid Gibson 1258a7a00a72SDavid Gibson env->spr[SPR_BOOKE_PID] = regs.pid; 1259a7a00a72SDavid Gibson 1260*c995e942SDavid Gibson for (i = 0; i < 32; i++) { 1261a7a00a72SDavid Gibson env->gpr[i] = regs.gpr[i]; 1262*c995e942SDavid Gibson } 1263a7a00a72SDavid Gibson 1264a7a00a72SDavid Gibson kvm_get_fp(cs); 1265a7a00a72SDavid Gibson 1266a7a00a72SDavid Gibson if (cap_booke_sregs) { 1267a7a00a72SDavid Gibson ret = kvmppc_get_booke_sregs(cpu); 1268a7a00a72SDavid Gibson if (ret < 0) { 1269a7a00a72SDavid Gibson return ret; 1270a7a00a72SDavid Gibson } 1271a7a00a72SDavid Gibson } 1272a7a00a72SDavid Gibson 1273a7a00a72SDavid Gibson if (cap_segstate) { 1274a7a00a72SDavid Gibson ret = kvmppc_get_books_sregs(cpu); 1275a7a00a72SDavid Gibson if (ret < 0) { 1276a7a00a72SDavid Gibson return ret; 1277a7a00a72SDavid Gibson } 1278fafc0b6aSAlexander Graf } 1279ba5e5090SAlexander Graf 1280d67d40eaSDavid Gibson if (cap_hior) { 1281d67d40eaSDavid Gibson kvm_get_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); 1282d67d40eaSDavid Gibson } 1283d67d40eaSDavid Gibson 1284d67d40eaSDavid Gibson if (cap_one_reg) { 1285d67d40eaSDavid Gibson int i; 1286d67d40eaSDavid Gibson 1287*c995e942SDavid Gibson /* 1288*c995e942SDavid Gibson * We deliberately ignore errors here, for kernels which have 1289d67d40eaSDavid Gibson * the ONE_REG calls, but don't support the specific 1290d67d40eaSDavid Gibson * registers, there's a reasonable chance things will still 1291*c995e942SDavid Gibson * work, at least until we try to migrate. 1292*c995e942SDavid Gibson */ 1293d67d40eaSDavid Gibson for (i = 0; i < 1024; i++) { 1294d67d40eaSDavid Gibson uint64_t id = env->spr_cb[i].one_reg_id; 1295d67d40eaSDavid Gibson 1296d67d40eaSDavid Gibson if (id != 0) { 1297d67d40eaSDavid Gibson kvm_get_one_spr(cs, id, i); 1298d67d40eaSDavid Gibson } 1299d67d40eaSDavid Gibson } 13009b00ea49SDavid Gibson 13019b00ea49SDavid Gibson #ifdef TARGET_PPC64 130280b3f79bSAlexey Kardashevskiy if (msr_ts) { 130380b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) { 130480b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); 130580b3f79bSAlexey Kardashevskiy } 130680b3f79bSAlexey Kardashevskiy for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) { 130780b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); 130880b3f79bSAlexey Kardashevskiy } 130980b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); 131080b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); 131180b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); 131280b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); 131380b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); 131480b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); 131580b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); 131680b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); 131780b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); 131880b3f79bSAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); 131980b3f79bSAlexey Kardashevskiy } 132080b3f79bSAlexey Kardashevskiy 13219b00ea49SDavid Gibson if (cap_papr) { 13229b00ea49SDavid Gibson if (kvm_get_vpa(cs) < 0) { 1323da56ff91SPeter Maydell DPRINTF("Warning: Unable to get VPA information from KVM\n"); 13249b00ea49SDavid Gibson } 13259b00ea49SDavid Gibson } 132698a8b524SAlexey Kardashevskiy 132798a8b524SAlexey Kardashevskiy kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); 13289b00ea49SDavid Gibson #endif 1329d67d40eaSDavid Gibson } 1330d67d40eaSDavid Gibson 1331d76d1650Saurel32 return 0; 1332d76d1650Saurel32 } 1333d76d1650Saurel32 13341bc22652SAndreas Färber int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level) 1335fc87e185SAlexander Graf { 1336fc87e185SAlexander Graf unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET; 1337fc87e185SAlexander Graf 1338fc87e185SAlexander Graf if (irq != PPC_INTERRUPT_EXT) { 1339fc87e185SAlexander Graf return 0; 1340fc87e185SAlexander Graf } 1341fc87e185SAlexander Graf 1342fc87e185SAlexander Graf if (!kvm_enabled() || !cap_interrupt_unset || !cap_interrupt_level) { 1343fc87e185SAlexander Graf return 0; 1344fc87e185SAlexander Graf } 1345fc87e185SAlexander Graf 13461bc22652SAndreas Färber kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); 1347fc87e185SAlexander Graf 1348fc87e185SAlexander Graf return 0; 1349fc87e185SAlexander Graf } 1350fc87e185SAlexander Graf 1351a69dc537SThomas Huth #if defined(TARGET_PPC64) 135216415335SAlexander Graf #define PPC_INPUT_INT PPC970_INPUT_INT 135316415335SAlexander Graf #else 135416415335SAlexander Graf #define PPC_INPUT_INT PPC6xx_INPUT_INT 135516415335SAlexander Graf #endif 135616415335SAlexander Graf 135720d695a9SAndreas Färber void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 1358d76d1650Saurel32 { 135920d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 136020d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1361d76d1650Saurel32 int r; 1362d76d1650Saurel32 unsigned irq; 1363d76d1650Saurel32 13644b8523eeSJan Kiszka qemu_mutex_lock_iothread(); 13654b8523eeSJan Kiszka 1366*c995e942SDavid Gibson /* 1367*c995e942SDavid Gibson * PowerPC QEMU tracks the various core input pins (interrupt, 1368*c995e942SDavid Gibson * critical interrupt, reset, etc) in PPC-specific 1369*c995e942SDavid Gibson * env->irq_input_state. 1370*c995e942SDavid Gibson */ 1371fc87e185SAlexander Graf if (!cap_interrupt_level && 1372fc87e185SAlexander Graf run->ready_for_interrupt_injection && 1373259186a7SAndreas Färber (cs->interrupt_request & CPU_INTERRUPT_HARD) && 137416415335SAlexander Graf (env->irq_input_state & (1 << PPC_INPUT_INT))) 1375d76d1650Saurel32 { 1376*c995e942SDavid Gibson /* 1377*c995e942SDavid Gibson * For now KVM disregards the 'irq' argument. However, in the 1378*c995e942SDavid Gibson * future KVM could cache it in-kernel to avoid a heavyweight 1379*c995e942SDavid Gibson * exit when reading the UIC. 1380d76d1650Saurel32 */ 1381fc87e185SAlexander Graf irq = KVM_INTERRUPT_SET; 1382d76d1650Saurel32 1383da56ff91SPeter Maydell DPRINTF("injected interrupt %d\n", irq); 13841bc22652SAndreas Färber r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq); 138555e5c285SAndreas Färber if (r < 0) { 138655e5c285SAndreas Färber printf("cpu %d fail inject %x\n", cs->cpu_index, irq); 138755e5c285SAndreas Färber } 1388c821c2bdSAlexander Graf 1389c821c2bdSAlexander Graf /* Always wake up soon in case the interrupt was level based */ 1390bc72ad67SAlex Bligh timer_mod(idle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 139173bcb24dSRutuja Shah (NANOSECONDS_PER_SECOND / 50)); 1392d76d1650Saurel32 } 1393d76d1650Saurel32 1394*c995e942SDavid Gibson /* 1395*c995e942SDavid Gibson * We don't know if there are more interrupts pending after 1396*c995e942SDavid Gibson * this. However, the guest will return to userspace in the course 1397*c995e942SDavid Gibson * of handling this one anyways, so we will get a chance to 1398*c995e942SDavid Gibson * deliver the rest. 1399*c995e942SDavid Gibson */ 14004b8523eeSJan Kiszka 14014b8523eeSJan Kiszka qemu_mutex_unlock_iothread(); 1402d76d1650Saurel32 } 1403d76d1650Saurel32 14044c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 1405d76d1650Saurel32 { 14064c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 1407d76d1650Saurel32 } 1408d76d1650Saurel32 140920d695a9SAndreas Färber int kvm_arch_process_async_events(CPUState *cs) 14100af691d7SMarcelo Tosatti { 1411259186a7SAndreas Färber return cs->halted; 14120af691d7SMarcelo Tosatti } 14130af691d7SMarcelo Tosatti 1414259186a7SAndreas Färber static int kvmppc_handle_halt(PowerPCCPU *cpu) 1415d76d1650Saurel32 { 1416259186a7SAndreas Färber CPUState *cs = CPU(cpu); 1417259186a7SAndreas Färber CPUPPCState *env = &cpu->env; 1418259186a7SAndreas Färber 1419259186a7SAndreas Färber if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) { 1420259186a7SAndreas Färber cs->halted = 1; 142127103424SAndreas Färber cs->exception_index = EXCP_HLT; 1422d76d1650Saurel32 } 1423d76d1650Saurel32 1424bb4ea393SJan Kiszka return 0; 1425d76d1650Saurel32 } 1426d76d1650Saurel32 1427d76d1650Saurel32 /* map dcr access to existing qemu dcr emulation */ 1428*c995e942SDavid Gibson static int kvmppc_handle_dcr_read(CPUPPCState *env, 1429*c995e942SDavid Gibson uint32_t dcrn, uint32_t *data) 1430d76d1650Saurel32 { 1431*c995e942SDavid Gibson if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) { 1432d76d1650Saurel32 fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn); 1433*c995e942SDavid Gibson } 1434d76d1650Saurel32 1435bb4ea393SJan Kiszka return 0; 1436d76d1650Saurel32 } 1437d76d1650Saurel32 1438*c995e942SDavid Gibson static int kvmppc_handle_dcr_write(CPUPPCState *env, 1439*c995e942SDavid Gibson uint32_t dcrn, uint32_t data) 1440d76d1650Saurel32 { 1441*c995e942SDavid Gibson if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) { 1442d76d1650Saurel32 fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn); 1443*c995e942SDavid Gibson } 1444d76d1650Saurel32 1445bb4ea393SJan Kiszka return 0; 1446d76d1650Saurel32 } 1447d76d1650Saurel32 14488a0548f9SBharat Bhushan int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 14498a0548f9SBharat Bhushan { 14508a0548f9SBharat Bhushan /* Mixed endian case is not handled */ 14518a0548f9SBharat Bhushan uint32_t sc = debug_inst_opcode; 14528a0548f9SBharat Bhushan 14538a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 14548a0548f9SBharat Bhushan sizeof(sc), 0) || 14558a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 1)) { 14568a0548f9SBharat Bhushan return -EINVAL; 14578a0548f9SBharat Bhushan } 14588a0548f9SBharat Bhushan 14598a0548f9SBharat Bhushan return 0; 14608a0548f9SBharat Bhushan } 14618a0548f9SBharat Bhushan 14628a0548f9SBharat Bhushan int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 14638a0548f9SBharat Bhushan { 14648a0548f9SBharat Bhushan uint32_t sc; 14658a0548f9SBharat Bhushan 14668a0548f9SBharat Bhushan if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&sc, sizeof(sc), 0) || 14678a0548f9SBharat Bhushan sc != debug_inst_opcode || 14688a0548f9SBharat Bhushan cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 14698a0548f9SBharat Bhushan sizeof(sc), 1)) { 14708a0548f9SBharat Bhushan return -EINVAL; 14718a0548f9SBharat Bhushan } 14728a0548f9SBharat Bhushan 14738a0548f9SBharat Bhushan return 0; 14748a0548f9SBharat Bhushan } 14758a0548f9SBharat Bhushan 147688365d17SBharat Bhushan static int find_hw_breakpoint(target_ulong addr, int type) 147788365d17SBharat Bhushan { 147888365d17SBharat Bhushan int n; 147988365d17SBharat Bhushan 148088365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 148188365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 148288365d17SBharat Bhushan 148388365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 148488365d17SBharat Bhushan if (hw_debug_points[n].addr == addr && 148588365d17SBharat Bhushan hw_debug_points[n].type == type) { 148688365d17SBharat Bhushan return n; 148788365d17SBharat Bhushan } 148888365d17SBharat Bhushan } 148988365d17SBharat Bhushan 149088365d17SBharat Bhushan return -1; 149188365d17SBharat Bhushan } 149288365d17SBharat Bhushan 149388365d17SBharat Bhushan static int find_hw_watchpoint(target_ulong addr, int *flag) 149488365d17SBharat Bhushan { 149588365d17SBharat Bhushan int n; 149688365d17SBharat Bhushan 149788365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_ACCESS); 149888365d17SBharat Bhushan if (n >= 0) { 149988365d17SBharat Bhushan *flag = BP_MEM_ACCESS; 150088365d17SBharat Bhushan return n; 150188365d17SBharat Bhushan } 150288365d17SBharat Bhushan 150388365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_WRITE); 150488365d17SBharat Bhushan if (n >= 0) { 150588365d17SBharat Bhushan *flag = BP_MEM_WRITE; 150688365d17SBharat Bhushan return n; 150788365d17SBharat Bhushan } 150888365d17SBharat Bhushan 150988365d17SBharat Bhushan n = find_hw_breakpoint(addr, GDB_WATCHPOINT_READ); 151088365d17SBharat Bhushan if (n >= 0) { 151188365d17SBharat Bhushan *flag = BP_MEM_READ; 151288365d17SBharat Bhushan return n; 151388365d17SBharat Bhushan } 151488365d17SBharat Bhushan 151588365d17SBharat Bhushan return -1; 151688365d17SBharat Bhushan } 151788365d17SBharat Bhushan 151888365d17SBharat Bhushan int kvm_arch_insert_hw_breakpoint(target_ulong addr, 151988365d17SBharat Bhushan target_ulong len, int type) 152088365d17SBharat Bhushan { 152188365d17SBharat Bhushan if ((nb_hw_breakpoint + nb_hw_watchpoint) >= ARRAY_SIZE(hw_debug_points)) { 152288365d17SBharat Bhushan return -ENOBUFS; 152388365d17SBharat Bhushan } 152488365d17SBharat Bhushan 152588365d17SBharat Bhushan hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].addr = addr; 152688365d17SBharat Bhushan hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].type = type; 152788365d17SBharat Bhushan 152888365d17SBharat Bhushan switch (type) { 152988365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 153088365d17SBharat Bhushan if (nb_hw_breakpoint >= max_hw_breakpoint) { 153188365d17SBharat Bhushan return -ENOBUFS; 153288365d17SBharat Bhushan } 153388365d17SBharat Bhushan 153488365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 153588365d17SBharat Bhushan return -EEXIST; 153688365d17SBharat Bhushan } 153788365d17SBharat Bhushan 153888365d17SBharat Bhushan nb_hw_breakpoint++; 153988365d17SBharat Bhushan break; 154088365d17SBharat Bhushan 154188365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 154288365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 154388365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 154488365d17SBharat Bhushan if (nb_hw_watchpoint >= max_hw_watchpoint) { 154588365d17SBharat Bhushan return -ENOBUFS; 154688365d17SBharat Bhushan } 154788365d17SBharat Bhushan 154888365d17SBharat Bhushan if (find_hw_breakpoint(addr, type) >= 0) { 154988365d17SBharat Bhushan return -EEXIST; 155088365d17SBharat Bhushan } 155188365d17SBharat Bhushan 155288365d17SBharat Bhushan nb_hw_watchpoint++; 155388365d17SBharat Bhushan break; 155488365d17SBharat Bhushan 155588365d17SBharat Bhushan default: 155688365d17SBharat Bhushan return -ENOSYS; 155788365d17SBharat Bhushan } 155888365d17SBharat Bhushan 155988365d17SBharat Bhushan return 0; 156088365d17SBharat Bhushan } 156188365d17SBharat Bhushan 156288365d17SBharat Bhushan int kvm_arch_remove_hw_breakpoint(target_ulong addr, 156388365d17SBharat Bhushan target_ulong len, int type) 156488365d17SBharat Bhushan { 156588365d17SBharat Bhushan int n; 156688365d17SBharat Bhushan 156788365d17SBharat Bhushan n = find_hw_breakpoint(addr, type); 156888365d17SBharat Bhushan if (n < 0) { 156988365d17SBharat Bhushan return -ENOENT; 157088365d17SBharat Bhushan } 157188365d17SBharat Bhushan 157288365d17SBharat Bhushan switch (type) { 157388365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 157488365d17SBharat Bhushan nb_hw_breakpoint--; 157588365d17SBharat Bhushan break; 157688365d17SBharat Bhushan 157788365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 157888365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 157988365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 158088365d17SBharat Bhushan nb_hw_watchpoint--; 158188365d17SBharat Bhushan break; 158288365d17SBharat Bhushan 158388365d17SBharat Bhushan default: 158488365d17SBharat Bhushan return -ENOSYS; 158588365d17SBharat Bhushan } 158688365d17SBharat Bhushan hw_debug_points[n] = hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint]; 158788365d17SBharat Bhushan 158888365d17SBharat Bhushan return 0; 158988365d17SBharat Bhushan } 159088365d17SBharat Bhushan 159188365d17SBharat Bhushan void kvm_arch_remove_all_hw_breakpoints(void) 159288365d17SBharat Bhushan { 159388365d17SBharat Bhushan nb_hw_breakpoint = nb_hw_watchpoint = 0; 159488365d17SBharat Bhushan } 159588365d17SBharat Bhushan 15968a0548f9SBharat Bhushan void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 15978a0548f9SBharat Bhushan { 159888365d17SBharat Bhushan int n; 159988365d17SBharat Bhushan 16008a0548f9SBharat Bhushan /* Software Breakpoint updates */ 16018a0548f9SBharat Bhushan if (kvm_sw_breakpoints_active(cs)) { 16028a0548f9SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 16038a0548f9SBharat Bhushan } 160488365d17SBharat Bhushan 160588365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) 160688365d17SBharat Bhushan <= ARRAY_SIZE(hw_debug_points)); 160788365d17SBharat Bhushan assert((nb_hw_breakpoint + nb_hw_watchpoint) <= ARRAY_SIZE(dbg->arch.bp)); 160888365d17SBharat Bhushan 160988365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 161088365d17SBharat Bhushan dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; 161188365d17SBharat Bhushan memset(dbg->arch.bp, 0, sizeof(dbg->arch.bp)); 161288365d17SBharat Bhushan for (n = 0; n < nb_hw_breakpoint + nb_hw_watchpoint; n++) { 161388365d17SBharat Bhushan switch (hw_debug_points[n].type) { 161488365d17SBharat Bhushan case GDB_BREAKPOINT_HW: 161588365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_BREAKPOINT; 161688365d17SBharat Bhushan break; 161788365d17SBharat Bhushan case GDB_WATCHPOINT_WRITE: 161888365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE; 161988365d17SBharat Bhushan break; 162088365d17SBharat Bhushan case GDB_WATCHPOINT_READ: 162188365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_READ; 162288365d17SBharat Bhushan break; 162388365d17SBharat Bhushan case GDB_WATCHPOINT_ACCESS: 162488365d17SBharat Bhushan dbg->arch.bp[n].type = KVMPPC_DEBUG_WATCH_WRITE | 162588365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_READ; 162688365d17SBharat Bhushan break; 162788365d17SBharat Bhushan default: 162888365d17SBharat Bhushan cpu_abort(cs, "Unsupported breakpoint type\n"); 162988365d17SBharat Bhushan } 163088365d17SBharat Bhushan dbg->arch.bp[n].addr = hw_debug_points[n].addr; 163188365d17SBharat Bhushan } 163288365d17SBharat Bhushan } 16338a0548f9SBharat Bhushan } 16348a0548f9SBharat Bhushan 16352cbd1581SFabiano Rosas static int kvm_handle_hw_breakpoint(CPUState *cs, 16362cbd1581SFabiano Rosas struct kvm_debug_exit_arch *arch_info) 16378a0548f9SBharat Bhushan { 16388a0548f9SBharat Bhushan int handle = 0; 163988365d17SBharat Bhushan int n; 164088365d17SBharat Bhushan int flag = 0; 16418a0548f9SBharat Bhushan 164288365d17SBharat Bhushan if (nb_hw_breakpoint + nb_hw_watchpoint > 0) { 164388365d17SBharat Bhushan if (arch_info->status & KVMPPC_DEBUG_BREAKPOINT) { 164488365d17SBharat Bhushan n = find_hw_breakpoint(arch_info->address, GDB_BREAKPOINT_HW); 164588365d17SBharat Bhushan if (n >= 0) { 164688365d17SBharat Bhushan handle = 1; 164788365d17SBharat Bhushan } 164888365d17SBharat Bhushan } else if (arch_info->status & (KVMPPC_DEBUG_WATCH_READ | 164988365d17SBharat Bhushan KVMPPC_DEBUG_WATCH_WRITE)) { 165088365d17SBharat Bhushan n = find_hw_watchpoint(arch_info->address, &flag); 165188365d17SBharat Bhushan if (n >= 0) { 165288365d17SBharat Bhushan handle = 1; 165388365d17SBharat Bhushan cs->watchpoint_hit = &hw_watchpoint; 165488365d17SBharat Bhushan hw_watchpoint.vaddr = hw_debug_points[n].addr; 165588365d17SBharat Bhushan hw_watchpoint.flags = flag; 165688365d17SBharat Bhushan } 165788365d17SBharat Bhushan } 165888365d17SBharat Bhushan } 16592cbd1581SFabiano Rosas return handle; 16602cbd1581SFabiano Rosas } 16612cbd1581SFabiano Rosas 1662468e3a1aSFabiano Rosas static int kvm_handle_singlestep(void) 1663468e3a1aSFabiano Rosas { 1664468e3a1aSFabiano Rosas return 1; 1665468e3a1aSFabiano Rosas } 1666468e3a1aSFabiano Rosas 1667468e3a1aSFabiano Rosas static int kvm_handle_sw_breakpoint(void) 1668468e3a1aSFabiano Rosas { 1669468e3a1aSFabiano Rosas return 1; 1670468e3a1aSFabiano Rosas } 1671468e3a1aSFabiano Rosas 16722cbd1581SFabiano Rosas static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) 16732cbd1581SFabiano Rosas { 16742cbd1581SFabiano Rosas CPUState *cs = CPU(cpu); 16752cbd1581SFabiano Rosas CPUPPCState *env = &cpu->env; 16762cbd1581SFabiano Rosas struct kvm_debug_exit_arch *arch_info = &run->debug.arch; 16772cbd1581SFabiano Rosas 16782cbd1581SFabiano Rosas if (cs->singlestep_enabled) { 1679468e3a1aSFabiano Rosas return kvm_handle_singlestep(); 1680468e3a1aSFabiano Rosas } 1681468e3a1aSFabiano Rosas 1682468e3a1aSFabiano Rosas if (arch_info->status) { 1683468e3a1aSFabiano Rosas return kvm_handle_hw_breakpoint(cs, arch_info); 1684468e3a1aSFabiano Rosas } 1685468e3a1aSFabiano Rosas 1686468e3a1aSFabiano Rosas if (kvm_find_sw_breakpoint(cs, arch_info->address)) { 1687468e3a1aSFabiano Rosas return kvm_handle_sw_breakpoint(); 1688468e3a1aSFabiano Rosas } 1689468e3a1aSFabiano Rosas 1690468e3a1aSFabiano Rosas /* 1691468e3a1aSFabiano Rosas * QEMU is not able to handle debug exception, so inject 16928a0548f9SBharat Bhushan * program exception to guest; 16938a0548f9SBharat Bhushan * Yes program exception NOT debug exception !! 169488365d17SBharat Bhushan * When QEMU is using debug resources then debug exception must 169588365d17SBharat Bhushan * be always set. To achieve this we set MSR_DE and also set 169688365d17SBharat Bhushan * MSRP_DEP so guest cannot change MSR_DE. 169788365d17SBharat Bhushan * When emulating debug resource for guest we want guest 169888365d17SBharat Bhushan * to control MSR_DE (enable/disable debug interrupt on need). 169988365d17SBharat Bhushan * Supporting both configurations are NOT possible. 170088365d17SBharat Bhushan * So the result is that we cannot share debug resources 170188365d17SBharat Bhushan * between QEMU and Guest on BOOKE architecture. 170288365d17SBharat Bhushan * In the current design QEMU gets the priority over guest, 170388365d17SBharat Bhushan * this means that if QEMU is using debug resources then guest 170488365d17SBharat Bhushan * cannot use them; 17058a0548f9SBharat Bhushan * For software breakpoint QEMU uses a privileged instruction; 17068a0548f9SBharat Bhushan * So there cannot be any reason that we are here for guest 17078a0548f9SBharat Bhushan * set debug exception, only possibility is guest executed a 17088a0548f9SBharat Bhushan * privileged / illegal instruction and that's why we are 17098a0548f9SBharat Bhushan * injecting a program interrupt. 17108a0548f9SBharat Bhushan */ 17118a0548f9SBharat Bhushan cpu_synchronize_state(cs); 1712468e3a1aSFabiano Rosas /* 1713468e3a1aSFabiano Rosas * env->nip is PC, so increment this by 4 to use 17148a0548f9SBharat Bhushan * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4. 17158a0548f9SBharat Bhushan */ 17168a0548f9SBharat Bhushan env->nip += 4; 17178a0548f9SBharat Bhushan cs->exception_index = POWERPC_EXCP_PROGRAM; 17188a0548f9SBharat Bhushan env->error_code = POWERPC_EXCP_INVAL; 17198a0548f9SBharat Bhushan ppc_cpu_do_interrupt(cs); 17208a0548f9SBharat Bhushan 1721468e3a1aSFabiano Rosas return 0; 17228a0548f9SBharat Bhushan } 17238a0548f9SBharat Bhushan 172420d695a9SAndreas Färber int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 1725d76d1650Saurel32 { 172620d695a9SAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 172720d695a9SAndreas Färber CPUPPCState *env = &cpu->env; 1728bb4ea393SJan Kiszka int ret; 1729d76d1650Saurel32 17304b8523eeSJan Kiszka qemu_mutex_lock_iothread(); 17314b8523eeSJan Kiszka 1732d76d1650Saurel32 switch (run->exit_reason) { 1733d76d1650Saurel32 case KVM_EXIT_DCR: 1734d76d1650Saurel32 if (run->dcr.is_write) { 1735da56ff91SPeter Maydell DPRINTF("handle dcr write\n"); 1736d76d1650Saurel32 ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); 1737d76d1650Saurel32 } else { 1738da56ff91SPeter Maydell DPRINTF("handle dcr read\n"); 1739d76d1650Saurel32 ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); 1740d76d1650Saurel32 } 1741d76d1650Saurel32 break; 1742d76d1650Saurel32 case KVM_EXIT_HLT: 1743da56ff91SPeter Maydell DPRINTF("handle halt\n"); 1744259186a7SAndreas Färber ret = kvmppc_handle_halt(cpu); 1745d76d1650Saurel32 break; 1746c6304a4aSDavid Gibson #if defined(TARGET_PPC64) 1747f61b4bedSAlexander Graf case KVM_EXIT_PAPR_HCALL: 1748da56ff91SPeter Maydell DPRINTF("handle PAPR hypercall\n"); 174920d695a9SAndreas Färber run->papr_hcall.ret = spapr_hypercall(cpu, 1750aa100fa4SAndreas Färber run->papr_hcall.nr, 1751f61b4bedSAlexander Graf run->papr_hcall.args); 175278e8fde2SDavid Gibson ret = 0; 1753f61b4bedSAlexander Graf break; 1754f61b4bedSAlexander Graf #endif 17555b95b8b9SAlexander Graf case KVM_EXIT_EPR: 1756da56ff91SPeter Maydell DPRINTF("handle epr\n"); 1757933b19eaSAlexander Graf run->epr.epr = ldl_phys(cs->as, env->mpic_iack); 17585b95b8b9SAlexander Graf ret = 0; 17595b95b8b9SAlexander Graf break; 176031f2cb8fSBharat Bhushan case KVM_EXIT_WATCHDOG: 1761da56ff91SPeter Maydell DPRINTF("handle watchdog expiry\n"); 176231f2cb8fSBharat Bhushan watchdog_perform_action(); 176331f2cb8fSBharat Bhushan ret = 0; 176431f2cb8fSBharat Bhushan break; 176531f2cb8fSBharat Bhushan 17668a0548f9SBharat Bhushan case KVM_EXIT_DEBUG: 17678a0548f9SBharat Bhushan DPRINTF("handle debug exception\n"); 17688a0548f9SBharat Bhushan if (kvm_handle_debug(cpu, run)) { 17698a0548f9SBharat Bhushan ret = EXCP_DEBUG; 17708a0548f9SBharat Bhushan break; 17718a0548f9SBharat Bhushan } 17728a0548f9SBharat Bhushan /* re-enter, this exception was guest-internal */ 17738a0548f9SBharat Bhushan ret = 0; 17748a0548f9SBharat Bhushan break; 17758a0548f9SBharat Bhushan 177673aaec4aSJan Kiszka default: 177773aaec4aSJan Kiszka fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); 177873aaec4aSJan Kiszka ret = -1; 177973aaec4aSJan Kiszka break; 1780d76d1650Saurel32 } 1781d76d1650Saurel32 17824b8523eeSJan Kiszka qemu_mutex_unlock_iothread(); 1783d76d1650Saurel32 return ret; 1784d76d1650Saurel32 } 1785d76d1650Saurel32 178631f2cb8fSBharat Bhushan int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 178731f2cb8fSBharat Bhushan { 178831f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 178931f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 179031f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 179131f2cb8fSBharat Bhushan .id = KVM_REG_PPC_OR_TSR, 179231f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 179331f2cb8fSBharat Bhushan }; 179431f2cb8fSBharat Bhushan 179531f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 179631f2cb8fSBharat Bhushan } 179731f2cb8fSBharat Bhushan 179831f2cb8fSBharat Bhushan int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits) 179931f2cb8fSBharat Bhushan { 180031f2cb8fSBharat Bhushan 180131f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 180231f2cb8fSBharat Bhushan uint32_t bits = tsr_bits; 180331f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 180431f2cb8fSBharat Bhushan .id = KVM_REG_PPC_CLEAR_TSR, 180531f2cb8fSBharat Bhushan .addr = (uintptr_t) &bits, 180631f2cb8fSBharat Bhushan }; 180731f2cb8fSBharat Bhushan 180831f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 180931f2cb8fSBharat Bhushan } 181031f2cb8fSBharat Bhushan 181131f2cb8fSBharat Bhushan int kvmppc_set_tcr(PowerPCCPU *cpu) 181231f2cb8fSBharat Bhushan { 181331f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 181431f2cb8fSBharat Bhushan CPUPPCState *env = &cpu->env; 181531f2cb8fSBharat Bhushan uint32_t tcr = env->spr[SPR_BOOKE_TCR]; 181631f2cb8fSBharat Bhushan 181731f2cb8fSBharat Bhushan struct kvm_one_reg reg = { 181831f2cb8fSBharat Bhushan .id = KVM_REG_PPC_TCR, 181931f2cb8fSBharat Bhushan .addr = (uintptr_t) &tcr, 182031f2cb8fSBharat Bhushan }; 182131f2cb8fSBharat Bhushan 182231f2cb8fSBharat Bhushan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 182331f2cb8fSBharat Bhushan } 182431f2cb8fSBharat Bhushan 182531f2cb8fSBharat Bhushan int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu) 182631f2cb8fSBharat Bhushan { 182731f2cb8fSBharat Bhushan CPUState *cs = CPU(cpu); 182831f2cb8fSBharat Bhushan int ret; 182931f2cb8fSBharat Bhushan 183031f2cb8fSBharat Bhushan if (!kvm_enabled()) { 183131f2cb8fSBharat Bhushan return -1; 183231f2cb8fSBharat Bhushan } 183331f2cb8fSBharat Bhushan 183431f2cb8fSBharat Bhushan if (!cap_ppc_watchdog) { 183531f2cb8fSBharat Bhushan printf("warning: KVM does not support watchdog"); 183631f2cb8fSBharat Bhushan return -1; 183731f2cb8fSBharat Bhushan } 183831f2cb8fSBharat Bhushan 183948add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_BOOKE_WATCHDOG, 0); 184031f2cb8fSBharat Bhushan if (ret < 0) { 184131f2cb8fSBharat Bhushan fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n", 184231f2cb8fSBharat Bhushan __func__, strerror(-ret)); 184331f2cb8fSBharat Bhushan return ret; 184431f2cb8fSBharat Bhushan } 184531f2cb8fSBharat Bhushan 184631f2cb8fSBharat Bhushan return ret; 184731f2cb8fSBharat Bhushan } 184831f2cb8fSBharat Bhushan 1849dc333cd6SAlexander Graf static int read_cpuinfo(const char *field, char *value, int len) 1850dc333cd6SAlexander Graf { 1851dc333cd6SAlexander Graf FILE *f; 1852dc333cd6SAlexander Graf int ret = -1; 1853dc333cd6SAlexander Graf int field_len = strlen(field); 1854dc333cd6SAlexander Graf char line[512]; 1855dc333cd6SAlexander Graf 1856dc333cd6SAlexander Graf f = fopen("/proc/cpuinfo", "r"); 1857dc333cd6SAlexander Graf if (!f) { 1858dc333cd6SAlexander Graf return -1; 1859dc333cd6SAlexander Graf } 1860dc333cd6SAlexander Graf 1861dc333cd6SAlexander Graf do { 1862dc333cd6SAlexander Graf if (!fgets(line, sizeof(line), f)) { 1863dc333cd6SAlexander Graf break; 1864dc333cd6SAlexander Graf } 1865dc333cd6SAlexander Graf if (!strncmp(line, field, field_len)) { 1866ae215068SJim Meyering pstrcpy(value, len, line); 1867dc333cd6SAlexander Graf ret = 0; 1868dc333cd6SAlexander Graf break; 1869dc333cd6SAlexander Graf } 1870dc333cd6SAlexander Graf } while (*line); 1871dc333cd6SAlexander Graf 1872dc333cd6SAlexander Graf fclose(f); 1873dc333cd6SAlexander Graf 1874dc333cd6SAlexander Graf return ret; 1875dc333cd6SAlexander Graf } 1876dc333cd6SAlexander Graf 1877dc333cd6SAlexander Graf uint32_t kvmppc_get_tbfreq(void) 1878dc333cd6SAlexander Graf { 1879dc333cd6SAlexander Graf char line[512]; 1880dc333cd6SAlexander Graf char *ns; 188173bcb24dSRutuja Shah uint32_t retval = NANOSECONDS_PER_SECOND; 1882dc333cd6SAlexander Graf 1883dc333cd6SAlexander Graf if (read_cpuinfo("timebase", line, sizeof(line))) { 1884dc333cd6SAlexander Graf return retval; 1885dc333cd6SAlexander Graf } 1886dc333cd6SAlexander Graf 1887*c995e942SDavid Gibson ns = strchr(line, ':'); 1888*c995e942SDavid Gibson if (!ns) { 1889dc333cd6SAlexander Graf return retval; 1890dc333cd6SAlexander Graf } 1891dc333cd6SAlexander Graf 1892dc333cd6SAlexander Graf ns++; 1893dc333cd6SAlexander Graf 1894f9b8e7f6SShraddha Barke return atoi(ns); 1895ef951443SNikunj A Dadhania } 1896ef951443SNikunj A Dadhania 1897ef951443SNikunj A Dadhania bool kvmppc_get_host_serial(char **value) 1898ef951443SNikunj A Dadhania { 1899ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/system-id", value, NULL, 1900ef951443SNikunj A Dadhania NULL); 1901ef951443SNikunj A Dadhania } 1902ef951443SNikunj A Dadhania 1903ef951443SNikunj A Dadhania bool kvmppc_get_host_model(char **value) 1904ef951443SNikunj A Dadhania { 1905ef951443SNikunj A Dadhania return g_file_get_contents("/proc/device-tree/model", value, NULL, NULL); 1906dc333cd6SAlexander Graf } 19074513d923SGleb Natapov 1908eadaada1SAlexander Graf /* Try to find a device tree node for a CPU with clock-frequency property */ 1909eadaada1SAlexander Graf static int kvmppc_find_cpu_dt(char *buf, int buf_len) 1910eadaada1SAlexander Graf { 1911eadaada1SAlexander Graf struct dirent *dirp; 1912eadaada1SAlexander Graf DIR *dp; 1913eadaada1SAlexander Graf 1914*c995e942SDavid Gibson dp = opendir(PROC_DEVTREE_CPU); 1915*c995e942SDavid Gibson if (!dp) { 1916eadaada1SAlexander Graf printf("Can't open directory " PROC_DEVTREE_CPU "\n"); 1917eadaada1SAlexander Graf return -1; 1918eadaada1SAlexander Graf } 1919eadaada1SAlexander Graf 1920eadaada1SAlexander Graf buf[0] = '\0'; 1921eadaada1SAlexander Graf while ((dirp = readdir(dp)) != NULL) { 1922eadaada1SAlexander Graf FILE *f; 1923eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s/clock-frequency", PROC_DEVTREE_CPU, 1924eadaada1SAlexander Graf dirp->d_name); 1925eadaada1SAlexander Graf f = fopen(buf, "r"); 1926eadaada1SAlexander Graf if (f) { 1927eadaada1SAlexander Graf snprintf(buf, buf_len, "%s%s", PROC_DEVTREE_CPU, dirp->d_name); 1928eadaada1SAlexander Graf fclose(f); 1929eadaada1SAlexander Graf break; 1930eadaada1SAlexander Graf } 1931eadaada1SAlexander Graf buf[0] = '\0'; 1932eadaada1SAlexander Graf } 1933eadaada1SAlexander Graf closedir(dp); 1934eadaada1SAlexander Graf if (buf[0] == '\0') { 1935eadaada1SAlexander Graf printf("Unknown host!\n"); 1936eadaada1SAlexander Graf return -1; 1937eadaada1SAlexander Graf } 1938eadaada1SAlexander Graf 1939eadaada1SAlexander Graf return 0; 1940eadaada1SAlexander Graf } 1941eadaada1SAlexander Graf 19427d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_dt(const char *filename) 1943eadaada1SAlexander Graf { 19449bc884b7SDavid Gibson union { 19459bc884b7SDavid Gibson uint32_t v32; 19469bc884b7SDavid Gibson uint64_t v64; 19479bc884b7SDavid Gibson } u; 1948eadaada1SAlexander Graf FILE *f; 1949eadaada1SAlexander Graf int len; 1950eadaada1SAlexander Graf 19517d94a30bSSukadev Bhattiprolu f = fopen(filename, "rb"); 1952eadaada1SAlexander Graf if (!f) { 1953eadaada1SAlexander Graf return -1; 1954eadaada1SAlexander Graf } 1955eadaada1SAlexander Graf 19569bc884b7SDavid Gibson len = fread(&u, 1, sizeof(u), f); 1957eadaada1SAlexander Graf fclose(f); 1958eadaada1SAlexander Graf switch (len) { 19599bc884b7SDavid Gibson case 4: 19609bc884b7SDavid Gibson /* property is a 32-bit quantity */ 19619bc884b7SDavid Gibson return be32_to_cpu(u.v32); 19629bc884b7SDavid Gibson case 8: 19639bc884b7SDavid Gibson return be64_to_cpu(u.v64); 1964eadaada1SAlexander Graf } 1965eadaada1SAlexander Graf 1966eadaada1SAlexander Graf return 0; 1967eadaada1SAlexander Graf } 1968eadaada1SAlexander Graf 1969*c995e942SDavid Gibson /* 1970*c995e942SDavid Gibson * Read a CPU node property from the host device tree that's a single 19717d94a30bSSukadev Bhattiprolu * integer (32-bit or 64-bit). Returns 0 if anything goes wrong 1972*c995e942SDavid Gibson * (can't find or open the property, or doesn't understand the format) 1973*c995e942SDavid Gibson */ 19747d94a30bSSukadev Bhattiprolu static uint64_t kvmppc_read_int_cpu_dt(const char *propname) 19757d94a30bSSukadev Bhattiprolu { 19767d94a30bSSukadev Bhattiprolu char buf[PATH_MAX], *tmp; 19777d94a30bSSukadev Bhattiprolu uint64_t val; 19787d94a30bSSukadev Bhattiprolu 19797d94a30bSSukadev Bhattiprolu if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { 19807d94a30bSSukadev Bhattiprolu return -1; 19817d94a30bSSukadev Bhattiprolu } 19827d94a30bSSukadev Bhattiprolu 19837d94a30bSSukadev Bhattiprolu tmp = g_strdup_printf("%s/%s", buf, propname); 19847d94a30bSSukadev Bhattiprolu val = kvmppc_read_int_dt(tmp); 19857d94a30bSSukadev Bhattiprolu g_free(tmp); 19867d94a30bSSukadev Bhattiprolu 19877d94a30bSSukadev Bhattiprolu return val; 19887d94a30bSSukadev Bhattiprolu } 19897d94a30bSSukadev Bhattiprolu 19909bc884b7SDavid Gibson uint64_t kvmppc_get_clockfreq(void) 19919bc884b7SDavid Gibson { 19929bc884b7SDavid Gibson return kvmppc_read_int_cpu_dt("clock-frequency"); 19939bc884b7SDavid Gibson } 19949bc884b7SDavid Gibson 19957d050527SSuraj Jitindar Singh static int kvmppc_get_dec_bits(void) 19967d050527SSuraj Jitindar Singh { 19977d050527SSuraj Jitindar Singh int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits"); 19987d050527SSuraj Jitindar Singh 19997d050527SSuraj Jitindar Singh if (nr_bits > 0) { 20007d050527SSuraj Jitindar Singh return nr_bits; 20017d050527SSuraj Jitindar Singh } 20027d050527SSuraj Jitindar Singh return 0; 20037d050527SSuraj Jitindar Singh } 20047d050527SSuraj Jitindar Singh 20051a61a9aeSStuart Yoder static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo) 200645024f09SAlexander Graf { 2007a60f24b5SAndreas Färber PowerPCCPU *cpu = ppc_env_get_cpu(env); 2008a60f24b5SAndreas Färber CPUState *cs = CPU(cpu); 200945024f09SAlexander Graf 20106fd33a75SAlexander Graf if (kvm_vm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) && 20111a61a9aeSStuart Yoder !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) { 20121a61a9aeSStuart Yoder return 0; 20131a61a9aeSStuart Yoder } 201445024f09SAlexander Graf 20151a61a9aeSStuart Yoder return 1; 20161a61a9aeSStuart Yoder } 20171a61a9aeSStuart Yoder 20181a61a9aeSStuart Yoder int kvmppc_get_hasidle(CPUPPCState *env) 20191a61a9aeSStuart Yoder { 20201a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 20211a61a9aeSStuart Yoder 20221a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo) && 20231a61a9aeSStuart Yoder (pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) { 20241a61a9aeSStuart Yoder return 1; 20251a61a9aeSStuart Yoder } 20261a61a9aeSStuart Yoder 20271a61a9aeSStuart Yoder return 0; 20281a61a9aeSStuart Yoder } 20291a61a9aeSStuart Yoder 20301a61a9aeSStuart Yoder int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) 20311a61a9aeSStuart Yoder { 20321a61a9aeSStuart Yoder uint32_t *hc = (uint32_t *)buf; 20331a61a9aeSStuart Yoder struct kvm_ppc_pvinfo pvinfo; 20341a61a9aeSStuart Yoder 20351a61a9aeSStuart Yoder if (!kvmppc_get_pvinfo(env, &pvinfo)) { 20361a61a9aeSStuart Yoder memcpy(buf, pvinfo.hcall, buf_len); 203745024f09SAlexander Graf return 0; 203845024f09SAlexander Graf } 203945024f09SAlexander Graf 204045024f09SAlexander Graf /* 2041d13fc32eSAlexander Graf * Fallback to always fail hypercalls regardless of endianness: 204245024f09SAlexander Graf * 2043d13fc32eSAlexander Graf * tdi 0,r0,72 (becomes b .+8 in wrong endian, nop in good endian) 204445024f09SAlexander Graf * li r3, -1 2045d13fc32eSAlexander Graf * b .+8 (becomes nop in wrong endian) 2046d13fc32eSAlexander Graf * bswap32(li r3, -1) 204745024f09SAlexander Graf */ 204845024f09SAlexander Graf 2049d13fc32eSAlexander Graf hc[0] = cpu_to_be32(0x08000048); 2050d13fc32eSAlexander Graf hc[1] = cpu_to_be32(0x3860ffff); 2051d13fc32eSAlexander Graf hc[2] = cpu_to_be32(0x48000008); 2052d13fc32eSAlexander Graf hc[3] = cpu_to_be32(bswap32(0x3860ffff)); 205345024f09SAlexander Graf 20540ddbd053SAlexey Kardashevskiy return 1; 205545024f09SAlexander Graf } 205645024f09SAlexander Graf 2057026bfd89SDavid Gibson static inline int kvmppc_enable_hcall(KVMState *s, target_ulong hcall) 2058026bfd89SDavid Gibson { 2059026bfd89SDavid Gibson return kvm_vm_enable_cap(s, KVM_CAP_PPC_ENABLE_HCALL, 0, hcall, 1); 2060026bfd89SDavid Gibson } 2061026bfd89SDavid Gibson 2062026bfd89SDavid Gibson void kvmppc_enable_logical_ci_hcalls(void) 2063026bfd89SDavid Gibson { 2064026bfd89SDavid Gibson /* 2065026bfd89SDavid Gibson * FIXME: it would be nice if we could detect the cases where 2066026bfd89SDavid Gibson * we're using a device which requires the in kernel 2067026bfd89SDavid Gibson * implementation of these hcalls, but the kernel lacks them and 2068026bfd89SDavid Gibson * produce a warning. 2069026bfd89SDavid Gibson */ 2070026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_LOAD); 2071026bfd89SDavid Gibson kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_STORE); 2072026bfd89SDavid Gibson } 2073026bfd89SDavid Gibson 2074ef9971ddSAlexey Kardashevskiy void kvmppc_enable_set_mode_hcall(void) 2075ef9971ddSAlexey Kardashevskiy { 2076ef9971ddSAlexey Kardashevskiy kvmppc_enable_hcall(kvm_state, H_SET_MODE); 2077ef9971ddSAlexey Kardashevskiy } 2078ef9971ddSAlexey Kardashevskiy 20795145ad4fSNathan Whitehorn void kvmppc_enable_clear_ref_mod_hcalls(void) 20805145ad4fSNathan Whitehorn { 20815145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_REF); 20825145ad4fSNathan Whitehorn kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD); 20835145ad4fSNathan Whitehorn } 20845145ad4fSNathan Whitehorn 208568f9f708SSuraj Jitindar Singh void kvmppc_enable_h_page_init(void) 208668f9f708SSuraj Jitindar Singh { 208768f9f708SSuraj Jitindar Singh kvmppc_enable_hcall(kvm_state, H_PAGE_INIT); 208868f9f708SSuraj Jitindar Singh } 208968f9f708SSuraj Jitindar Singh 20901bc22652SAndreas Färber void kvmppc_set_papr(PowerPCCPU *cpu) 2091f61b4bedSAlexander Graf { 20921bc22652SAndreas Färber CPUState *cs = CPU(cpu); 2093f61b4bedSAlexander Graf int ret; 2094f61b4bedSAlexander Graf 2095da20aed1SDavid Gibson if (!kvm_enabled()) { 2096da20aed1SDavid Gibson return; 2097da20aed1SDavid Gibson } 2098da20aed1SDavid Gibson 209948add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0); 2100f61b4bedSAlexander Graf if (ret) { 2101072ed5f2SThomas Huth error_report("This vCPU type or KVM version does not support PAPR"); 2102072ed5f2SThomas Huth exit(1); 2103f61b4bedSAlexander Graf } 21049b00ea49SDavid Gibson 2105*c995e942SDavid Gibson /* 2106*c995e942SDavid Gibson * Update the capability flag so we sync the right information 2107*c995e942SDavid Gibson * with kvm 2108*c995e942SDavid Gibson */ 21099b00ea49SDavid Gibson cap_papr = 1; 2110f1af19d7SDavid Gibson } 2111f61b4bedSAlexander Graf 2112d6e166c0SDavid Gibson int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr) 21136db5bb0fSAlexey Kardashevskiy { 2114d6e166c0SDavid Gibson return kvm_set_one_reg(CPU(cpu), KVM_REG_PPC_ARCH_COMPAT, &compat_pvr); 21156db5bb0fSAlexey Kardashevskiy } 21166db5bb0fSAlexey Kardashevskiy 21175b95b8b9SAlexander Graf void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy) 21185b95b8b9SAlexander Graf { 21195b95b8b9SAlexander Graf CPUState *cs = CPU(cpu); 21205b95b8b9SAlexander Graf int ret; 21215b95b8b9SAlexander Graf 212248add816SCornelia Huck ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_EPR, 0, mpic_proxy); 21235b95b8b9SAlexander Graf if (ret && mpic_proxy) { 2124072ed5f2SThomas Huth error_report("This KVM version does not support EPR"); 2125072ed5f2SThomas Huth exit(1); 21265b95b8b9SAlexander Graf } 21275b95b8b9SAlexander Graf } 21285b95b8b9SAlexander Graf 2129e97c3636SDavid Gibson int kvmppc_smt_threads(void) 2130e97c3636SDavid Gibson { 2131e97c3636SDavid Gibson return cap_ppc_smt ? cap_ppc_smt : 1; 2132e97c3636SDavid Gibson } 2133e97c3636SDavid Gibson 2134fa98fbfcSSam Bobroff int kvmppc_set_smt_threads(int smt) 2135fa98fbfcSSam Bobroff { 2136fa98fbfcSSam Bobroff int ret; 2137fa98fbfcSSam Bobroff 2138fa98fbfcSSam Bobroff ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SMT, 0, smt, 0); 2139fa98fbfcSSam Bobroff if (!ret) { 2140fa98fbfcSSam Bobroff cap_ppc_smt = smt; 2141fa98fbfcSSam Bobroff } 2142fa98fbfcSSam Bobroff return ret; 2143fa98fbfcSSam Bobroff } 2144fa98fbfcSSam Bobroff 2145fa98fbfcSSam Bobroff void kvmppc_hint_smt_possible(Error **errp) 2146fa98fbfcSSam Bobroff { 2147fa98fbfcSSam Bobroff int i; 2148fa98fbfcSSam Bobroff GString *g; 2149fa98fbfcSSam Bobroff char *s; 2150fa98fbfcSSam Bobroff 2151fa98fbfcSSam Bobroff assert(kvm_enabled()); 2152fa98fbfcSSam Bobroff if (cap_ppc_smt_possible) { 2153fa98fbfcSSam Bobroff g = g_string_new("Available VSMT modes:"); 2154fa98fbfcSSam Bobroff for (i = 63; i >= 0; i--) { 2155fa98fbfcSSam Bobroff if ((1UL << i) & cap_ppc_smt_possible) { 2156fa98fbfcSSam Bobroff g_string_append_printf(g, " %lu", (1UL << i)); 2157fa98fbfcSSam Bobroff } 2158fa98fbfcSSam Bobroff } 2159fa98fbfcSSam Bobroff s = g_string_free(g, false); 2160fa98fbfcSSam Bobroff error_append_hint(errp, "%s.\n", s); 2161fa98fbfcSSam Bobroff g_free(s); 2162fa98fbfcSSam Bobroff } else { 2163fa98fbfcSSam Bobroff error_append_hint(errp, 2164fa98fbfcSSam Bobroff "This KVM seems to be too old to support VSMT.\n"); 2165fa98fbfcSSam Bobroff } 2166fa98fbfcSSam Bobroff } 2167fa98fbfcSSam Bobroff 2168fa98fbfcSSam Bobroff 21697f763a5dSDavid Gibson #ifdef TARGET_PPC64 21707f763a5dSDavid Gibson uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift) 21717f763a5dSDavid Gibson { 2172f36951c1SDavid Gibson struct kvm_ppc_smmu_info info; 2173f36951c1SDavid Gibson long rampagesize, best_page_shift; 2174f36951c1SDavid Gibson int i; 2175f36951c1SDavid Gibson 2176*c995e942SDavid Gibson /* 2177*c995e942SDavid Gibson * Find the largest hardware supported page size that's less than 2178*c995e942SDavid Gibson * or equal to the (logical) backing page size of guest RAM 2179*c995e942SDavid Gibson */ 2180ab256960SGreg Kurz kvm_get_smmu_info(&info, &error_fatal); 21819c607668SAlexey Kardashevskiy rampagesize = qemu_getrampagesize(); 2182f36951c1SDavid Gibson best_page_shift = 0; 2183f36951c1SDavid Gibson 2184f36951c1SDavid Gibson for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) { 2185f36951c1SDavid Gibson struct kvm_ppc_one_seg_page_size *sps = &info.sps[i]; 2186f36951c1SDavid Gibson 2187f36951c1SDavid Gibson if (!sps->page_shift) { 2188f36951c1SDavid Gibson continue; 2189f36951c1SDavid Gibson } 2190f36951c1SDavid Gibson 2191f36951c1SDavid Gibson if ((sps->page_shift > best_page_shift) 2192f36951c1SDavid Gibson && ((1UL << sps->page_shift) <= rampagesize)) { 2193f36951c1SDavid Gibson best_page_shift = sps->page_shift; 2194f36951c1SDavid Gibson } 2195f36951c1SDavid Gibson } 2196f36951c1SDavid Gibson 21977f763a5dSDavid Gibson return MIN(current_size, 2198f36951c1SDavid Gibson 1ULL << (best_page_shift + hash_shift - 7)); 21997f763a5dSDavid Gibson } 22007f763a5dSDavid Gibson #endif 22017f763a5dSDavid Gibson 2202da95324eSAlexey Kardashevskiy bool kvmppc_spapr_use_multitce(void) 2203da95324eSAlexey Kardashevskiy { 2204da95324eSAlexey Kardashevskiy return cap_spapr_multitce; 2205da95324eSAlexey Kardashevskiy } 2206da95324eSAlexey Kardashevskiy 22073dc410aeSAlexey Kardashevskiy int kvmppc_spapr_enable_inkernel_multitce(void) 22083dc410aeSAlexey Kardashevskiy { 22093dc410aeSAlexey Kardashevskiy int ret; 22103dc410aeSAlexey Kardashevskiy 22113dc410aeSAlexey Kardashevskiy ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_ENABLE_HCALL, 0, 22123dc410aeSAlexey Kardashevskiy H_PUT_TCE_INDIRECT, 1); 22133dc410aeSAlexey Kardashevskiy if (!ret) { 22143dc410aeSAlexey Kardashevskiy ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_ENABLE_HCALL, 0, 22153dc410aeSAlexey Kardashevskiy H_STUFF_TCE, 1); 22163dc410aeSAlexey Kardashevskiy } 22173dc410aeSAlexey Kardashevskiy 22183dc410aeSAlexey Kardashevskiy return ret; 22193dc410aeSAlexey Kardashevskiy } 22203dc410aeSAlexey Kardashevskiy 2221d6ee2a7cSAlexey Kardashevskiy void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift, 2222d6ee2a7cSAlexey Kardashevskiy uint64_t bus_offset, uint32_t nb_table, 2223d6ee2a7cSAlexey Kardashevskiy int *pfd, bool need_vfio) 22240f5cb298SDavid Gibson { 22250f5cb298SDavid Gibson long len; 22260f5cb298SDavid Gibson int fd; 22270f5cb298SDavid Gibson void *table; 22280f5cb298SDavid Gibson 2229*c995e942SDavid Gibson /* 2230*c995e942SDavid Gibson * Must set fd to -1 so we don't try to munmap when called for 2231b5aec396SDavid Gibson * destroying the table, which the upper layers -will- do 2232b5aec396SDavid Gibson */ 2233b5aec396SDavid Gibson *pfd = -1; 22346a81dd17SDavid Gibson if (!cap_spapr_tce || (need_vfio && !cap_spapr_vfio)) { 22350f5cb298SDavid Gibson return NULL; 22360f5cb298SDavid Gibson } 22370f5cb298SDavid Gibson 2238d6ee2a7cSAlexey Kardashevskiy if (cap_spapr_tce_64) { 2239d6ee2a7cSAlexey Kardashevskiy struct kvm_create_spapr_tce_64 args = { 2240d6ee2a7cSAlexey Kardashevskiy .liobn = liobn, 2241d6ee2a7cSAlexey Kardashevskiy .page_shift = page_shift, 2242d6ee2a7cSAlexey Kardashevskiy .offset = bus_offset >> page_shift, 2243d6ee2a7cSAlexey Kardashevskiy .size = nb_table, 2244d6ee2a7cSAlexey Kardashevskiy .flags = 0 2245d6ee2a7cSAlexey Kardashevskiy }; 2246d6ee2a7cSAlexey Kardashevskiy fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE_64, &args); 2247d6ee2a7cSAlexey Kardashevskiy if (fd < 0) { 2248d6ee2a7cSAlexey Kardashevskiy fprintf(stderr, 2249d6ee2a7cSAlexey Kardashevskiy "KVM: Failed to create TCE64 table for liobn 0x%x\n", 2250d6ee2a7cSAlexey Kardashevskiy liobn); 2251d6ee2a7cSAlexey Kardashevskiy return NULL; 2252d6ee2a7cSAlexey Kardashevskiy } 2253d6ee2a7cSAlexey Kardashevskiy } else if (cap_spapr_tce) { 2254d6ee2a7cSAlexey Kardashevskiy uint64_t window_size = (uint64_t) nb_table << page_shift; 2255d6ee2a7cSAlexey Kardashevskiy struct kvm_create_spapr_tce args = { 2256d6ee2a7cSAlexey Kardashevskiy .liobn = liobn, 2257d6ee2a7cSAlexey Kardashevskiy .window_size = window_size, 2258d6ee2a7cSAlexey Kardashevskiy }; 2259d6ee2a7cSAlexey Kardashevskiy if ((window_size != args.window_size) || bus_offset) { 2260d6ee2a7cSAlexey Kardashevskiy return NULL; 2261d6ee2a7cSAlexey Kardashevskiy } 22620f5cb298SDavid Gibson fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); 22630f5cb298SDavid Gibson if (fd < 0) { 2264b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", 2265b5aec396SDavid Gibson liobn); 22660f5cb298SDavid Gibson return NULL; 22670f5cb298SDavid Gibson } 2268d6ee2a7cSAlexey Kardashevskiy } else { 2269d6ee2a7cSAlexey Kardashevskiy return NULL; 2270d6ee2a7cSAlexey Kardashevskiy } 22710f5cb298SDavid Gibson 2272d6ee2a7cSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22730f5cb298SDavid Gibson /* FIXME: round this up to page size */ 22740f5cb298SDavid Gibson 227574b41e56SDavid Gibson table = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 22760f5cb298SDavid Gibson if (table == MAP_FAILED) { 2277b5aec396SDavid Gibson fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n", 2278b5aec396SDavid Gibson liobn); 22790f5cb298SDavid Gibson close(fd); 22800f5cb298SDavid Gibson return NULL; 22810f5cb298SDavid Gibson } 22820f5cb298SDavid Gibson 22830f5cb298SDavid Gibson *pfd = fd; 22840f5cb298SDavid Gibson return table; 22850f5cb298SDavid Gibson } 22860f5cb298SDavid Gibson 2287523e7b8aSAlexey Kardashevskiy int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t nb_table) 22880f5cb298SDavid Gibson { 22890f5cb298SDavid Gibson long len; 22900f5cb298SDavid Gibson 22910f5cb298SDavid Gibson if (fd < 0) { 22920f5cb298SDavid Gibson return -1; 22930f5cb298SDavid Gibson } 22940f5cb298SDavid Gibson 2295523e7b8aSAlexey Kardashevskiy len = nb_table * sizeof(uint64_t); 22960f5cb298SDavid Gibson if ((munmap(table, len) < 0) || 22970f5cb298SDavid Gibson (close(fd) < 0)) { 2298b5aec396SDavid Gibson fprintf(stderr, "KVM: Unexpected error removing TCE table: %s", 2299b5aec396SDavid Gibson strerror(errno)); 23000f5cb298SDavid Gibson /* Leak the table */ 23010f5cb298SDavid Gibson } 23020f5cb298SDavid Gibson 23030f5cb298SDavid Gibson return 0; 23040f5cb298SDavid Gibson } 23050f5cb298SDavid Gibson 23067f763a5dSDavid Gibson int kvmppc_reset_htab(int shift_hint) 23077f763a5dSDavid Gibson { 23087f763a5dSDavid Gibson uint32_t shift = shift_hint; 23097f763a5dSDavid Gibson 2310ace9a2cbSDavid Gibson if (!kvm_enabled()) { 2311ace9a2cbSDavid Gibson /* Full emulation, tell caller to allocate htab itself */ 2312ace9a2cbSDavid Gibson return 0; 2313ace9a2cbSDavid Gibson } 23146977afdaSGreg Kurz if (kvm_vm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) { 23157f763a5dSDavid Gibson int ret; 23167f763a5dSDavid Gibson ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift); 2317ace9a2cbSDavid Gibson if (ret == -ENOTTY) { 2318*c995e942SDavid Gibson /* 2319*c995e942SDavid Gibson * At least some versions of PR KVM advertise the 2320ace9a2cbSDavid Gibson * capability, but don't implement the ioctl(). Oops. 2321ace9a2cbSDavid Gibson * Return 0 so that we allocate the htab in qemu, as is 2322*c995e942SDavid Gibson * correct for PR. 2323*c995e942SDavid Gibson */ 2324ace9a2cbSDavid Gibson return 0; 2325ace9a2cbSDavid Gibson } else if (ret < 0) { 23267f763a5dSDavid Gibson return ret; 23277f763a5dSDavid Gibson } 23287f763a5dSDavid Gibson return shift; 23297f763a5dSDavid Gibson } 23307f763a5dSDavid Gibson 2331*c995e942SDavid Gibson /* 2332*c995e942SDavid Gibson * We have a kernel that predates the htab reset calls. For PR 2333ace9a2cbSDavid Gibson * KVM, we need to allocate the htab ourselves, for an HV KVM of 2334*c995e942SDavid Gibson * this era, it has allocated a 16MB fixed size hash table 2335*c995e942SDavid Gibson * already. 2336*c995e942SDavid Gibson */ 233796c9cff0SThomas Huth if (kvmppc_is_pr(kvm_state)) { 2338ace9a2cbSDavid Gibson /* PR - tell caller to allocate htab */ 23397f763a5dSDavid Gibson return 0; 2340ace9a2cbSDavid Gibson } else { 2341ace9a2cbSDavid Gibson /* HV - assume 16MB kernel allocated htab */ 2342ace9a2cbSDavid Gibson return 24; 2343ace9a2cbSDavid Gibson } 23447f763a5dSDavid Gibson } 23457f763a5dSDavid Gibson 2346a1e98583SDavid Gibson static inline uint32_t mfpvr(void) 2347a1e98583SDavid Gibson { 2348a1e98583SDavid Gibson uint32_t pvr; 2349a1e98583SDavid Gibson 2350a1e98583SDavid Gibson asm ("mfpvr %0" 2351a1e98583SDavid Gibson : "=r"(pvr)); 2352a1e98583SDavid Gibson return pvr; 2353a1e98583SDavid Gibson } 2354a1e98583SDavid Gibson 2355a7342588SDavid Gibson static void alter_insns(uint64_t *word, uint64_t flags, bool on) 2356a7342588SDavid Gibson { 2357a7342588SDavid Gibson if (on) { 2358a7342588SDavid Gibson *word |= flags; 2359a7342588SDavid Gibson } else { 2360a7342588SDavid Gibson *word &= ~flags; 2361a7342588SDavid Gibson } 2362a7342588SDavid Gibson } 2363a7342588SDavid Gibson 23642985b86bSAndreas Färber static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) 23652985b86bSAndreas Färber { 23662985b86bSAndreas Färber PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); 23670cbad81fSDavid Gibson uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size"); 23680cbad81fSDavid Gibson uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); 2369a1e98583SDavid Gibson 2370cfe34f44SAndreas Färber /* Now fix up the class with information we can query from the host */ 23713bc9ccc0SAlexey Kardashevskiy pcc->pvr = mfpvr(); 2372a7342588SDavid Gibson 23733f2ca480SDavid Gibson alter_insns(&pcc->insns_flags, PPC_ALTIVEC, 23743f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); 23753f2ca480SDavid Gibson alter_insns(&pcc->insns_flags2, PPC2_VSX, 23763f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_VSX); 23773f2ca480SDavid Gibson alter_insns(&pcc->insns_flags2, PPC2_DFP, 23783f2ca480SDavid Gibson qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_DFP); 23790cbad81fSDavid Gibson 23800cbad81fSDavid Gibson if (dcache_size != -1) { 23810cbad81fSDavid Gibson pcc->l1_dcache_size = dcache_size; 23820cbad81fSDavid Gibson } 23830cbad81fSDavid Gibson 23840cbad81fSDavid Gibson if (icache_size != -1) { 23850cbad81fSDavid Gibson pcc->l1_icache_size = icache_size; 23860cbad81fSDavid Gibson } 2387c64abd1fSSam Bobroff 2388c64abd1fSSam Bobroff #if defined(TARGET_PPC64) 2389c64abd1fSSam Bobroff pcc->radix_page_info = kvm_get_radix_page_info(); 23905f3066d8SDavid Gibson 23915f3066d8SDavid Gibson if ((pcc->pvr & 0xffffff00) == CPU_POWERPC_POWER9_DD1) { 23925f3066d8SDavid Gibson /* 23935f3066d8SDavid Gibson * POWER9 DD1 has some bugs which make it not really ISA 3.00 23945f3066d8SDavid Gibson * compliant. More importantly, advertising ISA 3.00 23955f3066d8SDavid Gibson * architected mode may prevent guests from activating 23965f3066d8SDavid Gibson * necessary DD1 workarounds. 23975f3066d8SDavid Gibson */ 23985f3066d8SDavid Gibson pcc->pcr_supported &= ~(PCR_COMPAT_3_00 | PCR_COMPAT_2_07 23995f3066d8SDavid Gibson | PCR_COMPAT_2_06 | PCR_COMPAT_2_05); 24005f3066d8SDavid Gibson } 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 24958acc2ae5SSuraj Jitindar Singh static void kvmppc_get_cpu_characteristics(KVMState *s) 24968acc2ae5SSuraj Jitindar Singh { 24978acc2ae5SSuraj Jitindar Singh struct kvm_ppc_cpu_char c; 24988acc2ae5SSuraj Jitindar Singh int ret; 24998acc2ae5SSuraj Jitindar Singh 25008acc2ae5SSuraj Jitindar Singh /* Assume broken */ 25018acc2ae5SSuraj Jitindar Singh cap_ppc_safe_cache = 0; 25028acc2ae5SSuraj Jitindar Singh cap_ppc_safe_bounds_check = 0; 25038acc2ae5SSuraj Jitindar Singh cap_ppc_safe_indirect_branch = 0; 25048acc2ae5SSuraj Jitindar Singh 25058acc2ae5SSuraj Jitindar Singh ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR); 25068acc2ae5SSuraj Jitindar Singh if (!ret) { 25078acc2ae5SSuraj Jitindar Singh return; 25088acc2ae5SSuraj Jitindar Singh } 25098acc2ae5SSuraj Jitindar Singh ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c); 25108acc2ae5SSuraj Jitindar Singh if (ret < 0) { 25118acc2ae5SSuraj Jitindar Singh return; 25128acc2ae5SSuraj Jitindar Singh } 25138fea7044SSuraj Jitindar Singh 25148fea7044SSuraj Jitindar Singh cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); 25158fea7044SSuraj Jitindar Singh cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); 25168fea7044SSuraj Jitindar Singh cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); 25178ff43ee4SSuraj Jitindar Singh cap_ppc_count_cache_flush_assist = 25188ff43ee4SSuraj Jitindar Singh parse_cap_ppc_count_cache_flush_assist(c); 25198acc2ae5SSuraj Jitindar Singh } 25208acc2ae5SSuraj Jitindar Singh 25218acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_cache(void) 25228acc2ae5SSuraj Jitindar Singh { 25238acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_cache; 25248acc2ae5SSuraj Jitindar Singh } 25258acc2ae5SSuraj Jitindar Singh 25268acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_bounds_check(void) 25278acc2ae5SSuraj Jitindar Singh { 25288acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_bounds_check; 25298acc2ae5SSuraj Jitindar Singh } 25308acc2ae5SSuraj Jitindar Singh 25318acc2ae5SSuraj Jitindar Singh int kvmppc_get_cap_safe_indirect_branch(void) 25328acc2ae5SSuraj Jitindar Singh { 25338acc2ae5SSuraj Jitindar Singh return cap_ppc_safe_indirect_branch; 25348acc2ae5SSuraj Jitindar Singh } 25358acc2ae5SSuraj Jitindar Singh 25368ff43ee4SSuraj Jitindar Singh int kvmppc_get_cap_count_cache_flush_assist(void) 25378ff43ee4SSuraj Jitindar Singh { 25388ff43ee4SSuraj Jitindar Singh return cap_ppc_count_cache_flush_assist; 25398ff43ee4SSuraj Jitindar Singh } 25408ff43ee4SSuraj Jitindar Singh 2541b9a477b7SSuraj Jitindar Singh bool kvmppc_has_cap_nested_kvm_hv(void) 2542b9a477b7SSuraj Jitindar Singh { 2543b9a477b7SSuraj Jitindar Singh return !!cap_ppc_nested_kvm_hv; 2544b9a477b7SSuraj Jitindar Singh } 2545b9a477b7SSuraj Jitindar Singh 2546b9a477b7SSuraj Jitindar Singh int kvmppc_set_cap_nested_kvm_hv(int enable) 2547b9a477b7SSuraj Jitindar Singh { 2548b9a477b7SSuraj Jitindar Singh return kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_NESTED_HV, 0, enable); 2549b9a477b7SSuraj Jitindar Singh } 2550b9a477b7SSuraj Jitindar Singh 25519ded780cSAlexey Kardashevskiy bool kvmppc_has_cap_spapr_vfio(void) 25529ded780cSAlexey Kardashevskiy { 25539ded780cSAlexey Kardashevskiy return cap_spapr_vfio; 25549ded780cSAlexey Kardashevskiy } 25559ded780cSAlexey Kardashevskiy 25567d050527SSuraj Jitindar Singh int kvmppc_get_cap_large_decr(void) 25577d050527SSuraj Jitindar Singh { 25587d050527SSuraj Jitindar Singh return cap_large_decr; 25597d050527SSuraj Jitindar Singh } 25607d050527SSuraj Jitindar Singh 25617d050527SSuraj Jitindar Singh int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable) 25627d050527SSuraj Jitindar Singh { 25637d050527SSuraj Jitindar Singh CPUState *cs = CPU(cpu); 25647d050527SSuraj Jitindar Singh uint64_t lpcr; 25657d050527SSuraj Jitindar Singh 25667d050527SSuraj Jitindar Singh kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25677d050527SSuraj Jitindar Singh /* Do we need to modify the LPCR? */ 25687d050527SSuraj Jitindar Singh if (!!(lpcr & LPCR_LD) != !!enable) { 25697d050527SSuraj Jitindar Singh if (enable) { 25707d050527SSuraj Jitindar Singh lpcr |= LPCR_LD; 25717d050527SSuraj Jitindar Singh } else { 25727d050527SSuraj Jitindar Singh lpcr &= ~LPCR_LD; 25737d050527SSuraj Jitindar Singh } 25747d050527SSuraj Jitindar Singh kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25757d050527SSuraj Jitindar Singh kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr); 25767d050527SSuraj Jitindar Singh 25777d050527SSuraj Jitindar Singh if (!!(lpcr & LPCR_LD) != !!enable) { 25787d050527SSuraj Jitindar Singh return -1; 25797d050527SSuraj Jitindar Singh } 25807d050527SSuraj Jitindar Singh } 25817d050527SSuraj Jitindar Singh 25827d050527SSuraj Jitindar Singh return 0; 25837d050527SSuraj Jitindar Singh } 25847d050527SSuraj Jitindar Singh 258552b2519cSThomas Huth PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) 258652b2519cSThomas Huth { 258752b2519cSThomas Huth uint32_t host_pvr = mfpvr(); 258852b2519cSThomas Huth PowerPCCPUClass *pvr_pcc; 258952b2519cSThomas Huth 259052b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr(host_pvr); 259152b2519cSThomas Huth if (pvr_pcc == NULL) { 259252b2519cSThomas Huth pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr); 259352b2519cSThomas Huth } 259452b2519cSThomas Huth 259552b2519cSThomas Huth return pvr_pcc; 259652b2519cSThomas Huth } 259752b2519cSThomas Huth 25982e9c10ebSIgor Mammedov static int kvm_ppc_register_host_cpu_type(MachineState *ms) 25995ba4576bSAndreas Färber { 26005ba4576bSAndreas Färber TypeInfo type_info = { 26015ba4576bSAndreas Färber .name = TYPE_HOST_POWERPC_CPU, 26025ba4576bSAndreas Färber .class_init = kvmppc_host_cpu_class_init, 26035ba4576bSAndreas Färber }; 26042e9c10ebSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(ms); 26055ba4576bSAndreas Färber PowerPCCPUClass *pvr_pcc; 260692e926e1SGreg Kurz ObjectClass *oc; 26075b79b1caSAlexey Kardashevskiy DeviceClass *dc; 2608715d4b96SThomas Huth int i; 26095ba4576bSAndreas Färber 261052b2519cSThomas Huth pvr_pcc = kvm_ppc_get_host_cpu_class(); 26113bc9ccc0SAlexey Kardashevskiy if (pvr_pcc == NULL) { 26125ba4576bSAndreas Färber return -1; 26135ba4576bSAndreas Färber } 26145ba4576bSAndreas Färber type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); 26155ba4576bSAndreas Färber type_register(&type_info); 26162e9c10ebSIgor Mammedov if (object_dynamic_cast(OBJECT(ms), TYPE_SPAPR_MACHINE)) { 26172e9c10ebSIgor Mammedov /* override TCG default cpu type with 'host' cpu model */ 26182e9c10ebSIgor Mammedov mc->default_cpu_type = TYPE_HOST_POWERPC_CPU; 26192e9c10ebSIgor Mammedov } 26205b79b1caSAlexey Kardashevskiy 262192e926e1SGreg Kurz oc = object_class_by_name(type_info.name); 262292e926e1SGreg Kurz g_assert(oc); 262392e926e1SGreg Kurz 2624715d4b96SThomas Huth /* 2625715d4b96SThomas Huth * Update generic CPU family class alias (e.g. on a POWER8NVL host, 2626715d4b96SThomas Huth * we want "POWER8" to be a "family" alias that points to the current 2627715d4b96SThomas Huth * host CPU type, too) 2628715d4b96SThomas Huth */ 2629715d4b96SThomas Huth dc = DEVICE_CLASS(ppc_cpu_get_family_class(pvr_pcc)); 2630715d4b96SThomas Huth for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { 2631c5354f54SIgor Mammedov if (strcasecmp(ppc_cpu_aliases[i].alias, dc->desc) == 0) { 2632715d4b96SThomas Huth char *suffix; 2633715d4b96SThomas Huth 2634715d4b96SThomas Huth ppc_cpu_aliases[i].model = g_strdup(object_class_get_name(oc)); 2635c9137065SIgor Mammedov suffix = strstr(ppc_cpu_aliases[i].model, POWERPC_CPU_TYPE_SUFFIX); 2636715d4b96SThomas Huth if (suffix) { 2637715d4b96SThomas Huth *suffix = 0; 2638715d4b96SThomas Huth } 2639715d4b96SThomas Huth break; 2640715d4b96SThomas Huth } 2641715d4b96SThomas Huth } 2642715d4b96SThomas Huth 26435ba4576bSAndreas Färber return 0; 26445ba4576bSAndreas Färber } 26455ba4576bSAndreas Färber 2646feaa64c4SDavid Gibson int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function) 2647feaa64c4SDavid Gibson { 2648feaa64c4SDavid Gibson struct kvm_rtas_token_args args = { 2649feaa64c4SDavid Gibson .token = token, 2650feaa64c4SDavid Gibson }; 2651feaa64c4SDavid Gibson 2652feaa64c4SDavid Gibson if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_RTAS)) { 2653feaa64c4SDavid Gibson return -ENOENT; 2654feaa64c4SDavid Gibson } 2655feaa64c4SDavid Gibson 2656feaa64c4SDavid Gibson strncpy(args.name, function, sizeof(args.name)); 2657feaa64c4SDavid Gibson 2658feaa64c4SDavid Gibson return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args); 2659feaa64c4SDavid Gibson } 266012b1143bSDavid Gibson 266114b0d748SGreg Kurz int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp) 2662e68cb8b4SAlexey Kardashevskiy { 2663e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_fd s = { 2664e68cb8b4SAlexey Kardashevskiy .flags = write ? KVM_GET_HTAB_WRITE : 0, 266514b0d748SGreg Kurz .start_index = index, 2666e68cb8b4SAlexey Kardashevskiy }; 266782be8e73SGreg Kurz int ret; 2668e68cb8b4SAlexey Kardashevskiy 2669e68cb8b4SAlexey Kardashevskiy if (!cap_htab_fd) { 267014b0d748SGreg Kurz error_setg(errp, "KVM version doesn't support %s the HPT", 267114b0d748SGreg Kurz write ? "writing" : "reading"); 267282be8e73SGreg Kurz return -ENOTSUP; 2673e68cb8b4SAlexey Kardashevskiy } 2674e68cb8b4SAlexey Kardashevskiy 267582be8e73SGreg Kurz ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s); 267682be8e73SGreg Kurz if (ret < 0) { 267714b0d748SGreg Kurz error_setg(errp, "Unable to open fd for %s HPT %s KVM: %s", 267814b0d748SGreg Kurz write ? "writing" : "reading", write ? "to" : "from", 267914b0d748SGreg Kurz strerror(errno)); 268082be8e73SGreg Kurz return -errno; 268182be8e73SGreg Kurz } 268282be8e73SGreg Kurz 268382be8e73SGreg Kurz return ret; 2684e68cb8b4SAlexey Kardashevskiy } 2685e68cb8b4SAlexey Kardashevskiy 2686e68cb8b4SAlexey Kardashevskiy int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) 2687e68cb8b4SAlexey Kardashevskiy { 2688bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 2689e68cb8b4SAlexey Kardashevskiy uint8_t buf[bufsize]; 2690e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2691e68cb8b4SAlexey Kardashevskiy 2692e68cb8b4SAlexey Kardashevskiy do { 2693e68cb8b4SAlexey Kardashevskiy rc = read(fd, buf, bufsize); 2694e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2695e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error reading data from KVM HTAB fd: %s\n", 2696e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2697e68cb8b4SAlexey Kardashevskiy return rc; 2698e68cb8b4SAlexey Kardashevskiy } else if (rc) { 2699e094c4c1SCédric Le Goater uint8_t *buffer = buf; 2700e094c4c1SCédric Le Goater ssize_t n = rc; 2701e094c4c1SCédric Le Goater while (n) { 2702e094c4c1SCédric Le Goater struct kvm_get_htab_header *head = 2703e094c4c1SCédric Le Goater (struct kvm_get_htab_header *) buffer; 2704e094c4c1SCédric Le Goater size_t chunksize = sizeof(*head) + 2705e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid; 2706e094c4c1SCédric Le Goater 2707e094c4c1SCédric Le Goater qemu_put_be32(f, head->index); 2708e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_valid); 2709e094c4c1SCédric Le Goater qemu_put_be16(f, head->n_invalid); 2710e094c4c1SCédric Le Goater qemu_put_buffer(f, (void *)(head + 1), 2711e094c4c1SCédric Le Goater HASH_PTE_SIZE_64 * head->n_valid); 2712e094c4c1SCédric Le Goater 2713e094c4c1SCédric Le Goater buffer += chunksize; 2714e094c4c1SCédric Le Goater n -= chunksize; 2715e094c4c1SCédric Le Goater } 2716e68cb8b4SAlexey Kardashevskiy } 2717e68cb8b4SAlexey Kardashevskiy } while ((rc != 0) 2718*c995e942SDavid Gibson && ((max_ns < 0) || 2719*c995e942SDavid Gibson ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns))); 2720e68cb8b4SAlexey Kardashevskiy 2721e68cb8b4SAlexey Kardashevskiy return (rc == 0) ? 1 : 0; 2722e68cb8b4SAlexey Kardashevskiy } 2723e68cb8b4SAlexey Kardashevskiy 2724e68cb8b4SAlexey Kardashevskiy int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, 2725e68cb8b4SAlexey Kardashevskiy uint16_t n_valid, uint16_t n_invalid) 2726e68cb8b4SAlexey Kardashevskiy { 2727e68cb8b4SAlexey Kardashevskiy struct kvm_get_htab_header *buf; 2728e68cb8b4SAlexey Kardashevskiy size_t chunksize = sizeof(*buf) + n_valid * HASH_PTE_SIZE_64; 2729e68cb8b4SAlexey Kardashevskiy ssize_t rc; 2730e68cb8b4SAlexey Kardashevskiy 2731e68cb8b4SAlexey Kardashevskiy buf = alloca(chunksize); 2732e68cb8b4SAlexey Kardashevskiy buf->index = index; 2733e68cb8b4SAlexey Kardashevskiy buf->n_valid = n_valid; 2734e68cb8b4SAlexey Kardashevskiy buf->n_invalid = n_invalid; 2735e68cb8b4SAlexey Kardashevskiy 2736e68cb8b4SAlexey Kardashevskiy qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64 * n_valid); 2737e68cb8b4SAlexey Kardashevskiy 2738e68cb8b4SAlexey Kardashevskiy rc = write(fd, buf, chunksize); 2739e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 2740e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Error writing KVM hash table: %s\n", 2741e68cb8b4SAlexey Kardashevskiy strerror(errno)); 2742e68cb8b4SAlexey Kardashevskiy return rc; 2743e68cb8b4SAlexey Kardashevskiy } 2744e68cb8b4SAlexey Kardashevskiy if (rc != chunksize) { 2745e68cb8b4SAlexey Kardashevskiy /* We should never get a short write on a single chunk */ 2746e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Short write, restoring KVM hash table\n"); 2747e68cb8b4SAlexey Kardashevskiy return -1; 2748e68cb8b4SAlexey Kardashevskiy } 2749e68cb8b4SAlexey Kardashevskiy return 0; 2750e68cb8b4SAlexey Kardashevskiy } 2751e68cb8b4SAlexey Kardashevskiy 275220d695a9SAndreas Färber bool kvm_arch_stop_on_emulation_error(CPUState *cpu) 27534513d923SGleb Natapov { 27544513d923SGleb Natapov return true; 27554513d923SGleb Natapov } 2756a1b87fe0SJan Kiszka 275782169660SScott Wood void kvm_arch_init_irq_routing(KVMState *s) 275882169660SScott Wood { 275982169660SScott Wood } 2760c65f9a07SGreg Kurz 27611ad9f0a4SDavid Gibson void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, hwaddr ptex, int n) 27621ad9f0a4SDavid Gibson { 27631ad9f0a4SDavid Gibson int fd, rc; 27641ad9f0a4SDavid Gibson int i; 27657c43bca0SAneesh Kumar K.V 276614b0d748SGreg Kurz fd = kvmppc_get_htab_fd(false, ptex, &error_abort); 27671ad9f0a4SDavid Gibson 27681ad9f0a4SDavid Gibson i = 0; 27691ad9f0a4SDavid Gibson while (i < n) { 27701ad9f0a4SDavid Gibson struct kvm_get_htab_header *hdr; 27711ad9f0a4SDavid Gibson int m = n < HPTES_PER_GROUP ? n : HPTES_PER_GROUP; 27721ad9f0a4SDavid Gibson char buf[sizeof(*hdr) + m * HASH_PTE_SIZE_64]; 27731ad9f0a4SDavid Gibson 27741ad9f0a4SDavid Gibson rc = read(fd, buf, sizeof(buf)); 27751ad9f0a4SDavid Gibson if (rc < 0) { 27761ad9f0a4SDavid Gibson hw_error("kvmppc_read_hptes: Unable to read HPTEs"); 27771ad9f0a4SDavid Gibson } 27781ad9f0a4SDavid Gibson 27791ad9f0a4SDavid Gibson hdr = (struct kvm_get_htab_header *)buf; 27801ad9f0a4SDavid Gibson while ((i < n) && ((char *)hdr < (buf + rc))) { 2781a36593e1SAlexey Kardashevskiy int invalid = hdr->n_invalid, valid = hdr->n_valid; 27821ad9f0a4SDavid Gibson 27831ad9f0a4SDavid Gibson if (hdr->index != (ptex + i)) { 27841ad9f0a4SDavid Gibson hw_error("kvmppc_read_hptes: Unexpected HPTE index %"PRIu32 27851ad9f0a4SDavid Gibson " != (%"HWADDR_PRIu" + %d", hdr->index, ptex, i); 27861ad9f0a4SDavid Gibson } 27871ad9f0a4SDavid Gibson 2788a36593e1SAlexey Kardashevskiy if (n - i < valid) { 2789a36593e1SAlexey Kardashevskiy valid = n - i; 2790a36593e1SAlexey Kardashevskiy } 2791a36593e1SAlexey Kardashevskiy memcpy(hptes + i, hdr + 1, HASH_PTE_SIZE_64 * valid); 2792a36593e1SAlexey Kardashevskiy i += valid; 27931ad9f0a4SDavid Gibson 27941ad9f0a4SDavid Gibson if ((n - i) < invalid) { 27951ad9f0a4SDavid Gibson invalid = n - i; 27961ad9f0a4SDavid Gibson } 27971ad9f0a4SDavid Gibson memset(hptes + i, 0, invalid * HASH_PTE_SIZE_64); 2798a36593e1SAlexey Kardashevskiy i += invalid; 27991ad9f0a4SDavid Gibson 28001ad9f0a4SDavid Gibson hdr = (struct kvm_get_htab_header *) 28011ad9f0a4SDavid Gibson ((char *)(hdr + 1) + HASH_PTE_SIZE_64 * hdr->n_valid); 28021ad9f0a4SDavid Gibson } 28031ad9f0a4SDavid Gibson } 28041ad9f0a4SDavid Gibson 28051ad9f0a4SDavid Gibson close(fd); 28061ad9f0a4SDavid Gibson } 28071ad9f0a4SDavid Gibson 28081ad9f0a4SDavid Gibson void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) 28097c43bca0SAneesh Kumar K.V { 28101ad9f0a4SDavid Gibson int fd, rc; 28111ad9f0a4SDavid Gibson struct { 28121ad9f0a4SDavid Gibson struct kvm_get_htab_header hdr; 28131ad9f0a4SDavid Gibson uint64_t pte0; 28141ad9f0a4SDavid Gibson uint64_t pte1; 28151ad9f0a4SDavid Gibson } buf; 2816c1385933SAneesh Kumar K.V 281714b0d748SGreg Kurz fd = kvmppc_get_htab_fd(true, 0 /* Ignored */, &error_abort); 2818c1385933SAneesh Kumar K.V 28191ad9f0a4SDavid Gibson buf.hdr.n_valid = 1; 28201ad9f0a4SDavid Gibson buf.hdr.n_invalid = 0; 28211ad9f0a4SDavid Gibson buf.hdr.index = ptex; 28221ad9f0a4SDavid Gibson buf.pte0 = cpu_to_be64(pte0); 28231ad9f0a4SDavid Gibson buf.pte1 = cpu_to_be64(pte1); 28241ad9f0a4SDavid Gibson 28251ad9f0a4SDavid Gibson rc = write(fd, &buf, sizeof(buf)); 28261ad9f0a4SDavid Gibson if (rc != sizeof(buf)) { 28271ad9f0a4SDavid Gibson hw_error("kvmppc_write_hpte: Unable to update KVM HPT"); 2828c1385933SAneesh Kumar K.V } 28291ad9f0a4SDavid Gibson close(fd); 2830c1385933SAneesh Kumar K.V } 28319e03a040SFrank Blaschka 28329e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 2833dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 28349e03a040SFrank Blaschka { 28359e03a040SFrank Blaschka return 0; 28369e03a040SFrank Blaschka } 28371850b6b7SEric Auger 283838d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 283938d87493SPeter Xu int vector, PCIDevice *dev) 284038d87493SPeter Xu { 284138d87493SPeter Xu return 0; 284238d87493SPeter Xu } 284338d87493SPeter Xu 284438d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 284538d87493SPeter Xu { 284638d87493SPeter Xu return 0; 284738d87493SPeter Xu } 284838d87493SPeter Xu 28491850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 28501850b6b7SEric Auger { 28511850b6b7SEric Auger return data & 0xffff; 28521850b6b7SEric Auger } 28534d9392beSThomas Huth 28544d9392beSThomas Huth int kvmppc_enable_hwrng(void) 28554d9392beSThomas Huth { 28564d9392beSThomas Huth if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG)) { 28574d9392beSThomas Huth return -1; 28584d9392beSThomas Huth } 28594d9392beSThomas Huth 28604d9392beSThomas Huth return kvmppc_enable_hcall(kvm_state, H_RANDOM); 28614d9392beSThomas Huth } 286230f4b05bSDavid Gibson 286330f4b05bSDavid Gibson void kvmppc_check_papr_resize_hpt(Error **errp) 286430f4b05bSDavid Gibson { 286530f4b05bSDavid Gibson if (!kvm_enabled()) { 2866b55d295eSDavid Gibson return; /* No KVM, we're good */ 2867b55d295eSDavid Gibson } 2868b55d295eSDavid Gibson 2869b55d295eSDavid Gibson if (cap_resize_hpt) { 2870b55d295eSDavid Gibson return; /* Kernel has explicit support, we're good */ 2871b55d295eSDavid Gibson } 2872b55d295eSDavid Gibson 2873b55d295eSDavid Gibson /* Otherwise fallback on looking for PR KVM */ 2874b55d295eSDavid Gibson if (kvmppc_is_pr(kvm_state)) { 287530f4b05bSDavid Gibson return; 287630f4b05bSDavid Gibson } 287730f4b05bSDavid Gibson 287830f4b05bSDavid Gibson error_setg(errp, 287930f4b05bSDavid Gibson "Hash page table resizing not available with this KVM version"); 288030f4b05bSDavid Gibson } 2881b55d295eSDavid Gibson 2882b55d295eSDavid Gibson int kvmppc_resize_hpt_prepare(PowerPCCPU *cpu, target_ulong flags, int shift) 2883b55d295eSDavid Gibson { 2884b55d295eSDavid Gibson CPUState *cs = CPU(cpu); 2885b55d295eSDavid Gibson struct kvm_ppc_resize_hpt rhpt = { 2886b55d295eSDavid Gibson .flags = flags, 2887b55d295eSDavid Gibson .shift = shift, 2888b55d295eSDavid Gibson }; 2889b55d295eSDavid Gibson 2890b55d295eSDavid Gibson if (!cap_resize_hpt) { 2891b55d295eSDavid Gibson return -ENOSYS; 2892b55d295eSDavid Gibson } 2893b55d295eSDavid Gibson 2894b55d295eSDavid Gibson return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_PREPARE, &rhpt); 2895b55d295eSDavid Gibson } 2896b55d295eSDavid Gibson 2897b55d295eSDavid Gibson int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, target_ulong flags, int shift) 2898b55d295eSDavid Gibson { 2899b55d295eSDavid Gibson CPUState *cs = CPU(cpu); 2900b55d295eSDavid Gibson struct kvm_ppc_resize_hpt rhpt = { 2901b55d295eSDavid Gibson .flags = flags, 2902b55d295eSDavid Gibson .shift = shift, 2903b55d295eSDavid Gibson }; 2904b55d295eSDavid Gibson 2905b55d295eSDavid Gibson if (!cap_resize_hpt) { 2906b55d295eSDavid Gibson return -ENOSYS; 2907b55d295eSDavid Gibson } 2908b55d295eSDavid Gibson 2909b55d295eSDavid Gibson return kvm_vm_ioctl(cs->kvm_state, KVM_PPC_RESIZE_HPT_COMMIT, &rhpt); 2910b55d295eSDavid Gibson } 2911b55d295eSDavid Gibson 2912c363a37aSDaniel Henrique Barboza /* 2913c363a37aSDaniel Henrique Barboza * This is a helper function to detect a post migration scenario 2914c363a37aSDaniel Henrique Barboza * in which a guest, running as KVM-HV, freezes in cpu_post_load because 2915c363a37aSDaniel Henrique Barboza * the guest kernel can't handle a PVR value other than the actual host 2916c363a37aSDaniel Henrique Barboza * PVR in KVM_SET_SREGS, even if pvr_match() returns true. 2917c363a37aSDaniel Henrique Barboza * 2918c363a37aSDaniel Henrique Barboza * If we don't have cap_ppc_pvr_compat and we're not running in PR 2919c363a37aSDaniel Henrique Barboza * (so, we're HV), return true. The workaround itself is done in 2920c363a37aSDaniel Henrique Barboza * cpu_post_load. 2921c363a37aSDaniel Henrique Barboza * 2922c363a37aSDaniel Henrique Barboza * The order here is important: we'll only check for KVM PR as a 2923c363a37aSDaniel Henrique Barboza * fallback if the guest kernel can't handle the situation itself. 2924c363a37aSDaniel Henrique Barboza * We need to avoid as much as possible querying the running KVM type 2925c363a37aSDaniel Henrique Barboza * in QEMU level. 2926c363a37aSDaniel Henrique Barboza */ 2927c363a37aSDaniel Henrique Barboza bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu) 2928c363a37aSDaniel Henrique Barboza { 2929c363a37aSDaniel Henrique Barboza CPUState *cs = CPU(cpu); 2930c363a37aSDaniel Henrique Barboza 2931c363a37aSDaniel Henrique Barboza if (!kvm_enabled()) { 2932c363a37aSDaniel Henrique Barboza return false; 2933c363a37aSDaniel Henrique Barboza } 2934c363a37aSDaniel Henrique Barboza 2935c363a37aSDaniel Henrique Barboza if (cap_ppc_pvr_compat) { 2936c363a37aSDaniel Henrique Barboza return false; 2937c363a37aSDaniel Henrique Barboza } 2938c363a37aSDaniel Henrique Barboza 2939c363a37aSDaniel Henrique Barboza return !kvmppc_is_pr(cs->kvm_state); 2940c363a37aSDaniel Henrique Barboza } 2941a84f7179SNikunj A Dadhania 2942a84f7179SNikunj A Dadhania void kvmppc_set_reg_ppc_online(PowerPCCPU *cpu, unsigned int online) 2943a84f7179SNikunj A Dadhania { 2944a84f7179SNikunj A Dadhania CPUState *cs = CPU(cpu); 2945a84f7179SNikunj A Dadhania 2946a84f7179SNikunj A Dadhania if (kvm_enabled()) { 2947a84f7179SNikunj A Dadhania kvm_set_one_reg(cs, KVM_REG_PPC_ONLINE, &online); 2948a84f7179SNikunj A Dadhania } 2949a84f7179SNikunj A Dadhania } 2950