arch/arm64/kvm/mmio.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/mmio.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/mmio.c
Extension
.c
Size
6058 bytes
Lines
260
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
		case unpack_vcpu_flag(EXCEPT_AA32_UND):
		case unpack_vcpu_flag(EXCEPT_AA32_IABT):
		case unpack_vcpu_flag(EXCEPT_AA32_DABT):
			return true;
		default:
			return false;
		}
	} else {
		switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
		case unpack_vcpu_flag(EXCEPT_AA64_EL1_SYNC):
		case unpack_vcpu_flag(EXCEPT_AA64_EL2_SYNC):
		case unpack_vcpu_flag(EXCEPT_AA64_EL1_SERR):
		case unpack_vcpu_flag(EXCEPT_AA64_EL2_SERR):
			return true;
		default:
			return false;
		}
	}
}

/**
 * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
 *			     or in-kernel IO emulation
 *
 * @vcpu: The VCPU pointer
 */
int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
{
	unsigned long data;
	unsigned int len;
	int mask;

	/*
	 * Detect if the MMIO return was already handled or if userspace aborted
	 * the MMIO access.
	 */
	if (unlikely(!vcpu->mmio_needed || kvm_pending_external_abort(vcpu)))
		return 1;

	vcpu->mmio_needed = 0;

	if (!kvm_vcpu_dabt_iswrite(vcpu)) {
		struct kvm_run *run = vcpu->run;

		len = kvm_vcpu_dabt_get_as(vcpu);
		data = kvm_mmio_read_buf(run->mmio.data, len);

		if (kvm_vcpu_dabt_issext(vcpu) &&
		    len < sizeof(unsigned long)) {
			mask = 1U << ((len * 8) - 1);
			data = (data ^ mask) - mask;
		}

		if (!kvm_vcpu_dabt_issf(vcpu))
			data = data & 0xffffffff;

		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
			       &data);
		data = vcpu_data_host_to_guest(vcpu, data, len);
		vcpu_set_reg(vcpu, kvm_vcpu_dabt_get_rd(vcpu), data);
	}

	/*
	 * The MMIO instruction is emulated and should not be re-executed
	 * in the guest.
	 */
	kvm_incr_pc(vcpu);

	return 1;
}

int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
{
	struct kvm_run *run = vcpu->run;
	unsigned long data;
	unsigned long rt;
	int ret;
	bool is_write;
	int len;
	u8 data_buf[8];
	u64 esr;

	esr = kvm_vcpu_get_esr(vcpu);

	/*
	 * No valid syndrome? Ask userspace for help if it has
	 * volunteered to do so, and bail out otherwise.
	 *
	 * In the protected VM case, there isn't much userspace can do

Annotation

Implementation Notes