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" 21e2132e0bSSanjay Lal #include "sysemu/kvm.h" 22719d109bSHuacai Chen #include "sysemu/kvm_int.h" 2354d31236SMarkus Armbruster #include "sysemu/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 64e2132e0bSSanjay Lal int kvm_arch_init_vcpu(CPUState *cs) 65e2132e0bSSanjay Lal { 664c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 67e2132e0bSSanjay Lal int ret = 0; 68e2132e0bSSanjay Lal 69e2132e0bSSanjay Lal qemu_add_vm_change_state_handler(kvm_mips_update_state, cs); 70e2132e0bSSanjay Lal 71152db36aSJames Hogan if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 72152db36aSJames Hogan ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0); 73152db36aSJames Hogan if (ret < 0) { 74152db36aSJames Hogan /* mark unsupported so it gets disabled on reset */ 75152db36aSJames Hogan kvm_mips_fpu_cap = 0; 76152db36aSJames Hogan ret = 0; 77152db36aSJames Hogan } 78152db36aSJames Hogan } 79152db36aSJames Hogan 8025a13628SPhilippe Mathieu-Daudé if (kvm_mips_msa_cap && ase_msa_available(env)) { 81bee62662SJames Hogan ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0); 82bee62662SJames Hogan if (ret < 0) { 83bee62662SJames Hogan /* mark unsupported so it gets disabled on reset */ 84bee62662SJames Hogan kvm_mips_msa_cap = 0; 85bee62662SJames Hogan ret = 0; 86bee62662SJames Hogan } 87bee62662SJames Hogan } 88bee62662SJames Hogan 89e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 90e2132e0bSSanjay Lal return ret; 91e2132e0bSSanjay Lal } 92e2132e0bSSanjay Lal 93b1115c99SLiran Alon int kvm_arch_destroy_vcpu(CPUState *cs) 94b1115c99SLiran Alon { 95b1115c99SLiran Alon return 0; 96b1115c99SLiran Alon } 97b1115c99SLiran Alon 98e2132e0bSSanjay Lal void kvm_mips_reset_vcpu(MIPSCPU *cpu) 99e2132e0bSSanjay Lal { 1000e928b12SJames Hogan CPUMIPSState *env = &cpu->env; 1010e928b12SJames Hogan 102152db36aSJames Hogan if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 1032ab4b135SAlistair Francis warn_report("KVM does not support FPU, disabling"); 1040e928b12SJames Hogan env->CP0_Config1 &= ~(1 << CP0C1_FP); 1050e928b12SJames Hogan } 10625a13628SPhilippe Mathieu-Daudé if (!kvm_mips_msa_cap && ase_msa_available(env)) { 1072ab4b135SAlistair Francis warn_report("KVM does not support MSA, disabling"); 108bee62662SJames Hogan env->CP0_Config3 &= ~(1 << CP0C3_MSAP); 109bee62662SJames Hogan } 1100e928b12SJames Hogan 111e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 112e2132e0bSSanjay Lal } 113e2132e0bSSanjay Lal 114e2132e0bSSanjay Lal int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 115e2132e0bSSanjay Lal { 116e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 117e2132e0bSSanjay Lal return 0; 118e2132e0bSSanjay Lal } 119e2132e0bSSanjay Lal 120e2132e0bSSanjay Lal int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 121e2132e0bSSanjay Lal { 122e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 123e2132e0bSSanjay Lal return 0; 124e2132e0bSSanjay Lal } 125e2132e0bSSanjay Lal 126e2132e0bSSanjay Lal static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) 127e2132e0bSSanjay Lal { 128e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 129e2132e0bSSanjay Lal 130e2132e0bSSanjay Lal return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP)); 131e2132e0bSSanjay Lal } 132e2132e0bSSanjay Lal 133e2132e0bSSanjay Lal 134e2132e0bSSanjay Lal void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 135e2132e0bSSanjay Lal { 136e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 137e2132e0bSSanjay Lal int r; 138e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 139e2132e0bSSanjay Lal 140195801d7SStefan Hajnoczi bql_lock(); 1414b8523eeSJan Kiszka 142e2132e0bSSanjay Lal if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 143e2132e0bSSanjay Lal cpu_mips_io_interrupts_pending(cpu)) { 144e2132e0bSSanjay Lal intr.cpu = -1; 145e2132e0bSSanjay Lal intr.irq = 2; 146e2132e0bSSanjay Lal r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 147e2132e0bSSanjay Lal if (r < 0) { 148e2132e0bSSanjay Lal error_report("%s: cpu %d: failed to inject IRQ %x", 149e2132e0bSSanjay Lal __func__, cs->cpu_index, intr.irq); 150e2132e0bSSanjay Lal } 151e2132e0bSSanjay Lal } 1524b8523eeSJan Kiszka 153195801d7SStefan Hajnoczi bql_unlock(); 154e2132e0bSSanjay Lal } 155e2132e0bSSanjay Lal 1564c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 157e2132e0bSSanjay Lal { 1584c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 159e2132e0bSSanjay Lal } 160e2132e0bSSanjay Lal 161e2132e0bSSanjay Lal int kvm_arch_process_async_events(CPUState *cs) 162e2132e0bSSanjay Lal { 163e2132e0bSSanjay Lal return cs->halted; 164e2132e0bSSanjay Lal } 165e2132e0bSSanjay Lal 166e2132e0bSSanjay Lal int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 167e2132e0bSSanjay Lal { 168e2132e0bSSanjay Lal int ret; 169e2132e0bSSanjay Lal 170e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 171e2132e0bSSanjay Lal switch (run->exit_reason) { 172e2132e0bSSanjay Lal default: 173e2132e0bSSanjay Lal error_report("%s: unknown exit reason %d", 174e2132e0bSSanjay Lal __func__, run->exit_reason); 175e2132e0bSSanjay Lal ret = -1; 176e2132e0bSSanjay Lal break; 177e2132e0bSSanjay Lal } 178e2132e0bSSanjay Lal 179e2132e0bSSanjay Lal return ret; 180e2132e0bSSanjay Lal } 181e2132e0bSSanjay Lal 182e2132e0bSSanjay Lal bool kvm_arch_stop_on_emulation_error(CPUState *cs) 183e2132e0bSSanjay Lal { 184e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 185e2132e0bSSanjay Lal return true; 186e2132e0bSSanjay Lal } 187e2132e0bSSanjay Lal 188e2132e0bSSanjay Lal void kvm_arch_init_irq_routing(KVMState *s) 189e2132e0bSSanjay Lal { 190e2132e0bSSanjay Lal } 191e2132e0bSSanjay Lal 192e2132e0bSSanjay Lal int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level) 193e2132e0bSSanjay Lal { 194e2132e0bSSanjay Lal CPUState *cs = CPU(cpu); 195e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 196e2132e0bSSanjay Lal 19711cb076bSPhilippe Mathieu-Daudé assert(kvm_enabled()); 198e2132e0bSSanjay Lal 199e2132e0bSSanjay Lal intr.cpu = -1; 200e2132e0bSSanjay Lal 201e2132e0bSSanjay Lal if (level) { 202e2132e0bSSanjay Lal intr.irq = irq; 203e2132e0bSSanjay Lal } else { 204e2132e0bSSanjay Lal intr.irq = -irq; 205e2132e0bSSanjay Lal } 206e2132e0bSSanjay Lal 207e2132e0bSSanjay Lal kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 208e2132e0bSSanjay Lal 209e2132e0bSSanjay Lal return 0; 210e2132e0bSSanjay Lal } 211e2132e0bSSanjay Lal 212e2132e0bSSanjay Lal int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) 213e2132e0bSSanjay Lal { 214e2132e0bSSanjay Lal CPUState *cs = current_cpu; 215e2132e0bSSanjay Lal CPUState *dest_cs = CPU(cpu); 216e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 217e2132e0bSSanjay Lal 21811cb076bSPhilippe Mathieu-Daudé assert(kvm_enabled()); 219e2132e0bSSanjay Lal 220e2132e0bSSanjay Lal intr.cpu = dest_cs->cpu_index; 221e2132e0bSSanjay Lal 222e2132e0bSSanjay Lal if (level) { 223e2132e0bSSanjay Lal intr.irq = irq; 224e2132e0bSSanjay Lal } else { 225e2132e0bSSanjay Lal intr.irq = -irq; 226e2132e0bSSanjay Lal } 227e2132e0bSSanjay Lal 228e2132e0bSSanjay Lal DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq); 229e2132e0bSSanjay Lal 230e2132e0bSSanjay Lal kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 231e2132e0bSSanjay Lal 232e2132e0bSSanjay Lal return 0; 233e2132e0bSSanjay Lal } 234e2132e0bSSanjay Lal 235e2132e0bSSanjay Lal #define MIPS_CP0_32(_R, _S) \ 2365a2db896SJames Hogan (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) 237e2132e0bSSanjay Lal 238e2132e0bSSanjay Lal #define MIPS_CP0_64(_R, _S) \ 2395a2db896SJames Hogan (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) 240e2132e0bSSanjay Lal 241e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) 2427e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0) 243e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0) 244e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2) 245e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0) 2467e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1) 2477e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5) 2487e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6) 2497e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7) 250e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0) 2517e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6) 252e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0) 253e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0) 254e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0) 255e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0) 256e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0) 257e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) 258e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) 259e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) 260461a1582SJames Hogan #define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) 2617e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1) 26203cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) 26303cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) 26403cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) 26503cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 26603cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) 26703cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) 2687e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6) 2697e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) 270e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 2717e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2) 2727e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3) 2737e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4) 2747e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5) 2757e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6) 2767e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7) 277e2132e0bSSanjay Lal 278e2132e0bSSanjay Lal static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, 279e2132e0bSSanjay Lal int32_t *addr) 280e2132e0bSSanjay Lal { 281e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 282e2132e0bSSanjay Lal .id = reg_id, 283f8b3e48bSJames Hogan .addr = (uintptr_t)addr 284e2132e0bSSanjay Lal }; 285e2132e0bSSanjay Lal 286e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 287e2132e0bSSanjay Lal } 288e2132e0bSSanjay Lal 2890759487bSJames Hogan static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id, 2900759487bSJames Hogan uint32_t *addr) 2910759487bSJames Hogan { 2920759487bSJames Hogan struct kvm_one_reg cp0reg = { 2930759487bSJames Hogan .id = reg_id, 2940759487bSJames Hogan .addr = (uintptr_t)addr 2950759487bSJames Hogan }; 2960759487bSJames Hogan 2970759487bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 2980759487bSJames Hogan } 2990759487bSJames Hogan 300e2132e0bSSanjay Lal static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, 301e2132e0bSSanjay Lal target_ulong *addr) 302e2132e0bSSanjay Lal { 303e2132e0bSSanjay Lal uint64_t val64 = *addr; 304e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 305e2132e0bSSanjay Lal .id = reg_id, 306e2132e0bSSanjay Lal .addr = (uintptr_t)&val64 307e2132e0bSSanjay Lal }; 308e2132e0bSSanjay Lal 309e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 310e2132e0bSSanjay Lal } 311e2132e0bSSanjay Lal 312e2132e0bSSanjay Lal static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id, 313d319f83fSJames Hogan int64_t *addr) 314d319f83fSJames Hogan { 315d319f83fSJames Hogan struct kvm_one_reg cp0reg = { 316d319f83fSJames Hogan .id = reg_id, 317d319f83fSJames Hogan .addr = (uintptr_t)addr 318d319f83fSJames Hogan }; 319d319f83fSJames Hogan 320d319f83fSJames Hogan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 321d319f83fSJames Hogan } 322d319f83fSJames Hogan 323d319f83fSJames Hogan static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id, 324e2132e0bSSanjay Lal uint64_t *addr) 325e2132e0bSSanjay Lal { 326e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 327e2132e0bSSanjay Lal .id = reg_id, 328e2132e0bSSanjay Lal .addr = (uintptr_t)addr 329e2132e0bSSanjay Lal }; 330e2132e0bSSanjay Lal 331e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 332e2132e0bSSanjay Lal } 333e2132e0bSSanjay Lal 334e2132e0bSSanjay Lal static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id, 335e2132e0bSSanjay Lal int32_t *addr) 336e2132e0bSSanjay Lal { 337e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 338e2132e0bSSanjay Lal .id = reg_id, 339f8b3e48bSJames Hogan .addr = (uintptr_t)addr 340e2132e0bSSanjay Lal }; 341e2132e0bSSanjay Lal 342f8b3e48bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 343e2132e0bSSanjay Lal } 344e2132e0bSSanjay Lal 3450759487bSJames Hogan static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id, 3460759487bSJames Hogan uint32_t *addr) 3470759487bSJames Hogan { 3480759487bSJames Hogan struct kvm_one_reg cp0reg = { 3490759487bSJames Hogan .id = reg_id, 3500759487bSJames Hogan .addr = (uintptr_t)addr 3510759487bSJames Hogan }; 3520759487bSJames Hogan 3530759487bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 3540759487bSJames Hogan } 3550759487bSJames Hogan 356182f42fdSPeter Maydell static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id, 357e2132e0bSSanjay Lal target_ulong *addr) 358e2132e0bSSanjay Lal { 359e2132e0bSSanjay Lal int ret; 360e2132e0bSSanjay Lal uint64_t val64 = 0; 361e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 362e2132e0bSSanjay Lal .id = reg_id, 363e2132e0bSSanjay Lal .addr = (uintptr_t)&val64 364e2132e0bSSanjay Lal }; 365e2132e0bSSanjay Lal 366e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 367e2132e0bSSanjay Lal if (ret >= 0) { 368e2132e0bSSanjay Lal *addr = val64; 369e2132e0bSSanjay Lal } 370e2132e0bSSanjay Lal return ret; 371e2132e0bSSanjay Lal } 372e2132e0bSSanjay Lal 373182f42fdSPeter Maydell static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id, 374d319f83fSJames Hogan int64_t *addr) 375d319f83fSJames Hogan { 376d319f83fSJames Hogan struct kvm_one_reg cp0reg = { 377d319f83fSJames Hogan .id = reg_id, 378d319f83fSJames Hogan .addr = (uintptr_t)addr 379d319f83fSJames Hogan }; 380d319f83fSJames Hogan 381d319f83fSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 382d319f83fSJames Hogan } 383d319f83fSJames Hogan 384d319f83fSJames Hogan static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, 385e2132e0bSSanjay Lal uint64_t *addr) 386e2132e0bSSanjay Lal { 387e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 388e2132e0bSSanjay Lal .id = reg_id, 389e2132e0bSSanjay Lal .addr = (uintptr_t)addr 390e2132e0bSSanjay Lal }; 391e2132e0bSSanjay Lal 392e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 393e2132e0bSSanjay Lal } 394e2132e0bSSanjay Lal 39503cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M) 396152db36aSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \ 397152db36aSJames Hogan (1U << CP0C1_FP)) 39803cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M) 399bee62662SJames Hogan #define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \ 400bee62662SJames Hogan (1U << CP0C3_MSAP)) 40103cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M) 402bee62662SJames Hogan #define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \ 403bee62662SJames Hogan (1U << CP0C5_UFE) | \ 404152db36aSJames Hogan (1U << CP0C5_FRE) | \ 405152db36aSJames Hogan (1U << CP0C5_UFR)) 4067e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \ 4077e0896b0SHuacai Chen (0x3fU << CP0C6_KPOS) | \ 4087e0896b0SHuacai Chen (1U << CP0C6_KE) | \ 4097e0896b0SHuacai Chen (1U << CP0C6_VTLBONLY) | \ 4107e0896b0SHuacai Chen (1U << CP0C6_LASX) | \ 4117e0896b0SHuacai Chen (1U << CP0C6_SSEN) | \ 4127e0896b0SHuacai Chen (1U << CP0C6_DISDRTIME) | \ 4137e0896b0SHuacai Chen (1U << CP0C6_PIXNUEN) | \ 4147e0896b0SHuacai Chen (1U << CP0C6_SCRAND) | \ 4157e0896b0SHuacai Chen (1U << CP0C6_LLEXCEN) | \ 4167e0896b0SHuacai Chen (1U << CP0C6_DISVC) | \ 4177e0896b0SHuacai Chen (1U << CP0C6_VCLRU) | \ 4187e0896b0SHuacai Chen (1U << CP0C6_DCLRU) | \ 4197e0896b0SHuacai Chen (1U << CP0C6_PIXUEN) | \ 4207e0896b0SHuacai Chen (1U << CP0C6_DISBLKLYEN) | \ 4217e0896b0SHuacai Chen (1U << CP0C6_UMEMUALEN) | \ 4227e0896b0SHuacai Chen (1U << CP0C6_SFBEN) | \ 4237e0896b0SHuacai Chen (1U << CP0C6_FLTINT) | \ 4247e0896b0SHuacai Chen (1U << CP0C6_VLTINT) | \ 4257e0896b0SHuacai Chen (1U << CP0C6_DISBTB) | \ 4267e0896b0SHuacai Chen (3U << CP0C6_STPREFCTL) | \ 4277e0896b0SHuacai Chen (1U << CP0C6_INSTPREF) | \ 4287e0896b0SHuacai Chen (1U << CP0C6_DATAPREF)) 42903cbfd7bSJames Hogan 43003cbfd7bSJames Hogan static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, 43103cbfd7bSJames Hogan int32_t *addr, int32_t mask) 43203cbfd7bSJames Hogan { 43303cbfd7bSJames Hogan int err; 43403cbfd7bSJames Hogan int32_t tmp, change; 43503cbfd7bSJames Hogan 43603cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, reg_id, &tmp); 43703cbfd7bSJames Hogan if (err < 0) { 43803cbfd7bSJames Hogan return err; 43903cbfd7bSJames Hogan } 44003cbfd7bSJames Hogan 44103cbfd7bSJames Hogan /* only change bits in mask */ 44203cbfd7bSJames Hogan change = (*addr ^ tmp) & mask; 44303cbfd7bSJames Hogan if (!change) { 44403cbfd7bSJames Hogan return 0; 44503cbfd7bSJames Hogan } 44603cbfd7bSJames Hogan 44703cbfd7bSJames Hogan tmp = tmp ^ change; 44803cbfd7bSJames Hogan return kvm_mips_put_one_reg(cs, reg_id, &tmp); 44903cbfd7bSJames Hogan } 45003cbfd7bSJames Hogan 451e2132e0bSSanjay Lal /* 452e2132e0bSSanjay Lal * We freeze the KVM timer when either the VM clock is stopped or the state is 453e2132e0bSSanjay Lal * saved (the state is dirty). 454e2132e0bSSanjay Lal */ 455e2132e0bSSanjay Lal 456e2132e0bSSanjay Lal /* 457e2132e0bSSanjay Lal * Save the state of the KVM timer when VM clock is stopped or state is synced 458e2132e0bSSanjay Lal * to QEMU. 459e2132e0bSSanjay Lal */ 460e2132e0bSSanjay Lal static int kvm_mips_save_count(CPUState *cs) 461e2132e0bSSanjay Lal { 4624c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 463e2132e0bSSanjay Lal uint64_t count_ctl; 464e2132e0bSSanjay Lal int err, ret = 0; 465e2132e0bSSanjay Lal 466e2132e0bSSanjay Lal /* freeze KVM timer */ 467d319f83fSJames Hogan err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 468e2132e0bSSanjay Lal if (err < 0) { 469e2132e0bSSanjay Lal DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err); 470e2132e0bSSanjay Lal ret = err; 471e2132e0bSSanjay Lal } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 472e2132e0bSSanjay Lal count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 473d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 474e2132e0bSSanjay Lal if (err < 0) { 475e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 476e2132e0bSSanjay Lal ret = err; 477e2132e0bSSanjay Lal } 478e2132e0bSSanjay Lal } 479e2132e0bSSanjay Lal 480e2132e0bSSanjay Lal /* read CP0_Cause */ 481e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 482e2132e0bSSanjay Lal if (err < 0) { 483e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err); 484e2132e0bSSanjay Lal ret = err; 485e2132e0bSSanjay Lal } 486e2132e0bSSanjay Lal 487e2132e0bSSanjay Lal /* read CP0_Count */ 488e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 489e2132e0bSSanjay Lal if (err < 0) { 490e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err); 491e2132e0bSSanjay Lal ret = err; 492e2132e0bSSanjay Lal } 493e2132e0bSSanjay Lal 494e2132e0bSSanjay Lal return ret; 495e2132e0bSSanjay Lal } 496e2132e0bSSanjay Lal 497e2132e0bSSanjay Lal /* 498e2132e0bSSanjay Lal * Restore the state of the KVM timer when VM clock is restarted or state is 499e2132e0bSSanjay Lal * synced to KVM. 500e2132e0bSSanjay Lal */ 501e2132e0bSSanjay Lal static int kvm_mips_restore_count(CPUState *cs) 502e2132e0bSSanjay Lal { 5034c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 504e2132e0bSSanjay Lal uint64_t count_ctl; 505e2132e0bSSanjay Lal int err_dc, err, ret = 0; 506e2132e0bSSanjay Lal 507e2132e0bSSanjay Lal /* check the timer is frozen */ 508d319f83fSJames Hogan err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 509e2132e0bSSanjay Lal if (err_dc < 0) { 510e2132e0bSSanjay Lal DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc); 511e2132e0bSSanjay Lal ret = err_dc; 512e2132e0bSSanjay Lal } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 513e2132e0bSSanjay Lal /* freeze timer (sets COUNT_RESUME for us) */ 514e2132e0bSSanjay Lal count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 515d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 516e2132e0bSSanjay Lal if (err < 0) { 517e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 518e2132e0bSSanjay Lal ret = err; 519e2132e0bSSanjay Lal } 520e2132e0bSSanjay Lal } 521e2132e0bSSanjay Lal 522e2132e0bSSanjay Lal /* load CP0_Cause */ 523e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 524e2132e0bSSanjay Lal if (err < 0) { 525e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err); 526e2132e0bSSanjay Lal ret = err; 527e2132e0bSSanjay Lal } 528e2132e0bSSanjay Lal 529e2132e0bSSanjay Lal /* load CP0_Count */ 530e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 531e2132e0bSSanjay Lal if (err < 0) { 532e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err); 533e2132e0bSSanjay Lal ret = err; 534e2132e0bSSanjay Lal } 535e2132e0bSSanjay Lal 536e2132e0bSSanjay Lal /* resume KVM timer */ 537e2132e0bSSanjay Lal if (err_dc >= 0) { 538e2132e0bSSanjay Lal count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC; 539d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 540e2132e0bSSanjay Lal if (err < 0) { 541e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err); 542e2132e0bSSanjay Lal ret = err; 543e2132e0bSSanjay Lal } 544e2132e0bSSanjay Lal } 545e2132e0bSSanjay Lal 546e2132e0bSSanjay Lal return ret; 547e2132e0bSSanjay Lal } 548e2132e0bSSanjay Lal 549e2132e0bSSanjay Lal /* 550e2132e0bSSanjay Lal * Handle the VM clock being started or stopped 551e2132e0bSSanjay Lal */ 552538f0497SPhilippe Mathieu-Daudé static void kvm_mips_update_state(void *opaque, bool running, RunState state) 553e2132e0bSSanjay Lal { 554e2132e0bSSanjay Lal CPUState *cs = opaque; 555e2132e0bSSanjay Lal int ret; 556e2132e0bSSanjay Lal uint64_t count_resume; 557e2132e0bSSanjay Lal 558e2132e0bSSanjay Lal /* 559e2132e0bSSanjay Lal * If state is already dirty (synced to QEMU) then the KVM timer state is 560e2132e0bSSanjay Lal * already saved and can be restored when it is synced back to KVM. 561e2132e0bSSanjay Lal */ 562e2132e0bSSanjay Lal if (!running) { 56399f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 564e2132e0bSSanjay Lal ret = kvm_mips_save_count(cs); 565e2132e0bSSanjay Lal if (ret < 0) { 566288cb949SAlistair Francis warn_report("Failed saving count"); 567e2132e0bSSanjay Lal } 568e2132e0bSSanjay Lal } 569e2132e0bSSanjay Lal } else { 570e2132e0bSSanjay Lal /* Set clock restore time to now */ 571906b53a2SPaolo Bonzini count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 572d319f83fSJames Hogan ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME, 573e2132e0bSSanjay Lal &count_resume); 574e2132e0bSSanjay Lal if (ret < 0) { 575288cb949SAlistair Francis warn_report("Failed setting COUNT_RESUME"); 576e2132e0bSSanjay Lal return; 577e2132e0bSSanjay Lal } 578e2132e0bSSanjay Lal 57999f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 580e2132e0bSSanjay Lal ret = kvm_mips_restore_count(cs); 581e2132e0bSSanjay Lal if (ret < 0) { 582288cb949SAlistair Francis warn_report("Failed restoring count"); 583e2132e0bSSanjay Lal } 584e2132e0bSSanjay Lal } 585e2132e0bSSanjay Lal } 586e2132e0bSSanjay Lal } 587e2132e0bSSanjay Lal 588152db36aSJames Hogan static int kvm_mips_put_fpu_registers(CPUState *cs, int level) 589152db36aSJames Hogan { 5904c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 591152db36aSJames Hogan int err, ret = 0; 592152db36aSJames Hogan unsigned int i; 593152db36aSJames Hogan 594152db36aSJames Hogan /* Only put FPU state if we're emulating a CPU with an FPU */ 595152db36aSJames Hogan if (env->CP0_Config1 & (1 << CP0C1_FP)) { 596152db36aSJames Hogan /* FPU Control Registers */ 597152db36aSJames Hogan if (level == KVM_PUT_FULL_STATE) { 598152db36aSJames Hogan err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 599152db36aSJames Hogan &env->active_fpu.fcr0); 600152db36aSJames Hogan if (err < 0) { 601152db36aSJames Hogan DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err); 602152db36aSJames Hogan ret = err; 603152db36aSJames Hogan } 604152db36aSJames Hogan } 605152db36aSJames Hogan err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 606152db36aSJames Hogan &env->active_fpu.fcr31); 607152db36aSJames Hogan if (err < 0) { 608152db36aSJames Hogan DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err); 609152db36aSJames Hogan ret = err; 610152db36aSJames Hogan } 611152db36aSJames Hogan 612bee62662SJames Hogan /* 613bee62662SJames Hogan * FPU register state is a subset of MSA vector state, so don't put FPU 614bee62662SJames Hogan * registers if we're emulating a CPU with MSA. 615bee62662SJames Hogan */ 61625a13628SPhilippe Mathieu-Daudé if (!ase_msa_available(env)) { 617152db36aSJames Hogan /* Floating point registers */ 618152db36aSJames Hogan for (i = 0; i < 32; ++i) { 619152db36aSJames Hogan if (env->CP0_Status & (1 << CP0St_FR)) { 620152db36aSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 621152db36aSJames Hogan &env->active_fpu.fpr[i].d); 622152db36aSJames Hogan } else { 623152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 624152db36aSJames Hogan &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 625152db36aSJames Hogan } 626152db36aSJames Hogan if (err < 0) { 627152db36aSJames Hogan DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err); 628152db36aSJames Hogan ret = err; 629152db36aSJames Hogan } 630152db36aSJames Hogan } 631152db36aSJames Hogan } 632bee62662SJames Hogan } 633bee62662SJames Hogan 634bee62662SJames Hogan /* Only put MSA state if we're emulating a CPU with MSA */ 63525a13628SPhilippe Mathieu-Daudé if (ase_msa_available(env)) { 636bee62662SJames Hogan /* MSA Control Registers */ 637bee62662SJames Hogan if (level == KVM_PUT_FULL_STATE) { 638bee62662SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR, 639bee62662SJames Hogan &env->msair); 640bee62662SJames Hogan if (err < 0) { 641bee62662SJames Hogan DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err); 642bee62662SJames Hogan ret = err; 643bee62662SJames Hogan } 644bee62662SJames Hogan } 645bee62662SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 646bee62662SJames Hogan &env->active_tc.msacsr); 647bee62662SJames Hogan if (err < 0) { 648bee62662SJames Hogan DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err); 649bee62662SJames Hogan ret = err; 650bee62662SJames Hogan } 651bee62662SJames Hogan 652bee62662SJames Hogan /* Vector registers (includes FP registers) */ 653bee62662SJames Hogan for (i = 0; i < 32; ++i) { 654bee62662SJames Hogan /* Big endian MSA not supported by QEMU yet anyway */ 655bee62662SJames Hogan err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 656bee62662SJames Hogan env->active_fpu.fpr[i].wr.d); 657bee62662SJames Hogan if (err < 0) { 658bee62662SJames Hogan DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err); 659bee62662SJames Hogan ret = err; 660bee62662SJames Hogan } 661bee62662SJames Hogan } 662bee62662SJames Hogan } 663152db36aSJames Hogan 664152db36aSJames Hogan return ret; 665152db36aSJames Hogan } 666152db36aSJames Hogan 667152db36aSJames Hogan static int kvm_mips_get_fpu_registers(CPUState *cs) 668152db36aSJames Hogan { 6694c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 670152db36aSJames Hogan int err, ret = 0; 671152db36aSJames Hogan unsigned int i; 672152db36aSJames Hogan 673152db36aSJames Hogan /* Only get FPU state if we're emulating a CPU with an FPU */ 674152db36aSJames Hogan if (env->CP0_Config1 & (1 << CP0C1_FP)) { 675152db36aSJames Hogan /* FPU Control Registers */ 676152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 677152db36aSJames Hogan &env->active_fpu.fcr0); 678152db36aSJames Hogan if (err < 0) { 679152db36aSJames Hogan DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err); 680152db36aSJames Hogan ret = err; 681152db36aSJames Hogan } 682152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 683152db36aSJames Hogan &env->active_fpu.fcr31); 684152db36aSJames Hogan if (err < 0) { 685152db36aSJames Hogan DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err); 686152db36aSJames Hogan ret = err; 687152db36aSJames Hogan } else { 688152db36aSJames Hogan restore_fp_status(env); 689152db36aSJames Hogan } 690152db36aSJames Hogan 691bee62662SJames Hogan /* 692bee62662SJames Hogan * FPU register state is a subset of MSA vector state, so don't save FPU 693bee62662SJames Hogan * registers if we're emulating a CPU with MSA. 694bee62662SJames Hogan */ 69525a13628SPhilippe Mathieu-Daudé if (!ase_msa_available(env)) { 696152db36aSJames Hogan /* Floating point registers */ 697152db36aSJames Hogan for (i = 0; i < 32; ++i) { 698152db36aSJames Hogan if (env->CP0_Status & (1 << CP0St_FR)) { 699152db36aSJames Hogan err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 700152db36aSJames Hogan &env->active_fpu.fpr[i].d); 701152db36aSJames Hogan } else { 702152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 703152db36aSJames Hogan &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 704152db36aSJames Hogan } 705152db36aSJames Hogan if (err < 0) { 706152db36aSJames Hogan DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err); 707152db36aSJames Hogan ret = err; 708152db36aSJames Hogan } 709152db36aSJames Hogan } 710152db36aSJames Hogan } 711bee62662SJames Hogan } 712bee62662SJames Hogan 713bee62662SJames Hogan /* Only get MSA state if we're emulating a CPU with MSA */ 71425a13628SPhilippe Mathieu-Daudé if (ase_msa_available(env)) { 715bee62662SJames Hogan /* MSA Control Registers */ 716bee62662SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR, 717bee62662SJames Hogan &env->msair); 718bee62662SJames Hogan if (err < 0) { 719bee62662SJames Hogan DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err); 720bee62662SJames Hogan ret = err; 721bee62662SJames Hogan } 722bee62662SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 723bee62662SJames Hogan &env->active_tc.msacsr); 724bee62662SJames Hogan if (err < 0) { 725bee62662SJames Hogan DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err); 726bee62662SJames Hogan ret = err; 727bee62662SJames Hogan } else { 728bee62662SJames Hogan restore_msa_fp_status(env); 729bee62662SJames Hogan } 730bee62662SJames Hogan 731bee62662SJames Hogan /* Vector registers (includes FP registers) */ 732bee62662SJames Hogan for (i = 0; i < 32; ++i) { 733bee62662SJames Hogan /* Big endian MSA not supported by QEMU yet anyway */ 734bee62662SJames Hogan err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 735bee62662SJames Hogan env->active_fpu.fpr[i].wr.d); 736bee62662SJames Hogan if (err < 0) { 737bee62662SJames Hogan DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err); 738bee62662SJames Hogan ret = err; 739bee62662SJames Hogan } 740bee62662SJames Hogan } 741bee62662SJames Hogan } 742152db36aSJames Hogan 743152db36aSJames Hogan return ret; 744152db36aSJames Hogan } 745152db36aSJames Hogan 746152db36aSJames Hogan 747e2132e0bSSanjay Lal static int kvm_mips_put_cp0_registers(CPUState *cs, int level) 748e2132e0bSSanjay Lal { 7494c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 750e2132e0bSSanjay Lal int err, ret = 0; 751e2132e0bSSanjay Lal 752e2132e0bSSanjay Lal (void)level; 753e2132e0bSSanjay Lal 754e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 755e2132e0bSSanjay Lal if (err < 0) { 756e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err); 757e2132e0bSSanjay Lal ret = err; 758e2132e0bSSanjay Lal } 7597e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 7607e0896b0SHuacai Chen if (err < 0) { 7617e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err); 7627e0896b0SHuacai Chen ret = err; 7637e0896b0SHuacai Chen } 764e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 765e2132e0bSSanjay Lal &env->CP0_Context); 766e2132e0bSSanjay Lal if (err < 0) { 767e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err); 768e2132e0bSSanjay Lal ret = err; 769e2132e0bSSanjay Lal } 770e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 771e2132e0bSSanjay Lal &env->active_tc.CP0_UserLocal); 772e2132e0bSSanjay Lal if (err < 0) { 773e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err); 774e2132e0bSSanjay Lal ret = err; 775e2132e0bSSanjay Lal } 776e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 777e2132e0bSSanjay Lal &env->CP0_PageMask); 778e2132e0bSSanjay Lal if (err < 0) { 779e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err); 780e2132e0bSSanjay Lal ret = err; 781e2132e0bSSanjay Lal } 7827e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 7837e0896b0SHuacai Chen &env->CP0_PageGrain); 7847e0896b0SHuacai Chen if (err < 0) { 7857e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err); 7867e0896b0SHuacai Chen ret = err; 7877e0896b0SHuacai Chen } 7887e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 7897e0896b0SHuacai Chen &env->CP0_PWBase); 7907e0896b0SHuacai Chen if (err < 0) { 7917e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err); 7927e0896b0SHuacai Chen ret = err; 7937e0896b0SHuacai Chen } 7947e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 7957e0896b0SHuacai Chen &env->CP0_PWField); 7967e0896b0SHuacai Chen if (err < 0) { 7977e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err); 7987e0896b0SHuacai Chen ret = err; 7997e0896b0SHuacai Chen } 8007e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 8017e0896b0SHuacai Chen &env->CP0_PWSize); 8027e0896b0SHuacai Chen if (err < 0) { 8037e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err); 8047e0896b0SHuacai Chen ret = err; 8057e0896b0SHuacai Chen } 806e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 807e2132e0bSSanjay Lal if (err < 0) { 808e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err); 809e2132e0bSSanjay Lal ret = err; 810e2132e0bSSanjay Lal } 8117e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 8127e0896b0SHuacai Chen if (err < 0) { 8137e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err); 8147e0896b0SHuacai Chen ret = err; 8157e0896b0SHuacai Chen } 816e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 817e2132e0bSSanjay Lal if (err < 0) { 818e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err); 819e2132e0bSSanjay Lal ret = err; 820e2132e0bSSanjay Lal } 821e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 822e2132e0bSSanjay Lal &env->CP0_BadVAddr); 823e2132e0bSSanjay Lal if (err < 0) { 824e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err); 825e2132e0bSSanjay Lal ret = err; 826e2132e0bSSanjay Lal } 827e2132e0bSSanjay Lal 828e2132e0bSSanjay Lal /* If VM clock stopped then state will be restored when it is restarted */ 829e2132e0bSSanjay Lal if (runstate_is_running()) { 830e2132e0bSSanjay Lal err = kvm_mips_restore_count(cs); 831e2132e0bSSanjay Lal if (err < 0) { 832e2132e0bSSanjay Lal ret = err; 833e2132e0bSSanjay Lal } 834e2132e0bSSanjay Lal } 835e2132e0bSSanjay Lal 836e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 837e2132e0bSSanjay Lal &env->CP0_EntryHi); 838e2132e0bSSanjay Lal if (err < 0) { 839e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err); 840e2132e0bSSanjay Lal ret = err; 841e2132e0bSSanjay Lal } 842e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 843e2132e0bSSanjay Lal &env->CP0_Compare); 844e2132e0bSSanjay Lal if (err < 0) { 845e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err); 846e2132e0bSSanjay Lal ret = err; 847e2132e0bSSanjay Lal } 848e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 849e2132e0bSSanjay Lal if (err < 0) { 850e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err); 851e2132e0bSSanjay Lal ret = err; 852e2132e0bSSanjay Lal } 853e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 854e2132e0bSSanjay Lal if (err < 0) { 855e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err); 856e2132e0bSSanjay Lal ret = err; 857e2132e0bSSanjay Lal } 858461a1582SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 859461a1582SJames Hogan if (err < 0) { 860461a1582SJames Hogan DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); 861461a1582SJames Hogan ret = err; 862461a1582SJames Hogan } 8637e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 8647e0896b0SHuacai Chen if (err < 0) { 8657e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err); 8667e0896b0SHuacai Chen ret = err; 8677e0896b0SHuacai Chen } 86803cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, 86903cbfd7bSJames Hogan &env->CP0_Config0, 87003cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG_MASK); 87103cbfd7bSJames Hogan if (err < 0) { 87203cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err); 87303cbfd7bSJames Hogan ret = err; 87403cbfd7bSJames Hogan } 87503cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, 87603cbfd7bSJames Hogan &env->CP0_Config1, 87703cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG1_MASK); 87803cbfd7bSJames Hogan if (err < 0) { 87903cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err); 88003cbfd7bSJames Hogan ret = err; 88103cbfd7bSJames Hogan } 88203cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, 88303cbfd7bSJames Hogan &env->CP0_Config2, 88403cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG2_MASK); 88503cbfd7bSJames Hogan if (err < 0) { 88603cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err); 88703cbfd7bSJames Hogan ret = err; 88803cbfd7bSJames Hogan } 88903cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, 89003cbfd7bSJames Hogan &env->CP0_Config3, 89103cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG3_MASK); 89203cbfd7bSJames Hogan if (err < 0) { 89303cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err); 89403cbfd7bSJames Hogan ret = err; 89503cbfd7bSJames Hogan } 89603cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, 89703cbfd7bSJames Hogan &env->CP0_Config4, 89803cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG4_MASK); 89903cbfd7bSJames Hogan if (err < 0) { 90003cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err); 90103cbfd7bSJames Hogan ret = err; 90203cbfd7bSJames Hogan } 90303cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, 90403cbfd7bSJames Hogan &env->CP0_Config5, 90503cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG5_MASK); 90603cbfd7bSJames Hogan if (err < 0) { 90703cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); 90803cbfd7bSJames Hogan ret = err; 90903cbfd7bSJames Hogan } 9107e0896b0SHuacai Chen err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, 9117e0896b0SHuacai Chen &env->CP0_Config6, 9127e0896b0SHuacai Chen KVM_REG_MIPS_CP0_CONFIG6_MASK); 9137e0896b0SHuacai Chen if (err < 0) { 9147e0896b0SHuacai Chen DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err); 9157e0896b0SHuacai Chen ret = err; 9167e0896b0SHuacai Chen } 9177e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 9187e0896b0SHuacai Chen &env->CP0_XContext); 9197e0896b0SHuacai Chen if (err < 0) { 9207e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err); 9217e0896b0SHuacai Chen ret = err; 9227e0896b0SHuacai Chen } 923e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 924e2132e0bSSanjay Lal &env->CP0_ErrorEPC); 925e2132e0bSSanjay Lal if (err < 0) { 926e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err); 927e2132e0bSSanjay Lal ret = err; 928e2132e0bSSanjay Lal } 9297e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 9307e0896b0SHuacai Chen &env->CP0_KScratch[0]); 9317e0896b0SHuacai Chen if (err < 0) { 9327e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err); 9337e0896b0SHuacai Chen ret = err; 9347e0896b0SHuacai Chen } 9357e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 9367e0896b0SHuacai Chen &env->CP0_KScratch[1]); 9377e0896b0SHuacai Chen if (err < 0) { 9387e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err); 9397e0896b0SHuacai Chen ret = err; 9407e0896b0SHuacai Chen } 9417e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 9427e0896b0SHuacai Chen &env->CP0_KScratch[2]); 9437e0896b0SHuacai Chen if (err < 0) { 9447e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err); 9457e0896b0SHuacai Chen ret = err; 9467e0896b0SHuacai Chen } 9477e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 9487e0896b0SHuacai Chen &env->CP0_KScratch[3]); 9497e0896b0SHuacai Chen if (err < 0) { 9507e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err); 9517e0896b0SHuacai Chen ret = err; 9527e0896b0SHuacai Chen } 9537e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 9547e0896b0SHuacai Chen &env->CP0_KScratch[4]); 9557e0896b0SHuacai Chen if (err < 0) { 9567e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err); 9577e0896b0SHuacai Chen ret = err; 9587e0896b0SHuacai Chen } 9597e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 9607e0896b0SHuacai Chen &env->CP0_KScratch[5]); 9617e0896b0SHuacai Chen if (err < 0) { 9627e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err); 9637e0896b0SHuacai Chen ret = err; 9647e0896b0SHuacai Chen } 965e2132e0bSSanjay Lal 966e2132e0bSSanjay Lal return ret; 967e2132e0bSSanjay Lal } 968e2132e0bSSanjay Lal 969e2132e0bSSanjay Lal static int kvm_mips_get_cp0_registers(CPUState *cs) 970e2132e0bSSanjay Lal { 9714c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 972e2132e0bSSanjay Lal int err, ret = 0; 973e2132e0bSSanjay Lal 974e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 975e2132e0bSSanjay Lal if (err < 0) { 976e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err); 977e2132e0bSSanjay Lal ret = err; 978e2132e0bSSanjay Lal } 9797e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 9807e0896b0SHuacai Chen if (err < 0) { 9817e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err); 9827e0896b0SHuacai Chen ret = err; 9837e0896b0SHuacai Chen } 984e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 985e2132e0bSSanjay Lal &env->CP0_Context); 986e2132e0bSSanjay Lal if (err < 0) { 987e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err); 988e2132e0bSSanjay Lal ret = err; 989e2132e0bSSanjay Lal } 990e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 991e2132e0bSSanjay Lal &env->active_tc.CP0_UserLocal); 992e2132e0bSSanjay Lal if (err < 0) { 993e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err); 994e2132e0bSSanjay Lal ret = err; 995e2132e0bSSanjay Lal } 996e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 997e2132e0bSSanjay Lal &env->CP0_PageMask); 998e2132e0bSSanjay Lal if (err < 0) { 999e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err); 1000e2132e0bSSanjay Lal ret = err; 1001e2132e0bSSanjay Lal } 10027e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 10037e0896b0SHuacai Chen &env->CP0_PageGrain); 10047e0896b0SHuacai Chen if (err < 0) { 10057e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err); 10067e0896b0SHuacai Chen ret = err; 10077e0896b0SHuacai Chen } 10087e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 10097e0896b0SHuacai Chen &env->CP0_PWBase); 10107e0896b0SHuacai Chen if (err < 0) { 10117e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err); 10127e0896b0SHuacai Chen ret = err; 10137e0896b0SHuacai Chen } 10147e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 10157e0896b0SHuacai Chen &env->CP0_PWField); 10167e0896b0SHuacai Chen if (err < 0) { 10177e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err); 10187e0896b0SHuacai Chen ret = err; 10197e0896b0SHuacai Chen } 10207e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 10217e0896b0SHuacai Chen &env->CP0_PWSize); 10227e0896b0SHuacai Chen if (err < 0) { 10237e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err); 10247e0896b0SHuacai Chen ret = err; 10257e0896b0SHuacai Chen } 1026e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 1027e2132e0bSSanjay Lal if (err < 0) { 1028e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err); 1029e2132e0bSSanjay Lal ret = err; 1030e2132e0bSSanjay Lal } 10317e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 10327e0896b0SHuacai Chen if (err < 0) { 10337e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err); 10347e0896b0SHuacai Chen ret = err; 10357e0896b0SHuacai Chen } 1036e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 1037e2132e0bSSanjay Lal if (err < 0) { 1038e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err); 1039e2132e0bSSanjay Lal ret = err; 1040e2132e0bSSanjay Lal } 1041e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 1042e2132e0bSSanjay Lal &env->CP0_BadVAddr); 1043e2132e0bSSanjay Lal if (err < 0) { 1044e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err); 1045e2132e0bSSanjay Lal ret = err; 1046e2132e0bSSanjay Lal } 1047e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 1048e2132e0bSSanjay Lal &env->CP0_EntryHi); 1049e2132e0bSSanjay Lal if (err < 0) { 1050e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err); 1051e2132e0bSSanjay Lal ret = err; 1052e2132e0bSSanjay Lal } 1053e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 1054e2132e0bSSanjay Lal &env->CP0_Compare); 1055e2132e0bSSanjay Lal if (err < 0) { 1056e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err); 1057e2132e0bSSanjay Lal ret = err; 1058e2132e0bSSanjay Lal } 1059e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 1060e2132e0bSSanjay Lal if (err < 0) { 1061e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err); 1062e2132e0bSSanjay Lal ret = err; 1063e2132e0bSSanjay Lal } 1064e2132e0bSSanjay Lal 1065e2132e0bSSanjay Lal /* If VM clock stopped then state was already saved when it was stopped */ 1066e2132e0bSSanjay Lal if (runstate_is_running()) { 1067e2132e0bSSanjay Lal err = kvm_mips_save_count(cs); 1068e2132e0bSSanjay Lal if (err < 0) { 1069e2132e0bSSanjay Lal ret = err; 1070e2132e0bSSanjay Lal } 1071e2132e0bSSanjay Lal } 1072e2132e0bSSanjay Lal 1073e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 1074e2132e0bSSanjay Lal if (err < 0) { 1075e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err); 1076e2132e0bSSanjay Lal ret = err; 1077e2132e0bSSanjay Lal } 1078461a1582SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 1079461a1582SJames Hogan if (err < 0) { 1080461a1582SJames Hogan DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); 1081461a1582SJames Hogan ret = err; 1082461a1582SJames Hogan } 10837e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 10847e0896b0SHuacai Chen if (err < 0) { 10857e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err); 10867e0896b0SHuacai Chen ret = err; 10877e0896b0SHuacai Chen } 108803cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); 108903cbfd7bSJames Hogan if (err < 0) { 109003cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); 109103cbfd7bSJames Hogan ret = err; 109203cbfd7bSJames Hogan } 109303cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1); 109403cbfd7bSJames Hogan if (err < 0) { 109503cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err); 109603cbfd7bSJames Hogan ret = err; 109703cbfd7bSJames Hogan } 109803cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2); 109903cbfd7bSJames Hogan if (err < 0) { 110003cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err); 110103cbfd7bSJames Hogan ret = err; 110203cbfd7bSJames Hogan } 110303cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3); 110403cbfd7bSJames Hogan if (err < 0) { 110503cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err); 110603cbfd7bSJames Hogan ret = err; 110703cbfd7bSJames Hogan } 110803cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4); 110903cbfd7bSJames Hogan if (err < 0) { 111003cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err); 111103cbfd7bSJames Hogan ret = err; 111203cbfd7bSJames Hogan } 111303cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5); 111403cbfd7bSJames Hogan if (err < 0) { 111503cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); 111603cbfd7bSJames Hogan ret = err; 111703cbfd7bSJames Hogan } 11187e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6); 11197e0896b0SHuacai Chen if (err < 0) { 11207e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err); 11217e0896b0SHuacai Chen ret = err; 11227e0896b0SHuacai Chen } 11237e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 11247e0896b0SHuacai Chen &env->CP0_XContext); 11257e0896b0SHuacai Chen if (err < 0) { 11267e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err); 11277e0896b0SHuacai Chen ret = err; 11287e0896b0SHuacai Chen } 1129e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 1130e2132e0bSSanjay Lal &env->CP0_ErrorEPC); 1131e2132e0bSSanjay Lal if (err < 0) { 1132e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err); 1133e2132e0bSSanjay Lal ret = err; 1134e2132e0bSSanjay Lal } 11357e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 11367e0896b0SHuacai Chen &env->CP0_KScratch[0]); 11377e0896b0SHuacai Chen if (err < 0) { 11387e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err); 11397e0896b0SHuacai Chen ret = err; 11407e0896b0SHuacai Chen } 11417e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 11427e0896b0SHuacai Chen &env->CP0_KScratch[1]); 11437e0896b0SHuacai Chen if (err < 0) { 11447e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err); 11457e0896b0SHuacai Chen ret = err; 11467e0896b0SHuacai Chen } 11477e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 11487e0896b0SHuacai Chen &env->CP0_KScratch[2]); 11497e0896b0SHuacai Chen if (err < 0) { 11507e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err); 11517e0896b0SHuacai Chen ret = err; 11527e0896b0SHuacai Chen } 11537e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 11547e0896b0SHuacai Chen &env->CP0_KScratch[3]); 11557e0896b0SHuacai Chen if (err < 0) { 11567e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err); 11577e0896b0SHuacai Chen ret = err; 11587e0896b0SHuacai Chen } 11597e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 11607e0896b0SHuacai Chen &env->CP0_KScratch[4]); 11617e0896b0SHuacai Chen if (err < 0) { 11627e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err); 11637e0896b0SHuacai Chen ret = err; 11647e0896b0SHuacai Chen } 11657e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 11667e0896b0SHuacai Chen &env->CP0_KScratch[5]); 11677e0896b0SHuacai Chen if (err < 0) { 11687e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err); 11697e0896b0SHuacai Chen ret = err; 11707e0896b0SHuacai Chen } 1171e2132e0bSSanjay Lal 1172e2132e0bSSanjay Lal return ret; 1173e2132e0bSSanjay Lal } 1174e2132e0bSSanjay Lal 1175*a1676bb3SJulia Suvorova int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) 1176e2132e0bSSanjay Lal { 11774c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 1178e2132e0bSSanjay Lal struct kvm_regs regs; 1179e2132e0bSSanjay Lal int ret; 1180e2132e0bSSanjay Lal int i; 1181e2132e0bSSanjay Lal 1182e2132e0bSSanjay Lal /* Set the registers based on QEMU's view of things */ 1183e2132e0bSSanjay Lal for (i = 0; i < 32; i++) { 118402dae26aSJames Hogan regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; 1185e2132e0bSSanjay Lal } 1186e2132e0bSSanjay Lal 118702dae26aSJames Hogan regs.hi = (int64_t)(target_long)env->active_tc.HI[0]; 118802dae26aSJames Hogan regs.lo = (int64_t)(target_long)env->active_tc.LO[0]; 118902dae26aSJames Hogan regs.pc = (int64_t)(target_long)env->active_tc.PC; 1190e2132e0bSSanjay Lal 1191e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 1192e2132e0bSSanjay Lal 1193e2132e0bSSanjay Lal if (ret < 0) { 1194e2132e0bSSanjay Lal return ret; 1195e2132e0bSSanjay Lal } 1196e2132e0bSSanjay Lal 1197e2132e0bSSanjay Lal ret = kvm_mips_put_cp0_registers(cs, level); 1198e2132e0bSSanjay Lal if (ret < 0) { 1199e2132e0bSSanjay Lal return ret; 1200e2132e0bSSanjay Lal } 1201e2132e0bSSanjay Lal 1202152db36aSJames Hogan ret = kvm_mips_put_fpu_registers(cs, level); 1203152db36aSJames Hogan if (ret < 0) { 1204152db36aSJames Hogan return ret; 1205152db36aSJames Hogan } 1206152db36aSJames Hogan 1207e2132e0bSSanjay Lal return ret; 1208e2132e0bSSanjay Lal } 1209e2132e0bSSanjay Lal 1210*a1676bb3SJulia Suvorova int kvm_arch_get_registers(CPUState *cs, Error **errp) 1211e2132e0bSSanjay Lal { 12124c44a980SPhilippe Mathieu-Daudé CPUMIPSState *env = cpu_env(cs); 1213e2132e0bSSanjay Lal int ret = 0; 1214e2132e0bSSanjay Lal struct kvm_regs regs; 1215e2132e0bSSanjay Lal int i; 1216e2132e0bSSanjay Lal 1217e2132e0bSSanjay Lal /* Get the current register set as KVM seems it */ 1218e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1219e2132e0bSSanjay Lal 1220e2132e0bSSanjay Lal if (ret < 0) { 1221e2132e0bSSanjay Lal return ret; 1222e2132e0bSSanjay Lal } 1223e2132e0bSSanjay Lal 1224e2132e0bSSanjay Lal for (i = 0; i < 32; i++) { 1225e2132e0bSSanjay Lal env->active_tc.gpr[i] = regs.gpr[i]; 1226e2132e0bSSanjay Lal } 1227e2132e0bSSanjay Lal 1228e2132e0bSSanjay Lal env->active_tc.HI[0] = regs.hi; 1229e2132e0bSSanjay Lal env->active_tc.LO[0] = regs.lo; 1230e2132e0bSSanjay Lal env->active_tc.PC = regs.pc; 1231e2132e0bSSanjay Lal 1232e2132e0bSSanjay Lal kvm_mips_get_cp0_registers(cs); 1233152db36aSJames Hogan kvm_mips_get_fpu_registers(cs); 1234e2132e0bSSanjay Lal 1235e2132e0bSSanjay Lal return ret; 1236e2132e0bSSanjay Lal } 12379e03a040SFrank Blaschka 12389e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1239dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 12409e03a040SFrank Blaschka { 12419e03a040SFrank Blaschka return 0; 12429e03a040SFrank Blaschka } 12431850b6b7SEric Auger 124438d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 124538d87493SPeter Xu int vector, PCIDevice *dev) 124638d87493SPeter Xu { 124738d87493SPeter Xu return 0; 124838d87493SPeter Xu } 124938d87493SPeter Xu 125038d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 125138d87493SPeter Xu { 125238d87493SPeter Xu return 0; 125338d87493SPeter Xu } 125438d87493SPeter Xu 12551850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 12561850b6b7SEric Auger { 12571850b6b7SEric Auger abort(); 12581850b6b7SEric Auger } 1259719d109bSHuacai Chen 12605e0d6590SAkihiko Odaki int kvm_arch_get_default_type(MachineState *machine) 1261719d109bSHuacai Chen { 1262a8448735SPaolo Bonzini #if defined(KVM_CAP_MIPS_VZ) 1263719d109bSHuacai Chen int r; 1264719d109bSHuacai Chen KVMState *s = KVM_STATE(machine->accelerator); 1265719d109bSHuacai Chen 1266719d109bSHuacai Chen r = kvm_check_extension(s, KVM_CAP_MIPS_VZ); 1267719d109bSHuacai Chen if (r > 0) { 1268719d109bSHuacai Chen return KVM_VM_MIPS_VZ; 1269719d109bSHuacai Chen } 1270719d109bSHuacai Chen #endif 1271719d109bSHuacai Chen 1272875b3eb8SAkihiko Odaki error_report("KVM_VM_MIPS_VZ type is not available"); 1273719d109bSHuacai Chen return -1; 1274719d109bSHuacai Chen } 127592a5199bSTom Lendacky 12763dba0a33SPaolo Bonzini void kvm_arch_accel_class_init(ObjectClass *oc) 12773dba0a33SPaolo Bonzini { 12783dba0a33SPaolo Bonzini } 1279