Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2012 - Virtual Open Systems and Columbia University
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Author: Christoffer Dall <c.dall@virtualopensystems.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/kvm_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <asm/kvm_emulate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <trace/events/kvm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	void *datap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 		u8	byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 		u16	hword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 		u32	word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 		u64	dword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	} tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	switch (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		tmp.byte	= data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 		datap		= &tmp.byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		tmp.hword	= data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		datap		= &tmp.hword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		tmp.word	= data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		datap		= &tmp.word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		tmp.dword	= data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		datap		= &tmp.dword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	memcpy(buf, datap, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	unsigned long data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		u16	hword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		u32	word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		u64	dword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	} tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	switch (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		data = *(u8 *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		memcpy(&tmp.hword, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		data = tmp.hword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		memcpy(&tmp.word, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		data = tmp.word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		memcpy(&tmp.dword, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		data = tmp.dword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  *			     or in-kernel IO emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * @vcpu: The VCPU pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	unsigned long data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	/* Detect an already handled MMIO return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (unlikely(!vcpu->mmio_needed))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	vcpu->mmio_needed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	if (!kvm_vcpu_dabt_iswrite(vcpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		struct kvm_run *run = vcpu->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		len = kvm_vcpu_dabt_get_as(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		data = kvm_mmio_read_buf(run->mmio.data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		if (kvm_vcpu_dabt_issext(vcpu) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		    len < sizeof(unsigned long)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			mask = 1U << ((len * 8) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			data = (data ^ mask) - mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		if (!kvm_vcpu_dabt_issf(vcpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			data = data & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			       &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		data = vcpu_data_host_to_guest(vcpu, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	 * The MMIO instruction is emulated and should not be re-executed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	 * in the guest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	kvm_incr_pc(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	struct kvm_run *run = vcpu->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	unsigned long data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	unsigned long rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	bool is_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	u8 data_buf[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	 * No valid syndrome? Ask userspace for help if it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	 * volunteered to do so, and bail out otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (!kvm_vcpu_dabt_isvalid(vcpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		if (vcpu->kvm->arch.return_nisv_io_abort_to_user) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			run->exit_reason = KVM_EXIT_ARM_NISV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			run->arm_nisv.esr_iss = kvm_vcpu_dabt_iss_nisv_sanitized(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			run->arm_nisv.fault_ipa = fault_ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		kvm_pr_unimpl("Data abort outside memslots with no valid syndrome info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	 * Prepare MMIO operation. First decode the syndrome data we get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	 * from the CPU. Then try if some in-kernel emulation feels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	 * responsible, otherwise let user space do its magic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	is_write = kvm_vcpu_dabt_iswrite(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	len = kvm_vcpu_dabt_get_as(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	rt = kvm_vcpu_dabt_get_rd(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	if (is_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 					       len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		kvm_mmio_write_buf(data_buf, len, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				       data_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			       fault_ipa, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				      data_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	/* Now prepare kvm_run for the potential return to userland. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	run->mmio.is_write	= is_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	run->mmio.phys_addr	= fault_ipa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	run->mmio.len		= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	vcpu->mmio_needed	= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		/* We handled the access successfully in the kernel. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		if (!is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			memcpy(run->mmio.data, data_buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		vcpu->stat.mmio_exit_kernel++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		kvm_handle_mmio_return(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (is_write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		memcpy(run->mmio.data, data_buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	vcpu->stat.mmio_exit_user++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	run->exit_reason	= KVM_EXIT_MMIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }