/* * Using the register cache from interrupt context is generally not allowed, as * caching a register and marking it available/dirty can't be done atomically, * i.e. accesses from interrupt context may clobber state or read stale data if * the vCPU task is in the process of updating the cache. The exception is if * KVM is handling a PMI IRQ/NMI VM-Exit, as that bound code sequence doesn't * touch the cache, it runs after the cache is reset (post VM-Exit), and PMIs * need to access several registers that are cacheable.
*/ #define kvm_assert_register_caching_allowed(vcpu) \
lockdep_assert_once(in_task() || kvm_arch_pmi_in_guest(vcpu))
/* * avail dirty * 0 0 register in VMCS/VMCB * 0 1 *INVALID* * 1 0 register in vcpu->arch * 1 1 register in vcpu->arch, needs to be stored back
*/ staticinlinebool kvm_register_is_available(struct kvm_vcpu *vcpu, enum kvm_reg reg)
{
kvm_assert_register_caching_allowed(vcpu); return test_bit(reg, (unsignedlong *)&vcpu->arch.regs_avail);
}
/* * kvm_register_test_and_mark_available() is a special snowflake that uses an * arch bitop directly to avoid the explicit instrumentation that comes with * the generic bitops. This allows code that cannot be instrumented (noinstr * functions), e.g. the low level VM-Enter/VM-Exit paths, to cache registers.
*/ static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu *vcpu, enum kvm_reg reg)
{
kvm_assert_register_caching_allowed(vcpu); return arch___test_and_set_bit(reg, (unsignedlong *)&vcpu->arch.regs_avail);
}
/* * The "raw" register helpers are only for cases where the full 64 bits of a * register are read/written irrespective of current vCPU mode. In other words, * odds are good you shouldn't be using the raw variants.
*/ staticinlineunsignedlong kvm_register_read_raw(struct kvm_vcpu *vcpu, int reg)
{ if (WARN_ON_ONCE((unsignedint)reg >= NR_VCPU_REGS)) return 0;
if (!kvm_register_is_available(vcpu, reg))
kvm_x86_call(cache_reg)(vcpu, reg);
return vcpu->arch.regs[reg];
}
staticinlinevoid kvm_register_write_raw(struct kvm_vcpu *vcpu, int reg, unsignedlong val)
{ if (WARN_ON_ONCE((unsignedint)reg >= NR_VCPU_REGS)) return;
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.