1e2132e0bSSanjay Lal /* 2e2132e0bSSanjay Lal * This file is subject to the terms and conditions of the GNU General Public 3e2132e0bSSanjay Lal * License. See the file "COPYING" in the main directory of this archive 4e2132e0bSSanjay Lal * for more details. 5e2132e0bSSanjay Lal * 6e2132e0bSSanjay Lal * KVM/MIPS: MIPS specific KVM APIs 7e2132e0bSSanjay Lal * 8e2132e0bSSanjay Lal * Copyright (C) 2012-2014 Imagination Technologies Ltd. 9e2132e0bSSanjay Lal * Authors: Sanjay Lal <sanjayl@kymasys.com> 10e2132e0bSSanjay Lal */ 11e2132e0bSSanjay Lal 12c684822aSPeter Maydell #include "qemu/osdep.h" 13e2132e0bSSanjay Lal #include <sys/ioctl.h> 14e2132e0bSSanjay Lal 15e2132e0bSSanjay Lal #include <linux/kvm.h> 16e2132e0bSSanjay Lal 1733c11879SPaolo Bonzini #include "cpu.h" 1826aa3d9aSPhilippe Mathieu-Daudé #include "internal.h" 19e2132e0bSSanjay Lal #include "qemu/error-report.h" 20db725815SMarkus Armbruster #include "qemu/main-loop.h" 2132cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h" 2232cad1ffSPhilippe Mathieu-Daudé #include "system/kvm_int.h" 2332cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h" 24e2132e0bSSanjay Lal #include "kvm_mips.h" 25719d109bSHuacai Chen #include "hw/boards.h" 2681ddae7cSPhilippe Mathieu-Daudé #include "fpu_helper.h" 27e2132e0bSSanjay Lal 28e2132e0bSSanjay Lal #define DEBUG_KVM 0 29e2132e0bSSanjay Lal 30e2132e0bSSanjay Lal #define DPRINTF(fmt, ...) \ 31e2132e0bSSanjay Lal do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) 32e2132e0bSSanjay Lal 33152db36aSJames Hogan static int kvm_mips_fpu_cap; 34bee62662SJames Hogan static int kvm_mips_msa_cap; 35152db36aSJames Hogan 36e2132e0bSSanjay Lal const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 37e2132e0bSSanjay Lal KVM_CAP_LAST_INFO 38e2132e0bSSanjay Lal }; 39e2132e0bSSanjay Lal 40538f0497SPhilippe Mathieu-Daudé static void kvm_mips_update_state(void *opaque, bool running, RunState state); 41e2132e0bSSanjay Lal 42e2132e0bSSanjay Lal unsigned long kvm_arch_vcpu_id(CPUState *cs) 43e2132e0bSSanjay Lal { 44e2132e0bSSanjay Lal return cs->cpu_index; 45e2132e0bSSanjay Lal } 46e2132e0bSSanjay Lal 47b16565b3SMarcel Apfelbaum int kvm_arch_init(MachineState *ms, KVMState *s) 48e2132e0bSSanjay Lal { 49e2132e0bSSanjay Lal /* MIPS has 128 signals */ 50e2132e0bSSanjay Lal kvm_set_sigmask_len(s, 16); 51e2132e0bSSanjay Lal 52152db36aSJames Hogan kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU); 53bee62662SJames Hogan kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA); 54152db36aSJames Hogan 55e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 56e2132e0bSSanjay Lal return 0; 57e2132e0bSSanjay Lal } 58e2132e0bSSanjay Lal 594376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 60d525ffabSPaolo Bonzini { 61d525ffabSPaolo Bonzini return 0; 62d525ffabSPaolo Bonzini } 63d525ffabSPaolo Bonzini 64*a668268dSXiaoyao Li int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp) 65*a668268dSXiaoyao Li { 66*a668268dSXiaoyao Li return 0; 67*a668268dSXiaoyao Li } 68*a668268dSXiaoyao Li 69e2132e0bSSanjay Lal int kvm_arch_init_vcpu(CPUState *cs) 70e2132e0bSSanjay Lal { 714c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 72e2132e0bSSanjay Lal int ret = 0; 73e2132e0bSSanjay Lal 74e2132e0bSSanjay Lal qemu_add_vm_change_state_handler(kvm_mips_update_state, cs); 75e2132e0bSSanjay Lal 76152db36aSJames Hogan if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 77152db36aSJames Hogan ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0); 78152db36aSJames Hogan if (ret < 0) { 79152db36aSJames Hogan /* mark unsupported so it gets disabled on reset */ 80152db36aSJames Hogan kvm_mips_fpu_cap = 0; 81152db36aSJames Hogan ret = 0; 82152db36aSJames Hogan } 83152db36aSJames Hogan } 84152db36aSJames Hogan 8525a13628SPhilippe Mathieu-Daudé if (kvm_mips_msa_cap && ase_msa_available(env)) { 86bee62662SJames Hogan ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0); 87bee62662SJames Hogan if (ret < 0) { 88bee62662SJames Hogan /* mark unsupported so it gets disabled on reset */ 89bee62662SJames Hogan kvm_mips_msa_cap = 0; 90bee62662SJames Hogan ret = 0; 91bee62662SJames Hogan } 92bee62662SJames Hogan } 93bee62662SJames Hogan 94e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 95e2132e0bSSanjay Lal return ret; 96e2132e0bSSanjay Lal } 97e2132e0bSSanjay Lal 98b1115c99SLiran Alon int kvm_arch_destroy_vcpu(CPUState *cs) 99b1115c99SLiran Alon { 100b1115c99SLiran Alon return 0; 101b1115c99SLiran Alon } 102b1115c99SLiran Alon 103e2132e0bSSanjay Lal void kvm_mips_reset_vcpu(MIPSCPU *cpu) 104e2132e0bSSanjay Lal { 1050e928b12SJames Hogan CPUMIPSState *env = &cpu->env; 1060e928b12SJames Hogan 107152db36aSJames Hogan if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 1082ab4b135SAlistair Francis warn_report("KVM does not support FPU, disabling"); 1090e928b12SJames Hogan env->CP0_Config1 &= ~(1 << CP0C1_FP); 1100e928b12SJames Hogan } 11125a13628SPhilippe Mathieu-Daudé if (!kvm_mips_msa_cap && ase_msa_available(env)) { 1122ab4b135SAlistair Francis warn_report("KVM does not support MSA, disabling"); 113bee62662SJames Hogan env->CP0_Config3 &= ~(1 << CP0C3_MSAP); 114bee62662SJames Hogan } 1150e928b12SJames Hogan 116e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 117e2132e0bSSanjay Lal } 118e2132e0bSSanjay Lal 119e2132e0bSSanjay Lal int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 120e2132e0bSSanjay Lal { 121e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 122e2132e0bSSanjay Lal return 0; 123e2132e0bSSanjay Lal } 124e2132e0bSSanjay Lal 125e2132e0bSSanjay Lal int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 126e2132e0bSSanjay Lal { 127e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 128e2132e0bSSanjay Lal return 0; 129e2132e0bSSanjay Lal } 130e2132e0bSSanjay Lal 131e2132e0bSSanjay Lal static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) 132e2132e0bSSanjay Lal { 133e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 134e2132e0bSSanjay Lal 135e2132e0bSSanjay Lal return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP)); 136e2132e0bSSanjay Lal } 137e2132e0bSSanjay Lal 138e2132e0bSSanjay Lal 139e2132e0bSSanjay Lal void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 140e2132e0bSSanjay Lal { 141e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 142e2132e0bSSanjay Lal int r; 143e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 144e2132e0bSSanjay Lal 145195801d7SStefan Hajnoczi bql_lock(); 1464b8523eeSJan Kiszka 147e2132e0bSSanjay Lal if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 148e2132e0bSSanjay Lal cpu_mips_io_interrupts_pending(cpu)) { 149e2132e0bSSanjay Lal intr.cpu = -1; 150e2132e0bSSanjay Lal intr.irq = 2; 151e2132e0bSSanjay Lal r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 152e2132e0bSSanjay Lal if (r < 0) { 153e2132e0bSSanjay Lal error_report("%s: cpu %d: failed to inject IRQ %x", 154e2132e0bSSanjay Lal __func__, cs->cpu_index, intr.irq); 155e2132e0bSSanjay Lal } 156e2132e0bSSanjay Lal } 1574b8523eeSJan Kiszka 158195801d7SStefan Hajnoczi bql_unlock(); 159e2132e0bSSanjay Lal } 160e2132e0bSSanjay Lal 1614c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 162e2132e0bSSanjay Lal { 1634c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 164e2132e0bSSanjay Lal } 165e2132e0bSSanjay Lal 166e2132e0bSSanjay Lal int kvm_arch_process_async_events(CPUState *cs) 167e2132e0bSSanjay Lal { 168e2132e0bSSanjay Lal return cs->halted; 169e2132e0bSSanjay Lal } 170e2132e0bSSanjay Lal 171e2132e0bSSanjay Lal int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 172e2132e0bSSanjay Lal { 173e2132e0bSSanjay Lal int ret; 174e2132e0bSSanjay Lal 175e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 176e2132e0bSSanjay Lal switch (run->exit_reason) { 177e2132e0bSSanjay Lal default: 178e2132e0bSSanjay Lal error_report("%s: unknown exit reason %d", 179e2132e0bSSanjay Lal __func__, run->exit_reason); 180e2132e0bSSanjay Lal ret = -1; 181e2132e0bSSanjay Lal break; 182e2132e0bSSanjay Lal } 183e2132e0bSSanjay Lal 184e2132e0bSSanjay Lal return ret; 185e2132e0bSSanjay Lal } 186e2132e0bSSanjay Lal 187e2132e0bSSanjay Lal bool kvm_arch_stop_on_emulation_error(CPUState *cs) 188e2132e0bSSanjay Lal { 189e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 190e2132e0bSSanjay Lal return true; 191e2132e0bSSanjay Lal } 192e2132e0bSSanjay Lal 193e2132e0bSSanjay Lal void kvm_arch_init_irq_routing(KVMState *s) 194e2132e0bSSanjay Lal { 195e2132e0bSSanjay Lal } 196e2132e0bSSanjay Lal 197e2132e0bSSanjay Lal int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level) 198e2132e0bSSanjay Lal { 199e2132e0bSSanjay Lal CPUState *cs = CPU(cpu); 200e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 201e2132e0bSSanjay Lal 20211cb076bSPhilippe Mathieu-Daudé assert(kvm_enabled()); 203e2132e0bSSanjay Lal 204e2132e0bSSanjay Lal intr.cpu = -1; 205e2132e0bSSanjay Lal 206e2132e0bSSanjay Lal if (level) { 207e2132e0bSSanjay Lal intr.irq = irq; 208e2132e0bSSanjay Lal } else { 209e2132e0bSSanjay Lal intr.irq = -irq; 210e2132e0bSSanjay Lal } 211e2132e0bSSanjay Lal 212e2132e0bSSanjay Lal kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 213e2132e0bSSanjay Lal 214e2132e0bSSanjay Lal return 0; 215e2132e0bSSanjay Lal } 216e2132e0bSSanjay Lal 217e2132e0bSSanjay Lal int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) 218e2132e0bSSanjay Lal { 219e2132e0bSSanjay Lal CPUState *cs = current_cpu; 220e2132e0bSSanjay Lal CPUState *dest_cs = CPU(cpu); 221e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 222e2132e0bSSanjay Lal 22311cb076bSPhilippe Mathieu-Daudé assert(kvm_enabled()); 224e2132e0bSSanjay Lal 225e2132e0bSSanjay Lal intr.cpu = dest_cs->cpu_index; 226e2132e0bSSanjay Lal 227e2132e0bSSanjay Lal if (level) { 228e2132e0bSSanjay Lal intr.irq = irq; 229e2132e0bSSanjay Lal } else { 230e2132e0bSSanjay Lal intr.irq = -irq; 231e2132e0bSSanjay Lal } 232e2132e0bSSanjay Lal 233e2132e0bSSanjay Lal DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq); 234e2132e0bSSanjay Lal 235e2132e0bSSanjay Lal kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 236e2132e0bSSanjay Lal 237e2132e0bSSanjay Lal return 0; 238e2132e0bSSanjay Lal } 239e2132e0bSSanjay Lal 240e2132e0bSSanjay Lal #define MIPS_CP0_32(_R, _S) \ 2415a2db896SJames Hogan (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) 242e2132e0bSSanjay Lal 243e2132e0bSSanjay Lal #define MIPS_CP0_64(_R, _S) \ 2445a2db896SJames Hogan (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) 245e2132e0bSSanjay Lal 246e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) 2477e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0) 248e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0) 249e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2) 250e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0) 2517e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1) 2527e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5) 2537e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6) 2547e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7) 255e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0) 2567e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6) 257e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0) 258e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0) 259e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0) 260e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0) 261e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0) 262e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) 263e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) 264e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) 265461a1582SJames Hogan #define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) 2667e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1) 26703cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) 26803cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) 26903cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) 27003cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 27103cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) 27203cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) 2737e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6) 2747e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) 275e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 2767e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2) 2777e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3) 2787e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4) 2797e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5) 2807e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6) 2817e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7) 282e2132e0bSSanjay Lal 283e2132e0bSSanjay Lal static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, 284e2132e0bSSanjay Lal int32_t *addr) 285e2132e0bSSanjay Lal { 286e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 287e2132e0bSSanjay Lal .id = reg_id, 288f8b3e48bSJames Hogan .addr = (uintptr_t)addr 289e2132e0bSSanjay Lal }; 290e2132e0bSSanjay Lal 291e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 292e2132e0bSSanjay Lal } 293e2132e0bSSanjay Lal 2940759487bSJames Hogan static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id, 2950759487bSJames Hogan uint32_t *addr) 2960759487bSJames Hogan { 2970759487bSJames Hogan struct kvm_one_reg cp0reg = { 2980759487bSJames Hogan .id = reg_id, 2990759487bSJames Hogan .addr = (uintptr_t)addr 3000759487bSJames Hogan }; 3010759487bSJames Hogan 3020759487bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 3030759487bSJames Hogan } 3040759487bSJames Hogan 305e2132e0bSSanjay Lal static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, 306e2132e0bSSanjay Lal target_ulong *addr) 307e2132e0bSSanjay Lal { 308e2132e0bSSanjay Lal uint64_t val64 = *addr; 309e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 310e2132e0bSSanjay Lal .id = reg_id, 311e2132e0bSSanjay Lal .addr = (uintptr_t)&val64 312e2132e0bSSanjay Lal }; 313e2132e0bSSanjay Lal 314e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 315e2132e0bSSanjay Lal } 316e2132e0bSSanjay Lal 317e2132e0bSSanjay Lal static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id, 318d319f83fSJames Hogan int64_t *addr) 319d319f83fSJames Hogan { 320d319f83fSJames Hogan struct kvm_one_reg cp0reg = { 321d319f83fSJames Hogan .id = reg_id, 322d319f83fSJames Hogan .addr = (uintptr_t)addr 323d319f83fSJames Hogan }; 324d319f83fSJames Hogan 325d319f83fSJames Hogan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 326d319f83fSJames Hogan } 327d319f83fSJames Hogan 328d319f83fSJames Hogan static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id, 329e2132e0bSSanjay Lal uint64_t *addr) 330e2132e0bSSanjay Lal { 331e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 332e2132e0bSSanjay Lal .id = reg_id, 333e2132e0bSSanjay Lal .addr = (uintptr_t)addr 334e2132e0bSSanjay Lal }; 335e2132e0bSSanjay Lal 336e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 337e2132e0bSSanjay Lal } 338e2132e0bSSanjay Lal 339e2132e0bSSanjay Lal static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id, 340e2132e0bSSanjay Lal int32_t *addr) 341e2132e0bSSanjay Lal { 342e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 343e2132e0bSSanjay Lal .id = reg_id, 344f8b3e48bSJames Hogan .addr = (uintptr_t)addr 345e2132e0bSSanjay Lal }; 346e2132e0bSSanjay Lal 347f8b3e48bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 348e2132e0bSSanjay Lal } 349e2132e0bSSanjay Lal 3500759487bSJames Hogan static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id, 3510759487bSJames Hogan uint32_t *addr) 3520759487bSJames Hogan { 3530759487bSJames Hogan struct kvm_one_reg cp0reg = { 3540759487bSJames Hogan .id = reg_id, 3550759487bSJames Hogan .addr = (uintptr_t)addr 3560759487bSJames Hogan }; 3570759487bSJames Hogan 3580759487bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 3590759487bSJames Hogan } 3600759487bSJames Hogan 361182f42fdSPeter Maydell static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id, 362e2132e0bSSanjay Lal target_ulong *addr) 363e2132e0bSSanjay Lal { 364e2132e0bSSanjay Lal int ret; 365e2132e0bSSanjay Lal uint64_t val64 = 0; 366e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 367e2132e0bSSanjay Lal .id = reg_id, 368e2132e0bSSanjay Lal .addr = (uintptr_t)&val64 369e2132e0bSSanjay Lal }; 370e2132e0bSSanjay Lal 371e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 372e2132e0bSSanjay Lal if (ret >= 0) { 373e2132e0bSSanjay Lal *addr = val64; 374e2132e0bSSanjay Lal } 375e2132e0bSSanjay Lal return ret; 376e2132e0bSSanjay Lal } 377e2132e0bSSanjay Lal 378182f42fdSPeter Maydell static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id, 379d319f83fSJames Hogan int64_t *addr) 380d319f83fSJames Hogan { 381d319f83fSJames Hogan struct kvm_one_reg cp0reg = { 382d319f83fSJames Hogan .id = reg_id, 383d319f83fSJames Hogan .addr = (uintptr_t)addr 384d319f83fSJames Hogan }; 385d319f83fSJames Hogan 386d319f83fSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 387d319f83fSJames Hogan } 388d319f83fSJames Hogan 389d319f83fSJames Hogan static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, 390e2132e0bSSanjay Lal uint64_t *addr) 391e2132e0bSSanjay Lal { 392e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 393e2132e0bSSanjay Lal .id = reg_id, 394e2132e0bSSanjay Lal .addr = (uintptr_t)addr 395e2132e0bSSanjay Lal }; 396e2132e0bSSanjay Lal 397e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 398e2132e0bSSanjay Lal } 399e2132e0bSSanjay Lal 40003cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M) 401152db36aSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \ 402152db36aSJames Hogan (1U << CP0C1_FP)) 40303cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M) 404bee62662SJames Hogan #define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \ 405bee62662SJames Hogan (1U << CP0C3_MSAP)) 40603cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M) 407bee62662SJames Hogan #define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \ 408bee62662SJames Hogan (1U << CP0C5_UFE) | \ 409152db36aSJames Hogan (1U << CP0C5_FRE) | \ 410152db36aSJames Hogan (1U << CP0C5_UFR)) 4117e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \ 4127e0896b0SHuacai Chen (0x3fU << CP0C6_KPOS) | \ 4137e0896b0SHuacai Chen (1U << CP0C6_KE) | \ 4147e0896b0SHuacai Chen (1U << CP0C6_VTLBONLY) | \ 4157e0896b0SHuacai Chen (1U << CP0C6_LASX) | \ 4167e0896b0SHuacai Chen (1U << CP0C6_SSEN) | \ 4177e0896b0SHuacai Chen (1U << CP0C6_DISDRTIME) | \ 4187e0896b0SHuacai Chen (1U << CP0C6_PIXNUEN) | \ 4197e0896b0SHuacai Chen (1U << CP0C6_SCRAND) | \ 4207e0896b0SHuacai Chen (1U << CP0C6_LLEXCEN) | \ 4217e0896b0SHuacai Chen (1U << CP0C6_DISVC) | \ 4227e0896b0SHuacai Chen (1U << CP0C6_VCLRU) | \ 4237e0896b0SHuacai Chen (1U << CP0C6_DCLRU) | \ 4247e0896b0SHuacai Chen (1U << CP0C6_PIXUEN) | \ 4257e0896b0SHuacai Chen (1U << CP0C6_DISBLKLYEN) | \ 4267e0896b0SHuacai Chen (1U << CP0C6_UMEMUALEN) | \ 4277e0896b0SHuacai Chen (1U << CP0C6_SFBEN) | \ 4287e0896b0SHuacai Chen (1U << CP0C6_FLTINT) | \ 4297e0896b0SHuacai Chen (1U << CP0C6_VLTINT) | \ 4307e0896b0SHuacai Chen (1U << CP0C6_DISBTB) | \ 4317e0896b0SHuacai Chen (3U << CP0C6_STPREFCTL) | \ 4327e0896b0SHuacai Chen (1U << CP0C6_INSTPREF) | \ 4337e0896b0SHuacai Chen (1U << CP0C6_DATAPREF)) 43403cbfd7bSJames Hogan 43503cbfd7bSJames Hogan static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, 43603cbfd7bSJames Hogan int32_t *addr, int32_t mask) 43703cbfd7bSJames Hogan { 43803cbfd7bSJames Hogan int err; 43903cbfd7bSJames Hogan int32_t tmp, change; 44003cbfd7bSJames Hogan 44103cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, reg_id, &tmp); 44203cbfd7bSJames Hogan if (err < 0) { 44303cbfd7bSJames Hogan return err; 44403cbfd7bSJames Hogan } 44503cbfd7bSJames Hogan 44603cbfd7bSJames Hogan /* only change bits in mask */ 44703cbfd7bSJames Hogan change = (*addr ^ tmp) & mask; 44803cbfd7bSJames Hogan if (!change) { 44903cbfd7bSJames Hogan return 0; 45003cbfd7bSJames Hogan } 45103cbfd7bSJames Hogan 45203cbfd7bSJames Hogan tmp = tmp ^ change; 45303cbfd7bSJames Hogan return kvm_mips_put_one_reg(cs, reg_id, &tmp); 45403cbfd7bSJames Hogan } 45503cbfd7bSJames Hogan 456e2132e0bSSanjay Lal /* 457e2132e0bSSanjay Lal * We freeze the KVM timer when either the VM clock is stopped or the state is 458e2132e0bSSanjay Lal * saved (the state is dirty). 459e2132e0bSSanjay Lal */ 460e2132e0bSSanjay Lal 461e2132e0bSSanjay Lal /* 462e2132e0bSSanjay Lal * Save the state of the KVM timer when VM clock is stopped or state is synced 463e2132e0bSSanjay Lal * to QEMU. 464e2132e0bSSanjay Lal */ 465e2132e0bSSanjay Lal static int kvm_mips_save_count(CPUState *cs) 466e2132e0bSSanjay Lal { 4674c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 468e2132e0bSSanjay Lal uint64_t count_ctl; 469e2132e0bSSanjay Lal int err, ret = 0; 470e2132e0bSSanjay Lal 471e2132e0bSSanjay Lal /* freeze KVM timer */ 472d319f83fSJames Hogan err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 473e2132e0bSSanjay Lal if (err < 0) { 474e2132e0bSSanjay Lal DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err); 475e2132e0bSSanjay Lal ret = err; 476e2132e0bSSanjay Lal } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 477e2132e0bSSanjay Lal count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 478d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 479e2132e0bSSanjay Lal if (err < 0) { 480e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 481e2132e0bSSanjay Lal ret = err; 482e2132e0bSSanjay Lal } 483e2132e0bSSanjay Lal } 484e2132e0bSSanjay Lal 485e2132e0bSSanjay Lal /* read CP0_Cause */ 486e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 487e2132e0bSSanjay Lal if (err < 0) { 488e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err); 489e2132e0bSSanjay Lal ret = err; 490e2132e0bSSanjay Lal } 491e2132e0bSSanjay Lal 492e2132e0bSSanjay Lal /* read CP0_Count */ 493e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 494e2132e0bSSanjay Lal if (err < 0) { 495e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err); 496e2132e0bSSanjay Lal ret = err; 497e2132e0bSSanjay Lal } 498e2132e0bSSanjay Lal 499e2132e0bSSanjay Lal return ret; 500e2132e0bSSanjay Lal } 501e2132e0bSSanjay Lal 502e2132e0bSSanjay Lal /* 503e2132e0bSSanjay Lal * Restore the state of the KVM timer when VM clock is restarted or state is 504e2132e0bSSanjay Lal * synced to KVM. 505e2132e0bSSanjay Lal */ 506e2132e0bSSanjay Lal static int kvm_mips_restore_count(CPUState *cs) 507e2132e0bSSanjay Lal { 5084c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 509e2132e0bSSanjay Lal uint64_t count_ctl; 510e2132e0bSSanjay Lal int err_dc, err, ret = 0; 511e2132e0bSSanjay Lal 512e2132e0bSSanjay Lal /* check the timer is frozen */ 513d319f83fSJames Hogan err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 514e2132e0bSSanjay Lal if (err_dc < 0) { 515e2132e0bSSanjay Lal DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc); 516e2132e0bSSanjay Lal ret = err_dc; 517e2132e0bSSanjay Lal } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 518e2132e0bSSanjay Lal /* freeze timer (sets COUNT_RESUME for us) */ 519e2132e0bSSanjay Lal count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 520d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 521e2132e0bSSanjay Lal if (err < 0) { 522e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 523e2132e0bSSanjay Lal ret = err; 524e2132e0bSSanjay Lal } 525e2132e0bSSanjay Lal } 526e2132e0bSSanjay Lal 527e2132e0bSSanjay Lal /* load CP0_Cause */ 528e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 529e2132e0bSSanjay Lal if (err < 0) { 530e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err); 531e2132e0bSSanjay Lal ret = err; 532e2132e0bSSanjay Lal } 533e2132e0bSSanjay Lal 534e2132e0bSSanjay Lal /* load CP0_Count */ 535e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 536e2132e0bSSanjay Lal if (err < 0) { 537e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err); 538e2132e0bSSanjay Lal ret = err; 539e2132e0bSSanjay Lal } 540e2132e0bSSanjay Lal 541e2132e0bSSanjay Lal /* resume KVM timer */ 542e2132e0bSSanjay Lal if (err_dc >= 0) { 543e2132e0bSSanjay Lal count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC; 544d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 545e2132e0bSSanjay Lal if (err < 0) { 546e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err); 547e2132e0bSSanjay Lal ret = err; 548e2132e0bSSanjay Lal } 549e2132e0bSSanjay Lal } 550e2132e0bSSanjay Lal 551e2132e0bSSanjay Lal return ret; 552e2132e0bSSanjay Lal } 553e2132e0bSSanjay Lal 554e2132e0bSSanjay Lal /* 555e2132e0bSSanjay Lal * Handle the VM clock being started or stopped 556e2132e0bSSanjay Lal */ 557538f0497SPhilippe Mathieu-Daudé static void kvm_mips_update_state(void *opaque, bool running, RunState state) 558e2132e0bSSanjay Lal { 559e2132e0bSSanjay Lal CPUState *cs = opaque; 560e2132e0bSSanjay Lal int ret; 561e2132e0bSSanjay Lal uint64_t count_resume; 562e2132e0bSSanjay Lal 563e2132e0bSSanjay Lal /* 564e2132e0bSSanjay Lal * If state is already dirty (synced to QEMU) then the KVM timer state is 565e2132e0bSSanjay Lal * already saved and can be restored when it is synced back to KVM. 566e2132e0bSSanjay Lal */ 567e2132e0bSSanjay Lal if (!running) { 56899f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 569e2132e0bSSanjay Lal ret = kvm_mips_save_count(cs); 570e2132e0bSSanjay Lal if (ret < 0) { 571288cb949SAlistair Francis warn_report("Failed saving count"); 572e2132e0bSSanjay Lal } 573e2132e0bSSanjay Lal } 574e2132e0bSSanjay Lal } else { 575e2132e0bSSanjay Lal /* Set clock restore time to now */ 576906b53a2SPaolo Bonzini count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 577d319f83fSJames Hogan ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME, 578e2132e0bSSanjay Lal &count_resume); 579e2132e0bSSanjay Lal if (ret < 0) { 580288cb949SAlistair Francis warn_report("Failed setting COUNT_RESUME"); 581e2132e0bSSanjay Lal return; 582e2132e0bSSanjay Lal } 583e2132e0bSSanjay Lal 58499f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 585e2132e0bSSanjay Lal ret = kvm_mips_restore_count(cs); 586e2132e0bSSanjay Lal if (ret < 0) { 587288cb949SAlistair Francis warn_report("Failed restoring count"); 588e2132e0bSSanjay Lal } 589e2132e0bSSanjay Lal } 590e2132e0bSSanjay Lal } 591e2132e0bSSanjay Lal } 592e2132e0bSSanjay Lal 593152db36aSJames Hogan static int kvm_mips_put_fpu_registers(CPUState *cs, int level) 594152db36aSJames Hogan { 5954c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 596152db36aSJames Hogan int err, ret = 0; 597152db36aSJames Hogan unsigned int i; 598152db36aSJames Hogan 599152db36aSJames Hogan /* Only put FPU state if we're emulating a CPU with an FPU */ 600152db36aSJames Hogan if (env->CP0_Config1 & (1 << CP0C1_FP)) { 601152db36aSJames Hogan /* FPU Control Registers */ 602152db36aSJames Hogan if (level == KVM_PUT_FULL_STATE) { 603152db36aSJames Hogan err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 604152db36aSJames Hogan &env->active_fpu.fcr0); 605152db36aSJames Hogan if (err < 0) { 606152db36aSJames Hogan DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err); 607152db36aSJames Hogan ret = err; 608152db36aSJames Hogan } 609152db36aSJames Hogan } 610152db36aSJames Hogan err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 611152db36aSJames Hogan &env->active_fpu.fcr31); 612152db36aSJames Hogan if (err < 0) { 613152db36aSJames Hogan DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err); 614152db36aSJames Hogan ret = err; 615152db36aSJames Hogan } 616152db36aSJames Hogan 617bee62662SJames Hogan /* 618bee62662SJames Hogan * FPU register state is a subset of MSA vector state, so don't put FPU 619bee62662SJames Hogan * registers if we're emulating a CPU with MSA. 620bee62662SJames Hogan */ 62125a13628SPhilippe Mathieu-Daudé if (!ase_msa_available(env)) { 622152db36aSJames Hogan /* Floating point registers */ 623152db36aSJames Hogan for (i = 0; i < 32; ++i) { 624152db36aSJames Hogan if (env->CP0_Status & (1 << CP0St_FR)) { 625152db36aSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 626152db36aSJames Hogan &env->active_fpu.fpr[i].d); 627152db36aSJames Hogan } else { 628152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 629152db36aSJames Hogan &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 630152db36aSJames Hogan } 631152db36aSJames Hogan if (err < 0) { 632152db36aSJames Hogan DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err); 633152db36aSJames Hogan ret = err; 634152db36aSJames Hogan } 635152db36aSJames Hogan } 636152db36aSJames Hogan } 637bee62662SJames Hogan } 638bee62662SJames Hogan 639bee62662SJames Hogan /* Only put MSA state if we're emulating a CPU with MSA */ 64025a13628SPhilippe Mathieu-Daudé if (ase_msa_available(env)) { 641bee62662SJames Hogan /* MSA Control Registers */ 642bee62662SJames Hogan if (level == KVM_PUT_FULL_STATE) { 643bee62662SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR, 644bee62662SJames Hogan &env->msair); 645bee62662SJames Hogan if (err < 0) { 646bee62662SJames Hogan DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err); 647bee62662SJames Hogan ret = err; 648bee62662SJames Hogan } 649bee62662SJames Hogan } 650bee62662SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 651bee62662SJames Hogan &env->active_tc.msacsr); 652bee62662SJames Hogan if (err < 0) { 653bee62662SJames Hogan DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err); 654bee62662SJames Hogan ret = err; 655bee62662SJames Hogan } 656bee62662SJames Hogan 657bee62662SJames Hogan /* Vector registers (includes FP registers) */ 658bee62662SJames Hogan for (i = 0; i < 32; ++i) { 659bee62662SJames Hogan /* Big endian MSA not supported by QEMU yet anyway */ 660bee62662SJames Hogan err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 661bee62662SJames Hogan env->active_fpu.fpr[i].wr.d); 662bee62662SJames Hogan if (err < 0) { 663bee62662SJames Hogan DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err); 664bee62662SJames Hogan ret = err; 665bee62662SJames Hogan } 666bee62662SJames Hogan } 667bee62662SJames Hogan } 668152db36aSJames Hogan 669152db36aSJames Hogan return ret; 670152db36aSJames Hogan } 671152db36aSJames Hogan 672152db36aSJames Hogan static int kvm_mips_get_fpu_registers(CPUState *cs) 673152db36aSJames Hogan { 6744c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 675152db36aSJames Hogan int err, ret = 0; 676152db36aSJames Hogan unsigned int i; 677152db36aSJames Hogan 678152db36aSJames Hogan /* Only get FPU state if we're emulating a CPU with an FPU */ 679152db36aSJames Hogan if (env->CP0_Config1 & (1 << CP0C1_FP)) { 680152db36aSJames Hogan /* FPU Control Registers */ 681152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 682152db36aSJames Hogan &env->active_fpu.fcr0); 683152db36aSJames Hogan if (err < 0) { 684152db36aSJames Hogan DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err); 685152db36aSJames Hogan ret = err; 686152db36aSJames Hogan } 687152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 688152db36aSJames Hogan &env->active_fpu.fcr31); 689152db36aSJames Hogan if (err < 0) { 690152db36aSJames Hogan DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err); 691152db36aSJames Hogan ret = err; 692152db36aSJames Hogan } else { 693152db36aSJames Hogan restore_fp_status(env); 694152db36aSJames Hogan } 695152db36aSJames Hogan 696bee62662SJames Hogan /* 697bee62662SJames Hogan * FPU register state is a subset of MSA vector state, so don't save FPU 698bee62662SJames Hogan * registers if we're emulating a CPU with MSA. 699bee62662SJames Hogan */ 70025a13628SPhilippe Mathieu-Daudé if (!ase_msa_available(env)) { 701152db36aSJames Hogan /* Floating point registers */ 702152db36aSJames Hogan for (i = 0; i < 32; ++i) { 703152db36aSJames Hogan if (env->CP0_Status & (1 << CP0St_FR)) { 704152db36aSJames Hogan err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 705152db36aSJames Hogan &env->active_fpu.fpr[i].d); 706152db36aSJames Hogan } else { 707152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 708152db36aSJames Hogan &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 709152db36aSJames Hogan } 710152db36aSJames Hogan if (err < 0) { 711152db36aSJames Hogan DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err); 712152db36aSJames Hogan ret = err; 713152db36aSJames Hogan } 714152db36aSJames Hogan } 715152db36aSJames Hogan } 716bee62662SJames Hogan } 717bee62662SJames Hogan 718bee62662SJames Hogan /* Only get MSA state if we're emulating a CPU with MSA */ 71925a13628SPhilippe Mathieu-Daudé if (ase_msa_available(env)) { 720bee62662SJames Hogan /* MSA Control Registers */ 721bee62662SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR, 722bee62662SJames Hogan &env->msair); 723bee62662SJames Hogan if (err < 0) { 724bee62662SJames Hogan DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err); 725bee62662SJames Hogan ret = err; 726bee62662SJames Hogan } 727bee62662SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 728bee62662SJames Hogan &env->active_tc.msacsr); 729bee62662SJames Hogan if (err < 0) { 730bee62662SJames Hogan DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err); 731bee62662SJames Hogan ret = err; 732bee62662SJames Hogan } else { 733bee62662SJames Hogan restore_msa_fp_status(env); 734bee62662SJames Hogan } 735bee62662SJames Hogan 736bee62662SJames Hogan /* Vector registers (includes FP registers) */ 737bee62662SJames Hogan for (i = 0; i < 32; ++i) { 738bee62662SJames Hogan /* Big endian MSA not supported by QEMU yet anyway */ 739bee62662SJames Hogan err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 740bee62662SJames Hogan env->active_fpu.fpr[i].wr.d); 741bee62662SJames Hogan if (err < 0) { 742bee62662SJames Hogan DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err); 743bee62662SJames Hogan ret = err; 744bee62662SJames Hogan } 745bee62662SJames Hogan } 746bee62662SJames Hogan } 747152db36aSJames Hogan 748152db36aSJames Hogan return ret; 749152db36aSJames Hogan } 750152db36aSJames Hogan 751152db36aSJames Hogan 752e2132e0bSSanjay Lal static int kvm_mips_put_cp0_registers(CPUState *cs, int level) 753e2132e0bSSanjay Lal { 7544c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 755e2132e0bSSanjay Lal int err, ret = 0; 756e2132e0bSSanjay Lal 757e2132e0bSSanjay Lal (void)level; 758e2132e0bSSanjay Lal 759e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 760e2132e0bSSanjay Lal if (err < 0) { 761e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err); 762e2132e0bSSanjay Lal ret = err; 763e2132e0bSSanjay Lal } 7647e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 7657e0896b0SHuacai Chen if (err < 0) { 7667e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err); 7677e0896b0SHuacai Chen ret = err; 7687e0896b0SHuacai Chen } 769e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 770e2132e0bSSanjay Lal &env->CP0_Context); 771e2132e0bSSanjay Lal if (err < 0) { 772e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err); 773e2132e0bSSanjay Lal ret = err; 774e2132e0bSSanjay Lal } 775e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 776e2132e0bSSanjay Lal &env->active_tc.CP0_UserLocal); 777e2132e0bSSanjay Lal if (err < 0) { 778e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err); 779e2132e0bSSanjay Lal ret = err; 780e2132e0bSSanjay Lal } 781e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 782e2132e0bSSanjay Lal &env->CP0_PageMask); 783e2132e0bSSanjay Lal if (err < 0) { 784e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err); 785e2132e0bSSanjay Lal ret = err; 786e2132e0bSSanjay Lal } 7877e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 7887e0896b0SHuacai Chen &env->CP0_PageGrain); 7897e0896b0SHuacai Chen if (err < 0) { 7907e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err); 7917e0896b0SHuacai Chen ret = err; 7927e0896b0SHuacai Chen } 7937e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 7947e0896b0SHuacai Chen &env->CP0_PWBase); 7957e0896b0SHuacai Chen if (err < 0) { 7967e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err); 7977e0896b0SHuacai Chen ret = err; 7987e0896b0SHuacai Chen } 7997e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 8007e0896b0SHuacai Chen &env->CP0_PWField); 8017e0896b0SHuacai Chen if (err < 0) { 8027e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err); 8037e0896b0SHuacai Chen ret = err; 8047e0896b0SHuacai Chen } 8057e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 8067e0896b0SHuacai Chen &env->CP0_PWSize); 8077e0896b0SHuacai Chen if (err < 0) { 8087e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err); 8097e0896b0SHuacai Chen ret = err; 8107e0896b0SHuacai Chen } 811e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 812e2132e0bSSanjay Lal if (err < 0) { 813e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err); 814e2132e0bSSanjay Lal ret = err; 815e2132e0bSSanjay Lal } 8167e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 8177e0896b0SHuacai Chen if (err < 0) { 8187e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err); 8197e0896b0SHuacai Chen ret = err; 8207e0896b0SHuacai Chen } 821e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 822e2132e0bSSanjay Lal if (err < 0) { 823e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err); 824e2132e0bSSanjay Lal ret = err; 825e2132e0bSSanjay Lal } 826e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 827e2132e0bSSanjay Lal &env->CP0_BadVAddr); 828e2132e0bSSanjay Lal if (err < 0) { 829e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err); 830e2132e0bSSanjay Lal ret = err; 831e2132e0bSSanjay Lal } 832e2132e0bSSanjay Lal 833e2132e0bSSanjay Lal /* If VM clock stopped then state will be restored when it is restarted */ 834e2132e0bSSanjay Lal if (runstate_is_running()) { 835e2132e0bSSanjay Lal err = kvm_mips_restore_count(cs); 836e2132e0bSSanjay Lal if (err < 0) { 837e2132e0bSSanjay Lal ret = err; 838e2132e0bSSanjay Lal } 839e2132e0bSSanjay Lal } 840e2132e0bSSanjay Lal 841e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 842e2132e0bSSanjay Lal &env->CP0_EntryHi); 843e2132e0bSSanjay Lal if (err < 0) { 844e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err); 845e2132e0bSSanjay Lal ret = err; 846e2132e0bSSanjay Lal } 847e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 848e2132e0bSSanjay Lal &env->CP0_Compare); 849e2132e0bSSanjay Lal if (err < 0) { 850e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err); 851e2132e0bSSanjay Lal ret = err; 852e2132e0bSSanjay Lal } 853e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 854e2132e0bSSanjay Lal if (err < 0) { 855e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err); 856e2132e0bSSanjay Lal ret = err; 857e2132e0bSSanjay Lal } 858e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 859e2132e0bSSanjay Lal if (err < 0) { 860e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err); 861e2132e0bSSanjay Lal ret = err; 862e2132e0bSSanjay Lal } 863461a1582SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 864461a1582SJames Hogan if (err < 0) { 865461a1582SJames Hogan DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); 866461a1582SJames Hogan ret = err; 867461a1582SJames Hogan } 8687e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 8697e0896b0SHuacai Chen if (err < 0) { 8707e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err); 8717e0896b0SHuacai Chen ret = err; 8727e0896b0SHuacai Chen } 87303cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, 87403cbfd7bSJames Hogan &env->CP0_Config0, 87503cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG_MASK); 87603cbfd7bSJames Hogan if (err < 0) { 87703cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err); 87803cbfd7bSJames Hogan ret = err; 87903cbfd7bSJames Hogan } 88003cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, 88103cbfd7bSJames Hogan &env->CP0_Config1, 88203cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG1_MASK); 88303cbfd7bSJames Hogan if (err < 0) { 88403cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err); 88503cbfd7bSJames Hogan ret = err; 88603cbfd7bSJames Hogan } 88703cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, 88803cbfd7bSJames Hogan &env->CP0_Config2, 88903cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG2_MASK); 89003cbfd7bSJames Hogan if (err < 0) { 89103cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err); 89203cbfd7bSJames Hogan ret = err; 89303cbfd7bSJames Hogan } 89403cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, 89503cbfd7bSJames Hogan &env->CP0_Config3, 89603cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG3_MASK); 89703cbfd7bSJames Hogan if (err < 0) { 89803cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err); 89903cbfd7bSJames Hogan ret = err; 90003cbfd7bSJames Hogan } 90103cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, 90203cbfd7bSJames Hogan &env->CP0_Config4, 90303cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG4_MASK); 90403cbfd7bSJames Hogan if (err < 0) { 90503cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err); 90603cbfd7bSJames Hogan ret = err; 90703cbfd7bSJames Hogan } 90803cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, 90903cbfd7bSJames Hogan &env->CP0_Config5, 91003cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG5_MASK); 91103cbfd7bSJames Hogan if (err < 0) { 91203cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); 91303cbfd7bSJames Hogan ret = err; 91403cbfd7bSJames Hogan } 9157e0896b0SHuacai Chen err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, 9167e0896b0SHuacai Chen &env->CP0_Config6, 9177e0896b0SHuacai Chen KVM_REG_MIPS_CP0_CONFIG6_MASK); 9187e0896b0SHuacai Chen if (err < 0) { 9197e0896b0SHuacai Chen DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err); 9207e0896b0SHuacai Chen ret = err; 9217e0896b0SHuacai Chen } 9227e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 9237e0896b0SHuacai Chen &env->CP0_XContext); 9247e0896b0SHuacai Chen if (err < 0) { 9257e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err); 9267e0896b0SHuacai Chen ret = err; 9277e0896b0SHuacai Chen } 928e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 929e2132e0bSSanjay Lal &env->CP0_ErrorEPC); 930e2132e0bSSanjay Lal if (err < 0) { 931e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err); 932e2132e0bSSanjay Lal ret = err; 933e2132e0bSSanjay Lal } 9347e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 9357e0896b0SHuacai Chen &env->CP0_KScratch[0]); 9367e0896b0SHuacai Chen if (err < 0) { 9377e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err); 9387e0896b0SHuacai Chen ret = err; 9397e0896b0SHuacai Chen } 9407e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 9417e0896b0SHuacai Chen &env->CP0_KScratch[1]); 9427e0896b0SHuacai Chen if (err < 0) { 9437e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err); 9447e0896b0SHuacai Chen ret = err; 9457e0896b0SHuacai Chen } 9467e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 9477e0896b0SHuacai Chen &env->CP0_KScratch[2]); 9487e0896b0SHuacai Chen if (err < 0) { 9497e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err); 9507e0896b0SHuacai Chen ret = err; 9517e0896b0SHuacai Chen } 9527e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 9537e0896b0SHuacai Chen &env->CP0_KScratch[3]); 9547e0896b0SHuacai Chen if (err < 0) { 9557e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err); 9567e0896b0SHuacai Chen ret = err; 9577e0896b0SHuacai Chen } 9587e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 9597e0896b0SHuacai Chen &env->CP0_KScratch[4]); 9607e0896b0SHuacai Chen if (err < 0) { 9617e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err); 9627e0896b0SHuacai Chen ret = err; 9637e0896b0SHuacai Chen } 9647e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 9657e0896b0SHuacai Chen &env->CP0_KScratch[5]); 9667e0896b0SHuacai Chen if (err < 0) { 9677e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err); 9687e0896b0SHuacai Chen ret = err; 9697e0896b0SHuacai Chen } 970e2132e0bSSanjay Lal 971e2132e0bSSanjay Lal return ret; 972e2132e0bSSanjay Lal } 973e2132e0bSSanjay Lal 974e2132e0bSSanjay Lal static int kvm_mips_get_cp0_registers(CPUState *cs) 975e2132e0bSSanjay Lal { 9764c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 977e2132e0bSSanjay Lal int err, ret = 0; 978e2132e0bSSanjay Lal 979e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 980e2132e0bSSanjay Lal if (err < 0) { 981e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err); 982e2132e0bSSanjay Lal ret = err; 983e2132e0bSSanjay Lal } 9847e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 9857e0896b0SHuacai Chen if (err < 0) { 9867e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err); 9877e0896b0SHuacai Chen ret = err; 9887e0896b0SHuacai Chen } 989e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 990e2132e0bSSanjay Lal &env->CP0_Context); 991e2132e0bSSanjay Lal if (err < 0) { 992e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err); 993e2132e0bSSanjay Lal ret = err; 994e2132e0bSSanjay Lal } 995e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 996e2132e0bSSanjay Lal &env->active_tc.CP0_UserLocal); 997e2132e0bSSanjay Lal if (err < 0) { 998e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err); 999e2132e0bSSanjay Lal ret = err; 1000e2132e0bSSanjay Lal } 1001e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 1002e2132e0bSSanjay Lal &env->CP0_PageMask); 1003e2132e0bSSanjay Lal if (err < 0) { 1004e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err); 1005e2132e0bSSanjay Lal ret = err; 1006e2132e0bSSanjay Lal } 10077e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 10087e0896b0SHuacai Chen &env->CP0_PageGrain); 10097e0896b0SHuacai Chen if (err < 0) { 10107e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err); 10117e0896b0SHuacai Chen ret = err; 10127e0896b0SHuacai Chen } 10137e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 10147e0896b0SHuacai Chen &env->CP0_PWBase); 10157e0896b0SHuacai Chen if (err < 0) { 10167e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err); 10177e0896b0SHuacai Chen ret = err; 10187e0896b0SHuacai Chen } 10197e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 10207e0896b0SHuacai Chen &env->CP0_PWField); 10217e0896b0SHuacai Chen if (err < 0) { 10227e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err); 10237e0896b0SHuacai Chen ret = err; 10247e0896b0SHuacai Chen } 10257e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 10267e0896b0SHuacai Chen &env->CP0_PWSize); 10277e0896b0SHuacai Chen if (err < 0) { 10287e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err); 10297e0896b0SHuacai Chen ret = err; 10307e0896b0SHuacai Chen } 1031e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 1032e2132e0bSSanjay Lal if (err < 0) { 1033e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err); 1034e2132e0bSSanjay Lal ret = err; 1035e2132e0bSSanjay Lal } 10367e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 10377e0896b0SHuacai Chen if (err < 0) { 10387e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err); 10397e0896b0SHuacai Chen ret = err; 10407e0896b0SHuacai Chen } 1041e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 1042e2132e0bSSanjay Lal if (err < 0) { 1043e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err); 1044e2132e0bSSanjay Lal ret = err; 1045e2132e0bSSanjay Lal } 1046e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 1047e2132e0bSSanjay Lal &env->CP0_BadVAddr); 1048e2132e0bSSanjay Lal if (err < 0) { 1049e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err); 1050e2132e0bSSanjay Lal ret = err; 1051e2132e0bSSanjay Lal } 1052e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 1053e2132e0bSSanjay Lal &env->CP0_EntryHi); 1054e2132e0bSSanjay Lal if (err < 0) { 1055e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err); 1056e2132e0bSSanjay Lal ret = err; 1057e2132e0bSSanjay Lal } 1058e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 1059e2132e0bSSanjay Lal &env->CP0_Compare); 1060e2132e0bSSanjay Lal if (err < 0) { 1061e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err); 1062e2132e0bSSanjay Lal ret = err; 1063e2132e0bSSanjay Lal } 1064e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 1065e2132e0bSSanjay Lal if (err < 0) { 1066e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err); 1067e2132e0bSSanjay Lal ret = err; 1068e2132e0bSSanjay Lal } 1069e2132e0bSSanjay Lal 1070e2132e0bSSanjay Lal /* If VM clock stopped then state was already saved when it was stopped */ 1071e2132e0bSSanjay Lal if (runstate_is_running()) { 1072e2132e0bSSanjay Lal err = kvm_mips_save_count(cs); 1073e2132e0bSSanjay Lal if (err < 0) { 1074e2132e0bSSanjay Lal ret = err; 1075e2132e0bSSanjay Lal } 1076e2132e0bSSanjay Lal } 1077e2132e0bSSanjay Lal 1078e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 1079e2132e0bSSanjay Lal if (err < 0) { 1080e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err); 1081e2132e0bSSanjay Lal ret = err; 1082e2132e0bSSanjay Lal } 1083461a1582SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 1084461a1582SJames Hogan if (err < 0) { 1085461a1582SJames Hogan DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); 1086461a1582SJames Hogan ret = err; 1087461a1582SJames Hogan } 10887e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 10897e0896b0SHuacai Chen if (err < 0) { 10907e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err); 10917e0896b0SHuacai Chen ret = err; 10927e0896b0SHuacai Chen } 109303cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); 109403cbfd7bSJames Hogan if (err < 0) { 109503cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); 109603cbfd7bSJames Hogan ret = err; 109703cbfd7bSJames Hogan } 109803cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1); 109903cbfd7bSJames Hogan if (err < 0) { 110003cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err); 110103cbfd7bSJames Hogan ret = err; 110203cbfd7bSJames Hogan } 110303cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2); 110403cbfd7bSJames Hogan if (err < 0) { 110503cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err); 110603cbfd7bSJames Hogan ret = err; 110703cbfd7bSJames Hogan } 110803cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3); 110903cbfd7bSJames Hogan if (err < 0) { 111003cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err); 111103cbfd7bSJames Hogan ret = err; 111203cbfd7bSJames Hogan } 111303cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4); 111403cbfd7bSJames Hogan if (err < 0) { 111503cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err); 111603cbfd7bSJames Hogan ret = err; 111703cbfd7bSJames Hogan } 111803cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5); 111903cbfd7bSJames Hogan if (err < 0) { 112003cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); 112103cbfd7bSJames Hogan ret = err; 112203cbfd7bSJames Hogan } 11237e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6); 11247e0896b0SHuacai Chen if (err < 0) { 11257e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err); 11267e0896b0SHuacai Chen ret = err; 11277e0896b0SHuacai Chen } 11287e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 11297e0896b0SHuacai Chen &env->CP0_XContext); 11307e0896b0SHuacai Chen if (err < 0) { 11317e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err); 11327e0896b0SHuacai Chen ret = err; 11337e0896b0SHuacai Chen } 1134e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 1135e2132e0bSSanjay Lal &env->CP0_ErrorEPC); 1136e2132e0bSSanjay Lal if (err < 0) { 1137e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err); 1138e2132e0bSSanjay Lal ret = err; 1139e2132e0bSSanjay Lal } 11407e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 11417e0896b0SHuacai Chen &env->CP0_KScratch[0]); 11427e0896b0SHuacai Chen if (err < 0) { 11437e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err); 11447e0896b0SHuacai Chen ret = err; 11457e0896b0SHuacai Chen } 11467e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 11477e0896b0SHuacai Chen &env->CP0_KScratch[1]); 11487e0896b0SHuacai Chen if (err < 0) { 11497e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err); 11507e0896b0SHuacai Chen ret = err; 11517e0896b0SHuacai Chen } 11527e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 11537e0896b0SHuacai Chen &env->CP0_KScratch[2]); 11547e0896b0SHuacai Chen if (err < 0) { 11557e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err); 11567e0896b0SHuacai Chen ret = err; 11577e0896b0SHuacai Chen } 11587e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 11597e0896b0SHuacai Chen &env->CP0_KScratch[3]); 11607e0896b0SHuacai Chen if (err < 0) { 11617e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err); 11627e0896b0SHuacai Chen ret = err; 11637e0896b0SHuacai Chen } 11647e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 11657e0896b0SHuacai Chen &env->CP0_KScratch[4]); 11667e0896b0SHuacai Chen if (err < 0) { 11677e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err); 11687e0896b0SHuacai Chen ret = err; 11697e0896b0SHuacai Chen } 11707e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 11717e0896b0SHuacai Chen &env->CP0_KScratch[5]); 11727e0896b0SHuacai Chen if (err < 0) { 11737e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err); 11747e0896b0SHuacai Chen ret = err; 11757e0896b0SHuacai Chen } 1176e2132e0bSSanjay Lal 1177e2132e0bSSanjay Lal return ret; 1178e2132e0bSSanjay Lal } 1179e2132e0bSSanjay Lal 1180a1676bb3SJulia Suvorova int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) 1181e2132e0bSSanjay Lal { 11824c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 1183e2132e0bSSanjay Lal struct kvm_regs regs; 1184e2132e0bSSanjay Lal int ret; 1185e2132e0bSSanjay Lal int i; 1186e2132e0bSSanjay Lal 1187e2132e0bSSanjay Lal /* Set the registers based on QEMU's view of things */ 1188e2132e0bSSanjay Lal for (i = 0; i < 32; i++) { 118902dae26aSJames Hogan regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; 1190e2132e0bSSanjay Lal } 1191e2132e0bSSanjay Lal 119202dae26aSJames Hogan regs.hi = (int64_t)(target_long)env->active_tc.HI[0]; 119302dae26aSJames Hogan regs.lo = (int64_t)(target_long)env->active_tc.LO[0]; 119402dae26aSJames Hogan regs.pc = (int64_t)(target_long)env->active_tc.PC; 1195e2132e0bSSanjay Lal 1196e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 1197e2132e0bSSanjay Lal 1198e2132e0bSSanjay Lal if (ret < 0) { 1199e2132e0bSSanjay Lal return ret; 1200e2132e0bSSanjay Lal } 1201e2132e0bSSanjay Lal 1202e2132e0bSSanjay Lal ret = kvm_mips_put_cp0_registers(cs, level); 1203e2132e0bSSanjay Lal if (ret < 0) { 1204e2132e0bSSanjay Lal return ret; 1205e2132e0bSSanjay Lal } 1206e2132e0bSSanjay Lal 1207152db36aSJames Hogan ret = kvm_mips_put_fpu_registers(cs, level); 1208152db36aSJames Hogan if (ret < 0) { 1209152db36aSJames Hogan return ret; 1210152db36aSJames Hogan } 1211152db36aSJames Hogan 1212e2132e0bSSanjay Lal return ret; 1213e2132e0bSSanjay Lal } 1214e2132e0bSSanjay Lal 1215a1676bb3SJulia Suvorova int kvm_arch_get_registers(CPUState *cs, Error **errp) 1216e2132e0bSSanjay Lal { 12174c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 1218e2132e0bSSanjay Lal int ret = 0; 1219e2132e0bSSanjay Lal struct kvm_regs regs; 1220e2132e0bSSanjay Lal int i; 1221e2132e0bSSanjay Lal 1222e2132e0bSSanjay Lal /* Get the current register set as KVM seems it */ 1223e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1224e2132e0bSSanjay Lal 1225e2132e0bSSanjay Lal if (ret < 0) { 1226e2132e0bSSanjay Lal return ret; 1227e2132e0bSSanjay Lal } 1228e2132e0bSSanjay Lal 1229e2132e0bSSanjay Lal for (i = 0; i < 32; i++) { 1230e2132e0bSSanjay Lal env->active_tc.gpr[i] = regs.gpr[i]; 1231e2132e0bSSanjay Lal } 1232e2132e0bSSanjay Lal 1233e2132e0bSSanjay Lal env->active_tc.HI[0] = regs.hi; 1234e2132e0bSSanjay Lal env->active_tc.LO[0] = regs.lo; 1235e2132e0bSSanjay Lal env->active_tc.PC = regs.pc; 1236e2132e0bSSanjay Lal 1237e2132e0bSSanjay Lal kvm_mips_get_cp0_registers(cs); 1238152db36aSJames Hogan kvm_mips_get_fpu_registers(cs); 1239e2132e0bSSanjay Lal 1240e2132e0bSSanjay Lal return ret; 1241e2132e0bSSanjay Lal } 12429e03a040SFrank Blaschka 12439e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1244dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 12459e03a040SFrank Blaschka { 12469e03a040SFrank Blaschka return 0; 12479e03a040SFrank Blaschka } 12481850b6b7SEric Auger 124938d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 125038d87493SPeter Xu int vector, PCIDevice *dev) 125138d87493SPeter Xu { 125238d87493SPeter Xu return 0; 125338d87493SPeter Xu } 125438d87493SPeter Xu 125538d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 125638d87493SPeter Xu { 125738d87493SPeter Xu return 0; 125838d87493SPeter Xu } 125938d87493SPeter Xu 12601850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 12611850b6b7SEric Auger { 12621850b6b7SEric Auger abort(); 12631850b6b7SEric Auger } 1264719d109bSHuacai Chen 12655e0d6590SAkihiko Odaki int kvm_arch_get_default_type(MachineState *machine) 1266719d109bSHuacai Chen { 1267a8448735SPaolo Bonzini #if defined(KVM_CAP_MIPS_VZ) 1268719d109bSHuacai Chen int r; 1269719d109bSHuacai Chen KVMState *s = KVM_STATE(machine->accelerator); 1270719d109bSHuacai Chen 1271719d109bSHuacai Chen r = kvm_check_extension(s, KVM_CAP_MIPS_VZ); 1272719d109bSHuacai Chen if (r > 0) { 1273719d109bSHuacai Chen return KVM_VM_MIPS_VZ; 1274719d109bSHuacai Chen } 1275719d109bSHuacai Chen #endif 1276719d109bSHuacai Chen 1277875b3eb8SAkihiko Odaki error_report("KVM_VM_MIPS_VZ type is not available"); 1278719d109bSHuacai Chen return -1; 1279719d109bSHuacai Chen } 128092a5199bSTom Lendacky 12813dba0a33SPaolo Bonzini void kvm_arch_accel_class_init(ObjectClass *oc) 12823dba0a33SPaolo Bonzini { 12833dba0a33SPaolo Bonzini } 1284