| #include "kvm/kvm-cpu.h" |
| #include "kvm/kvm.h" |
| #include "kvm/virtio.h" |
| |
| #include <asm/ptrace.h> |
| |
| #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); |
| } |