1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * This file is subject to the terms and conditions of the GNU General Public 3fcf5ef2aSThomas Huth * License. See the file "COPYING" in the main directory of this archive 4fcf5ef2aSThomas Huth * for more details. 5fcf5ef2aSThomas Huth * 6fcf5ef2aSThomas Huth * KVM/MIPS: MIPS specific KVM APIs 7fcf5ef2aSThomas Huth * 8fcf5ef2aSThomas Huth * Copyright (C) 2012-2014 Imagination Technologies Ltd. 9fcf5ef2aSThomas Huth * Authors: Sanjay Lal <sanjayl@kymasys.com> 10fcf5ef2aSThomas Huth */ 11fcf5ef2aSThomas Huth 12fcf5ef2aSThomas Huth #include "qemu/osdep.h" 13fcf5ef2aSThomas Huth #include <sys/ioctl.h> 14fcf5ef2aSThomas Huth 15fcf5ef2aSThomas Huth #include <linux/kvm.h> 16fcf5ef2aSThomas Huth 17fcf5ef2aSThomas Huth #include "qemu-common.h" 18fcf5ef2aSThomas Huth #include "cpu.h" 1926aa3d9aSPhilippe Mathieu-Daudé #include "internal.h" 20fcf5ef2aSThomas Huth #include "qemu/error-report.h" 21db725815SMarkus Armbruster #include "qemu/main-loop.h" 22fcf5ef2aSThomas Huth #include "qemu/timer.h" 23fcf5ef2aSThomas Huth #include "sysemu/kvm.h" 24*719d109bSHuacai Chen #include "sysemu/kvm_int.h" 2554d31236SMarkus Armbruster #include "sysemu/runstate.h" 26fcf5ef2aSThomas Huth #include "sysemu/cpus.h" 27fcf5ef2aSThomas Huth #include "kvm_mips.h" 28fcf5ef2aSThomas Huth #include "exec/memattrs.h" 29*719d109bSHuacai Chen #include "hw/boards.h" 30fcf5ef2aSThomas Huth 31fcf5ef2aSThomas Huth #define DEBUG_KVM 0 32fcf5ef2aSThomas Huth 33fcf5ef2aSThomas Huth #define DPRINTF(fmt, ...) \ 34fcf5ef2aSThomas Huth do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) 35fcf5ef2aSThomas Huth 36fcf5ef2aSThomas Huth static int kvm_mips_fpu_cap; 37fcf5ef2aSThomas Huth static int kvm_mips_msa_cap; 38fcf5ef2aSThomas Huth 39fcf5ef2aSThomas Huth const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 40fcf5ef2aSThomas Huth KVM_CAP_LAST_INFO 41fcf5ef2aSThomas Huth }; 42fcf5ef2aSThomas Huth 43fcf5ef2aSThomas Huth static void kvm_mips_update_state(void *opaque, int running, RunState state); 44fcf5ef2aSThomas Huth 45fcf5ef2aSThomas Huth unsigned long kvm_arch_vcpu_id(CPUState *cs) 46fcf5ef2aSThomas Huth { 47fcf5ef2aSThomas Huth return cs->cpu_index; 48fcf5ef2aSThomas Huth } 49fcf5ef2aSThomas Huth 50fcf5ef2aSThomas Huth int kvm_arch_init(MachineState *ms, KVMState *s) 51fcf5ef2aSThomas Huth { 52fcf5ef2aSThomas Huth /* MIPS has 128 signals */ 53fcf5ef2aSThomas Huth kvm_set_sigmask_len(s, 16); 54fcf5ef2aSThomas Huth 55fcf5ef2aSThomas Huth kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU); 56fcf5ef2aSThomas Huth kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA); 57fcf5ef2aSThomas Huth 58fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 59fcf5ef2aSThomas Huth return 0; 60fcf5ef2aSThomas Huth } 61fcf5ef2aSThomas Huth 624376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 63d525ffabSPaolo Bonzini { 64d525ffabSPaolo Bonzini return 0; 65d525ffabSPaolo Bonzini } 66d525ffabSPaolo Bonzini 67fcf5ef2aSThomas Huth int kvm_arch_init_vcpu(CPUState *cs) 68fcf5ef2aSThomas Huth { 69fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 70fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 71fcf5ef2aSThomas Huth int ret = 0; 72fcf5ef2aSThomas Huth 73fcf5ef2aSThomas Huth qemu_add_vm_change_state_handler(kvm_mips_update_state, cs); 74fcf5ef2aSThomas Huth 75fcf5ef2aSThomas Huth if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 76fcf5ef2aSThomas Huth ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0); 77fcf5ef2aSThomas Huth if (ret < 0) { 78fcf5ef2aSThomas Huth /* mark unsupported so it gets disabled on reset */ 79fcf5ef2aSThomas Huth kvm_mips_fpu_cap = 0; 80fcf5ef2aSThomas Huth ret = 0; 81fcf5ef2aSThomas Huth } 82fcf5ef2aSThomas Huth } 83fcf5ef2aSThomas Huth 84fcf5ef2aSThomas Huth if (kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { 85fcf5ef2aSThomas Huth ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0); 86fcf5ef2aSThomas Huth if (ret < 0) { 87fcf5ef2aSThomas Huth /* mark unsupported so it gets disabled on reset */ 88fcf5ef2aSThomas Huth kvm_mips_msa_cap = 0; 89fcf5ef2aSThomas Huth ret = 0; 90fcf5ef2aSThomas Huth } 91fcf5ef2aSThomas Huth } 92fcf5ef2aSThomas Huth 93fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 94fcf5ef2aSThomas Huth return ret; 95fcf5ef2aSThomas Huth } 96fcf5ef2aSThomas Huth 97b1115c99SLiran Alon int kvm_arch_destroy_vcpu(CPUState *cs) 98b1115c99SLiran Alon { 99b1115c99SLiran Alon return 0; 100b1115c99SLiran Alon } 101b1115c99SLiran Alon 102fcf5ef2aSThomas Huth void kvm_mips_reset_vcpu(MIPSCPU *cpu) 103fcf5ef2aSThomas Huth { 104fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 105fcf5ef2aSThomas Huth 106fcf5ef2aSThomas Huth if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 1072ab4b135SAlistair Francis warn_report("KVM does not support FPU, disabling"); 108fcf5ef2aSThomas Huth env->CP0_Config1 &= ~(1 << CP0C1_FP); 109fcf5ef2aSThomas Huth } 110fcf5ef2aSThomas Huth if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { 1112ab4b135SAlistair Francis warn_report("KVM does not support MSA, disabling"); 112fcf5ef2aSThomas Huth env->CP0_Config3 &= ~(1 << CP0C3_MSAP); 113fcf5ef2aSThomas Huth } 114fcf5ef2aSThomas Huth 115fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 116fcf5ef2aSThomas Huth } 117fcf5ef2aSThomas Huth 118fcf5ef2aSThomas Huth int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 119fcf5ef2aSThomas Huth { 120fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 121fcf5ef2aSThomas Huth return 0; 122fcf5ef2aSThomas Huth } 123fcf5ef2aSThomas Huth 124fcf5ef2aSThomas Huth int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 125fcf5ef2aSThomas Huth { 126fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 127fcf5ef2aSThomas Huth return 0; 128fcf5ef2aSThomas Huth } 129fcf5ef2aSThomas Huth 130fcf5ef2aSThomas Huth static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) 131fcf5ef2aSThomas Huth { 132fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 133fcf5ef2aSThomas Huth 134fcf5ef2aSThomas Huth return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP)); 135fcf5ef2aSThomas Huth } 136fcf5ef2aSThomas Huth 137fcf5ef2aSThomas Huth 138fcf5ef2aSThomas Huth void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 139fcf5ef2aSThomas Huth { 140fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 141fcf5ef2aSThomas Huth int r; 142fcf5ef2aSThomas Huth struct kvm_mips_interrupt intr; 143fcf5ef2aSThomas Huth 144fcf5ef2aSThomas Huth qemu_mutex_lock_iothread(); 145fcf5ef2aSThomas Huth 146fcf5ef2aSThomas Huth if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 147fcf5ef2aSThomas Huth cpu_mips_io_interrupts_pending(cpu)) { 148fcf5ef2aSThomas Huth intr.cpu = -1; 149fcf5ef2aSThomas Huth intr.irq = 2; 150fcf5ef2aSThomas Huth r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 151fcf5ef2aSThomas Huth if (r < 0) { 152fcf5ef2aSThomas Huth error_report("%s: cpu %d: failed to inject IRQ %x", 153fcf5ef2aSThomas Huth __func__, cs->cpu_index, intr.irq); 154fcf5ef2aSThomas Huth } 155fcf5ef2aSThomas Huth } 156fcf5ef2aSThomas Huth 157fcf5ef2aSThomas Huth qemu_mutex_unlock_iothread(); 158fcf5ef2aSThomas Huth } 159fcf5ef2aSThomas Huth 160fcf5ef2aSThomas Huth MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 161fcf5ef2aSThomas Huth { 162fcf5ef2aSThomas Huth return MEMTXATTRS_UNSPECIFIED; 163fcf5ef2aSThomas Huth } 164fcf5ef2aSThomas Huth 165fcf5ef2aSThomas Huth int kvm_arch_process_async_events(CPUState *cs) 166fcf5ef2aSThomas Huth { 167fcf5ef2aSThomas Huth return cs->halted; 168fcf5ef2aSThomas Huth } 169fcf5ef2aSThomas Huth 170fcf5ef2aSThomas Huth int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 171fcf5ef2aSThomas Huth { 172fcf5ef2aSThomas Huth int ret; 173fcf5ef2aSThomas Huth 174fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 175fcf5ef2aSThomas Huth switch (run->exit_reason) { 176fcf5ef2aSThomas Huth default: 177fcf5ef2aSThomas Huth error_report("%s: unknown exit reason %d", 178fcf5ef2aSThomas Huth __func__, run->exit_reason); 179fcf5ef2aSThomas Huth ret = -1; 180fcf5ef2aSThomas Huth break; 181fcf5ef2aSThomas Huth } 182fcf5ef2aSThomas Huth 183fcf5ef2aSThomas Huth return ret; 184fcf5ef2aSThomas Huth } 185fcf5ef2aSThomas Huth 186fcf5ef2aSThomas Huth bool kvm_arch_stop_on_emulation_error(CPUState *cs) 187fcf5ef2aSThomas Huth { 188fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 189fcf5ef2aSThomas Huth return true; 190fcf5ef2aSThomas Huth } 191fcf5ef2aSThomas Huth 192fcf5ef2aSThomas Huth void kvm_arch_init_irq_routing(KVMState *s) 193fcf5ef2aSThomas Huth { 194fcf5ef2aSThomas Huth } 195fcf5ef2aSThomas Huth 196fcf5ef2aSThomas Huth int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level) 197fcf5ef2aSThomas Huth { 198fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 199fcf5ef2aSThomas Huth struct kvm_mips_interrupt intr; 200fcf5ef2aSThomas Huth 201fcf5ef2aSThomas Huth if (!kvm_enabled()) { 202fcf5ef2aSThomas Huth return 0; 203fcf5ef2aSThomas Huth } 204fcf5ef2aSThomas Huth 205fcf5ef2aSThomas Huth intr.cpu = -1; 206fcf5ef2aSThomas Huth 207fcf5ef2aSThomas Huth if (level) { 208fcf5ef2aSThomas Huth intr.irq = irq; 209fcf5ef2aSThomas Huth } else { 210fcf5ef2aSThomas Huth intr.irq = -irq; 211fcf5ef2aSThomas Huth } 212fcf5ef2aSThomas Huth 213fcf5ef2aSThomas Huth kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 214fcf5ef2aSThomas Huth 215fcf5ef2aSThomas Huth return 0; 216fcf5ef2aSThomas Huth } 217fcf5ef2aSThomas Huth 218fcf5ef2aSThomas Huth int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) 219fcf5ef2aSThomas Huth { 220fcf5ef2aSThomas Huth CPUState *cs = current_cpu; 221fcf5ef2aSThomas Huth CPUState *dest_cs = CPU(cpu); 222fcf5ef2aSThomas Huth struct kvm_mips_interrupt intr; 223fcf5ef2aSThomas Huth 224fcf5ef2aSThomas Huth if (!kvm_enabled()) { 225fcf5ef2aSThomas Huth return 0; 226fcf5ef2aSThomas Huth } 227fcf5ef2aSThomas Huth 228fcf5ef2aSThomas Huth intr.cpu = dest_cs->cpu_index; 229fcf5ef2aSThomas Huth 230fcf5ef2aSThomas Huth if (level) { 231fcf5ef2aSThomas Huth intr.irq = irq; 232fcf5ef2aSThomas Huth } else { 233fcf5ef2aSThomas Huth intr.irq = -irq; 234fcf5ef2aSThomas Huth } 235fcf5ef2aSThomas Huth 236fcf5ef2aSThomas Huth DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq); 237fcf5ef2aSThomas Huth 238fcf5ef2aSThomas Huth kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 239fcf5ef2aSThomas Huth 240fcf5ef2aSThomas Huth return 0; 241fcf5ef2aSThomas Huth } 242fcf5ef2aSThomas Huth 243fcf5ef2aSThomas Huth #define MIPS_CP0_32(_R, _S) \ 244fcf5ef2aSThomas Huth (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) 245fcf5ef2aSThomas Huth 246fcf5ef2aSThomas Huth #define MIPS_CP0_64(_R, _S) \ 247fcf5ef2aSThomas Huth (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) 248fcf5ef2aSThomas Huth 249fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) 2507e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0) 251fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0) 252fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2) 253fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0) 2547e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1) 2557e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5) 2567e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6) 2577e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7) 258fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0) 2597e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6) 260fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0) 261fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0) 262fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0) 263fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0) 264fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0) 265fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) 266fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) 267fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) 268fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) 2697e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1) 270fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) 271fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) 272fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) 273fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 274fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) 275fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) 2767e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6) 2777e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) 278fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 2797e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2) 2807e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3) 2817e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4) 2827e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5) 2837e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6) 2847e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7) 285fcf5ef2aSThomas Huth 286fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, 287fcf5ef2aSThomas Huth int32_t *addr) 288fcf5ef2aSThomas Huth { 289fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 290fcf5ef2aSThomas Huth .id = reg_id, 291fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 292fcf5ef2aSThomas Huth }; 293fcf5ef2aSThomas Huth 294fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 295fcf5ef2aSThomas Huth } 296fcf5ef2aSThomas Huth 297fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id, 298fcf5ef2aSThomas Huth uint32_t *addr) 299fcf5ef2aSThomas Huth { 300fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 301fcf5ef2aSThomas Huth .id = reg_id, 302fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 303fcf5ef2aSThomas Huth }; 304fcf5ef2aSThomas Huth 305fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 306fcf5ef2aSThomas Huth } 307fcf5ef2aSThomas Huth 308fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, 309fcf5ef2aSThomas Huth target_ulong *addr) 310fcf5ef2aSThomas Huth { 311fcf5ef2aSThomas Huth uint64_t val64 = *addr; 312fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 313fcf5ef2aSThomas Huth .id = reg_id, 314fcf5ef2aSThomas Huth .addr = (uintptr_t)&val64 315fcf5ef2aSThomas Huth }; 316fcf5ef2aSThomas Huth 317fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 318fcf5ef2aSThomas Huth } 319fcf5ef2aSThomas Huth 320fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id, 321fcf5ef2aSThomas Huth int64_t *addr) 322fcf5ef2aSThomas Huth { 323fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 324fcf5ef2aSThomas Huth .id = reg_id, 325fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 326fcf5ef2aSThomas Huth }; 327fcf5ef2aSThomas Huth 328fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 329fcf5ef2aSThomas Huth } 330fcf5ef2aSThomas Huth 331fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id, 332fcf5ef2aSThomas Huth uint64_t *addr) 333fcf5ef2aSThomas Huth { 334fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 335fcf5ef2aSThomas Huth .id = reg_id, 336fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 337fcf5ef2aSThomas Huth }; 338fcf5ef2aSThomas Huth 339fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 340fcf5ef2aSThomas Huth } 341fcf5ef2aSThomas Huth 342fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id, 343fcf5ef2aSThomas Huth int32_t *addr) 344fcf5ef2aSThomas Huth { 345fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 346fcf5ef2aSThomas Huth .id = reg_id, 347fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 348fcf5ef2aSThomas Huth }; 349fcf5ef2aSThomas Huth 350fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 351fcf5ef2aSThomas Huth } 352fcf5ef2aSThomas Huth 353fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id, 354fcf5ef2aSThomas Huth uint32_t *addr) 355fcf5ef2aSThomas Huth { 356fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 357fcf5ef2aSThomas Huth .id = reg_id, 358fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 359fcf5ef2aSThomas Huth }; 360fcf5ef2aSThomas Huth 361fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 362fcf5ef2aSThomas Huth } 363fcf5ef2aSThomas Huth 364fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id, 365fcf5ef2aSThomas Huth target_ulong *addr) 366fcf5ef2aSThomas Huth { 367fcf5ef2aSThomas Huth int ret; 368fcf5ef2aSThomas Huth uint64_t val64 = 0; 369fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 370fcf5ef2aSThomas Huth .id = reg_id, 371fcf5ef2aSThomas Huth .addr = (uintptr_t)&val64 372fcf5ef2aSThomas Huth }; 373fcf5ef2aSThomas Huth 374fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 375fcf5ef2aSThomas Huth if (ret >= 0) { 376fcf5ef2aSThomas Huth *addr = val64; 377fcf5ef2aSThomas Huth } 378fcf5ef2aSThomas Huth return ret; 379fcf5ef2aSThomas Huth } 380fcf5ef2aSThomas Huth 381fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id, 382fcf5ef2aSThomas Huth int64_t *addr) 383fcf5ef2aSThomas Huth { 384fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 385fcf5ef2aSThomas Huth .id = reg_id, 386fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 387fcf5ef2aSThomas Huth }; 388fcf5ef2aSThomas Huth 389fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 390fcf5ef2aSThomas Huth } 391fcf5ef2aSThomas Huth 392fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, 393fcf5ef2aSThomas Huth uint64_t *addr) 394fcf5ef2aSThomas Huth { 395fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 396fcf5ef2aSThomas Huth .id = reg_id, 397fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 398fcf5ef2aSThomas Huth }; 399fcf5ef2aSThomas Huth 400fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 401fcf5ef2aSThomas Huth } 402fcf5ef2aSThomas Huth 403fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M) 404fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \ 405fcf5ef2aSThomas Huth (1U << CP0C1_FP)) 406fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M) 407fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \ 408fcf5ef2aSThomas Huth (1U << CP0C3_MSAP)) 409fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M) 410fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \ 411fcf5ef2aSThomas Huth (1U << CP0C5_UFE) | \ 412fcf5ef2aSThomas Huth (1U << CP0C5_FRE) | \ 413fcf5ef2aSThomas Huth (1U << CP0C5_UFR)) 4147e0896b0SHuacai Chen #define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \ 4157e0896b0SHuacai Chen (0x3fU << CP0C6_KPOS) | \ 4167e0896b0SHuacai Chen (1U << CP0C6_KE) | \ 4177e0896b0SHuacai Chen (1U << CP0C6_VTLBONLY) | \ 4187e0896b0SHuacai Chen (1U << CP0C6_LASX) | \ 4197e0896b0SHuacai Chen (1U << CP0C6_SSEN) | \ 4207e0896b0SHuacai Chen (1U << CP0C6_DISDRTIME) | \ 4217e0896b0SHuacai Chen (1U << CP0C6_PIXNUEN) | \ 4227e0896b0SHuacai Chen (1U << CP0C6_SCRAND) | \ 4237e0896b0SHuacai Chen (1U << CP0C6_LLEXCEN) | \ 4247e0896b0SHuacai Chen (1U << CP0C6_DISVC) | \ 4257e0896b0SHuacai Chen (1U << CP0C6_VCLRU) | \ 4267e0896b0SHuacai Chen (1U << CP0C6_DCLRU) | \ 4277e0896b0SHuacai Chen (1U << CP0C6_PIXUEN) | \ 4287e0896b0SHuacai Chen (1U << CP0C6_DISBLKLYEN) | \ 4297e0896b0SHuacai Chen (1U << CP0C6_UMEMUALEN) | \ 4307e0896b0SHuacai Chen (1U << CP0C6_SFBEN) | \ 4317e0896b0SHuacai Chen (1U << CP0C6_FLTINT) | \ 4327e0896b0SHuacai Chen (1U << CP0C6_VLTINT) | \ 4337e0896b0SHuacai Chen (1U << CP0C6_DISBTB) | \ 4347e0896b0SHuacai Chen (3U << CP0C6_STPREFCTL) | \ 4357e0896b0SHuacai Chen (1U << CP0C6_INSTPREF) | \ 4367e0896b0SHuacai Chen (1U << CP0C6_DATAPREF)) 437fcf5ef2aSThomas Huth 438fcf5ef2aSThomas Huth static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, 439fcf5ef2aSThomas Huth int32_t *addr, int32_t mask) 440fcf5ef2aSThomas Huth { 441fcf5ef2aSThomas Huth int err; 442fcf5ef2aSThomas Huth int32_t tmp, change; 443fcf5ef2aSThomas Huth 444fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, reg_id, &tmp); 445fcf5ef2aSThomas Huth if (err < 0) { 446fcf5ef2aSThomas Huth return err; 447fcf5ef2aSThomas Huth } 448fcf5ef2aSThomas Huth 449fcf5ef2aSThomas Huth /* only change bits in mask */ 450fcf5ef2aSThomas Huth change = (*addr ^ tmp) & mask; 451fcf5ef2aSThomas Huth if (!change) { 452fcf5ef2aSThomas Huth return 0; 453fcf5ef2aSThomas Huth } 454fcf5ef2aSThomas Huth 455fcf5ef2aSThomas Huth tmp = tmp ^ change; 456fcf5ef2aSThomas Huth return kvm_mips_put_one_reg(cs, reg_id, &tmp); 457fcf5ef2aSThomas Huth } 458fcf5ef2aSThomas Huth 459fcf5ef2aSThomas Huth /* 460fcf5ef2aSThomas Huth * We freeze the KVM timer when either the VM clock is stopped or the state is 461fcf5ef2aSThomas Huth * saved (the state is dirty). 462fcf5ef2aSThomas Huth */ 463fcf5ef2aSThomas Huth 464fcf5ef2aSThomas Huth /* 465fcf5ef2aSThomas Huth * Save the state of the KVM timer when VM clock is stopped or state is synced 466fcf5ef2aSThomas Huth * to QEMU. 467fcf5ef2aSThomas Huth */ 468fcf5ef2aSThomas Huth static int kvm_mips_save_count(CPUState *cs) 469fcf5ef2aSThomas Huth { 470fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 471fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 472fcf5ef2aSThomas Huth uint64_t count_ctl; 473fcf5ef2aSThomas Huth int err, ret = 0; 474fcf5ef2aSThomas Huth 475fcf5ef2aSThomas Huth /* freeze KVM timer */ 476fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 477fcf5ef2aSThomas Huth if (err < 0) { 478fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err); 479fcf5ef2aSThomas Huth ret = err; 480fcf5ef2aSThomas Huth } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 481fcf5ef2aSThomas Huth count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 482fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 483fcf5ef2aSThomas Huth if (err < 0) { 484fcf5ef2aSThomas Huth DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 485fcf5ef2aSThomas Huth ret = err; 486fcf5ef2aSThomas Huth } 487fcf5ef2aSThomas Huth } 488fcf5ef2aSThomas Huth 489fcf5ef2aSThomas Huth /* read CP0_Cause */ 490fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 491fcf5ef2aSThomas Huth if (err < 0) { 492fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err); 493fcf5ef2aSThomas Huth ret = err; 494fcf5ef2aSThomas Huth } 495fcf5ef2aSThomas Huth 496fcf5ef2aSThomas Huth /* read CP0_Count */ 497fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 498fcf5ef2aSThomas Huth if (err < 0) { 499fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err); 500fcf5ef2aSThomas Huth ret = err; 501fcf5ef2aSThomas Huth } 502fcf5ef2aSThomas Huth 503fcf5ef2aSThomas Huth return ret; 504fcf5ef2aSThomas Huth } 505fcf5ef2aSThomas Huth 506fcf5ef2aSThomas Huth /* 507fcf5ef2aSThomas Huth * Restore the state of the KVM timer when VM clock is restarted or state is 508fcf5ef2aSThomas Huth * synced to KVM. 509fcf5ef2aSThomas Huth */ 510fcf5ef2aSThomas Huth static int kvm_mips_restore_count(CPUState *cs) 511fcf5ef2aSThomas Huth { 512fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 513fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 514fcf5ef2aSThomas Huth uint64_t count_ctl; 515fcf5ef2aSThomas Huth int err_dc, err, ret = 0; 516fcf5ef2aSThomas Huth 517fcf5ef2aSThomas Huth /* check the timer is frozen */ 518fcf5ef2aSThomas Huth err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 519fcf5ef2aSThomas Huth if (err_dc < 0) { 520fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc); 521fcf5ef2aSThomas Huth ret = err_dc; 522fcf5ef2aSThomas Huth } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 523fcf5ef2aSThomas Huth /* freeze timer (sets COUNT_RESUME for us) */ 524fcf5ef2aSThomas Huth count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 525fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 526fcf5ef2aSThomas Huth if (err < 0) { 527fcf5ef2aSThomas Huth DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 528fcf5ef2aSThomas Huth ret = err; 529fcf5ef2aSThomas Huth } 530fcf5ef2aSThomas Huth } 531fcf5ef2aSThomas Huth 532fcf5ef2aSThomas Huth /* load CP0_Cause */ 533fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 534fcf5ef2aSThomas Huth if (err < 0) { 535fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err); 536fcf5ef2aSThomas Huth ret = err; 537fcf5ef2aSThomas Huth } 538fcf5ef2aSThomas Huth 539fcf5ef2aSThomas Huth /* load CP0_Count */ 540fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 541fcf5ef2aSThomas Huth if (err < 0) { 542fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err); 543fcf5ef2aSThomas Huth ret = err; 544fcf5ef2aSThomas Huth } 545fcf5ef2aSThomas Huth 546fcf5ef2aSThomas Huth /* resume KVM timer */ 547fcf5ef2aSThomas Huth if (err_dc >= 0) { 548fcf5ef2aSThomas Huth count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC; 549fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 550fcf5ef2aSThomas Huth if (err < 0) { 551fcf5ef2aSThomas Huth DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err); 552fcf5ef2aSThomas Huth ret = err; 553fcf5ef2aSThomas Huth } 554fcf5ef2aSThomas Huth } 555fcf5ef2aSThomas Huth 556fcf5ef2aSThomas Huth return ret; 557fcf5ef2aSThomas Huth } 558fcf5ef2aSThomas Huth 559fcf5ef2aSThomas Huth /* 560fcf5ef2aSThomas Huth * Handle the VM clock being started or stopped 561fcf5ef2aSThomas Huth */ 562fcf5ef2aSThomas Huth static void kvm_mips_update_state(void *opaque, int running, RunState state) 563fcf5ef2aSThomas Huth { 564fcf5ef2aSThomas Huth CPUState *cs = opaque; 565fcf5ef2aSThomas Huth int ret; 566fcf5ef2aSThomas Huth uint64_t count_resume; 567fcf5ef2aSThomas Huth 568fcf5ef2aSThomas Huth /* 569fcf5ef2aSThomas Huth * If state is already dirty (synced to QEMU) then the KVM timer state is 570fcf5ef2aSThomas Huth * already saved and can be restored when it is synced back to KVM. 571fcf5ef2aSThomas Huth */ 572fcf5ef2aSThomas Huth if (!running) { 57399f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 574fcf5ef2aSThomas Huth ret = kvm_mips_save_count(cs); 575fcf5ef2aSThomas Huth if (ret < 0) { 576288cb949SAlistair Francis warn_report("Failed saving count"); 577fcf5ef2aSThomas Huth } 578fcf5ef2aSThomas Huth } 579fcf5ef2aSThomas Huth } else { 580fcf5ef2aSThomas Huth /* Set clock restore time to now */ 581fcf5ef2aSThomas Huth count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 582fcf5ef2aSThomas Huth ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME, 583fcf5ef2aSThomas Huth &count_resume); 584fcf5ef2aSThomas Huth if (ret < 0) { 585288cb949SAlistair Francis warn_report("Failed setting COUNT_RESUME"); 586fcf5ef2aSThomas Huth return; 587fcf5ef2aSThomas Huth } 588fcf5ef2aSThomas Huth 58999f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 590fcf5ef2aSThomas Huth ret = kvm_mips_restore_count(cs); 591fcf5ef2aSThomas Huth if (ret < 0) { 592288cb949SAlistair Francis warn_report("Failed restoring count"); 593fcf5ef2aSThomas Huth } 594fcf5ef2aSThomas Huth } 595fcf5ef2aSThomas Huth } 596fcf5ef2aSThomas Huth } 597fcf5ef2aSThomas Huth 598fcf5ef2aSThomas Huth static int kvm_mips_put_fpu_registers(CPUState *cs, int level) 599fcf5ef2aSThomas Huth { 600fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 601fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 602fcf5ef2aSThomas Huth int err, ret = 0; 603fcf5ef2aSThomas Huth unsigned int i; 604fcf5ef2aSThomas Huth 605fcf5ef2aSThomas Huth /* Only put FPU state if we're emulating a CPU with an FPU */ 606fcf5ef2aSThomas Huth if (env->CP0_Config1 & (1 << CP0C1_FP)) { 607fcf5ef2aSThomas Huth /* FPU Control Registers */ 608fcf5ef2aSThomas Huth if (level == KVM_PUT_FULL_STATE) { 609fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 610fcf5ef2aSThomas Huth &env->active_fpu.fcr0); 611fcf5ef2aSThomas Huth if (err < 0) { 612fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err); 613fcf5ef2aSThomas Huth ret = err; 614fcf5ef2aSThomas Huth } 615fcf5ef2aSThomas Huth } 616fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 617fcf5ef2aSThomas Huth &env->active_fpu.fcr31); 618fcf5ef2aSThomas Huth if (err < 0) { 619fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err); 620fcf5ef2aSThomas Huth ret = err; 621fcf5ef2aSThomas Huth } 622fcf5ef2aSThomas Huth 623fcf5ef2aSThomas Huth /* 624fcf5ef2aSThomas Huth * FPU register state is a subset of MSA vector state, so don't put FPU 625fcf5ef2aSThomas Huth * registers if we're emulating a CPU with MSA. 626fcf5ef2aSThomas Huth */ 627fcf5ef2aSThomas Huth if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { 628fcf5ef2aSThomas Huth /* Floating point registers */ 629fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 630fcf5ef2aSThomas Huth if (env->CP0_Status & (1 << CP0St_FR)) { 631fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 632fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].d); 633fcf5ef2aSThomas Huth } else { 634fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 635fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 636fcf5ef2aSThomas Huth } 637fcf5ef2aSThomas Huth if (err < 0) { 638fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err); 639fcf5ef2aSThomas Huth ret = err; 640fcf5ef2aSThomas Huth } 641fcf5ef2aSThomas Huth } 642fcf5ef2aSThomas Huth } 643fcf5ef2aSThomas Huth } 644fcf5ef2aSThomas Huth 645fcf5ef2aSThomas Huth /* Only put MSA state if we're emulating a CPU with MSA */ 646fcf5ef2aSThomas Huth if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 647fcf5ef2aSThomas Huth /* MSA Control Registers */ 648fcf5ef2aSThomas Huth if (level == KVM_PUT_FULL_STATE) { 649fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR, 650fcf5ef2aSThomas Huth &env->msair); 651fcf5ef2aSThomas Huth if (err < 0) { 652fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err); 653fcf5ef2aSThomas Huth ret = err; 654fcf5ef2aSThomas Huth } 655fcf5ef2aSThomas Huth } 656fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 657fcf5ef2aSThomas Huth &env->active_tc.msacsr); 658fcf5ef2aSThomas Huth if (err < 0) { 659fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err); 660fcf5ef2aSThomas Huth ret = err; 661fcf5ef2aSThomas Huth } 662fcf5ef2aSThomas Huth 663fcf5ef2aSThomas Huth /* Vector registers (includes FP registers) */ 664fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 665fcf5ef2aSThomas Huth /* Big endian MSA not supported by QEMU yet anyway */ 666fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 667fcf5ef2aSThomas Huth env->active_fpu.fpr[i].wr.d); 668fcf5ef2aSThomas Huth if (err < 0) { 669fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err); 670fcf5ef2aSThomas Huth ret = err; 671fcf5ef2aSThomas Huth } 672fcf5ef2aSThomas Huth } 673fcf5ef2aSThomas Huth } 674fcf5ef2aSThomas Huth 675fcf5ef2aSThomas Huth return ret; 676fcf5ef2aSThomas Huth } 677fcf5ef2aSThomas Huth 678fcf5ef2aSThomas Huth static int kvm_mips_get_fpu_registers(CPUState *cs) 679fcf5ef2aSThomas Huth { 680fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 681fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 682fcf5ef2aSThomas Huth int err, ret = 0; 683fcf5ef2aSThomas Huth unsigned int i; 684fcf5ef2aSThomas Huth 685fcf5ef2aSThomas Huth /* Only get FPU state if we're emulating a CPU with an FPU */ 686fcf5ef2aSThomas Huth if (env->CP0_Config1 & (1 << CP0C1_FP)) { 687fcf5ef2aSThomas Huth /* FPU Control Registers */ 688fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 689fcf5ef2aSThomas Huth &env->active_fpu.fcr0); 690fcf5ef2aSThomas Huth if (err < 0) { 691fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err); 692fcf5ef2aSThomas Huth ret = err; 693fcf5ef2aSThomas Huth } 694fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 695fcf5ef2aSThomas Huth &env->active_fpu.fcr31); 696fcf5ef2aSThomas Huth if (err < 0) { 697fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err); 698fcf5ef2aSThomas Huth ret = err; 699fcf5ef2aSThomas Huth } else { 700fcf5ef2aSThomas Huth restore_fp_status(env); 701fcf5ef2aSThomas Huth } 702fcf5ef2aSThomas Huth 703fcf5ef2aSThomas Huth /* 704fcf5ef2aSThomas Huth * FPU register state is a subset of MSA vector state, so don't save FPU 705fcf5ef2aSThomas Huth * registers if we're emulating a CPU with MSA. 706fcf5ef2aSThomas Huth */ 707fcf5ef2aSThomas Huth if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { 708fcf5ef2aSThomas Huth /* Floating point registers */ 709fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 710fcf5ef2aSThomas Huth if (env->CP0_Status & (1 << CP0St_FR)) { 711fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 712fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].d); 713fcf5ef2aSThomas Huth } else { 714fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 715fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 716fcf5ef2aSThomas Huth } 717fcf5ef2aSThomas Huth if (err < 0) { 718fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err); 719fcf5ef2aSThomas Huth ret = err; 720fcf5ef2aSThomas Huth } 721fcf5ef2aSThomas Huth } 722fcf5ef2aSThomas Huth } 723fcf5ef2aSThomas Huth } 724fcf5ef2aSThomas Huth 725fcf5ef2aSThomas Huth /* Only get MSA state if we're emulating a CPU with MSA */ 726fcf5ef2aSThomas Huth if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 727fcf5ef2aSThomas Huth /* MSA Control Registers */ 728fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR, 729fcf5ef2aSThomas Huth &env->msair); 730fcf5ef2aSThomas Huth if (err < 0) { 731fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err); 732fcf5ef2aSThomas Huth ret = err; 733fcf5ef2aSThomas Huth } 734fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 735fcf5ef2aSThomas Huth &env->active_tc.msacsr); 736fcf5ef2aSThomas Huth if (err < 0) { 737fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err); 738fcf5ef2aSThomas Huth ret = err; 739fcf5ef2aSThomas Huth } else { 740fcf5ef2aSThomas Huth restore_msa_fp_status(env); 741fcf5ef2aSThomas Huth } 742fcf5ef2aSThomas Huth 743fcf5ef2aSThomas Huth /* Vector registers (includes FP registers) */ 744fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 745fcf5ef2aSThomas Huth /* Big endian MSA not supported by QEMU yet anyway */ 746fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 747fcf5ef2aSThomas Huth env->active_fpu.fpr[i].wr.d); 748fcf5ef2aSThomas Huth if (err < 0) { 749fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err); 750fcf5ef2aSThomas Huth ret = err; 751fcf5ef2aSThomas Huth } 752fcf5ef2aSThomas Huth } 753fcf5ef2aSThomas Huth } 754fcf5ef2aSThomas Huth 755fcf5ef2aSThomas Huth return ret; 756fcf5ef2aSThomas Huth } 757fcf5ef2aSThomas Huth 758fcf5ef2aSThomas Huth 759fcf5ef2aSThomas Huth static int kvm_mips_put_cp0_registers(CPUState *cs, int level) 760fcf5ef2aSThomas Huth { 761fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 762fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 763fcf5ef2aSThomas Huth int err, ret = 0; 764fcf5ef2aSThomas Huth 765fcf5ef2aSThomas Huth (void)level; 766fcf5ef2aSThomas Huth 767fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 768fcf5ef2aSThomas Huth if (err < 0) { 769fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err); 770fcf5ef2aSThomas Huth ret = err; 771fcf5ef2aSThomas Huth } 7727e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 7737e0896b0SHuacai Chen if (err < 0) { 7747e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err); 7757e0896b0SHuacai Chen ret = err; 7767e0896b0SHuacai Chen } 777fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 778fcf5ef2aSThomas Huth &env->CP0_Context); 779fcf5ef2aSThomas Huth if (err < 0) { 780fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err); 781fcf5ef2aSThomas Huth ret = err; 782fcf5ef2aSThomas Huth } 783fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 784fcf5ef2aSThomas Huth &env->active_tc.CP0_UserLocal); 785fcf5ef2aSThomas Huth if (err < 0) { 786fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err); 787fcf5ef2aSThomas Huth ret = err; 788fcf5ef2aSThomas Huth } 789fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 790fcf5ef2aSThomas Huth &env->CP0_PageMask); 791fcf5ef2aSThomas Huth if (err < 0) { 792fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err); 793fcf5ef2aSThomas Huth ret = err; 794fcf5ef2aSThomas Huth } 7957e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 7967e0896b0SHuacai Chen &env->CP0_PageGrain); 7977e0896b0SHuacai Chen if (err < 0) { 7987e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err); 7997e0896b0SHuacai Chen ret = err; 8007e0896b0SHuacai Chen } 8017e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 8027e0896b0SHuacai Chen &env->CP0_PWBase); 8037e0896b0SHuacai Chen if (err < 0) { 8047e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err); 8057e0896b0SHuacai Chen ret = err; 8067e0896b0SHuacai Chen } 8077e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 8087e0896b0SHuacai Chen &env->CP0_PWField); 8097e0896b0SHuacai Chen if (err < 0) { 8107e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err); 8117e0896b0SHuacai Chen ret = err; 8127e0896b0SHuacai Chen } 8137e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 8147e0896b0SHuacai Chen &env->CP0_PWSize); 8157e0896b0SHuacai Chen if (err < 0) { 8167e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err); 8177e0896b0SHuacai Chen ret = err; 8187e0896b0SHuacai Chen } 819fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 820fcf5ef2aSThomas Huth if (err < 0) { 821fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err); 822fcf5ef2aSThomas Huth ret = err; 823fcf5ef2aSThomas Huth } 8247e0896b0SHuacai Chen err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 8257e0896b0SHuacai Chen if (err < 0) { 8267e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err); 8277e0896b0SHuacai Chen ret = err; 8287e0896b0SHuacai Chen } 829fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 830fcf5ef2aSThomas Huth if (err < 0) { 831fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err); 832fcf5ef2aSThomas Huth ret = err; 833fcf5ef2aSThomas Huth } 834fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 835fcf5ef2aSThomas Huth &env->CP0_BadVAddr); 836fcf5ef2aSThomas Huth if (err < 0) { 837fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err); 838fcf5ef2aSThomas Huth ret = err; 839fcf5ef2aSThomas Huth } 840fcf5ef2aSThomas Huth 841fcf5ef2aSThomas Huth /* If VM clock stopped then state will be restored when it is restarted */ 842fcf5ef2aSThomas Huth if (runstate_is_running()) { 843fcf5ef2aSThomas Huth err = kvm_mips_restore_count(cs); 844fcf5ef2aSThomas Huth if (err < 0) { 845fcf5ef2aSThomas Huth ret = err; 846fcf5ef2aSThomas Huth } 847fcf5ef2aSThomas Huth } 848fcf5ef2aSThomas Huth 849fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 850fcf5ef2aSThomas Huth &env->CP0_EntryHi); 851fcf5ef2aSThomas Huth if (err < 0) { 852fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err); 853fcf5ef2aSThomas Huth ret = err; 854fcf5ef2aSThomas Huth } 855fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 856fcf5ef2aSThomas Huth &env->CP0_Compare); 857fcf5ef2aSThomas Huth if (err < 0) { 858fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err); 859fcf5ef2aSThomas Huth ret = err; 860fcf5ef2aSThomas Huth } 861fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 862fcf5ef2aSThomas Huth if (err < 0) { 863fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err); 864fcf5ef2aSThomas Huth ret = err; 865fcf5ef2aSThomas Huth } 866fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 867fcf5ef2aSThomas Huth if (err < 0) { 868fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err); 869fcf5ef2aSThomas Huth ret = err; 870fcf5ef2aSThomas Huth } 871fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 872fcf5ef2aSThomas Huth if (err < 0) { 873fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); 874fcf5ef2aSThomas Huth ret = err; 875fcf5ef2aSThomas Huth } 8767e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 8777e0896b0SHuacai Chen if (err < 0) { 8787e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err); 8797e0896b0SHuacai Chen ret = err; 8807e0896b0SHuacai Chen } 881fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, 882fcf5ef2aSThomas Huth &env->CP0_Config0, 883fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG_MASK); 884fcf5ef2aSThomas Huth if (err < 0) { 885fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err); 886fcf5ef2aSThomas Huth ret = err; 887fcf5ef2aSThomas Huth } 888fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, 889fcf5ef2aSThomas Huth &env->CP0_Config1, 890fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG1_MASK); 891fcf5ef2aSThomas Huth if (err < 0) { 892fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err); 893fcf5ef2aSThomas Huth ret = err; 894fcf5ef2aSThomas Huth } 895fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, 896fcf5ef2aSThomas Huth &env->CP0_Config2, 897fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG2_MASK); 898fcf5ef2aSThomas Huth if (err < 0) { 899fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err); 900fcf5ef2aSThomas Huth ret = err; 901fcf5ef2aSThomas Huth } 902fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, 903fcf5ef2aSThomas Huth &env->CP0_Config3, 904fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG3_MASK); 905fcf5ef2aSThomas Huth if (err < 0) { 906fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err); 907fcf5ef2aSThomas Huth ret = err; 908fcf5ef2aSThomas Huth } 909fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, 910fcf5ef2aSThomas Huth &env->CP0_Config4, 911fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG4_MASK); 912fcf5ef2aSThomas Huth if (err < 0) { 913fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err); 914fcf5ef2aSThomas Huth ret = err; 915fcf5ef2aSThomas Huth } 916fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, 917fcf5ef2aSThomas Huth &env->CP0_Config5, 918fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG5_MASK); 919fcf5ef2aSThomas Huth if (err < 0) { 920fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); 921fcf5ef2aSThomas Huth ret = err; 922fcf5ef2aSThomas Huth } 9237e0896b0SHuacai Chen err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, 9247e0896b0SHuacai Chen &env->CP0_Config6, 9257e0896b0SHuacai Chen KVM_REG_MIPS_CP0_CONFIG6_MASK); 9267e0896b0SHuacai Chen if (err < 0) { 9277e0896b0SHuacai Chen DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err); 9287e0896b0SHuacai Chen ret = err; 9297e0896b0SHuacai Chen } 9307e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 9317e0896b0SHuacai Chen &env->CP0_XContext); 9327e0896b0SHuacai Chen if (err < 0) { 9337e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err); 9347e0896b0SHuacai Chen ret = err; 9357e0896b0SHuacai Chen } 936fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 937fcf5ef2aSThomas Huth &env->CP0_ErrorEPC); 938fcf5ef2aSThomas Huth if (err < 0) { 939fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err); 940fcf5ef2aSThomas Huth ret = err; 941fcf5ef2aSThomas Huth } 9427e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 9437e0896b0SHuacai Chen &env->CP0_KScratch[0]); 9447e0896b0SHuacai Chen if (err < 0) { 9457e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err); 9467e0896b0SHuacai Chen ret = err; 9477e0896b0SHuacai Chen } 9487e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 9497e0896b0SHuacai Chen &env->CP0_KScratch[1]); 9507e0896b0SHuacai Chen if (err < 0) { 9517e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err); 9527e0896b0SHuacai Chen ret = err; 9537e0896b0SHuacai Chen } 9547e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 9557e0896b0SHuacai Chen &env->CP0_KScratch[2]); 9567e0896b0SHuacai Chen if (err < 0) { 9577e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err); 9587e0896b0SHuacai Chen ret = err; 9597e0896b0SHuacai Chen } 9607e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 9617e0896b0SHuacai Chen &env->CP0_KScratch[3]); 9627e0896b0SHuacai Chen if (err < 0) { 9637e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err); 9647e0896b0SHuacai Chen ret = err; 9657e0896b0SHuacai Chen } 9667e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 9677e0896b0SHuacai Chen &env->CP0_KScratch[4]); 9687e0896b0SHuacai Chen if (err < 0) { 9697e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err); 9707e0896b0SHuacai Chen ret = err; 9717e0896b0SHuacai Chen } 9727e0896b0SHuacai Chen err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 9737e0896b0SHuacai Chen &env->CP0_KScratch[5]); 9747e0896b0SHuacai Chen if (err < 0) { 9757e0896b0SHuacai Chen DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err); 9767e0896b0SHuacai Chen ret = err; 9777e0896b0SHuacai Chen } 978fcf5ef2aSThomas Huth 979fcf5ef2aSThomas Huth return ret; 980fcf5ef2aSThomas Huth } 981fcf5ef2aSThomas Huth 982fcf5ef2aSThomas Huth static int kvm_mips_get_cp0_registers(CPUState *cs) 983fcf5ef2aSThomas Huth { 984fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 985fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 986fcf5ef2aSThomas Huth int err, ret = 0; 987fcf5ef2aSThomas Huth 988fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 989fcf5ef2aSThomas Huth if (err < 0) { 990fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err); 991fcf5ef2aSThomas Huth ret = err; 992fcf5ef2aSThomas Huth } 9937e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random); 9947e0896b0SHuacai Chen if (err < 0) { 9957e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err); 9967e0896b0SHuacai Chen ret = err; 9977e0896b0SHuacai Chen } 998fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 999fcf5ef2aSThomas Huth &env->CP0_Context); 1000fcf5ef2aSThomas Huth if (err < 0) { 1001fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err); 1002fcf5ef2aSThomas Huth ret = err; 1003fcf5ef2aSThomas Huth } 1004fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 1005fcf5ef2aSThomas Huth &env->active_tc.CP0_UserLocal); 1006fcf5ef2aSThomas Huth if (err < 0) { 1007fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err); 1008fcf5ef2aSThomas Huth ret = err; 1009fcf5ef2aSThomas Huth } 1010fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 1011fcf5ef2aSThomas Huth &env->CP0_PageMask); 1012fcf5ef2aSThomas Huth if (err < 0) { 1013fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err); 1014fcf5ef2aSThomas Huth ret = err; 1015fcf5ef2aSThomas Huth } 10167e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN, 10177e0896b0SHuacai Chen &env->CP0_PageGrain); 10187e0896b0SHuacai Chen if (err < 0) { 10197e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err); 10207e0896b0SHuacai Chen ret = err; 10217e0896b0SHuacai Chen } 10227e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE, 10237e0896b0SHuacai Chen &env->CP0_PWBase); 10247e0896b0SHuacai Chen if (err < 0) { 10257e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err); 10267e0896b0SHuacai Chen ret = err; 10277e0896b0SHuacai Chen } 10287e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD, 10297e0896b0SHuacai Chen &env->CP0_PWField); 10307e0896b0SHuacai Chen if (err < 0) { 10317e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err); 10327e0896b0SHuacai Chen ret = err; 10337e0896b0SHuacai Chen } 10347e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE, 10357e0896b0SHuacai Chen &env->CP0_PWSize); 10367e0896b0SHuacai Chen if (err < 0) { 10377e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err); 10387e0896b0SHuacai Chen ret = err; 10397e0896b0SHuacai Chen } 1040fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 1041fcf5ef2aSThomas Huth if (err < 0) { 1042fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err); 1043fcf5ef2aSThomas Huth ret = err; 1044fcf5ef2aSThomas Huth } 10457e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl); 10467e0896b0SHuacai Chen if (err < 0) { 10477e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err); 10487e0896b0SHuacai Chen ret = err; 10497e0896b0SHuacai Chen } 1050fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 1051fcf5ef2aSThomas Huth if (err < 0) { 1052fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err); 1053fcf5ef2aSThomas Huth ret = err; 1054fcf5ef2aSThomas Huth } 1055fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 1056fcf5ef2aSThomas Huth &env->CP0_BadVAddr); 1057fcf5ef2aSThomas Huth if (err < 0) { 1058fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err); 1059fcf5ef2aSThomas Huth ret = err; 1060fcf5ef2aSThomas Huth } 1061fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 1062fcf5ef2aSThomas Huth &env->CP0_EntryHi); 1063fcf5ef2aSThomas Huth if (err < 0) { 1064fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err); 1065fcf5ef2aSThomas Huth ret = err; 1066fcf5ef2aSThomas Huth } 1067fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 1068fcf5ef2aSThomas Huth &env->CP0_Compare); 1069fcf5ef2aSThomas Huth if (err < 0) { 1070fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err); 1071fcf5ef2aSThomas Huth ret = err; 1072fcf5ef2aSThomas Huth } 1073fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 1074fcf5ef2aSThomas Huth if (err < 0) { 1075fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err); 1076fcf5ef2aSThomas Huth ret = err; 1077fcf5ef2aSThomas Huth } 1078fcf5ef2aSThomas Huth 1079fcf5ef2aSThomas Huth /* If VM clock stopped then state was already saved when it was stopped */ 1080fcf5ef2aSThomas Huth if (runstate_is_running()) { 1081fcf5ef2aSThomas Huth err = kvm_mips_save_count(cs); 1082fcf5ef2aSThomas Huth if (err < 0) { 1083fcf5ef2aSThomas Huth ret = err; 1084fcf5ef2aSThomas Huth } 1085fcf5ef2aSThomas Huth } 1086fcf5ef2aSThomas Huth 1087fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 1088fcf5ef2aSThomas Huth if (err < 0) { 1089fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err); 1090fcf5ef2aSThomas Huth ret = err; 1091fcf5ef2aSThomas Huth } 1092fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 1093fcf5ef2aSThomas Huth if (err < 0) { 1094fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); 1095fcf5ef2aSThomas Huth ret = err; 1096fcf5ef2aSThomas Huth } 10977e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase); 10987e0896b0SHuacai Chen if (err < 0) { 10997e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err); 11007e0896b0SHuacai Chen ret = err; 11017e0896b0SHuacai Chen } 1102fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); 1103fcf5ef2aSThomas Huth if (err < 0) { 1104fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); 1105fcf5ef2aSThomas Huth ret = err; 1106fcf5ef2aSThomas Huth } 1107fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1); 1108fcf5ef2aSThomas Huth if (err < 0) { 1109fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err); 1110fcf5ef2aSThomas Huth ret = err; 1111fcf5ef2aSThomas Huth } 1112fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2); 1113fcf5ef2aSThomas Huth if (err < 0) { 1114fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err); 1115fcf5ef2aSThomas Huth ret = err; 1116fcf5ef2aSThomas Huth } 1117fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3); 1118fcf5ef2aSThomas Huth if (err < 0) { 1119fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err); 1120fcf5ef2aSThomas Huth ret = err; 1121fcf5ef2aSThomas Huth } 1122fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4); 1123fcf5ef2aSThomas Huth if (err < 0) { 1124fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err); 1125fcf5ef2aSThomas Huth ret = err; 1126fcf5ef2aSThomas Huth } 1127fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5); 1128fcf5ef2aSThomas Huth if (err < 0) { 1129fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); 1130fcf5ef2aSThomas Huth ret = err; 1131fcf5ef2aSThomas Huth } 11327e0896b0SHuacai Chen err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6); 11337e0896b0SHuacai Chen if (err < 0) { 11347e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err); 11357e0896b0SHuacai Chen ret = err; 11367e0896b0SHuacai Chen } 11377e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT, 11387e0896b0SHuacai Chen &env->CP0_XContext); 11397e0896b0SHuacai Chen if (err < 0) { 11407e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err); 11417e0896b0SHuacai Chen ret = err; 11427e0896b0SHuacai Chen } 1143fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 1144fcf5ef2aSThomas Huth &env->CP0_ErrorEPC); 1145fcf5ef2aSThomas Huth if (err < 0) { 1146fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err); 1147fcf5ef2aSThomas Huth ret = err; 1148fcf5ef2aSThomas Huth } 11497e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1, 11507e0896b0SHuacai Chen &env->CP0_KScratch[0]); 11517e0896b0SHuacai Chen if (err < 0) { 11527e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err); 11537e0896b0SHuacai Chen ret = err; 11547e0896b0SHuacai Chen } 11557e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2, 11567e0896b0SHuacai Chen &env->CP0_KScratch[1]); 11577e0896b0SHuacai Chen if (err < 0) { 11587e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err); 11597e0896b0SHuacai Chen ret = err; 11607e0896b0SHuacai Chen } 11617e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3, 11627e0896b0SHuacai Chen &env->CP0_KScratch[2]); 11637e0896b0SHuacai Chen if (err < 0) { 11647e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err); 11657e0896b0SHuacai Chen ret = err; 11667e0896b0SHuacai Chen } 11677e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4, 11687e0896b0SHuacai Chen &env->CP0_KScratch[3]); 11697e0896b0SHuacai Chen if (err < 0) { 11707e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err); 11717e0896b0SHuacai Chen ret = err; 11727e0896b0SHuacai Chen } 11737e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5, 11747e0896b0SHuacai Chen &env->CP0_KScratch[4]); 11757e0896b0SHuacai Chen if (err < 0) { 11767e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err); 11777e0896b0SHuacai Chen ret = err; 11787e0896b0SHuacai Chen } 11797e0896b0SHuacai Chen err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6, 11807e0896b0SHuacai Chen &env->CP0_KScratch[5]); 11817e0896b0SHuacai Chen if (err < 0) { 11827e0896b0SHuacai Chen DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err); 11837e0896b0SHuacai Chen ret = err; 11847e0896b0SHuacai Chen } 1185fcf5ef2aSThomas Huth 1186fcf5ef2aSThomas Huth return ret; 1187fcf5ef2aSThomas Huth } 1188fcf5ef2aSThomas Huth 1189fcf5ef2aSThomas Huth int kvm_arch_put_registers(CPUState *cs, int level) 1190fcf5ef2aSThomas Huth { 1191fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 1192fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 1193fcf5ef2aSThomas Huth struct kvm_regs regs; 1194fcf5ef2aSThomas Huth int ret; 1195fcf5ef2aSThomas Huth int i; 1196fcf5ef2aSThomas Huth 1197fcf5ef2aSThomas Huth /* Set the registers based on QEMU's view of things */ 1198fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 1199fcf5ef2aSThomas Huth regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; 1200fcf5ef2aSThomas Huth } 1201fcf5ef2aSThomas Huth 1202fcf5ef2aSThomas Huth regs.hi = (int64_t)(target_long)env->active_tc.HI[0]; 1203fcf5ef2aSThomas Huth regs.lo = (int64_t)(target_long)env->active_tc.LO[0]; 1204fcf5ef2aSThomas Huth regs.pc = (int64_t)(target_long)env->active_tc.PC; 1205fcf5ef2aSThomas Huth 1206fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 1207fcf5ef2aSThomas Huth 1208fcf5ef2aSThomas Huth if (ret < 0) { 1209fcf5ef2aSThomas Huth return ret; 1210fcf5ef2aSThomas Huth } 1211fcf5ef2aSThomas Huth 1212fcf5ef2aSThomas Huth ret = kvm_mips_put_cp0_registers(cs, level); 1213fcf5ef2aSThomas Huth if (ret < 0) { 1214fcf5ef2aSThomas Huth return ret; 1215fcf5ef2aSThomas Huth } 1216fcf5ef2aSThomas Huth 1217fcf5ef2aSThomas Huth ret = kvm_mips_put_fpu_registers(cs, level); 1218fcf5ef2aSThomas Huth if (ret < 0) { 1219fcf5ef2aSThomas Huth return ret; 1220fcf5ef2aSThomas Huth } 1221fcf5ef2aSThomas Huth 1222fcf5ef2aSThomas Huth return ret; 1223fcf5ef2aSThomas Huth } 1224fcf5ef2aSThomas Huth 1225fcf5ef2aSThomas Huth int kvm_arch_get_registers(CPUState *cs) 1226fcf5ef2aSThomas Huth { 1227fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 1228fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 1229fcf5ef2aSThomas Huth int ret = 0; 1230fcf5ef2aSThomas Huth struct kvm_regs regs; 1231fcf5ef2aSThomas Huth int i; 1232fcf5ef2aSThomas Huth 1233fcf5ef2aSThomas Huth /* Get the current register set as KVM seems it */ 1234fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1235fcf5ef2aSThomas Huth 1236fcf5ef2aSThomas Huth if (ret < 0) { 1237fcf5ef2aSThomas Huth return ret; 1238fcf5ef2aSThomas Huth } 1239fcf5ef2aSThomas Huth 1240fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 1241fcf5ef2aSThomas Huth env->active_tc.gpr[i] = regs.gpr[i]; 1242fcf5ef2aSThomas Huth } 1243fcf5ef2aSThomas Huth 1244fcf5ef2aSThomas Huth env->active_tc.HI[0] = regs.hi; 1245fcf5ef2aSThomas Huth env->active_tc.LO[0] = regs.lo; 1246fcf5ef2aSThomas Huth env->active_tc.PC = regs.pc; 1247fcf5ef2aSThomas Huth 1248fcf5ef2aSThomas Huth kvm_mips_get_cp0_registers(cs); 1249fcf5ef2aSThomas Huth kvm_mips_get_fpu_registers(cs); 1250fcf5ef2aSThomas Huth 1251fcf5ef2aSThomas Huth return ret; 1252fcf5ef2aSThomas Huth } 1253fcf5ef2aSThomas Huth 1254fcf5ef2aSThomas Huth int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1255fcf5ef2aSThomas Huth uint64_t address, uint32_t data, PCIDevice *dev) 1256fcf5ef2aSThomas Huth { 1257fcf5ef2aSThomas Huth return 0; 1258fcf5ef2aSThomas Huth } 1259fcf5ef2aSThomas Huth 1260fcf5ef2aSThomas Huth int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 1261fcf5ef2aSThomas Huth int vector, PCIDevice *dev) 1262fcf5ef2aSThomas Huth { 1263fcf5ef2aSThomas Huth return 0; 1264fcf5ef2aSThomas Huth } 1265fcf5ef2aSThomas Huth 1266fcf5ef2aSThomas Huth int kvm_arch_release_virq_post(int virq) 1267fcf5ef2aSThomas Huth { 1268fcf5ef2aSThomas Huth return 0; 1269fcf5ef2aSThomas Huth } 1270fcf5ef2aSThomas Huth 1271fcf5ef2aSThomas Huth int kvm_arch_msi_data_to_gsi(uint32_t data) 1272fcf5ef2aSThomas Huth { 1273fcf5ef2aSThomas Huth abort(); 1274fcf5ef2aSThomas Huth } 1275*719d109bSHuacai Chen 1276*719d109bSHuacai Chen int mips_kvm_type(MachineState *machine, const char *vm_type) 1277*719d109bSHuacai Chen { 1278*719d109bSHuacai Chen #if defined(KVM_CAP_MIPS_VZ) || defined(KVM_CAP_MIPS_TE) 1279*719d109bSHuacai Chen int r; 1280*719d109bSHuacai Chen KVMState *s = KVM_STATE(machine->accelerator); 1281*719d109bSHuacai Chen #endif 1282*719d109bSHuacai Chen 1283*719d109bSHuacai Chen #if defined(KVM_CAP_MIPS_VZ) 1284*719d109bSHuacai Chen r = kvm_check_extension(s, KVM_CAP_MIPS_VZ); 1285*719d109bSHuacai Chen if (r > 0) { 1286*719d109bSHuacai Chen return KVM_VM_MIPS_VZ; 1287*719d109bSHuacai Chen } 1288*719d109bSHuacai Chen #endif 1289*719d109bSHuacai Chen 1290*719d109bSHuacai Chen #if defined(KVM_CAP_MIPS_TE) 1291*719d109bSHuacai Chen r = kvm_check_extension(s, KVM_CAP_MIPS_TE); 1292*719d109bSHuacai Chen if (r > 0) { 1293*719d109bSHuacai Chen return KVM_VM_MIPS_TE; 1294*719d109bSHuacai Chen } 1295*719d109bSHuacai Chen #endif 1296*719d109bSHuacai Chen 1297*719d109bSHuacai Chen return -1; 1298*719d109bSHuacai Chen } 1299