xref: /kvmtool/arm/aarch64/kvm-cpu.c (revision 8ec1e8bf3bc2e99518d857a5164218d513d585ea)
11e0c135aSWill Deacon #include "kvm/kvm-cpu.h"
21e0c135aSWill Deacon #include "kvm/kvm.h"
3fc9d8ec3SMarc Zyngier #include "kvm/virtio.h"
41e0c135aSWill Deacon 
51e0c135aSWill Deacon #include <asm/ptrace.h>
61e0c135aSWill Deacon 
71e0c135aSWill Deacon #define COMPAT_PSR_F_BIT	0x00000040
81e0c135aSWill Deacon #define COMPAT_PSR_I_BIT	0x00000080
9fc9d8ec3SMarc Zyngier #define COMPAT_PSR_E_BIT	0x00000200
101e0c135aSWill Deacon #define COMPAT_PSR_MODE_SVC	0x00000013
111e0c135aSWill Deacon 
12fc9d8ec3SMarc Zyngier #define SCTLR_EL1_E0E_MASK	(1 << 24)
13fc9d8ec3SMarc Zyngier #define SCTLR_EL1_EE_MASK	(1 << 25)
14fc9d8ec3SMarc Zyngier 
155ae841d1SDave Martin static __u64 __core_reg_id(__u64 offset)
165ae841d1SDave Martin {
175ae841d1SDave Martin 	__u64 id = KVM_REG_ARM64 | KVM_REG_ARM_CORE | offset;
185ae841d1SDave Martin 
195ae841d1SDave Martin 	if (offset < KVM_REG_ARM_CORE_REG(fp_regs))
205ae841d1SDave Martin 		id |= KVM_REG_SIZE_U64;
215ae841d1SDave Martin 	else if (offset < KVM_REG_ARM_CORE_REG(fp_regs.fpsr))
225ae841d1SDave Martin 		id |= KVM_REG_SIZE_U128;
235ae841d1SDave Martin 	else
245ae841d1SDave Martin 		id |= KVM_REG_SIZE_U32;
255ae841d1SDave Martin 
265ae841d1SDave Martin 	return id;
275ae841d1SDave Martin }
285ae841d1SDave Martin 
295ae841d1SDave Martin #define ARM64_CORE_REG(x) __core_reg_id(KVM_REG_ARM_CORE_REG(x))
301e0c135aSWill Deacon 
31d06bc640SMarc Zyngier unsigned long kvm_cpu__get_vcpu_mpidr(struct kvm_cpu *vcpu)
32d06bc640SMarc Zyngier {
33d06bc640SMarc Zyngier 	struct kvm_one_reg reg;
34d06bc640SMarc Zyngier 	u64 mpidr;
35d06bc640SMarc Zyngier 
36d06bc640SMarc Zyngier 	reg.id = ARM64_SYS_REG(ARM_CPU_ID, ARM_CPU_ID_MPIDR);
37d06bc640SMarc Zyngier 	reg.addr = (u64)&mpidr;
38d06bc640SMarc Zyngier 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
39d06bc640SMarc Zyngier 		die("KVM_GET_ONE_REG failed (get_mpidr vcpu%ld", vcpu->cpu_id);
40d06bc640SMarc Zyngier 
41d06bc640SMarc Zyngier 	return mpidr;
42d06bc640SMarc Zyngier }
43d06bc640SMarc Zyngier 
441e0c135aSWill Deacon static void reset_vcpu_aarch32(struct kvm_cpu *vcpu)
451e0c135aSWill Deacon {
461e0c135aSWill Deacon 	struct kvm *kvm = vcpu->kvm;
471e0c135aSWill Deacon 	struct kvm_one_reg reg;
481e0c135aSWill Deacon 	u64 data;
491e0c135aSWill Deacon 
501e0c135aSWill Deacon 	reg.addr = (u64)&data;
511e0c135aSWill Deacon 
521e0c135aSWill Deacon 	/* pstate = all interrupts masked */
531e0c135aSWill Deacon 	data	= COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT | COMPAT_PSR_MODE_SVC;
541e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.pstate);
551e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
561e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (spsr[EL1])");
571e0c135aSWill Deacon 
581e0c135aSWill Deacon 	/* Secondary cores are stopped awaiting PSCI wakeup */
591e0c135aSWill Deacon 	if (vcpu->cpu_id != 0)
601e0c135aSWill Deacon 		return;
611e0c135aSWill Deacon 
621e0c135aSWill Deacon 	/* r0 = 0 */
631e0c135aSWill Deacon 	data	= 0;
641e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.regs[0]);
651e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
661e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (r0)");
671e0c135aSWill Deacon 
681e0c135aSWill Deacon 	/* r1 = machine type (-1) */
691e0c135aSWill Deacon 	data	= -1;
701e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.regs[1]);
711e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
721e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (r1)");
731e0c135aSWill Deacon 
741e0c135aSWill Deacon 	/* r2 = physical address of the device tree blob */
751e0c135aSWill Deacon 	data	= kvm->arch.dtb_guest_start;
761e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.regs[2]);
771e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
781e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (r2)");
791e0c135aSWill Deacon 
801e0c135aSWill Deacon 	/* pc = start of kernel image */
811e0c135aSWill Deacon 	data	= kvm->arch.kern_guest_start;
821e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.pc);
831e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
841e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (pc)");
851e0c135aSWill Deacon }
861e0c135aSWill Deacon 
871e0c135aSWill Deacon static void reset_vcpu_aarch64(struct kvm_cpu *vcpu)
881e0c135aSWill Deacon {
891e0c135aSWill Deacon 	struct kvm *kvm = vcpu->kvm;
901e0c135aSWill Deacon 	struct kvm_one_reg reg;
911e0c135aSWill Deacon 	u64 data;
921e0c135aSWill Deacon 
931e0c135aSWill Deacon 	reg.addr = (u64)&data;
941e0c135aSWill Deacon 
951e0c135aSWill Deacon 	/* pstate = all interrupts masked */
961e0c135aSWill Deacon 	data	= PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1h;
971e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.pstate);
981e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
991e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (spsr[EL1])");
1001e0c135aSWill Deacon 
1011e0c135aSWill Deacon 	/* x1...x3 = 0 */
1021e0c135aSWill Deacon 	data	= 0;
1031e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.regs[1]);
1041e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
1051e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (x1)");
1061e0c135aSWill Deacon 
1071e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.regs[2]);
1081e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
1091e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (x2)");
1101e0c135aSWill Deacon 
1111e0c135aSWill Deacon 	reg.id	= ARM64_CORE_REG(regs.regs[3]);
1121e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
1131e0c135aSWill Deacon 		die_perror("KVM_SET_ONE_REG failed (x3)");
1141e0c135aSWill Deacon 
1151e0c135aSWill Deacon 	/* Secondary cores are stopped awaiting PSCI wakeup */
1161e0c135aSWill Deacon 	if (vcpu->cpu_id == 0) {
1171e0c135aSWill Deacon 		/* x0 = physical address of the device tree blob */
1181e0c135aSWill Deacon 		data	= kvm->arch.dtb_guest_start;
1191e0c135aSWill Deacon 		reg.id	= ARM64_CORE_REG(regs.regs[0]);
1201e0c135aSWill Deacon 		if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
1211e0c135aSWill Deacon 			die_perror("KVM_SET_ONE_REG failed (x0)");
1221e0c135aSWill Deacon 
1231e0c135aSWill Deacon 		/* pc = start of kernel image */
1241e0c135aSWill Deacon 		data	= kvm->arch.kern_guest_start;
1251e0c135aSWill Deacon 		reg.id	= ARM64_CORE_REG(regs.pc);
1261e0c135aSWill Deacon 		if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
1271e0c135aSWill Deacon 			die_perror("KVM_SET_ONE_REG failed (pc)");
1281e0c135aSWill Deacon 	}
1291e0c135aSWill Deacon }
1301e0c135aSWill Deacon 
13174c5e7b2SDave Martin void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init)
13274c5e7b2SDave Martin {
133412ee137SAlexandru Elisei 	if (kvm->cfg.arch.aarch32_guest) {
134412ee137SAlexandru Elisei 		if (!kvm__supports_extension(kvm, KVM_CAP_ARM_EL1_32BIT))
135412ee137SAlexandru Elisei 			die("32bit guests are not supported\n");
136412ee137SAlexandru Elisei 		init->features[0] |= 1UL << KVM_ARM_VCPU_EL1_32BIT;
137412ee137SAlexandru Elisei 	}
138412ee137SAlexandru Elisei 
139412ee137SAlexandru Elisei 	if (kvm->cfg.arch.has_pmuv3) {
140412ee137SAlexandru Elisei 		if (!kvm__supports_extension(kvm, KVM_CAP_ARM_PMU_V3))
141412ee137SAlexandru Elisei 			die("PMUv3 is not supported");
142412ee137SAlexandru Elisei 		init->features[0] |= 1UL << KVM_ARM_VCPU_PMU_V3;
143412ee137SAlexandru Elisei 	}
144412ee137SAlexandru Elisei 
14574c5e7b2SDave Martin 	/* Enable pointer authentication if available */
14674c5e7b2SDave Martin 	if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) &&
14774c5e7b2SDave Martin 	    kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC)) {
14874c5e7b2SDave Martin 		init->features[0] |= 1UL << KVM_ARM_VCPU_PTRAUTH_ADDRESS;
14974c5e7b2SDave Martin 		init->features[0] |= 1UL << KVM_ARM_VCPU_PTRAUTH_GENERIC;
15074c5e7b2SDave Martin 	}
151a0eab49aSDave Martin 
152a0eab49aSDave Martin 	/* Enable SVE if available */
153a0eab49aSDave Martin 	if (kvm__supports_extension(kvm, KVM_CAP_ARM_SVE))
154a0eab49aSDave Martin 		init->features[0] |= 1UL << KVM_ARM_VCPU_SVE;
155a0eab49aSDave Martin }
156a0eab49aSDave Martin 
157a0eab49aSDave Martin int kvm_cpu__configure_features(struct kvm_cpu *vcpu)
158a0eab49aSDave Martin {
159a0eab49aSDave Martin 	if (kvm__supports_extension(vcpu->kvm, KVM_CAP_ARM_SVE)) {
160a0eab49aSDave Martin 		int feature = KVM_ARM_VCPU_SVE;
161a0eab49aSDave Martin 
162a0eab49aSDave Martin 		if (ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_FINALIZE, &feature)) {
163a0eab49aSDave Martin 			pr_err("KVM_ARM_VCPU_FINALIZE: %s", strerror(errno));
164a0eab49aSDave Martin 			return -1;
165a0eab49aSDave Martin 		}
166a0eab49aSDave Martin 	}
167a0eab49aSDave Martin 
168a0eab49aSDave Martin 	return 0;
16974c5e7b2SDave Martin }
17074c5e7b2SDave Martin 
1711e0c135aSWill Deacon void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
1721e0c135aSWill Deacon {
173*8ec1e8bfSAlexandru Elisei 	struct kvm *kvm = vcpu->kvm;
174*8ec1e8bfSAlexandru Elisei 	cpu_set_t *affinity;
175*8ec1e8bfSAlexandru Elisei 	int ret;
176*8ec1e8bfSAlexandru Elisei 
177*8ec1e8bfSAlexandru Elisei 	affinity = kvm->arch.vcpu_affinity_cpuset;
178*8ec1e8bfSAlexandru Elisei 	if (affinity) {
179*8ec1e8bfSAlexandru Elisei 		ret = sched_setaffinity(0, sizeof(cpu_set_t), affinity);
180*8ec1e8bfSAlexandru Elisei 		if (ret == -1)
181*8ec1e8bfSAlexandru Elisei 			die_perror("sched_setaffinity");
182*8ec1e8bfSAlexandru Elisei 	}
183*8ec1e8bfSAlexandru Elisei 
184*8ec1e8bfSAlexandru Elisei 	if (kvm->cfg.arch.aarch32_guest)
1851e0c135aSWill Deacon 		return reset_vcpu_aarch32(vcpu);
1861e0c135aSWill Deacon 	else
1871e0c135aSWill Deacon 		return reset_vcpu_aarch64(vcpu);
1881e0c135aSWill Deacon }
1891e0c135aSWill Deacon 
190fc9d8ec3SMarc Zyngier int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
191fc9d8ec3SMarc Zyngier {
192fc9d8ec3SMarc Zyngier 	struct kvm_one_reg reg;
193fc9d8ec3SMarc Zyngier 	u64 psr;
194fc9d8ec3SMarc Zyngier 	u64 sctlr;
195fc9d8ec3SMarc Zyngier 
196fc9d8ec3SMarc Zyngier 	/*
197fc9d8ec3SMarc Zyngier 	 * Quoting the definition given by Peter Maydell:
198fc9d8ec3SMarc Zyngier 	 *
199fc9d8ec3SMarc Zyngier 	 * "Endianness of the CPU which does the virtio reset at the
200fc9d8ec3SMarc Zyngier 	 * point when it does that reset"
201fc9d8ec3SMarc Zyngier 	 *
202fc9d8ec3SMarc Zyngier 	 * We first check for an AArch32 guest: its endianness can
203fc9d8ec3SMarc Zyngier 	 * change when using SETEND, which affects the CPSR.E bit.
204fc9d8ec3SMarc Zyngier 	 *
205fc9d8ec3SMarc Zyngier 	 * If we're AArch64, use SCTLR_EL1.E0E if access comes from
206fc9d8ec3SMarc Zyngier 	 * EL0, and SCTLR_EL1.EE if access comes from EL1.
207fc9d8ec3SMarc Zyngier 	 */
208fc9d8ec3SMarc Zyngier 	reg.id = ARM64_CORE_REG(regs.pstate);
209fc9d8ec3SMarc Zyngier 	reg.addr = (u64)&psr;
210fc9d8ec3SMarc Zyngier 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
211fc9d8ec3SMarc Zyngier 		die("KVM_GET_ONE_REG failed (spsr[EL1])");
212fc9d8ec3SMarc Zyngier 
213fc9d8ec3SMarc Zyngier 	if (psr & PSR_MODE32_BIT)
214fc9d8ec3SMarc Zyngier 		return (psr & COMPAT_PSR_E_BIT) ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE;
215fc9d8ec3SMarc Zyngier 
216fc9d8ec3SMarc Zyngier 	reg.id = ARM64_SYS_REG(ARM_CPU_CTRL, ARM_CPU_CTRL_SCTLR_EL1);
217fc9d8ec3SMarc Zyngier 	reg.addr = (u64)&sctlr;
218fc9d8ec3SMarc Zyngier 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
219fc9d8ec3SMarc Zyngier 		die("KVM_GET_ONE_REG failed (SCTLR_EL1)");
220fc9d8ec3SMarc Zyngier 
221fc9d8ec3SMarc Zyngier 	if ((psr & PSR_MODE_MASK) == PSR_MODE_EL0t)
222fc9d8ec3SMarc Zyngier 		sctlr &= SCTLR_EL1_E0E_MASK;
223fc9d8ec3SMarc Zyngier 	else
224fc9d8ec3SMarc Zyngier 		sctlr &= SCTLR_EL1_EE_MASK;
225fc9d8ec3SMarc Zyngier 	return sctlr ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE;
226fc9d8ec3SMarc Zyngier }
227fc9d8ec3SMarc Zyngier 
2281e0c135aSWill Deacon void kvm_cpu__show_code(struct kvm_cpu *vcpu)
2291e0c135aSWill Deacon {
2301e0c135aSWill Deacon 	struct kvm_one_reg reg;
2311e0c135aSWill Deacon 	unsigned long data;
23230c31b66SWill Deacon 	int debug_fd = kvm_cpu__get_debug_fd();
2331e0c135aSWill Deacon 
2341e0c135aSWill Deacon 	reg.addr = (u64)&data;
2351e0c135aSWill Deacon 
23630c31b66SWill Deacon 	dprintf(debug_fd, "\n*pc:\n");
2371e0c135aSWill Deacon 	reg.id = ARM64_CORE_REG(regs.pc);
2381e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
2391e0c135aSWill Deacon 		die("KVM_GET_ONE_REG failed (show_code @ PC)");
2401e0c135aSWill Deacon 
24130c31b66SWill Deacon 	kvm__dump_mem(vcpu->kvm, data, 32, debug_fd);
2421e0c135aSWill Deacon 
24330c31b66SWill Deacon 	dprintf(debug_fd, "\n*lr:\n");
2441e0c135aSWill Deacon 	reg.id = ARM64_CORE_REG(regs.regs[30]);
2451e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
2461e0c135aSWill Deacon 		die("KVM_GET_ONE_REG failed (show_code @ LR)");
2471e0c135aSWill Deacon 
24830c31b66SWill Deacon 	kvm__dump_mem(vcpu->kvm, data, 32, debug_fd);
2491e0c135aSWill Deacon }
2501e0c135aSWill Deacon 
2511e0c135aSWill Deacon void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
2521e0c135aSWill Deacon {
2531e0c135aSWill Deacon 	struct kvm_one_reg reg;
2541e0c135aSWill Deacon 	unsigned long data;
2551e0c135aSWill Deacon 	int debug_fd = kvm_cpu__get_debug_fd();
2561e0c135aSWill Deacon 
2571e0c135aSWill Deacon 	reg.addr = (u64)&data;
2581e0c135aSWill Deacon 	dprintf(debug_fd, "\n Registers:\n");
2591e0c135aSWill Deacon 
2601e0c135aSWill Deacon 	reg.id		= ARM64_CORE_REG(regs.pc);
2611e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
2621e0c135aSWill Deacon 		die("KVM_GET_ONE_REG failed (pc)");
2631e0c135aSWill Deacon 	dprintf(debug_fd, " PC:    0x%lx\n", data);
2641e0c135aSWill Deacon 
2651e0c135aSWill Deacon 	reg.id		= ARM64_CORE_REG(regs.pstate);
2661e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
2671e0c135aSWill Deacon 		die("KVM_GET_ONE_REG failed (pstate)");
2681e0c135aSWill Deacon 	dprintf(debug_fd, " PSTATE:    0x%lx\n", data);
2691e0c135aSWill Deacon 
2701e0c135aSWill Deacon 	reg.id		= ARM64_CORE_REG(sp_el1);
2711e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
2721e0c135aSWill Deacon 		die("KVM_GET_ONE_REG failed (sp_el1)");
2731e0c135aSWill Deacon 	dprintf(debug_fd, " SP_EL1:    0x%lx\n", data);
2741e0c135aSWill Deacon 
2751e0c135aSWill Deacon 	reg.id		= ARM64_CORE_REG(regs.regs[30]);
2761e0c135aSWill Deacon 	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
2771e0c135aSWill Deacon 		die("KVM_GET_ONE_REG failed (lr)");
2781e0c135aSWill Deacon 	dprintf(debug_fd, " LR:    0x%lx\n", data);
2791e0c135aSWill Deacon }
280