#include "kvm/kvm-cpu.h" #include "kvm/kvm.h" #include "kvm/virtio.h" #include #define ARM_CORE_REG(x) (KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE | \ KVM_REG_ARM_CORE_REG(x)) unsigned long kvm_cpu__get_vcpu_mpidr(struct kvm_cpu *vcpu) { struct kvm_one_reg reg; u32 mpidr; reg.id = ARM_CP15_REG32(ARM_CPU_ID, ARM_CPU_ID_MPIDR); reg.addr = (u64)(unsigned long)&mpidr; if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (get_mpidr vcpu%ld", vcpu->cpu_id); return mpidr; } void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu) { struct kvm *kvm = vcpu->kvm; struct kvm_one_reg reg; u32 data; /* Who said future-proofing was a good idea? */ reg.addr = (u64)(unsigned long)&data; /* cpsr = IRQs/FIQs masked */ data = PSR_I_BIT | PSR_F_BIT | SVC_MODE; reg.id = ARM_CORE_REG(usr_regs.ARM_cpsr); if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, ®) < 0) die_perror("KVM_SET_ONE_REG failed (cpsr)"); /* Secondary cores are stopped awaiting PSCI wakeup */ if (vcpu->cpu_id != 0) return; /* r0 = 0 */ data = 0; reg.id = ARM_CORE_REG(usr_regs.ARM_r0); if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, ®) < 0) die_perror("KVM_SET_ONE_REG failed (r0)"); /* r1 = machine type (-1) */ data = -1; reg.id = ARM_CORE_REG(usr_regs.ARM_r1); if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, ®) < 0) die_perror("KVM_SET_ONE_REG failed (r1)"); /* r2 = physical address of the device tree blob */ data = kvm->arch.dtb_guest_start; reg.id = ARM_CORE_REG(usr_regs.ARM_r2); if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, ®) < 0) die_perror("KVM_SET_ONE_REG failed (r2)"); /* pc = start of kernel image */ data = kvm->arch.kern_guest_start; reg.id = ARM_CORE_REG(usr_regs.ARM_pc); if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, ®) < 0) die_perror("KVM_SET_ONE_REG failed (pc)"); } int kvm_cpu__get_endianness(struct kvm_cpu *vcpu) { struct kvm_one_reg reg; u32 data; reg.id = ARM_CORE_REG(usr_regs.ARM_cpsr); reg.addr = (u64)(unsigned long)&data; if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (cpsr)"); return (data & PSR_E_BIT) ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE; } void kvm_cpu__show_code(struct kvm_cpu *vcpu) { struct kvm_one_reg reg; u32 data; int debug_fd = kvm_cpu__get_debug_fd(); reg.addr = (u64)(unsigned long)&data; dprintf(debug_fd, "\n*pc:\n"); reg.id = ARM_CORE_REG(usr_regs.ARM_pc); if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (show_code @ PC)"); kvm__dump_mem(vcpu->kvm, data, 32, debug_fd); dprintf(debug_fd, "\n*lr (svc):\n"); reg.id = ARM_CORE_REG(svc_regs[1]); if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (show_code @ LR_svc)"); data &= ~0x1; kvm__dump_mem(vcpu->kvm, data, 32, debug_fd); } void kvm_cpu__show_registers(struct kvm_cpu *vcpu) { struct kvm_one_reg reg; u32 data; int debug_fd = kvm_cpu__get_debug_fd(); reg.addr = (u64)(unsigned long)&data; dprintf(debug_fd, "\n Registers:\n"); reg.id = ARM_CORE_REG(usr_regs.ARM_pc); if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (pc)"); dprintf(debug_fd, " PC: 0x%x\n", data); reg.id = ARM_CORE_REG(usr_regs.ARM_cpsr); if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (cpsr)"); dprintf(debug_fd, " CPSR: 0x%x\n", data); reg.id = ARM_CORE_REG(svc_regs[0]); if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (SP_svc)"); dprintf(debug_fd, " SP_svc: 0x%x\n", data); reg.id = ARM_CORE_REG(svc_regs[1]); if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0) die("KVM_GET_ONE_REG failed (LR_svc)"); dprintf(debug_fd, " LR_svc: 0x%x\n", data); }