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 17e2132e0bSSanjay Lal #include "qemu-common.h" 1833c11879SPaolo Bonzini #include "cpu.h" 1926aa3d9aSPhilippe Mathieu-Daudé #include "internal.h" 20e2132e0bSSanjay Lal #include "qemu/error-report.h" 21db725815SMarkus Armbruster #include "qemu/main-loop.h" 22e2132e0bSSanjay Lal #include "qemu/timer.h" 23e2132e0bSSanjay Lal #include "sysemu/kvm.h" 2454d31236SMarkus Armbruster #include "sysemu/runstate.h" 25e2132e0bSSanjay Lal #include "sysemu/cpus.h" 26e2132e0bSSanjay Lal #include "kvm_mips.h" 274c663752SPaolo Bonzini #include "exec/memattrs.h" 28e2132e0bSSanjay Lal 29e2132e0bSSanjay Lal #define DEBUG_KVM 0 30e2132e0bSSanjay Lal 31e2132e0bSSanjay Lal #define DPRINTF(fmt, ...) \ 32e2132e0bSSanjay Lal do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) 33e2132e0bSSanjay Lal 34152db36aSJames Hogan static int kvm_mips_fpu_cap; 35bee62662SJames Hogan static int kvm_mips_msa_cap; 36152db36aSJames Hogan 37e2132e0bSSanjay Lal const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 38e2132e0bSSanjay Lal KVM_CAP_LAST_INFO 39e2132e0bSSanjay Lal }; 40e2132e0bSSanjay Lal 41e2132e0bSSanjay Lal static void kvm_mips_update_state(void *opaque, int running, RunState state); 42e2132e0bSSanjay Lal 43e2132e0bSSanjay Lal unsigned long kvm_arch_vcpu_id(CPUState *cs) 44e2132e0bSSanjay Lal { 45e2132e0bSSanjay Lal return cs->cpu_index; 46e2132e0bSSanjay Lal } 47e2132e0bSSanjay Lal 48b16565b3SMarcel Apfelbaum int kvm_arch_init(MachineState *ms, KVMState *s) 49e2132e0bSSanjay Lal { 50e2132e0bSSanjay Lal /* MIPS has 128 signals */ 51e2132e0bSSanjay Lal kvm_set_sigmask_len(s, 16); 52e2132e0bSSanjay Lal 53152db36aSJames Hogan kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU); 54bee62662SJames Hogan kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA); 55152db36aSJames Hogan 56e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 57e2132e0bSSanjay Lal return 0; 58e2132e0bSSanjay Lal } 59e2132e0bSSanjay Lal 604376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 61d525ffabSPaolo Bonzini { 62d525ffabSPaolo Bonzini return 0; 63d525ffabSPaolo Bonzini } 64d525ffabSPaolo Bonzini 65e2132e0bSSanjay Lal int kvm_arch_init_vcpu(CPUState *cs) 66e2132e0bSSanjay Lal { 67152db36aSJames Hogan MIPSCPU *cpu = MIPS_CPU(cs); 68152db36aSJames Hogan CPUMIPSState *env = &cpu->env; 69e2132e0bSSanjay Lal int ret = 0; 70e2132e0bSSanjay Lal 71e2132e0bSSanjay Lal qemu_add_vm_change_state_handler(kvm_mips_update_state, cs); 72e2132e0bSSanjay Lal 73152db36aSJames Hogan if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 74152db36aSJames Hogan ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0); 75152db36aSJames Hogan if (ret < 0) { 76152db36aSJames Hogan /* mark unsupported so it gets disabled on reset */ 77152db36aSJames Hogan kvm_mips_fpu_cap = 0; 78152db36aSJames Hogan ret = 0; 79152db36aSJames Hogan } 80152db36aSJames Hogan } 81152db36aSJames Hogan 82bee62662SJames Hogan if (kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { 83bee62662SJames Hogan ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0); 84bee62662SJames Hogan if (ret < 0) { 85bee62662SJames Hogan /* mark unsupported so it gets disabled on reset */ 86bee62662SJames Hogan kvm_mips_msa_cap = 0; 87bee62662SJames Hogan ret = 0; 88bee62662SJames Hogan } 89bee62662SJames Hogan } 90bee62662SJames Hogan 91e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 92e2132e0bSSanjay Lal return ret; 93e2132e0bSSanjay Lal } 94e2132e0bSSanjay Lal 95b1115c99SLiran Alon int kvm_arch_destroy_vcpu(CPUState *cs) 96b1115c99SLiran Alon { 97b1115c99SLiran Alon return 0; 98b1115c99SLiran Alon } 99b1115c99SLiran Alon 100e2132e0bSSanjay Lal void kvm_mips_reset_vcpu(MIPSCPU *cpu) 101e2132e0bSSanjay Lal { 1020e928b12SJames Hogan CPUMIPSState *env = &cpu->env; 1030e928b12SJames Hogan 104152db36aSJames Hogan if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 1052ab4b135SAlistair Francis warn_report("KVM does not support FPU, disabling"); 1060e928b12SJames Hogan env->CP0_Config1 &= ~(1 << CP0C1_FP); 1070e928b12SJames Hogan } 108bee62662SJames Hogan if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { 1092ab4b135SAlistair Francis warn_report("KVM does not support MSA, disabling"); 110bee62662SJames Hogan env->CP0_Config3 &= ~(1 << CP0C3_MSAP); 111bee62662SJames Hogan } 1120e928b12SJames Hogan 113e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 114e2132e0bSSanjay Lal } 115e2132e0bSSanjay Lal 116e2132e0bSSanjay Lal int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 117e2132e0bSSanjay Lal { 118e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 119e2132e0bSSanjay Lal return 0; 120e2132e0bSSanjay Lal } 121e2132e0bSSanjay Lal 122e2132e0bSSanjay Lal int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 123e2132e0bSSanjay Lal { 124e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 125e2132e0bSSanjay Lal return 0; 126e2132e0bSSanjay Lal } 127e2132e0bSSanjay Lal 128e2132e0bSSanjay Lal static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) 129e2132e0bSSanjay Lal { 130e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 131e2132e0bSSanjay Lal 132e2132e0bSSanjay Lal return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP)); 133e2132e0bSSanjay Lal } 134e2132e0bSSanjay Lal 135e2132e0bSSanjay Lal 136e2132e0bSSanjay Lal void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 137e2132e0bSSanjay Lal { 138e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 139e2132e0bSSanjay Lal int r; 140e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 141e2132e0bSSanjay Lal 1424b8523eeSJan Kiszka qemu_mutex_lock_iothread(); 1434b8523eeSJan Kiszka 144e2132e0bSSanjay Lal if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 145e2132e0bSSanjay Lal cpu_mips_io_interrupts_pending(cpu)) { 146e2132e0bSSanjay Lal intr.cpu = -1; 147e2132e0bSSanjay Lal intr.irq = 2; 148e2132e0bSSanjay Lal r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 149e2132e0bSSanjay Lal if (r < 0) { 150e2132e0bSSanjay Lal error_report("%s: cpu %d: failed to inject IRQ %x", 151e2132e0bSSanjay Lal __func__, cs->cpu_index, intr.irq); 152e2132e0bSSanjay Lal } 153e2132e0bSSanjay Lal } 1544b8523eeSJan Kiszka 1554b8523eeSJan Kiszka qemu_mutex_unlock_iothread(); 156e2132e0bSSanjay Lal } 157e2132e0bSSanjay Lal 1584c663752SPaolo Bonzini MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 159e2132e0bSSanjay Lal { 1604c663752SPaolo Bonzini return MEMTXATTRS_UNSPECIFIED; 161e2132e0bSSanjay Lal } 162e2132e0bSSanjay Lal 163e2132e0bSSanjay Lal int kvm_arch_process_async_events(CPUState *cs) 164e2132e0bSSanjay Lal { 165e2132e0bSSanjay Lal return cs->halted; 166e2132e0bSSanjay Lal } 167e2132e0bSSanjay Lal 168e2132e0bSSanjay Lal int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 169e2132e0bSSanjay Lal { 170e2132e0bSSanjay Lal int ret; 171e2132e0bSSanjay Lal 172e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 173e2132e0bSSanjay Lal switch (run->exit_reason) { 174e2132e0bSSanjay Lal default: 175e2132e0bSSanjay Lal error_report("%s: unknown exit reason %d", 176e2132e0bSSanjay Lal __func__, run->exit_reason); 177e2132e0bSSanjay Lal ret = -1; 178e2132e0bSSanjay Lal break; 179e2132e0bSSanjay Lal } 180e2132e0bSSanjay Lal 181e2132e0bSSanjay Lal return ret; 182e2132e0bSSanjay Lal } 183e2132e0bSSanjay Lal 184e2132e0bSSanjay Lal bool kvm_arch_stop_on_emulation_error(CPUState *cs) 185e2132e0bSSanjay Lal { 186e2132e0bSSanjay Lal DPRINTF("%s\n", __func__); 187e2132e0bSSanjay Lal return true; 188e2132e0bSSanjay Lal } 189e2132e0bSSanjay Lal 190e2132e0bSSanjay Lal void kvm_arch_init_irq_routing(KVMState *s) 191e2132e0bSSanjay Lal { 192e2132e0bSSanjay Lal } 193e2132e0bSSanjay Lal 194e2132e0bSSanjay Lal int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level) 195e2132e0bSSanjay Lal { 196e2132e0bSSanjay Lal CPUState *cs = CPU(cpu); 197e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 198e2132e0bSSanjay Lal 199e2132e0bSSanjay Lal if (!kvm_enabled()) { 200e2132e0bSSanjay Lal return 0; 201e2132e0bSSanjay Lal } 202e2132e0bSSanjay Lal 203e2132e0bSSanjay Lal intr.cpu = -1; 204e2132e0bSSanjay Lal 205e2132e0bSSanjay Lal if (level) { 206e2132e0bSSanjay Lal intr.irq = irq; 207e2132e0bSSanjay Lal } else { 208e2132e0bSSanjay Lal intr.irq = -irq; 209e2132e0bSSanjay Lal } 210e2132e0bSSanjay Lal 211e2132e0bSSanjay Lal kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 212e2132e0bSSanjay Lal 213e2132e0bSSanjay Lal return 0; 214e2132e0bSSanjay Lal } 215e2132e0bSSanjay Lal 216e2132e0bSSanjay Lal int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) 217e2132e0bSSanjay Lal { 218e2132e0bSSanjay Lal CPUState *cs = current_cpu; 219e2132e0bSSanjay Lal CPUState *dest_cs = CPU(cpu); 220e2132e0bSSanjay Lal struct kvm_mips_interrupt intr; 221e2132e0bSSanjay Lal 222e2132e0bSSanjay Lal if (!kvm_enabled()) { 223e2132e0bSSanjay Lal return 0; 224e2132e0bSSanjay Lal } 225e2132e0bSSanjay Lal 226e2132e0bSSanjay Lal intr.cpu = dest_cs->cpu_index; 227e2132e0bSSanjay Lal 228e2132e0bSSanjay Lal if (level) { 229e2132e0bSSanjay Lal intr.irq = irq; 230e2132e0bSSanjay Lal } else { 231e2132e0bSSanjay Lal intr.irq = -irq; 232e2132e0bSSanjay Lal } 233e2132e0bSSanjay Lal 234e2132e0bSSanjay Lal DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq); 235e2132e0bSSanjay Lal 236e2132e0bSSanjay Lal kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 237e2132e0bSSanjay Lal 238e2132e0bSSanjay Lal return 0; 239e2132e0bSSanjay Lal } 240e2132e0bSSanjay Lal 241e2132e0bSSanjay Lal #define MIPS_CP0_32(_R, _S) \ 2425a2db896SJames Hogan (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) 243e2132e0bSSanjay Lal 244e2132e0bSSanjay Lal #define MIPS_CP0_64(_R, _S) \ 2455a2db896SJames Hogan (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) 246e2132e0bSSanjay Lal 247e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) 248*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0) 249e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0) 250e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2) 251e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0) 252*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1) 253*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5) 254*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6) 255*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7) 256e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0) 257*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6) 258e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0) 259e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0) 260e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0) 261e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0) 262e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0) 263e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) 264e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) 265e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) 266461a1582SJames Hogan #define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) 267*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1) 26803cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) 26903cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) 27003cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) 27103cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 27203cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) 27303cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) 274*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6) 275*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) 276e2132e0bSSanjay Lal #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 277*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2) 278*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3) 279*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4) 280*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5) 281*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6) 282*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7) 283e2132e0bSSanjay Lal 284e2132e0bSSanjay Lal static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, 285e2132e0bSSanjay Lal int32_t *addr) 286e2132e0bSSanjay Lal { 287e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 288e2132e0bSSanjay Lal .id = reg_id, 289f8b3e48bSJames Hogan .addr = (uintptr_t)addr 290e2132e0bSSanjay Lal }; 291e2132e0bSSanjay Lal 292e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 293e2132e0bSSanjay Lal } 294e2132e0bSSanjay Lal 2950759487bSJames Hogan static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id, 2960759487bSJames Hogan uint32_t *addr) 2970759487bSJames Hogan { 2980759487bSJames Hogan struct kvm_one_reg cp0reg = { 2990759487bSJames Hogan .id = reg_id, 3000759487bSJames Hogan .addr = (uintptr_t)addr 3010759487bSJames Hogan }; 3020759487bSJames Hogan 3030759487bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 3040759487bSJames Hogan } 3050759487bSJames Hogan 306e2132e0bSSanjay Lal static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, 307e2132e0bSSanjay Lal target_ulong *addr) 308e2132e0bSSanjay Lal { 309e2132e0bSSanjay Lal uint64_t val64 = *addr; 310e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 311e2132e0bSSanjay Lal .id = reg_id, 312e2132e0bSSanjay Lal .addr = (uintptr_t)&val64 313e2132e0bSSanjay Lal }; 314e2132e0bSSanjay Lal 315e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 316e2132e0bSSanjay Lal } 317e2132e0bSSanjay Lal 318e2132e0bSSanjay Lal static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id, 319d319f83fSJames Hogan int64_t *addr) 320d319f83fSJames Hogan { 321d319f83fSJames Hogan struct kvm_one_reg cp0reg = { 322d319f83fSJames Hogan .id = reg_id, 323d319f83fSJames Hogan .addr = (uintptr_t)addr 324d319f83fSJames Hogan }; 325d319f83fSJames Hogan 326d319f83fSJames Hogan return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 327d319f83fSJames Hogan } 328d319f83fSJames Hogan 329d319f83fSJames Hogan static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id, 330e2132e0bSSanjay Lal uint64_t *addr) 331e2132e0bSSanjay Lal { 332e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 333e2132e0bSSanjay Lal .id = reg_id, 334e2132e0bSSanjay Lal .addr = (uintptr_t)addr 335e2132e0bSSanjay Lal }; 336e2132e0bSSanjay Lal 337e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 338e2132e0bSSanjay Lal } 339e2132e0bSSanjay Lal 340e2132e0bSSanjay Lal static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id, 341e2132e0bSSanjay Lal int32_t *addr) 342e2132e0bSSanjay Lal { 343e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 344e2132e0bSSanjay Lal .id = reg_id, 345f8b3e48bSJames Hogan .addr = (uintptr_t)addr 346e2132e0bSSanjay Lal }; 347e2132e0bSSanjay Lal 348f8b3e48bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 349e2132e0bSSanjay Lal } 350e2132e0bSSanjay Lal 3510759487bSJames Hogan static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id, 3520759487bSJames Hogan uint32_t *addr) 3530759487bSJames Hogan { 3540759487bSJames Hogan struct kvm_one_reg cp0reg = { 3550759487bSJames Hogan .id = reg_id, 3560759487bSJames Hogan .addr = (uintptr_t)addr 3570759487bSJames Hogan }; 3580759487bSJames Hogan 3590759487bSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 3600759487bSJames Hogan } 3610759487bSJames Hogan 362182f42fdSPeter Maydell static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id, 363e2132e0bSSanjay Lal target_ulong *addr) 364e2132e0bSSanjay Lal { 365e2132e0bSSanjay Lal int ret; 366e2132e0bSSanjay Lal uint64_t val64 = 0; 367e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 368e2132e0bSSanjay Lal .id = reg_id, 369e2132e0bSSanjay Lal .addr = (uintptr_t)&val64 370e2132e0bSSanjay Lal }; 371e2132e0bSSanjay Lal 372e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 373e2132e0bSSanjay Lal if (ret >= 0) { 374e2132e0bSSanjay Lal *addr = val64; 375e2132e0bSSanjay Lal } 376e2132e0bSSanjay Lal return ret; 377e2132e0bSSanjay Lal } 378e2132e0bSSanjay Lal 379182f42fdSPeter Maydell static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id, 380d319f83fSJames Hogan int64_t *addr) 381d319f83fSJames Hogan { 382d319f83fSJames Hogan struct kvm_one_reg cp0reg = { 383d319f83fSJames Hogan .id = reg_id, 384d319f83fSJames Hogan .addr = (uintptr_t)addr 385d319f83fSJames Hogan }; 386d319f83fSJames Hogan 387d319f83fSJames Hogan return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 388d319f83fSJames Hogan } 389d319f83fSJames Hogan 390d319f83fSJames Hogan static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, 391e2132e0bSSanjay Lal uint64_t *addr) 392e2132e0bSSanjay Lal { 393e2132e0bSSanjay Lal struct kvm_one_reg cp0reg = { 394e2132e0bSSanjay Lal .id = reg_id, 395e2132e0bSSanjay Lal .addr = (uintptr_t)addr 396e2132e0bSSanjay Lal }; 397e2132e0bSSanjay Lal 398e2132e0bSSanjay Lal return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 399e2132e0bSSanjay Lal } 400e2132e0bSSanjay Lal 40103cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M) 402152db36aSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \ 403152db36aSJames Hogan (1U << CP0C1_FP)) 40403cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M) 405bee62662SJames Hogan #define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \ 406bee62662SJames Hogan (1U << CP0C3_MSAP)) 40703cbfd7bSJames Hogan #define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M) 408bee62662SJames Hogan #define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \ 409bee62662SJames Hogan (1U << CP0C5_UFE) | \ 410152db36aSJames Hogan (1U << CP0C5_FRE) | \ 411152db36aSJames Hogan (1U << CP0C5_UFR)) 412*7e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \ 413*7e0896b0SHuacai Chen (0x3fU << CP0C6_KPOS) | \ 414*7e0896b0SHuacai Chen (1U << CP0C6_KE) | \ 415*7e0896b0SHuacai Chen (1U << CP0C6_VTLBONLY) | \ 416*7e0896b0SHuacai Chen (1U << CP0C6_LASX) | \ 417*7e0896b0SHuacai Chen (1U << CP0C6_SSEN) | \ 418*7e0896b0SHuacai Chen (1U << CP0C6_DISDRTIME) | \ 419*7e0896b0SHuacai Chen (1U << CP0C6_PIXNUEN) | \ 420*7e0896b0SHuacai Chen (1U << CP0C6_SCRAND) | \ 421*7e0896b0SHuacai Chen (1U << CP0C6_LLEXCEN) | \ 422*7e0896b0SHuacai Chen (1U << CP0C6_DISVC) | \ 423*7e0896b0SHuacai Chen (1U << CP0C6_VCLRU) | \ 424*7e0896b0SHuacai Chen (1U << CP0C6_DCLRU) | \ 425*7e0896b0SHuacai Chen (1U << CP0C6_PIXUEN) | \ 426*7e0896b0SHuacai Chen (1U << CP0C6_DISBLKLYEN) | \ 427*7e0896b0SHuacai Chen (1U << CP0C6_UMEMUALEN) | \ 428*7e0896b0SHuacai Chen (1U << CP0C6_SFBEN) | \ 429*7e0896b0SHuacai Chen (1U << CP0C6_FLTINT) | \ 430*7e0896b0SHuacai Chen (1U << CP0C6_VLTINT) | \ 431*7e0896b0SHuacai Chen (1U << CP0C6_DISBTB) | \ 432*7e0896b0SHuacai Chen (3U << CP0C6_STPREFCTL) | \ 433*7e0896b0SHuacai Chen (1U << CP0C6_INSTPREF) | \ 434*7e0896b0SHuacai Chen (1U << CP0C6_DATAPREF)) 43503cbfd7bSJames Hogan 43603cbfd7bSJames Hogan static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, 43703cbfd7bSJames Hogan int32_t *addr, int32_t mask) 43803cbfd7bSJames Hogan { 43903cbfd7bSJames Hogan int err; 44003cbfd7bSJames Hogan int32_t tmp, change; 44103cbfd7bSJames Hogan 44203cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, reg_id, &tmp); 44303cbfd7bSJames Hogan if (err < 0) { 44403cbfd7bSJames Hogan return err; 44503cbfd7bSJames Hogan } 44603cbfd7bSJames Hogan 44703cbfd7bSJames Hogan /* only change bits in mask */ 44803cbfd7bSJames Hogan change = (*addr ^ tmp) & mask; 44903cbfd7bSJames Hogan if (!change) { 45003cbfd7bSJames Hogan return 0; 45103cbfd7bSJames Hogan } 45203cbfd7bSJames Hogan 45303cbfd7bSJames Hogan tmp = tmp ^ change; 45403cbfd7bSJames Hogan return kvm_mips_put_one_reg(cs, reg_id, &tmp); 45503cbfd7bSJames Hogan } 45603cbfd7bSJames Hogan 457e2132e0bSSanjay Lal /* 458e2132e0bSSanjay Lal * We freeze the KVM timer when either the VM clock is stopped or the state is 459e2132e0bSSanjay Lal * saved (the state is dirty). 460e2132e0bSSanjay Lal */ 461e2132e0bSSanjay Lal 462e2132e0bSSanjay Lal /* 463e2132e0bSSanjay Lal * Save the state of the KVM timer when VM clock is stopped or state is synced 464e2132e0bSSanjay Lal * to QEMU. 465e2132e0bSSanjay Lal */ 466e2132e0bSSanjay Lal static int kvm_mips_save_count(CPUState *cs) 467e2132e0bSSanjay Lal { 468e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 469e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 470e2132e0bSSanjay Lal uint64_t count_ctl; 471e2132e0bSSanjay Lal int err, ret = 0; 472e2132e0bSSanjay Lal 473e2132e0bSSanjay Lal /* freeze KVM timer */ 474d319f83fSJames Hogan err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 475e2132e0bSSanjay Lal if (err < 0) { 476e2132e0bSSanjay Lal DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err); 477e2132e0bSSanjay Lal ret = err; 478e2132e0bSSanjay Lal } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 479e2132e0bSSanjay Lal count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 480d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 481e2132e0bSSanjay Lal if (err < 0) { 482e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 483e2132e0bSSanjay Lal ret = err; 484e2132e0bSSanjay Lal } 485e2132e0bSSanjay Lal } 486e2132e0bSSanjay Lal 487e2132e0bSSanjay Lal /* read CP0_Cause */ 488e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 489e2132e0bSSanjay Lal if (err < 0) { 490e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err); 491e2132e0bSSanjay Lal ret = err; 492e2132e0bSSanjay Lal } 493e2132e0bSSanjay Lal 494e2132e0bSSanjay Lal /* read CP0_Count */ 495e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 496e2132e0bSSanjay Lal if (err < 0) { 497e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err); 498e2132e0bSSanjay Lal ret = err; 499e2132e0bSSanjay Lal } 500e2132e0bSSanjay Lal 501e2132e0bSSanjay Lal return ret; 502e2132e0bSSanjay Lal } 503e2132e0bSSanjay Lal 504e2132e0bSSanjay Lal /* 505e2132e0bSSanjay Lal * Restore the state of the KVM timer when VM clock is restarted or state is 506e2132e0bSSanjay Lal * synced to KVM. 507e2132e0bSSanjay Lal */ 508e2132e0bSSanjay Lal static int kvm_mips_restore_count(CPUState *cs) 509e2132e0bSSanjay Lal { 510e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 511e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 512e2132e0bSSanjay Lal uint64_t count_ctl; 513e2132e0bSSanjay Lal int err_dc, err, ret = 0; 514e2132e0bSSanjay Lal 515e2132e0bSSanjay Lal /* check the timer is frozen */ 516d319f83fSJames Hogan err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 517e2132e0bSSanjay Lal if (err_dc < 0) { 518e2132e0bSSanjay Lal DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc); 519e2132e0bSSanjay Lal ret = err_dc; 520e2132e0bSSanjay Lal } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 521e2132e0bSSanjay Lal /* freeze timer (sets COUNT_RESUME for us) */ 522e2132e0bSSanjay Lal count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 523d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 524e2132e0bSSanjay Lal if (err < 0) { 525e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 526e2132e0bSSanjay Lal ret = err; 527e2132e0bSSanjay Lal } 528e2132e0bSSanjay Lal } 529e2132e0bSSanjay Lal 530e2132e0bSSanjay Lal /* load CP0_Cause */ 531e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 532e2132e0bSSanjay Lal if (err < 0) { 533e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err); 534e2132e0bSSanjay Lal ret = err; 535e2132e0bSSanjay Lal } 536e2132e0bSSanjay Lal 537e2132e0bSSanjay Lal /* load CP0_Count */ 538e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 539e2132e0bSSanjay Lal if (err < 0) { 540e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err); 541e2132e0bSSanjay Lal ret = err; 542e2132e0bSSanjay Lal } 543e2132e0bSSanjay Lal 544e2132e0bSSanjay Lal /* resume KVM timer */ 545e2132e0bSSanjay Lal if (err_dc >= 0) { 546e2132e0bSSanjay Lal count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC; 547d319f83fSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 548e2132e0bSSanjay Lal if (err < 0) { 549e2132e0bSSanjay Lal DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err); 550e2132e0bSSanjay Lal ret = err; 551e2132e0bSSanjay Lal } 552e2132e0bSSanjay Lal } 553e2132e0bSSanjay Lal 554e2132e0bSSanjay Lal return ret; 555e2132e0bSSanjay Lal } 556e2132e0bSSanjay Lal 557e2132e0bSSanjay Lal /* 558e2132e0bSSanjay Lal * Handle the VM clock being started or stopped 559e2132e0bSSanjay Lal */ 560e2132e0bSSanjay Lal static void kvm_mips_update_state(void *opaque, int running, RunState state) 561e2132e0bSSanjay Lal { 562e2132e0bSSanjay Lal CPUState *cs = opaque; 563e2132e0bSSanjay Lal int ret; 564e2132e0bSSanjay Lal uint64_t count_resume; 565e2132e0bSSanjay Lal 566e2132e0bSSanjay Lal /* 567e2132e0bSSanjay Lal * If state is already dirty (synced to QEMU) then the KVM timer state is 568e2132e0bSSanjay Lal * already saved and can be restored when it is synced back to KVM. 569e2132e0bSSanjay Lal */ 570e2132e0bSSanjay Lal if (!running) { 57199f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 572e2132e0bSSanjay Lal ret = kvm_mips_save_count(cs); 573e2132e0bSSanjay Lal if (ret < 0) { 574288cb949SAlistair Francis warn_report("Failed saving count"); 575e2132e0bSSanjay Lal } 576e2132e0bSSanjay Lal } 577e2132e0bSSanjay Lal } else { 578e2132e0bSSanjay Lal /* Set clock restore time to now */ 579906b53a2SPaolo Bonzini count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 580d319f83fSJames Hogan ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME, 581e2132e0bSSanjay Lal &count_resume); 582e2132e0bSSanjay Lal if (ret < 0) { 583288cb949SAlistair Francis warn_report("Failed setting COUNT_RESUME"); 584e2132e0bSSanjay Lal return; 585e2132e0bSSanjay Lal } 586e2132e0bSSanjay Lal 58799f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 588e2132e0bSSanjay Lal ret = kvm_mips_restore_count(cs); 589e2132e0bSSanjay Lal if (ret < 0) { 590288cb949SAlistair Francis warn_report("Failed restoring count"); 591e2132e0bSSanjay Lal } 592e2132e0bSSanjay Lal } 593e2132e0bSSanjay Lal } 594e2132e0bSSanjay Lal } 595e2132e0bSSanjay Lal 596152db36aSJames Hogan static int kvm_mips_put_fpu_registers(CPUState *cs, int level) 597152db36aSJames Hogan { 598152db36aSJames Hogan MIPSCPU *cpu = MIPS_CPU(cs); 599152db36aSJames Hogan CPUMIPSState *env = &cpu->env; 600152db36aSJames Hogan int err, ret = 0; 601152db36aSJames Hogan unsigned int i; 602152db36aSJames Hogan 603152db36aSJames Hogan /* Only put FPU state if we're emulating a CPU with an FPU */ 604152db36aSJames Hogan if (env->CP0_Config1 & (1 << CP0C1_FP)) { 605152db36aSJames Hogan /* FPU Control Registers */ 606152db36aSJames Hogan if (level == KVM_PUT_FULL_STATE) { 607152db36aSJames Hogan err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 608152db36aSJames Hogan &env->active_fpu.fcr0); 609152db36aSJames Hogan if (err < 0) { 610152db36aSJames Hogan DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err); 611152db36aSJames Hogan ret = err; 612152db36aSJames Hogan } 613152db36aSJames Hogan } 614152db36aSJames Hogan err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 615152db36aSJames Hogan &env->active_fpu.fcr31); 616152db36aSJames Hogan if (err < 0) { 617152db36aSJames Hogan DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err); 618152db36aSJames Hogan ret = err; 619152db36aSJames Hogan } 620152db36aSJames Hogan 621bee62662SJames Hogan /* 622bee62662SJames Hogan * FPU register state is a subset of MSA vector state, so don't put FPU 623bee62662SJames Hogan * registers if we're emulating a CPU with MSA. 624bee62662SJames Hogan */ 625bee62662SJames Hogan if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { 626152db36aSJames Hogan /* Floating point registers */ 627152db36aSJames Hogan for (i = 0; i < 32; ++i) { 628152db36aSJames Hogan if (env->CP0_Status & (1 << CP0St_FR)) { 629152db36aSJames Hogan err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 630152db36aSJames Hogan &env->active_fpu.fpr[i].d); 631152db36aSJames Hogan } else { 632152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 633152db36aSJames Hogan &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 634152db36aSJames Hogan } 635152db36aSJames Hogan if (err < 0) { 636152db36aSJames Hogan DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err); 637152db36aSJames Hogan ret = err; 638152db36aSJames Hogan } 639152db36aSJames Hogan } 640152db36aSJames Hogan } 641bee62662SJames Hogan } 642bee62662SJames Hogan 643bee62662SJames Hogan /* Only put MSA state if we're emulating a CPU with MSA */ 644bee62662SJames Hogan if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 645bee62662SJames Hogan /* MSA Control Registers */ 646bee62662SJames Hogan if (level == KVM_PUT_FULL_STATE) { 647bee62662SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR, 648bee62662SJames Hogan &env->msair); 649bee62662SJames Hogan if (err < 0) { 650bee62662SJames Hogan DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err); 651bee62662SJames Hogan ret = err; 652bee62662SJames Hogan } 653bee62662SJames Hogan } 654bee62662SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 655bee62662SJames Hogan &env->active_tc.msacsr); 656bee62662SJames Hogan if (err < 0) { 657bee62662SJames Hogan DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err); 658bee62662SJames Hogan ret = err; 659bee62662SJames Hogan } 660bee62662SJames Hogan 661bee62662SJames Hogan /* Vector registers (includes FP registers) */ 662bee62662SJames Hogan for (i = 0; i < 32; ++i) { 663bee62662SJames Hogan /* Big endian MSA not supported by QEMU yet anyway */ 664bee62662SJames Hogan err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 665bee62662SJames Hogan env->active_fpu.fpr[i].wr.d); 666bee62662SJames Hogan if (err < 0) { 667bee62662SJames Hogan DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err); 668bee62662SJames Hogan ret = err; 669bee62662SJames Hogan } 670bee62662SJames Hogan } 671bee62662SJames Hogan } 672152db36aSJames Hogan 673152db36aSJames Hogan return ret; 674152db36aSJames Hogan } 675152db36aSJames Hogan 676152db36aSJames Hogan static int kvm_mips_get_fpu_registers(CPUState *cs) 677152db36aSJames Hogan { 678152db36aSJames Hogan MIPSCPU *cpu = MIPS_CPU(cs); 679152db36aSJames Hogan CPUMIPSState *env = &cpu->env; 680152db36aSJames Hogan int err, ret = 0; 681152db36aSJames Hogan unsigned int i; 682152db36aSJames Hogan 683152db36aSJames Hogan /* Only get FPU state if we're emulating a CPU with an FPU */ 684152db36aSJames Hogan if (env->CP0_Config1 & (1 << CP0C1_FP)) { 685152db36aSJames Hogan /* FPU Control Registers */ 686152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 687152db36aSJames Hogan &env->active_fpu.fcr0); 688152db36aSJames Hogan if (err < 0) { 689152db36aSJames Hogan DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err); 690152db36aSJames Hogan ret = err; 691152db36aSJames Hogan } 692152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 693152db36aSJames Hogan &env->active_fpu.fcr31); 694152db36aSJames Hogan if (err < 0) { 695152db36aSJames Hogan DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err); 696152db36aSJames Hogan ret = err; 697152db36aSJames Hogan } else { 698152db36aSJames Hogan restore_fp_status(env); 699152db36aSJames Hogan } 700152db36aSJames Hogan 701bee62662SJames Hogan /* 702bee62662SJames Hogan * FPU register state is a subset of MSA vector state, so don't save FPU 703bee62662SJames Hogan * registers if we're emulating a CPU with MSA. 704bee62662SJames Hogan */ 705bee62662SJames Hogan if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { 706152db36aSJames Hogan /* Floating point registers */ 707152db36aSJames Hogan for (i = 0; i < 32; ++i) { 708152db36aSJames Hogan if (env->CP0_Status & (1 << CP0St_FR)) { 709152db36aSJames Hogan err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 710152db36aSJames Hogan &env->active_fpu.fpr[i].d); 711152db36aSJames Hogan } else { 712152db36aSJames Hogan err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 713152db36aSJames Hogan &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 714152db36aSJames Hogan } 715152db36aSJames Hogan if (err < 0) { 716152db36aSJames Hogan DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err); 717152db36aSJames Hogan ret = err; 718152db36aSJames Hogan } 719152db36aSJames Hogan } 720152db36aSJames Hogan } 721bee62662SJames Hogan } 722bee62662SJames Hogan 723bee62662SJames Hogan /* Only get MSA state if we're emulating a CPU with MSA */ 724bee62662SJames Hogan if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 725bee62662SJames Hogan /* MSA Control Registers */ 726bee62662SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR, 727bee62662SJames Hogan &env->msair); 728bee62662SJames Hogan if (err < 0) { 729bee62662SJames Hogan DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err); 730bee62662SJames Hogan ret = err; 731bee62662SJames Hogan } 732bee62662SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 733bee62662SJames Hogan &env->active_tc.msacsr); 734bee62662SJames Hogan if (err < 0) { 735bee62662SJames Hogan DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err); 736bee62662SJames Hogan ret = err; 737bee62662SJames Hogan } else { 738bee62662SJames Hogan restore_msa_fp_status(env); 739bee62662SJames Hogan } 740bee62662SJames Hogan 741bee62662SJames Hogan /* Vector registers (includes FP registers) */ 742bee62662SJames Hogan for (i = 0; i < 32; ++i) { 743bee62662SJames Hogan /* Big endian MSA not supported by QEMU yet anyway */ 744bee62662SJames Hogan err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 745bee62662SJames Hogan env->active_fpu.fpr[i].wr.d); 746bee62662SJames Hogan if (err < 0) { 747bee62662SJames Hogan DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err); 748bee62662SJames Hogan ret = err; 749bee62662SJames Hogan } 750bee62662SJames Hogan } 751bee62662SJames Hogan } 752152db36aSJames Hogan 753152db36aSJames Hogan return ret; 754152db36aSJames Hogan } 755152db36aSJames Hogan 756152db36aSJames Hogan 757e2132e0bSSanjay Lal static int kvm_mips_put_cp0_registers(CPUState *cs, int level) 758e2132e0bSSanjay Lal { 759e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 760e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 761e2132e0bSSanjay Lal int err, ret = 0; 762e2132e0bSSanjay Lal 763e2132e0bSSanjay Lal (void)level; 764e2132e0bSSanjay Lal 765e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 766e2132e0bSSanjay Lal if (err < 0) { 767e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err); 768e2132e0bSSanjay Lal ret = err; 769e2132e0bSSanjay Lal } 770*7e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 771*7e0896b0SHuacai Chen if (err < 0) { 772*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err); 773*7e0896b0SHuacai Chen ret = err; 774*7e0896b0SHuacai Chen } 775e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 776e2132e0bSSanjay Lal &env->CP0_Context); 777e2132e0bSSanjay Lal if (err < 0) { 778e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err); 779e2132e0bSSanjay Lal ret = err; 780e2132e0bSSanjay Lal } 781e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 782e2132e0bSSanjay Lal &env->active_tc.CP0_UserLocal); 783e2132e0bSSanjay Lal if (err < 0) { 784e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err); 785e2132e0bSSanjay Lal ret = err; 786e2132e0bSSanjay Lal } 787e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 788e2132e0bSSanjay Lal &env->CP0_PageMask); 789e2132e0bSSanjay Lal if (err < 0) { 790e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err); 791e2132e0bSSanjay Lal ret = err; 792e2132e0bSSanjay Lal } 793*7e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 794*7e0896b0SHuacai Chen &env->CP0_PageGrain); 795*7e0896b0SHuacai Chen if (err < 0) { 796*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err); 797*7e0896b0SHuacai Chen ret = err; 798*7e0896b0SHuacai Chen } 799*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 800*7e0896b0SHuacai Chen &env->CP0_PWBase); 801*7e0896b0SHuacai Chen if (err < 0) { 802*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err); 803*7e0896b0SHuacai Chen ret = err; 804*7e0896b0SHuacai Chen } 805*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 806*7e0896b0SHuacai Chen &env->CP0_PWField); 807*7e0896b0SHuacai Chen if (err < 0) { 808*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err); 809*7e0896b0SHuacai Chen ret = err; 810*7e0896b0SHuacai Chen } 811*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 812*7e0896b0SHuacai Chen &env->CP0_PWSize); 813*7e0896b0SHuacai Chen if (err < 0) { 814*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err); 815*7e0896b0SHuacai Chen ret = err; 816*7e0896b0SHuacai Chen } 817e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 818e2132e0bSSanjay Lal if (err < 0) { 819e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err); 820e2132e0bSSanjay Lal ret = err; 821e2132e0bSSanjay Lal } 822*7e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 823*7e0896b0SHuacai Chen if (err < 0) { 824*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err); 825*7e0896b0SHuacai Chen ret = err; 826*7e0896b0SHuacai Chen } 827e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 828e2132e0bSSanjay Lal if (err < 0) { 829e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err); 830e2132e0bSSanjay Lal ret = err; 831e2132e0bSSanjay Lal } 832e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 833e2132e0bSSanjay Lal &env->CP0_BadVAddr); 834e2132e0bSSanjay Lal if (err < 0) { 835e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err); 836e2132e0bSSanjay Lal ret = err; 837e2132e0bSSanjay Lal } 838e2132e0bSSanjay Lal 839e2132e0bSSanjay Lal /* If VM clock stopped then state will be restored when it is restarted */ 840e2132e0bSSanjay Lal if (runstate_is_running()) { 841e2132e0bSSanjay Lal err = kvm_mips_restore_count(cs); 842e2132e0bSSanjay Lal if (err < 0) { 843e2132e0bSSanjay Lal ret = err; 844e2132e0bSSanjay Lal } 845e2132e0bSSanjay Lal } 846e2132e0bSSanjay Lal 847e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 848e2132e0bSSanjay Lal &env->CP0_EntryHi); 849e2132e0bSSanjay Lal if (err < 0) { 850e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err); 851e2132e0bSSanjay Lal ret = err; 852e2132e0bSSanjay Lal } 853e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 854e2132e0bSSanjay Lal &env->CP0_Compare); 855e2132e0bSSanjay Lal if (err < 0) { 856e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err); 857e2132e0bSSanjay Lal ret = err; 858e2132e0bSSanjay Lal } 859e2132e0bSSanjay Lal err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 860e2132e0bSSanjay Lal if (err < 0) { 861e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err); 862e2132e0bSSanjay Lal ret = err; 863e2132e0bSSanjay Lal } 864e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 865e2132e0bSSanjay Lal if (err < 0) { 866e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err); 867e2132e0bSSanjay Lal ret = err; 868e2132e0bSSanjay Lal } 869461a1582SJames Hogan err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 870461a1582SJames Hogan if (err < 0) { 871461a1582SJames Hogan DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); 872461a1582SJames Hogan ret = err; 873461a1582SJames Hogan } 874*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 875*7e0896b0SHuacai Chen if (err < 0) { 876*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err); 877*7e0896b0SHuacai Chen ret = err; 878*7e0896b0SHuacai Chen } 87903cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, 88003cbfd7bSJames Hogan &env->CP0_Config0, 88103cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG_MASK); 88203cbfd7bSJames Hogan if (err < 0) { 88303cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err); 88403cbfd7bSJames Hogan ret = err; 88503cbfd7bSJames Hogan } 88603cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, 88703cbfd7bSJames Hogan &env->CP0_Config1, 88803cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG1_MASK); 88903cbfd7bSJames Hogan if (err < 0) { 89003cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err); 89103cbfd7bSJames Hogan ret = err; 89203cbfd7bSJames Hogan } 89303cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, 89403cbfd7bSJames Hogan &env->CP0_Config2, 89503cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG2_MASK); 89603cbfd7bSJames Hogan if (err < 0) { 89703cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err); 89803cbfd7bSJames Hogan ret = err; 89903cbfd7bSJames Hogan } 90003cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, 90103cbfd7bSJames Hogan &env->CP0_Config3, 90203cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG3_MASK); 90303cbfd7bSJames Hogan if (err < 0) { 90403cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err); 90503cbfd7bSJames Hogan ret = err; 90603cbfd7bSJames Hogan } 90703cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, 90803cbfd7bSJames Hogan &env->CP0_Config4, 90903cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG4_MASK); 91003cbfd7bSJames Hogan if (err < 0) { 91103cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err); 91203cbfd7bSJames Hogan ret = err; 91303cbfd7bSJames Hogan } 91403cbfd7bSJames Hogan err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, 91503cbfd7bSJames Hogan &env->CP0_Config5, 91603cbfd7bSJames Hogan KVM_REG_MIPS_CP0_CONFIG5_MASK); 91703cbfd7bSJames Hogan if (err < 0) { 91803cbfd7bSJames Hogan DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); 91903cbfd7bSJames Hogan ret = err; 92003cbfd7bSJames Hogan } 921*7e0896b0SHuacai Chen err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, 922*7e0896b0SHuacai Chen &env->CP0_Config6, 923*7e0896b0SHuacai Chen KVM_REG_MIPS_CP0_CONFIG6_MASK); 924*7e0896b0SHuacai Chen if (err < 0) { 925*7e0896b0SHuacai Chen DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err); 926*7e0896b0SHuacai Chen ret = err; 927*7e0896b0SHuacai Chen } 928*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 929*7e0896b0SHuacai Chen &env->CP0_XContext); 930*7e0896b0SHuacai Chen if (err < 0) { 931*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err); 932*7e0896b0SHuacai Chen ret = err; 933*7e0896b0SHuacai Chen } 934e2132e0bSSanjay Lal err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 935e2132e0bSSanjay Lal &env->CP0_ErrorEPC); 936e2132e0bSSanjay Lal if (err < 0) { 937e2132e0bSSanjay Lal DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err); 938e2132e0bSSanjay Lal ret = err; 939e2132e0bSSanjay Lal } 940*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 941*7e0896b0SHuacai Chen &env->CP0_KScratch[0]); 942*7e0896b0SHuacai Chen if (err < 0) { 943*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err); 944*7e0896b0SHuacai Chen ret = err; 945*7e0896b0SHuacai Chen } 946*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 947*7e0896b0SHuacai Chen &env->CP0_KScratch[1]); 948*7e0896b0SHuacai Chen if (err < 0) { 949*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err); 950*7e0896b0SHuacai Chen ret = err; 951*7e0896b0SHuacai Chen } 952*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 953*7e0896b0SHuacai Chen &env->CP0_KScratch[2]); 954*7e0896b0SHuacai Chen if (err < 0) { 955*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err); 956*7e0896b0SHuacai Chen ret = err; 957*7e0896b0SHuacai Chen } 958*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 959*7e0896b0SHuacai Chen &env->CP0_KScratch[3]); 960*7e0896b0SHuacai Chen if (err < 0) { 961*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err); 962*7e0896b0SHuacai Chen ret = err; 963*7e0896b0SHuacai Chen } 964*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 965*7e0896b0SHuacai Chen &env->CP0_KScratch[4]); 966*7e0896b0SHuacai Chen if (err < 0) { 967*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err); 968*7e0896b0SHuacai Chen ret = err; 969*7e0896b0SHuacai Chen } 970*7e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 971*7e0896b0SHuacai Chen &env->CP0_KScratch[5]); 972*7e0896b0SHuacai Chen if (err < 0) { 973*7e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err); 974*7e0896b0SHuacai Chen ret = err; 975*7e0896b0SHuacai Chen } 976e2132e0bSSanjay Lal 977e2132e0bSSanjay Lal return ret; 978e2132e0bSSanjay Lal } 979e2132e0bSSanjay Lal 980e2132e0bSSanjay Lal static int kvm_mips_get_cp0_registers(CPUState *cs) 981e2132e0bSSanjay Lal { 982e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 983e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 984e2132e0bSSanjay Lal int err, ret = 0; 985e2132e0bSSanjay Lal 986e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 987e2132e0bSSanjay Lal if (err < 0) { 988e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err); 989e2132e0bSSanjay Lal ret = err; 990e2132e0bSSanjay Lal } 991*7e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 992*7e0896b0SHuacai Chen if (err < 0) { 993*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err); 994*7e0896b0SHuacai Chen ret = err; 995*7e0896b0SHuacai Chen } 996e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 997e2132e0bSSanjay Lal &env->CP0_Context); 998e2132e0bSSanjay Lal if (err < 0) { 999e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err); 1000e2132e0bSSanjay Lal ret = err; 1001e2132e0bSSanjay Lal } 1002e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 1003e2132e0bSSanjay Lal &env->active_tc.CP0_UserLocal); 1004e2132e0bSSanjay Lal if (err < 0) { 1005e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err); 1006e2132e0bSSanjay Lal ret = err; 1007e2132e0bSSanjay Lal } 1008e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 1009e2132e0bSSanjay Lal &env->CP0_PageMask); 1010e2132e0bSSanjay Lal if (err < 0) { 1011e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err); 1012e2132e0bSSanjay Lal ret = err; 1013e2132e0bSSanjay Lal } 1014*7e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 1015*7e0896b0SHuacai Chen &env->CP0_PageGrain); 1016*7e0896b0SHuacai Chen if (err < 0) { 1017*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err); 1018*7e0896b0SHuacai Chen ret = err; 1019*7e0896b0SHuacai Chen } 1020*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 1021*7e0896b0SHuacai Chen &env->CP0_PWBase); 1022*7e0896b0SHuacai Chen if (err < 0) { 1023*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err); 1024*7e0896b0SHuacai Chen ret = err; 1025*7e0896b0SHuacai Chen } 1026*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 1027*7e0896b0SHuacai Chen &env->CP0_PWField); 1028*7e0896b0SHuacai Chen if (err < 0) { 1029*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err); 1030*7e0896b0SHuacai Chen ret = err; 1031*7e0896b0SHuacai Chen } 1032*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 1033*7e0896b0SHuacai Chen &env->CP0_PWSize); 1034*7e0896b0SHuacai Chen if (err < 0) { 1035*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err); 1036*7e0896b0SHuacai Chen ret = err; 1037*7e0896b0SHuacai Chen } 1038e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 1039e2132e0bSSanjay Lal if (err < 0) { 1040e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err); 1041e2132e0bSSanjay Lal ret = err; 1042e2132e0bSSanjay Lal } 1043*7e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 1044*7e0896b0SHuacai Chen if (err < 0) { 1045*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err); 1046*7e0896b0SHuacai Chen ret = err; 1047*7e0896b0SHuacai Chen } 1048e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 1049e2132e0bSSanjay Lal if (err < 0) { 1050e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err); 1051e2132e0bSSanjay Lal ret = err; 1052e2132e0bSSanjay Lal } 1053e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 1054e2132e0bSSanjay Lal &env->CP0_BadVAddr); 1055e2132e0bSSanjay Lal if (err < 0) { 1056e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err); 1057e2132e0bSSanjay Lal ret = err; 1058e2132e0bSSanjay Lal } 1059e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 1060e2132e0bSSanjay Lal &env->CP0_EntryHi); 1061e2132e0bSSanjay Lal if (err < 0) { 1062e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err); 1063e2132e0bSSanjay Lal ret = err; 1064e2132e0bSSanjay Lal } 1065e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 1066e2132e0bSSanjay Lal &env->CP0_Compare); 1067e2132e0bSSanjay Lal if (err < 0) { 1068e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err); 1069e2132e0bSSanjay Lal ret = err; 1070e2132e0bSSanjay Lal } 1071e2132e0bSSanjay Lal err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 1072e2132e0bSSanjay Lal if (err < 0) { 1073e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err); 1074e2132e0bSSanjay Lal ret = err; 1075e2132e0bSSanjay Lal } 1076e2132e0bSSanjay Lal 1077e2132e0bSSanjay Lal /* If VM clock stopped then state was already saved when it was stopped */ 1078e2132e0bSSanjay Lal if (runstate_is_running()) { 1079e2132e0bSSanjay Lal err = kvm_mips_save_count(cs); 1080e2132e0bSSanjay Lal if (err < 0) { 1081e2132e0bSSanjay Lal ret = err; 1082e2132e0bSSanjay Lal } 1083e2132e0bSSanjay Lal } 1084e2132e0bSSanjay Lal 1085e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 1086e2132e0bSSanjay Lal if (err < 0) { 1087e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err); 1088e2132e0bSSanjay Lal ret = err; 1089e2132e0bSSanjay Lal } 1090461a1582SJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 1091461a1582SJames Hogan if (err < 0) { 1092461a1582SJames Hogan DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); 1093461a1582SJames Hogan ret = err; 1094461a1582SJames Hogan } 1095*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 1096*7e0896b0SHuacai Chen if (err < 0) { 1097*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err); 1098*7e0896b0SHuacai Chen ret = err; 1099*7e0896b0SHuacai Chen } 110003cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); 110103cbfd7bSJames Hogan if (err < 0) { 110203cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); 110303cbfd7bSJames Hogan ret = err; 110403cbfd7bSJames Hogan } 110503cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1); 110603cbfd7bSJames Hogan if (err < 0) { 110703cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err); 110803cbfd7bSJames Hogan ret = err; 110903cbfd7bSJames Hogan } 111003cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2); 111103cbfd7bSJames Hogan if (err < 0) { 111203cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err); 111303cbfd7bSJames Hogan ret = err; 111403cbfd7bSJames Hogan } 111503cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3); 111603cbfd7bSJames Hogan if (err < 0) { 111703cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err); 111803cbfd7bSJames Hogan ret = err; 111903cbfd7bSJames Hogan } 112003cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4); 112103cbfd7bSJames Hogan if (err < 0) { 112203cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err); 112303cbfd7bSJames Hogan ret = err; 112403cbfd7bSJames Hogan } 112503cbfd7bSJames Hogan err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5); 112603cbfd7bSJames Hogan if (err < 0) { 112703cbfd7bSJames Hogan DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); 112803cbfd7bSJames Hogan ret = err; 112903cbfd7bSJames Hogan } 1130*7e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6); 1131*7e0896b0SHuacai Chen if (err < 0) { 1132*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err); 1133*7e0896b0SHuacai Chen ret = err; 1134*7e0896b0SHuacai Chen } 1135*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 1136*7e0896b0SHuacai Chen &env->CP0_XContext); 1137*7e0896b0SHuacai Chen if (err < 0) { 1138*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err); 1139*7e0896b0SHuacai Chen ret = err; 1140*7e0896b0SHuacai Chen } 1141e2132e0bSSanjay Lal err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 1142e2132e0bSSanjay Lal &env->CP0_ErrorEPC); 1143e2132e0bSSanjay Lal if (err < 0) { 1144e2132e0bSSanjay Lal DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err); 1145e2132e0bSSanjay Lal ret = err; 1146e2132e0bSSanjay Lal } 1147*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 1148*7e0896b0SHuacai Chen &env->CP0_KScratch[0]); 1149*7e0896b0SHuacai Chen if (err < 0) { 1150*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err); 1151*7e0896b0SHuacai Chen ret = err; 1152*7e0896b0SHuacai Chen } 1153*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 1154*7e0896b0SHuacai Chen &env->CP0_KScratch[1]); 1155*7e0896b0SHuacai Chen if (err < 0) { 1156*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err); 1157*7e0896b0SHuacai Chen ret = err; 1158*7e0896b0SHuacai Chen } 1159*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 1160*7e0896b0SHuacai Chen &env->CP0_KScratch[2]); 1161*7e0896b0SHuacai Chen if (err < 0) { 1162*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err); 1163*7e0896b0SHuacai Chen ret = err; 1164*7e0896b0SHuacai Chen } 1165*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 1166*7e0896b0SHuacai Chen &env->CP0_KScratch[3]); 1167*7e0896b0SHuacai Chen if (err < 0) { 1168*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err); 1169*7e0896b0SHuacai Chen ret = err; 1170*7e0896b0SHuacai Chen } 1171*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 1172*7e0896b0SHuacai Chen &env->CP0_KScratch[4]); 1173*7e0896b0SHuacai Chen if (err < 0) { 1174*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err); 1175*7e0896b0SHuacai Chen ret = err; 1176*7e0896b0SHuacai Chen } 1177*7e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 1178*7e0896b0SHuacai Chen &env->CP0_KScratch[5]); 1179*7e0896b0SHuacai Chen if (err < 0) { 1180*7e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err); 1181*7e0896b0SHuacai Chen ret = err; 1182*7e0896b0SHuacai Chen } 1183e2132e0bSSanjay Lal 1184e2132e0bSSanjay Lal return ret; 1185e2132e0bSSanjay Lal } 1186e2132e0bSSanjay Lal 1187e2132e0bSSanjay Lal int kvm_arch_put_registers(CPUState *cs, int level) 1188e2132e0bSSanjay Lal { 1189e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 1190e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 1191e2132e0bSSanjay Lal struct kvm_regs regs; 1192e2132e0bSSanjay Lal int ret; 1193e2132e0bSSanjay Lal int i; 1194e2132e0bSSanjay Lal 1195e2132e0bSSanjay Lal /* Set the registers based on QEMU's view of things */ 1196e2132e0bSSanjay Lal for (i = 0; i < 32; i++) { 119702dae26aSJames Hogan regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; 1198e2132e0bSSanjay Lal } 1199e2132e0bSSanjay Lal 120002dae26aSJames Hogan regs.hi = (int64_t)(target_long)env->active_tc.HI[0]; 120102dae26aSJames Hogan regs.lo = (int64_t)(target_long)env->active_tc.LO[0]; 120202dae26aSJames Hogan regs.pc = (int64_t)(target_long)env->active_tc.PC; 1203e2132e0bSSanjay Lal 1204e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 1205e2132e0bSSanjay Lal 1206e2132e0bSSanjay Lal if (ret < 0) { 1207e2132e0bSSanjay Lal return ret; 1208e2132e0bSSanjay Lal } 1209e2132e0bSSanjay Lal 1210e2132e0bSSanjay Lal ret = kvm_mips_put_cp0_registers(cs, level); 1211e2132e0bSSanjay Lal if (ret < 0) { 1212e2132e0bSSanjay Lal return ret; 1213e2132e0bSSanjay Lal } 1214e2132e0bSSanjay Lal 1215152db36aSJames Hogan ret = kvm_mips_put_fpu_registers(cs, level); 1216152db36aSJames Hogan if (ret < 0) { 1217152db36aSJames Hogan return ret; 1218152db36aSJames Hogan } 1219152db36aSJames Hogan 1220e2132e0bSSanjay Lal return ret; 1221e2132e0bSSanjay Lal } 1222e2132e0bSSanjay Lal 1223e2132e0bSSanjay Lal int kvm_arch_get_registers(CPUState *cs) 1224e2132e0bSSanjay Lal { 1225e2132e0bSSanjay Lal MIPSCPU *cpu = MIPS_CPU(cs); 1226e2132e0bSSanjay Lal CPUMIPSState *env = &cpu->env; 1227e2132e0bSSanjay Lal int ret = 0; 1228e2132e0bSSanjay Lal struct kvm_regs regs; 1229e2132e0bSSanjay Lal int i; 1230e2132e0bSSanjay Lal 1231e2132e0bSSanjay Lal /* Get the current register set as KVM seems it */ 1232e2132e0bSSanjay Lal ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1233e2132e0bSSanjay Lal 1234e2132e0bSSanjay Lal if (ret < 0) { 1235e2132e0bSSanjay Lal return ret; 1236e2132e0bSSanjay Lal } 1237e2132e0bSSanjay Lal 1238e2132e0bSSanjay Lal for (i = 0; i < 32; i++) { 1239e2132e0bSSanjay Lal env->active_tc.gpr[i] = regs.gpr[i]; 1240e2132e0bSSanjay Lal } 1241e2132e0bSSanjay Lal 1242e2132e0bSSanjay Lal env->active_tc.HI[0] = regs.hi; 1243e2132e0bSSanjay Lal env->active_tc.LO[0] = regs.lo; 1244e2132e0bSSanjay Lal env->active_tc.PC = regs.pc; 1245e2132e0bSSanjay Lal 1246e2132e0bSSanjay Lal kvm_mips_get_cp0_registers(cs); 1247152db36aSJames Hogan kvm_mips_get_fpu_registers(cs); 1248e2132e0bSSanjay Lal 1249e2132e0bSSanjay Lal return ret; 1250e2132e0bSSanjay Lal } 12519e03a040SFrank Blaschka 12529e03a040SFrank Blaschka int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1253dc9f06caSPavel Fedin uint64_t address, uint32_t data, PCIDevice *dev) 12549e03a040SFrank Blaschka { 12559e03a040SFrank Blaschka return 0; 12569e03a040SFrank Blaschka } 12571850b6b7SEric Auger 125838d87493SPeter Xu int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 125938d87493SPeter Xu int vector, PCIDevice *dev) 126038d87493SPeter Xu { 126138d87493SPeter Xu return 0; 126238d87493SPeter Xu } 126338d87493SPeter Xu 126438d87493SPeter Xu int kvm_arch_release_virq_post(int virq) 126538d87493SPeter Xu { 126638d87493SPeter Xu return 0; 126738d87493SPeter Xu } 126838d87493SPeter Xu 12691850b6b7SEric Auger int kvm_arch_msi_data_to_gsi(uint32_t data) 12701850b6b7SEric Auger { 12711850b6b7SEric Auger abort(); 12721850b6b7SEric Auger } 1273