unsignedlong kvm_mmio_read_buf(constvoid *buf, unsignedint len)
{ unsignedlong data = 0; union {
u16 hword;
u32 word;
u64 dword;
} tmp;
switch (len) { case1:
data = *(u8 *)buf; break; case2:
memcpy(&tmp.hword, buf, len);
data = tmp.hword; break; case4:
memcpy(&tmp.word, buf, len);
data = tmp.word; break; case8:
memcpy(&tmp.dword, buf, len);
data = tmp.dword; break;
}
return data;
}
staticbool kvm_pending_external_abort(struct kvm_vcpu *vcpu)
{ if (!vcpu_get_flag(vcpu, PENDING_EXCEPTION)) returnfalse;
if (vcpu_el1_is_32bit(vcpu)) { 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): returntrue; default: returnfalse;
}
} 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): returntrue; default: returnfalse;
}
}
}
/** *kvm_handle_mmio_return--HandleMMIOloadsafteruserspaceemulation *orin-kernelIOemulation * *@vcpu:TheVCPUpointer
*/ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
{ unsignedlong data; unsignedint len; int mask;
/* *DetectiftheMMIOreturnwasalreadyhandledorifuserspaceaborted *theMMIOaccess.
*/ if (unlikely(!vcpu->mmio_needed || kvm_pending_external_abort(vcpu))) return1;
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(unsignedlong)) {
mask = 1U << ((len * 8) - 1);
data = (data ^ mask) - mask;
}
if (!kvm_vcpu_dabt_issf(vcpu))
data = data & 0xffffffff;
ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len,
data_buf);
}
/* Now prepare kvm_run for the potential return to userland. */
run->mmio.is_write = is_write;
run->mmio.phys_addr = fault_ipa;
run->mmio.len = len;
vcpu->mmio_needed = 1;
if (!ret) { /* We handled the access successfully in the kernel. */ if (!is_write)
memcpy(run->mmio.data, data_buf, len);
vcpu->stat.mmio_exit_kernel++;
kvm_handle_mmio_return(vcpu); return1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.