mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-09-06 13:41:44 +00:00
The kernel now exposes register accessor macros in the uapi/ headers for arm and arm64, so use those instead (and avoid the compile failure from the duplicate definitions). Signed-off-by: Will Deacon <will.deacon@arm.com>
133 lines
3.7 KiB
C
133 lines
3.7 KiB
C
#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);
|
|
}
|