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" 19fcf5ef2aSThomas Huth #include "qemu/error-report.h" 20fcf5ef2aSThomas Huth #include "qemu/timer.h" 21fcf5ef2aSThomas Huth #include "sysemu/sysemu.h" 22fcf5ef2aSThomas Huth #include "sysemu/kvm.h" 23fcf5ef2aSThomas Huth #include "sysemu/cpus.h" 24fcf5ef2aSThomas Huth #include "kvm_mips.h" 25fcf5ef2aSThomas Huth #include "exec/memattrs.h" 26fcf5ef2aSThomas Huth 27fcf5ef2aSThomas Huth #define DEBUG_KVM 0 28fcf5ef2aSThomas Huth 29fcf5ef2aSThomas Huth #define DPRINTF(fmt, ...) \ 30fcf5ef2aSThomas Huth do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) 31fcf5ef2aSThomas Huth 32fcf5ef2aSThomas Huth static int kvm_mips_fpu_cap; 33fcf5ef2aSThomas Huth static int kvm_mips_msa_cap; 34fcf5ef2aSThomas Huth 35fcf5ef2aSThomas Huth const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 36fcf5ef2aSThomas Huth KVM_CAP_LAST_INFO 37fcf5ef2aSThomas Huth }; 38fcf5ef2aSThomas Huth 39fcf5ef2aSThomas Huth static void kvm_mips_update_state(void *opaque, int running, RunState state); 40fcf5ef2aSThomas Huth 41fcf5ef2aSThomas Huth unsigned long kvm_arch_vcpu_id(CPUState *cs) 42fcf5ef2aSThomas Huth { 43fcf5ef2aSThomas Huth return cs->cpu_index; 44fcf5ef2aSThomas Huth } 45fcf5ef2aSThomas Huth 46fcf5ef2aSThomas Huth int kvm_arch_init(MachineState *ms, KVMState *s) 47fcf5ef2aSThomas Huth { 48fcf5ef2aSThomas Huth /* MIPS has 128 signals */ 49fcf5ef2aSThomas Huth kvm_set_sigmask_len(s, 16); 50fcf5ef2aSThomas Huth 51fcf5ef2aSThomas Huth kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU); 52fcf5ef2aSThomas Huth kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA); 53fcf5ef2aSThomas Huth 54fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 55fcf5ef2aSThomas Huth return 0; 56fcf5ef2aSThomas Huth } 57fcf5ef2aSThomas Huth 58d525ffabSPaolo Bonzini int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) 59d525ffabSPaolo Bonzini { 60d525ffabSPaolo Bonzini return 0; 61d525ffabSPaolo Bonzini } 62d525ffabSPaolo Bonzini 63fcf5ef2aSThomas Huth int kvm_arch_init_vcpu(CPUState *cs) 64fcf5ef2aSThomas Huth { 65fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 66fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 67fcf5ef2aSThomas Huth int ret = 0; 68fcf5ef2aSThomas Huth 69fcf5ef2aSThomas Huth qemu_add_vm_change_state_handler(kvm_mips_update_state, cs); 70fcf5ef2aSThomas Huth 71fcf5ef2aSThomas Huth if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 72fcf5ef2aSThomas Huth ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0); 73fcf5ef2aSThomas Huth if (ret < 0) { 74fcf5ef2aSThomas Huth /* mark unsupported so it gets disabled on reset */ 75fcf5ef2aSThomas Huth kvm_mips_fpu_cap = 0; 76fcf5ef2aSThomas Huth ret = 0; 77fcf5ef2aSThomas Huth } 78fcf5ef2aSThomas Huth } 79fcf5ef2aSThomas Huth 80fcf5ef2aSThomas Huth if (kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { 81fcf5ef2aSThomas Huth ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0); 82fcf5ef2aSThomas Huth if (ret < 0) { 83fcf5ef2aSThomas Huth /* mark unsupported so it gets disabled on reset */ 84fcf5ef2aSThomas Huth kvm_mips_msa_cap = 0; 85fcf5ef2aSThomas Huth ret = 0; 86fcf5ef2aSThomas Huth } 87fcf5ef2aSThomas Huth } 88fcf5ef2aSThomas Huth 89fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 90fcf5ef2aSThomas Huth return ret; 91fcf5ef2aSThomas Huth } 92fcf5ef2aSThomas Huth 93fcf5ef2aSThomas Huth void kvm_mips_reset_vcpu(MIPSCPU *cpu) 94fcf5ef2aSThomas Huth { 95fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 96fcf5ef2aSThomas Huth 97fcf5ef2aSThomas Huth if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) { 98fcf5ef2aSThomas Huth fprintf(stderr, "Warning: KVM does not support FPU, disabling\n"); 99fcf5ef2aSThomas Huth env->CP0_Config1 &= ~(1 << CP0C1_FP); 100fcf5ef2aSThomas Huth } 101fcf5ef2aSThomas Huth if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) { 102fcf5ef2aSThomas Huth fprintf(stderr, "Warning: KVM does not support MSA, disabling\n"); 103fcf5ef2aSThomas Huth env->CP0_Config3 &= ~(1 << CP0C3_MSAP); 104fcf5ef2aSThomas Huth } 105fcf5ef2aSThomas Huth 106fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 107fcf5ef2aSThomas Huth } 108fcf5ef2aSThomas Huth 109fcf5ef2aSThomas Huth int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 110fcf5ef2aSThomas Huth { 111fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 112fcf5ef2aSThomas Huth return 0; 113fcf5ef2aSThomas Huth } 114fcf5ef2aSThomas Huth 115fcf5ef2aSThomas Huth int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) 116fcf5ef2aSThomas Huth { 117fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 118fcf5ef2aSThomas Huth return 0; 119fcf5ef2aSThomas Huth } 120fcf5ef2aSThomas Huth 121fcf5ef2aSThomas Huth static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) 122fcf5ef2aSThomas Huth { 123fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 124fcf5ef2aSThomas Huth 125fcf5ef2aSThomas Huth return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP)); 126fcf5ef2aSThomas Huth } 127fcf5ef2aSThomas Huth 128fcf5ef2aSThomas Huth 129fcf5ef2aSThomas Huth void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 130fcf5ef2aSThomas Huth { 131fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 132fcf5ef2aSThomas Huth int r; 133fcf5ef2aSThomas Huth struct kvm_mips_interrupt intr; 134fcf5ef2aSThomas Huth 135fcf5ef2aSThomas Huth qemu_mutex_lock_iothread(); 136fcf5ef2aSThomas Huth 137fcf5ef2aSThomas Huth if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 138fcf5ef2aSThomas Huth cpu_mips_io_interrupts_pending(cpu)) { 139fcf5ef2aSThomas Huth intr.cpu = -1; 140fcf5ef2aSThomas Huth intr.irq = 2; 141fcf5ef2aSThomas Huth r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 142fcf5ef2aSThomas Huth if (r < 0) { 143fcf5ef2aSThomas Huth error_report("%s: cpu %d: failed to inject IRQ %x", 144fcf5ef2aSThomas Huth __func__, cs->cpu_index, intr.irq); 145fcf5ef2aSThomas Huth } 146fcf5ef2aSThomas Huth } 147fcf5ef2aSThomas Huth 148fcf5ef2aSThomas Huth qemu_mutex_unlock_iothread(); 149fcf5ef2aSThomas Huth } 150fcf5ef2aSThomas Huth 151fcf5ef2aSThomas Huth MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 152fcf5ef2aSThomas Huth { 153fcf5ef2aSThomas Huth return MEMTXATTRS_UNSPECIFIED; 154fcf5ef2aSThomas Huth } 155fcf5ef2aSThomas Huth 156fcf5ef2aSThomas Huth int kvm_arch_process_async_events(CPUState *cs) 157fcf5ef2aSThomas Huth { 158fcf5ef2aSThomas Huth return cs->halted; 159fcf5ef2aSThomas Huth } 160fcf5ef2aSThomas Huth 161fcf5ef2aSThomas Huth int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 162fcf5ef2aSThomas Huth { 163fcf5ef2aSThomas Huth int ret; 164fcf5ef2aSThomas Huth 165fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 166fcf5ef2aSThomas Huth switch (run->exit_reason) { 167fcf5ef2aSThomas Huth default: 168fcf5ef2aSThomas Huth error_report("%s: unknown exit reason %d", 169fcf5ef2aSThomas Huth __func__, run->exit_reason); 170fcf5ef2aSThomas Huth ret = -1; 171fcf5ef2aSThomas Huth break; 172fcf5ef2aSThomas Huth } 173fcf5ef2aSThomas Huth 174fcf5ef2aSThomas Huth return ret; 175fcf5ef2aSThomas Huth } 176fcf5ef2aSThomas Huth 177fcf5ef2aSThomas Huth bool kvm_arch_stop_on_emulation_error(CPUState *cs) 178fcf5ef2aSThomas Huth { 179fcf5ef2aSThomas Huth DPRINTF("%s\n", __func__); 180fcf5ef2aSThomas Huth return true; 181fcf5ef2aSThomas Huth } 182fcf5ef2aSThomas Huth 183fcf5ef2aSThomas Huth void kvm_arch_init_irq_routing(KVMState *s) 184fcf5ef2aSThomas Huth { 185fcf5ef2aSThomas Huth } 186fcf5ef2aSThomas Huth 187fcf5ef2aSThomas Huth int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level) 188fcf5ef2aSThomas Huth { 189fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 190fcf5ef2aSThomas Huth struct kvm_mips_interrupt intr; 191fcf5ef2aSThomas Huth 192fcf5ef2aSThomas Huth if (!kvm_enabled()) { 193fcf5ef2aSThomas Huth return 0; 194fcf5ef2aSThomas Huth } 195fcf5ef2aSThomas Huth 196fcf5ef2aSThomas Huth intr.cpu = -1; 197fcf5ef2aSThomas Huth 198fcf5ef2aSThomas Huth if (level) { 199fcf5ef2aSThomas Huth intr.irq = irq; 200fcf5ef2aSThomas Huth } else { 201fcf5ef2aSThomas Huth intr.irq = -irq; 202fcf5ef2aSThomas Huth } 203fcf5ef2aSThomas Huth 204fcf5ef2aSThomas Huth kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 205fcf5ef2aSThomas Huth 206fcf5ef2aSThomas Huth return 0; 207fcf5ef2aSThomas Huth } 208fcf5ef2aSThomas Huth 209fcf5ef2aSThomas Huth int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) 210fcf5ef2aSThomas Huth { 211fcf5ef2aSThomas Huth CPUState *cs = current_cpu; 212fcf5ef2aSThomas Huth CPUState *dest_cs = CPU(cpu); 213fcf5ef2aSThomas Huth struct kvm_mips_interrupt intr; 214fcf5ef2aSThomas Huth 215fcf5ef2aSThomas Huth if (!kvm_enabled()) { 216fcf5ef2aSThomas Huth return 0; 217fcf5ef2aSThomas Huth } 218fcf5ef2aSThomas Huth 219fcf5ef2aSThomas Huth intr.cpu = dest_cs->cpu_index; 220fcf5ef2aSThomas Huth 221fcf5ef2aSThomas Huth if (level) { 222fcf5ef2aSThomas Huth intr.irq = irq; 223fcf5ef2aSThomas Huth } else { 224fcf5ef2aSThomas Huth intr.irq = -irq; 225fcf5ef2aSThomas Huth } 226fcf5ef2aSThomas Huth 227fcf5ef2aSThomas Huth DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq); 228fcf5ef2aSThomas Huth 229fcf5ef2aSThomas Huth kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); 230fcf5ef2aSThomas Huth 231fcf5ef2aSThomas Huth return 0; 232fcf5ef2aSThomas Huth } 233fcf5ef2aSThomas Huth 234fcf5ef2aSThomas Huth #define MIPS_CP0_32(_R, _S) \ 235fcf5ef2aSThomas Huth (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) 236fcf5ef2aSThomas Huth 237fcf5ef2aSThomas Huth #define MIPS_CP0_64(_R, _S) \ 238fcf5ef2aSThomas Huth (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) 239fcf5ef2aSThomas Huth 240fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) 241fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0) 242fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2) 243fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0) 244fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0) 245fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0) 246fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0) 247fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0) 248fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0) 249fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0) 250fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) 251fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) 252fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) 253fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) 254fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) 255fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) 256fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) 257fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 258fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) 259fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) 260fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 261fcf5ef2aSThomas Huth 262fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id, 263fcf5ef2aSThomas Huth int32_t *addr) 264fcf5ef2aSThomas Huth { 265fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 266fcf5ef2aSThomas Huth .id = reg_id, 267fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 268fcf5ef2aSThomas Huth }; 269fcf5ef2aSThomas Huth 270fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 271fcf5ef2aSThomas Huth } 272fcf5ef2aSThomas Huth 273fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id, 274fcf5ef2aSThomas Huth uint32_t *addr) 275fcf5ef2aSThomas Huth { 276fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 277fcf5ef2aSThomas Huth .id = reg_id, 278fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 279fcf5ef2aSThomas Huth }; 280fcf5ef2aSThomas Huth 281fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 282fcf5ef2aSThomas Huth } 283fcf5ef2aSThomas Huth 284fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id, 285fcf5ef2aSThomas Huth target_ulong *addr) 286fcf5ef2aSThomas Huth { 287fcf5ef2aSThomas Huth uint64_t val64 = *addr; 288fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 289fcf5ef2aSThomas Huth .id = reg_id, 290fcf5ef2aSThomas Huth .addr = (uintptr_t)&val64 291fcf5ef2aSThomas Huth }; 292fcf5ef2aSThomas Huth 293fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 294fcf5ef2aSThomas Huth } 295fcf5ef2aSThomas Huth 296fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id, 297fcf5ef2aSThomas Huth int64_t *addr) 298fcf5ef2aSThomas Huth { 299fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 300fcf5ef2aSThomas Huth .id = reg_id, 301fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 302fcf5ef2aSThomas Huth }; 303fcf5ef2aSThomas Huth 304fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 305fcf5ef2aSThomas Huth } 306fcf5ef2aSThomas Huth 307fcf5ef2aSThomas Huth static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id, 308fcf5ef2aSThomas Huth uint64_t *addr) 309fcf5ef2aSThomas Huth { 310fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 311fcf5ef2aSThomas Huth .id = reg_id, 312fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 313fcf5ef2aSThomas Huth }; 314fcf5ef2aSThomas Huth 315fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg); 316fcf5ef2aSThomas Huth } 317fcf5ef2aSThomas Huth 318fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id, 319fcf5ef2aSThomas Huth int32_t *addr) 320fcf5ef2aSThomas Huth { 321fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 322fcf5ef2aSThomas Huth .id = reg_id, 323fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 324fcf5ef2aSThomas Huth }; 325fcf5ef2aSThomas Huth 326fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 327fcf5ef2aSThomas Huth } 328fcf5ef2aSThomas Huth 329fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id, 330fcf5ef2aSThomas Huth uint32_t *addr) 331fcf5ef2aSThomas Huth { 332fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 333fcf5ef2aSThomas Huth .id = reg_id, 334fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 335fcf5ef2aSThomas Huth }; 336fcf5ef2aSThomas Huth 337fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 338fcf5ef2aSThomas Huth } 339fcf5ef2aSThomas Huth 340fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id, 341fcf5ef2aSThomas Huth target_ulong *addr) 342fcf5ef2aSThomas Huth { 343fcf5ef2aSThomas Huth int ret; 344fcf5ef2aSThomas Huth uint64_t val64 = 0; 345fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 346fcf5ef2aSThomas Huth .id = reg_id, 347fcf5ef2aSThomas Huth .addr = (uintptr_t)&val64 348fcf5ef2aSThomas Huth }; 349fcf5ef2aSThomas Huth 350fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 351fcf5ef2aSThomas Huth if (ret >= 0) { 352fcf5ef2aSThomas Huth *addr = val64; 353fcf5ef2aSThomas Huth } 354fcf5ef2aSThomas Huth return ret; 355fcf5ef2aSThomas Huth } 356fcf5ef2aSThomas Huth 357fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id, 358fcf5ef2aSThomas Huth int64_t *addr) 359fcf5ef2aSThomas Huth { 360fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 361fcf5ef2aSThomas Huth .id = reg_id, 362fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 363fcf5ef2aSThomas Huth }; 364fcf5ef2aSThomas Huth 365fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 366fcf5ef2aSThomas Huth } 367fcf5ef2aSThomas Huth 368fcf5ef2aSThomas Huth static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id, 369fcf5ef2aSThomas Huth uint64_t *addr) 370fcf5ef2aSThomas Huth { 371fcf5ef2aSThomas Huth struct kvm_one_reg cp0reg = { 372fcf5ef2aSThomas Huth .id = reg_id, 373fcf5ef2aSThomas Huth .addr = (uintptr_t)addr 374fcf5ef2aSThomas Huth }; 375fcf5ef2aSThomas Huth 376fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg); 377fcf5ef2aSThomas Huth } 378fcf5ef2aSThomas Huth 379fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M) 380fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \ 381fcf5ef2aSThomas Huth (1U << CP0C1_FP)) 382fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M) 383fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \ 384fcf5ef2aSThomas Huth (1U << CP0C3_MSAP)) 385fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M) 386fcf5ef2aSThomas Huth #define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \ 387fcf5ef2aSThomas Huth (1U << CP0C5_UFE) | \ 388fcf5ef2aSThomas Huth (1U << CP0C5_FRE) | \ 389fcf5ef2aSThomas Huth (1U << CP0C5_UFR)) 390fcf5ef2aSThomas Huth 391fcf5ef2aSThomas Huth static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id, 392fcf5ef2aSThomas Huth int32_t *addr, int32_t mask) 393fcf5ef2aSThomas Huth { 394fcf5ef2aSThomas Huth int err; 395fcf5ef2aSThomas Huth int32_t tmp, change; 396fcf5ef2aSThomas Huth 397fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, reg_id, &tmp); 398fcf5ef2aSThomas Huth if (err < 0) { 399fcf5ef2aSThomas Huth return err; 400fcf5ef2aSThomas Huth } 401fcf5ef2aSThomas Huth 402fcf5ef2aSThomas Huth /* only change bits in mask */ 403fcf5ef2aSThomas Huth change = (*addr ^ tmp) & mask; 404fcf5ef2aSThomas Huth if (!change) { 405fcf5ef2aSThomas Huth return 0; 406fcf5ef2aSThomas Huth } 407fcf5ef2aSThomas Huth 408fcf5ef2aSThomas Huth tmp = tmp ^ change; 409fcf5ef2aSThomas Huth return kvm_mips_put_one_reg(cs, reg_id, &tmp); 410fcf5ef2aSThomas Huth } 411fcf5ef2aSThomas Huth 412fcf5ef2aSThomas Huth /* 413fcf5ef2aSThomas Huth * We freeze the KVM timer when either the VM clock is stopped or the state is 414fcf5ef2aSThomas Huth * saved (the state is dirty). 415fcf5ef2aSThomas Huth */ 416fcf5ef2aSThomas Huth 417fcf5ef2aSThomas Huth /* 418fcf5ef2aSThomas Huth * Save the state of the KVM timer when VM clock is stopped or state is synced 419fcf5ef2aSThomas Huth * to QEMU. 420fcf5ef2aSThomas Huth */ 421fcf5ef2aSThomas Huth static int kvm_mips_save_count(CPUState *cs) 422fcf5ef2aSThomas Huth { 423fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 424fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 425fcf5ef2aSThomas Huth uint64_t count_ctl; 426fcf5ef2aSThomas Huth int err, ret = 0; 427fcf5ef2aSThomas Huth 428fcf5ef2aSThomas Huth /* freeze KVM timer */ 429fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 430fcf5ef2aSThomas Huth if (err < 0) { 431fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err); 432fcf5ef2aSThomas Huth ret = err; 433fcf5ef2aSThomas Huth } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 434fcf5ef2aSThomas Huth count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 435fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 436fcf5ef2aSThomas Huth if (err < 0) { 437fcf5ef2aSThomas Huth DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 438fcf5ef2aSThomas Huth ret = err; 439fcf5ef2aSThomas Huth } 440fcf5ef2aSThomas Huth } 441fcf5ef2aSThomas Huth 442fcf5ef2aSThomas Huth /* read CP0_Cause */ 443fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 444fcf5ef2aSThomas Huth if (err < 0) { 445fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err); 446fcf5ef2aSThomas Huth ret = err; 447fcf5ef2aSThomas Huth } 448fcf5ef2aSThomas Huth 449fcf5ef2aSThomas Huth /* read CP0_Count */ 450fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 451fcf5ef2aSThomas Huth if (err < 0) { 452fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err); 453fcf5ef2aSThomas Huth ret = err; 454fcf5ef2aSThomas Huth } 455fcf5ef2aSThomas Huth 456fcf5ef2aSThomas Huth return ret; 457fcf5ef2aSThomas Huth } 458fcf5ef2aSThomas Huth 459fcf5ef2aSThomas Huth /* 460fcf5ef2aSThomas Huth * Restore the state of the KVM timer when VM clock is restarted or state is 461fcf5ef2aSThomas Huth * synced to KVM. 462fcf5ef2aSThomas Huth */ 463fcf5ef2aSThomas Huth static int kvm_mips_restore_count(CPUState *cs) 464fcf5ef2aSThomas Huth { 465fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 466fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 467fcf5ef2aSThomas Huth uint64_t count_ctl; 468fcf5ef2aSThomas Huth int err_dc, err, ret = 0; 469fcf5ef2aSThomas Huth 470fcf5ef2aSThomas Huth /* check the timer is frozen */ 471fcf5ef2aSThomas Huth err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 472fcf5ef2aSThomas Huth if (err_dc < 0) { 473fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc); 474fcf5ef2aSThomas Huth ret = err_dc; 475fcf5ef2aSThomas Huth } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) { 476fcf5ef2aSThomas Huth /* freeze timer (sets COUNT_RESUME for us) */ 477fcf5ef2aSThomas Huth count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC; 478fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 479fcf5ef2aSThomas Huth if (err < 0) { 480fcf5ef2aSThomas Huth DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err); 481fcf5ef2aSThomas Huth ret = err; 482fcf5ef2aSThomas Huth } 483fcf5ef2aSThomas Huth } 484fcf5ef2aSThomas Huth 485fcf5ef2aSThomas Huth /* load CP0_Cause */ 486fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause); 487fcf5ef2aSThomas Huth if (err < 0) { 488fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err); 489fcf5ef2aSThomas Huth ret = err; 490fcf5ef2aSThomas Huth } 491fcf5ef2aSThomas Huth 492fcf5ef2aSThomas Huth /* load CP0_Count */ 493fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count); 494fcf5ef2aSThomas Huth if (err < 0) { 495fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err); 496fcf5ef2aSThomas Huth ret = err; 497fcf5ef2aSThomas Huth } 498fcf5ef2aSThomas Huth 499fcf5ef2aSThomas Huth /* resume KVM timer */ 500fcf5ef2aSThomas Huth if (err_dc >= 0) { 501fcf5ef2aSThomas Huth count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC; 502fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl); 503fcf5ef2aSThomas Huth if (err < 0) { 504fcf5ef2aSThomas Huth DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err); 505fcf5ef2aSThomas Huth ret = err; 506fcf5ef2aSThomas Huth } 507fcf5ef2aSThomas Huth } 508fcf5ef2aSThomas Huth 509fcf5ef2aSThomas Huth return ret; 510fcf5ef2aSThomas Huth } 511fcf5ef2aSThomas Huth 512fcf5ef2aSThomas Huth /* 513fcf5ef2aSThomas Huth * Handle the VM clock being started or stopped 514fcf5ef2aSThomas Huth */ 515fcf5ef2aSThomas Huth static void kvm_mips_update_state(void *opaque, int running, RunState state) 516fcf5ef2aSThomas Huth { 517fcf5ef2aSThomas Huth CPUState *cs = opaque; 518fcf5ef2aSThomas Huth int ret; 519fcf5ef2aSThomas Huth uint64_t count_resume; 520fcf5ef2aSThomas Huth 521fcf5ef2aSThomas Huth /* 522fcf5ef2aSThomas Huth * If state is already dirty (synced to QEMU) then the KVM timer state is 523fcf5ef2aSThomas Huth * already saved and can be restored when it is synced back to KVM. 524fcf5ef2aSThomas Huth */ 525fcf5ef2aSThomas Huth if (!running) { 526*99f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 527fcf5ef2aSThomas Huth ret = kvm_mips_save_count(cs); 528fcf5ef2aSThomas Huth if (ret < 0) { 529fcf5ef2aSThomas Huth fprintf(stderr, "Failed saving count\n"); 530fcf5ef2aSThomas Huth } 531fcf5ef2aSThomas Huth } 532fcf5ef2aSThomas Huth } else { 533fcf5ef2aSThomas Huth /* Set clock restore time to now */ 534fcf5ef2aSThomas Huth count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 535fcf5ef2aSThomas Huth ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME, 536fcf5ef2aSThomas Huth &count_resume); 537fcf5ef2aSThomas Huth if (ret < 0) { 538fcf5ef2aSThomas Huth fprintf(stderr, "Failed setting COUNT_RESUME\n"); 539fcf5ef2aSThomas Huth return; 540fcf5ef2aSThomas Huth } 541fcf5ef2aSThomas Huth 542*99f31832SSergio Andres Gomez Del Real if (!cs->vcpu_dirty) { 543fcf5ef2aSThomas Huth ret = kvm_mips_restore_count(cs); 544fcf5ef2aSThomas Huth if (ret < 0) { 545fcf5ef2aSThomas Huth fprintf(stderr, "Failed restoring count\n"); 546fcf5ef2aSThomas Huth } 547fcf5ef2aSThomas Huth } 548fcf5ef2aSThomas Huth } 549fcf5ef2aSThomas Huth } 550fcf5ef2aSThomas Huth 551fcf5ef2aSThomas Huth static int kvm_mips_put_fpu_registers(CPUState *cs, int level) 552fcf5ef2aSThomas Huth { 553fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 554fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 555fcf5ef2aSThomas Huth int err, ret = 0; 556fcf5ef2aSThomas Huth unsigned int i; 557fcf5ef2aSThomas Huth 558fcf5ef2aSThomas Huth /* Only put FPU state if we're emulating a CPU with an FPU */ 559fcf5ef2aSThomas Huth if (env->CP0_Config1 & (1 << CP0C1_FP)) { 560fcf5ef2aSThomas Huth /* FPU Control Registers */ 561fcf5ef2aSThomas Huth if (level == KVM_PUT_FULL_STATE) { 562fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 563fcf5ef2aSThomas Huth &env->active_fpu.fcr0); 564fcf5ef2aSThomas Huth if (err < 0) { 565fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err); 566fcf5ef2aSThomas Huth ret = err; 567fcf5ef2aSThomas Huth } 568fcf5ef2aSThomas Huth } 569fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 570fcf5ef2aSThomas Huth &env->active_fpu.fcr31); 571fcf5ef2aSThomas Huth if (err < 0) { 572fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err); 573fcf5ef2aSThomas Huth ret = err; 574fcf5ef2aSThomas Huth } 575fcf5ef2aSThomas Huth 576fcf5ef2aSThomas Huth /* 577fcf5ef2aSThomas Huth * FPU register state is a subset of MSA vector state, so don't put FPU 578fcf5ef2aSThomas Huth * registers if we're emulating a CPU with MSA. 579fcf5ef2aSThomas Huth */ 580fcf5ef2aSThomas Huth if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { 581fcf5ef2aSThomas Huth /* Floating point registers */ 582fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 583fcf5ef2aSThomas Huth if (env->CP0_Status & (1 << CP0St_FR)) { 584fcf5ef2aSThomas Huth err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 585fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].d); 586fcf5ef2aSThomas Huth } else { 587fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 588fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 589fcf5ef2aSThomas Huth } 590fcf5ef2aSThomas Huth if (err < 0) { 591fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err); 592fcf5ef2aSThomas Huth ret = err; 593fcf5ef2aSThomas Huth } 594fcf5ef2aSThomas Huth } 595fcf5ef2aSThomas Huth } 596fcf5ef2aSThomas Huth } 597fcf5ef2aSThomas Huth 598fcf5ef2aSThomas Huth /* Only put MSA state if we're emulating a CPU with MSA */ 599fcf5ef2aSThomas Huth if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 600fcf5ef2aSThomas Huth /* MSA Control Registers */ 601fcf5ef2aSThomas Huth if (level == KVM_PUT_FULL_STATE) { 602fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR, 603fcf5ef2aSThomas Huth &env->msair); 604fcf5ef2aSThomas Huth if (err < 0) { 605fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err); 606fcf5ef2aSThomas Huth ret = err; 607fcf5ef2aSThomas Huth } 608fcf5ef2aSThomas Huth } 609fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 610fcf5ef2aSThomas Huth &env->active_tc.msacsr); 611fcf5ef2aSThomas Huth if (err < 0) { 612fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err); 613fcf5ef2aSThomas Huth ret = err; 614fcf5ef2aSThomas Huth } 615fcf5ef2aSThomas Huth 616fcf5ef2aSThomas Huth /* Vector registers (includes FP registers) */ 617fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 618fcf5ef2aSThomas Huth /* Big endian MSA not supported by QEMU yet anyway */ 619fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 620fcf5ef2aSThomas Huth env->active_fpu.fpr[i].wr.d); 621fcf5ef2aSThomas Huth if (err < 0) { 622fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err); 623fcf5ef2aSThomas Huth ret = err; 624fcf5ef2aSThomas Huth } 625fcf5ef2aSThomas Huth } 626fcf5ef2aSThomas Huth } 627fcf5ef2aSThomas Huth 628fcf5ef2aSThomas Huth return ret; 629fcf5ef2aSThomas Huth } 630fcf5ef2aSThomas Huth 631fcf5ef2aSThomas Huth static int kvm_mips_get_fpu_registers(CPUState *cs) 632fcf5ef2aSThomas Huth { 633fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 634fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 635fcf5ef2aSThomas Huth int err, ret = 0; 636fcf5ef2aSThomas Huth unsigned int i; 637fcf5ef2aSThomas Huth 638fcf5ef2aSThomas Huth /* Only get FPU state if we're emulating a CPU with an FPU */ 639fcf5ef2aSThomas Huth if (env->CP0_Config1 & (1 << CP0C1_FP)) { 640fcf5ef2aSThomas Huth /* FPU Control Registers */ 641fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR, 642fcf5ef2aSThomas Huth &env->active_fpu.fcr0); 643fcf5ef2aSThomas Huth if (err < 0) { 644fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err); 645fcf5ef2aSThomas Huth ret = err; 646fcf5ef2aSThomas Huth } 647fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR, 648fcf5ef2aSThomas Huth &env->active_fpu.fcr31); 649fcf5ef2aSThomas Huth if (err < 0) { 650fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err); 651fcf5ef2aSThomas Huth ret = err; 652fcf5ef2aSThomas Huth } else { 653fcf5ef2aSThomas Huth restore_fp_status(env); 654fcf5ef2aSThomas Huth } 655fcf5ef2aSThomas Huth 656fcf5ef2aSThomas Huth /* 657fcf5ef2aSThomas Huth * FPU register state is a subset of MSA vector state, so don't save FPU 658fcf5ef2aSThomas Huth * registers if we're emulating a CPU with MSA. 659fcf5ef2aSThomas Huth */ 660fcf5ef2aSThomas Huth if (!(env->CP0_Config3 & (1 << CP0C3_MSAP))) { 661fcf5ef2aSThomas Huth /* Floating point registers */ 662fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 663fcf5ef2aSThomas Huth if (env->CP0_Status & (1 << CP0St_FR)) { 664fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i), 665fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].d); 666fcf5ef2aSThomas Huth } else { 667fcf5ef2aSThomas Huth err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i), 668fcf5ef2aSThomas Huth &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]); 669fcf5ef2aSThomas Huth } 670fcf5ef2aSThomas Huth if (err < 0) { 671fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err); 672fcf5ef2aSThomas Huth ret = err; 673fcf5ef2aSThomas Huth } 674fcf5ef2aSThomas Huth } 675fcf5ef2aSThomas Huth } 676fcf5ef2aSThomas Huth } 677fcf5ef2aSThomas Huth 678fcf5ef2aSThomas Huth /* Only get MSA state if we're emulating a CPU with MSA */ 679fcf5ef2aSThomas Huth if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 680fcf5ef2aSThomas Huth /* MSA Control Registers */ 681fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR, 682fcf5ef2aSThomas Huth &env->msair); 683fcf5ef2aSThomas Huth if (err < 0) { 684fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err); 685fcf5ef2aSThomas Huth ret = err; 686fcf5ef2aSThomas Huth } 687fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR, 688fcf5ef2aSThomas Huth &env->active_tc.msacsr); 689fcf5ef2aSThomas Huth if (err < 0) { 690fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err); 691fcf5ef2aSThomas Huth ret = err; 692fcf5ef2aSThomas Huth } else { 693fcf5ef2aSThomas Huth restore_msa_fp_status(env); 694fcf5ef2aSThomas Huth } 695fcf5ef2aSThomas Huth 696fcf5ef2aSThomas Huth /* Vector registers (includes FP registers) */ 697fcf5ef2aSThomas Huth for (i = 0; i < 32; ++i) { 698fcf5ef2aSThomas Huth /* Big endian MSA not supported by QEMU yet anyway */ 699fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i), 700fcf5ef2aSThomas Huth env->active_fpu.fpr[i].wr.d); 701fcf5ef2aSThomas Huth if (err < 0) { 702fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err); 703fcf5ef2aSThomas Huth ret = err; 704fcf5ef2aSThomas Huth } 705fcf5ef2aSThomas Huth } 706fcf5ef2aSThomas Huth } 707fcf5ef2aSThomas Huth 708fcf5ef2aSThomas Huth return ret; 709fcf5ef2aSThomas Huth } 710fcf5ef2aSThomas Huth 711fcf5ef2aSThomas Huth 712fcf5ef2aSThomas Huth static int kvm_mips_put_cp0_registers(CPUState *cs, int level) 713fcf5ef2aSThomas Huth { 714fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 715fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 716fcf5ef2aSThomas Huth int err, ret = 0; 717fcf5ef2aSThomas Huth 718fcf5ef2aSThomas Huth (void)level; 719fcf5ef2aSThomas Huth 720fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 721fcf5ef2aSThomas Huth if (err < 0) { 722fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err); 723fcf5ef2aSThomas Huth ret = err; 724fcf5ef2aSThomas Huth } 725fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 726fcf5ef2aSThomas Huth &env->CP0_Context); 727fcf5ef2aSThomas Huth if (err < 0) { 728fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err); 729fcf5ef2aSThomas Huth ret = err; 730fcf5ef2aSThomas Huth } 731fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 732fcf5ef2aSThomas Huth &env->active_tc.CP0_UserLocal); 733fcf5ef2aSThomas Huth if (err < 0) { 734fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err); 735fcf5ef2aSThomas Huth ret = err; 736fcf5ef2aSThomas Huth } 737fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 738fcf5ef2aSThomas Huth &env->CP0_PageMask); 739fcf5ef2aSThomas Huth if (err < 0) { 740fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err); 741fcf5ef2aSThomas Huth ret = err; 742fcf5ef2aSThomas Huth } 743fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 744fcf5ef2aSThomas Huth if (err < 0) { 745fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err); 746fcf5ef2aSThomas Huth ret = err; 747fcf5ef2aSThomas Huth } 748fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 749fcf5ef2aSThomas Huth if (err < 0) { 750fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err); 751fcf5ef2aSThomas Huth ret = err; 752fcf5ef2aSThomas Huth } 753fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 754fcf5ef2aSThomas Huth &env->CP0_BadVAddr); 755fcf5ef2aSThomas Huth if (err < 0) { 756fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err); 757fcf5ef2aSThomas Huth ret = err; 758fcf5ef2aSThomas Huth } 759fcf5ef2aSThomas Huth 760fcf5ef2aSThomas Huth /* If VM clock stopped then state will be restored when it is restarted */ 761fcf5ef2aSThomas Huth if (runstate_is_running()) { 762fcf5ef2aSThomas Huth err = kvm_mips_restore_count(cs); 763fcf5ef2aSThomas Huth if (err < 0) { 764fcf5ef2aSThomas Huth ret = err; 765fcf5ef2aSThomas Huth } 766fcf5ef2aSThomas Huth } 767fcf5ef2aSThomas Huth 768fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 769fcf5ef2aSThomas Huth &env->CP0_EntryHi); 770fcf5ef2aSThomas Huth if (err < 0) { 771fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err); 772fcf5ef2aSThomas Huth ret = err; 773fcf5ef2aSThomas Huth } 774fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 775fcf5ef2aSThomas Huth &env->CP0_Compare); 776fcf5ef2aSThomas Huth if (err < 0) { 777fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err); 778fcf5ef2aSThomas Huth ret = err; 779fcf5ef2aSThomas Huth } 780fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 781fcf5ef2aSThomas Huth if (err < 0) { 782fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err); 783fcf5ef2aSThomas Huth ret = err; 784fcf5ef2aSThomas Huth } 785fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 786fcf5ef2aSThomas Huth if (err < 0) { 787fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err); 788fcf5ef2aSThomas Huth ret = err; 789fcf5ef2aSThomas Huth } 790fcf5ef2aSThomas Huth err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 791fcf5ef2aSThomas Huth if (err < 0) { 792fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err); 793fcf5ef2aSThomas Huth ret = err; 794fcf5ef2aSThomas Huth } 795fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, 796fcf5ef2aSThomas Huth &env->CP0_Config0, 797fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG_MASK); 798fcf5ef2aSThomas Huth if (err < 0) { 799fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err); 800fcf5ef2aSThomas Huth ret = err; 801fcf5ef2aSThomas Huth } 802fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, 803fcf5ef2aSThomas Huth &env->CP0_Config1, 804fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG1_MASK); 805fcf5ef2aSThomas Huth if (err < 0) { 806fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err); 807fcf5ef2aSThomas Huth ret = err; 808fcf5ef2aSThomas Huth } 809fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, 810fcf5ef2aSThomas Huth &env->CP0_Config2, 811fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG2_MASK); 812fcf5ef2aSThomas Huth if (err < 0) { 813fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err); 814fcf5ef2aSThomas Huth ret = err; 815fcf5ef2aSThomas Huth } 816fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, 817fcf5ef2aSThomas Huth &env->CP0_Config3, 818fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG3_MASK); 819fcf5ef2aSThomas Huth if (err < 0) { 820fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err); 821fcf5ef2aSThomas Huth ret = err; 822fcf5ef2aSThomas Huth } 823fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, 824fcf5ef2aSThomas Huth &env->CP0_Config4, 825fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG4_MASK); 826fcf5ef2aSThomas Huth if (err < 0) { 827fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err); 828fcf5ef2aSThomas Huth ret = err; 829fcf5ef2aSThomas Huth } 830fcf5ef2aSThomas Huth err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, 831fcf5ef2aSThomas Huth &env->CP0_Config5, 832fcf5ef2aSThomas Huth KVM_REG_MIPS_CP0_CONFIG5_MASK); 833fcf5ef2aSThomas Huth if (err < 0) { 834fcf5ef2aSThomas Huth DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err); 835fcf5ef2aSThomas Huth ret = err; 836fcf5ef2aSThomas Huth } 837fcf5ef2aSThomas Huth err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 838fcf5ef2aSThomas Huth &env->CP0_ErrorEPC); 839fcf5ef2aSThomas Huth if (err < 0) { 840fcf5ef2aSThomas Huth DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err); 841fcf5ef2aSThomas Huth ret = err; 842fcf5ef2aSThomas Huth } 843fcf5ef2aSThomas Huth 844fcf5ef2aSThomas Huth return ret; 845fcf5ef2aSThomas Huth } 846fcf5ef2aSThomas Huth 847fcf5ef2aSThomas Huth static int kvm_mips_get_cp0_registers(CPUState *cs) 848fcf5ef2aSThomas Huth { 849fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 850fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 851fcf5ef2aSThomas Huth int err, ret = 0; 852fcf5ef2aSThomas Huth 853fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index); 854fcf5ef2aSThomas Huth if (err < 0) { 855fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err); 856fcf5ef2aSThomas Huth ret = err; 857fcf5ef2aSThomas Huth } 858fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT, 859fcf5ef2aSThomas Huth &env->CP0_Context); 860fcf5ef2aSThomas Huth if (err < 0) { 861fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err); 862fcf5ef2aSThomas Huth ret = err; 863fcf5ef2aSThomas Huth } 864fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL, 865fcf5ef2aSThomas Huth &env->active_tc.CP0_UserLocal); 866fcf5ef2aSThomas Huth if (err < 0) { 867fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err); 868fcf5ef2aSThomas Huth ret = err; 869fcf5ef2aSThomas Huth } 870fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK, 871fcf5ef2aSThomas Huth &env->CP0_PageMask); 872fcf5ef2aSThomas Huth if (err < 0) { 873fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err); 874fcf5ef2aSThomas Huth ret = err; 875fcf5ef2aSThomas Huth } 876fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired); 877fcf5ef2aSThomas Huth if (err < 0) { 878fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err); 879fcf5ef2aSThomas Huth ret = err; 880fcf5ef2aSThomas Huth } 881fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna); 882fcf5ef2aSThomas Huth if (err < 0) { 883fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err); 884fcf5ef2aSThomas Huth ret = err; 885fcf5ef2aSThomas Huth } 886fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR, 887fcf5ef2aSThomas Huth &env->CP0_BadVAddr); 888fcf5ef2aSThomas Huth if (err < 0) { 889fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err); 890fcf5ef2aSThomas Huth ret = err; 891fcf5ef2aSThomas Huth } 892fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI, 893fcf5ef2aSThomas Huth &env->CP0_EntryHi); 894fcf5ef2aSThomas Huth if (err < 0) { 895fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err); 896fcf5ef2aSThomas Huth ret = err; 897fcf5ef2aSThomas Huth } 898fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE, 899fcf5ef2aSThomas Huth &env->CP0_Compare); 900fcf5ef2aSThomas Huth if (err < 0) { 901fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err); 902fcf5ef2aSThomas Huth ret = err; 903fcf5ef2aSThomas Huth } 904fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status); 905fcf5ef2aSThomas Huth if (err < 0) { 906fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err); 907fcf5ef2aSThomas Huth ret = err; 908fcf5ef2aSThomas Huth } 909fcf5ef2aSThomas Huth 910fcf5ef2aSThomas Huth /* If VM clock stopped then state was already saved when it was stopped */ 911fcf5ef2aSThomas Huth if (runstate_is_running()) { 912fcf5ef2aSThomas Huth err = kvm_mips_save_count(cs); 913fcf5ef2aSThomas Huth if (err < 0) { 914fcf5ef2aSThomas Huth ret = err; 915fcf5ef2aSThomas Huth } 916fcf5ef2aSThomas Huth } 917fcf5ef2aSThomas Huth 918fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC); 919fcf5ef2aSThomas Huth if (err < 0) { 920fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err); 921fcf5ef2aSThomas Huth ret = err; 922fcf5ef2aSThomas Huth } 923fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid); 924fcf5ef2aSThomas Huth if (err < 0) { 925fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err); 926fcf5ef2aSThomas Huth ret = err; 927fcf5ef2aSThomas Huth } 928fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0); 929fcf5ef2aSThomas Huth if (err < 0) { 930fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err); 931fcf5ef2aSThomas Huth ret = err; 932fcf5ef2aSThomas Huth } 933fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1); 934fcf5ef2aSThomas Huth if (err < 0) { 935fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err); 936fcf5ef2aSThomas Huth ret = err; 937fcf5ef2aSThomas Huth } 938fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2); 939fcf5ef2aSThomas Huth if (err < 0) { 940fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err); 941fcf5ef2aSThomas Huth ret = err; 942fcf5ef2aSThomas Huth } 943fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3); 944fcf5ef2aSThomas Huth if (err < 0) { 945fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err); 946fcf5ef2aSThomas Huth ret = err; 947fcf5ef2aSThomas Huth } 948fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4); 949fcf5ef2aSThomas Huth if (err < 0) { 950fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err); 951fcf5ef2aSThomas Huth ret = err; 952fcf5ef2aSThomas Huth } 953fcf5ef2aSThomas Huth err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5); 954fcf5ef2aSThomas Huth if (err < 0) { 955fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err); 956fcf5ef2aSThomas Huth ret = err; 957fcf5ef2aSThomas Huth } 958fcf5ef2aSThomas Huth err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC, 959fcf5ef2aSThomas Huth &env->CP0_ErrorEPC); 960fcf5ef2aSThomas Huth if (err < 0) { 961fcf5ef2aSThomas Huth DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err); 962fcf5ef2aSThomas Huth ret = err; 963fcf5ef2aSThomas Huth } 964fcf5ef2aSThomas Huth 965fcf5ef2aSThomas Huth return ret; 966fcf5ef2aSThomas Huth } 967fcf5ef2aSThomas Huth 968fcf5ef2aSThomas Huth int kvm_arch_put_registers(CPUState *cs, int level) 969fcf5ef2aSThomas Huth { 970fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 971fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 972fcf5ef2aSThomas Huth struct kvm_regs regs; 973fcf5ef2aSThomas Huth int ret; 974fcf5ef2aSThomas Huth int i; 975fcf5ef2aSThomas Huth 976fcf5ef2aSThomas Huth /* Set the registers based on QEMU's view of things */ 977fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 978fcf5ef2aSThomas Huth regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; 979fcf5ef2aSThomas Huth } 980fcf5ef2aSThomas Huth 981fcf5ef2aSThomas Huth regs.hi = (int64_t)(target_long)env->active_tc.HI[0]; 982fcf5ef2aSThomas Huth regs.lo = (int64_t)(target_long)env->active_tc.LO[0]; 983fcf5ef2aSThomas Huth regs.pc = (int64_t)(target_long)env->active_tc.PC; 984fcf5ef2aSThomas Huth 985fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); 986fcf5ef2aSThomas Huth 987fcf5ef2aSThomas Huth if (ret < 0) { 988fcf5ef2aSThomas Huth return ret; 989fcf5ef2aSThomas Huth } 990fcf5ef2aSThomas Huth 991fcf5ef2aSThomas Huth ret = kvm_mips_put_cp0_registers(cs, level); 992fcf5ef2aSThomas Huth if (ret < 0) { 993fcf5ef2aSThomas Huth return ret; 994fcf5ef2aSThomas Huth } 995fcf5ef2aSThomas Huth 996fcf5ef2aSThomas Huth ret = kvm_mips_put_fpu_registers(cs, level); 997fcf5ef2aSThomas Huth if (ret < 0) { 998fcf5ef2aSThomas Huth return ret; 999fcf5ef2aSThomas Huth } 1000fcf5ef2aSThomas Huth 1001fcf5ef2aSThomas Huth return ret; 1002fcf5ef2aSThomas Huth } 1003fcf5ef2aSThomas Huth 1004fcf5ef2aSThomas Huth int kvm_arch_get_registers(CPUState *cs) 1005fcf5ef2aSThomas Huth { 1006fcf5ef2aSThomas Huth MIPSCPU *cpu = MIPS_CPU(cs); 1007fcf5ef2aSThomas Huth CPUMIPSState *env = &cpu->env; 1008fcf5ef2aSThomas Huth int ret = 0; 1009fcf5ef2aSThomas Huth struct kvm_regs regs; 1010fcf5ef2aSThomas Huth int i; 1011fcf5ef2aSThomas Huth 1012fcf5ef2aSThomas Huth /* Get the current register set as KVM seems it */ 1013fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); 1014fcf5ef2aSThomas Huth 1015fcf5ef2aSThomas Huth if (ret < 0) { 1016fcf5ef2aSThomas Huth return ret; 1017fcf5ef2aSThomas Huth } 1018fcf5ef2aSThomas Huth 1019fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 1020fcf5ef2aSThomas Huth env->active_tc.gpr[i] = regs.gpr[i]; 1021fcf5ef2aSThomas Huth } 1022fcf5ef2aSThomas Huth 1023fcf5ef2aSThomas Huth env->active_tc.HI[0] = regs.hi; 1024fcf5ef2aSThomas Huth env->active_tc.LO[0] = regs.lo; 1025fcf5ef2aSThomas Huth env->active_tc.PC = regs.pc; 1026fcf5ef2aSThomas Huth 1027fcf5ef2aSThomas Huth kvm_mips_get_cp0_registers(cs); 1028fcf5ef2aSThomas Huth kvm_mips_get_fpu_registers(cs); 1029fcf5ef2aSThomas Huth 1030fcf5ef2aSThomas Huth return ret; 1031fcf5ef2aSThomas Huth } 1032fcf5ef2aSThomas Huth 1033fcf5ef2aSThomas Huth int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1034fcf5ef2aSThomas Huth uint64_t address, uint32_t data, PCIDevice *dev) 1035fcf5ef2aSThomas Huth { 1036fcf5ef2aSThomas Huth return 0; 1037fcf5ef2aSThomas Huth } 1038fcf5ef2aSThomas Huth 1039fcf5ef2aSThomas Huth int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 1040fcf5ef2aSThomas Huth int vector, PCIDevice *dev) 1041fcf5ef2aSThomas Huth { 1042fcf5ef2aSThomas Huth return 0; 1043fcf5ef2aSThomas Huth } 1044fcf5ef2aSThomas Huth 1045fcf5ef2aSThomas Huth int kvm_arch_release_virq_post(int virq) 1046fcf5ef2aSThomas Huth { 1047fcf5ef2aSThomas Huth return 0; 1048fcf5ef2aSThomas Huth } 1049fcf5ef2aSThomas Huth 1050fcf5ef2aSThomas Huth int kvm_arch_msi_data_to_gsi(uint32_t data) 1051fcf5ef2aSThomas Huth { 1052fcf5ef2aSThomas Huth abort(); 1053fcf5ef2aSThomas Huth } 1054