@@ -5334,6 +5334,7 @@ static int emulator_read_write(struct x86_emulate_ctxt *ctxt,
const struct read_write_emulator_ops *ops)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
+ struct kvm_memory_slot *slot;
gpa_t gpa;
int rc;
@@ -5375,7 +5376,14 @@ static int emulator_read_write(struct x86_emulate_ctxt *ctxt,
vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
- vcpu->run->exit_reason = KVM_EXIT_MMIO;
+ slot = kvm_vcpu_gfn_to_memslot(vcpu, gpa >> PAGE_SHIFT);
+ if (slot && ops->write && (kvm_roe_check_range(slot, gpa>>PAGE_SHIFT,
+ gpa - (gpa & PAGE_MASK), bytes) ||
+ gfn_is_full_roe(slot, gpa>>PAGE_SHIFT)))
+ vcpu->run->exit_reason = KVM_EXIT_ROE;
+ else
+ vcpu->run->exit_reason = KVM_EXIT_MMIO;
+
vcpu->run->mmio.phys_addr = gpa;
return ops->read_write_exit_mmio(vcpu, gpa, val, bytes);
@@ -13,4 +13,16 @@ void kvm_roe_arch_commit_protection(struct kvm *kvm,
struct kvm_memory_slot *slot);
int kvm_roe(struct kvm_vcpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3);
bool kvm_roe_arch_is_userspace(struct kvm_vcpu *vcpu);
+bool kvm_roe_check_range(struct kvm_memory_slot *slot, gfn_t gfn, int offset,
+ int len);
+static inline bool gfn_is_full_roe(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+ return test_bit(gfn - slot->base_gfn, slot->roe_bitmap);
+
+}
+static inline bool gfn_is_partial_roe(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+ return test_bit(gfn - slot->base_gfn, slot->partial_roe_bitmap);
+}
+
#endif
@@ -235,7 +235,7 @@ struct kvm_hyperv_exit {
#define KVM_EXIT_S390_STSI 25
#define KVM_EXIT_IOAPIC_EOI 26
#define KVM_EXIT_HYPERV 27
-
+#define KVM_EXIT_ROE 28
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
#define KVM_INTERNAL_ERROR_EMULATION 1
@@ -62,6 +62,7 @@
#include "async_pf.h"
#include "vfio.h"
#include "roe_generic.h"
+#include <kvm/roe.h>
#define CREATE_TRACE_POINTS
#include <trace/events/kvm.h>
@@ -60,7 +60,7 @@ bool kvm_roe_check_range(struct kvm_memory_slot *slot, gfn_t gfn, int offset,
return false;
return kvm_roe_protected_range(slot, gpa, len);
}
-
+EXPORT_SYMBOL_GPL(kvm_roe_check_range);
void kvm_roe_free(struct kvm_memory_slot *slot)
{
@@ -14,12 +14,5 @@ void kvm_roe_free(struct kvm_memory_slot *slot);
int kvm_roe_init(struct kvm_memory_slot *slot);
bool kvm_roe_check_range(struct kvm_memory_slot *slot, gfn_t gfn, int offset,
int len);
-static inline bool gfn_is_full_roe(struct kvm_memory_slot *slot, gfn_t gfn)
-{
- return test_bit(gfn - slot->base_gfn, slot->roe_bitmap);
-}
-static inline bool gfn_is_partial_roe(struct kvm_memory_slot *slot, gfn_t gfn)
-{
- return test_bit(gfn - slot->base_gfn, slot->partial_roe_bitmap);
-}
+
#endif
The problem is that qemu will not be able to detect ROE violations, so one option would be create host API to tell if a given page is ROE protected, or create ROE violation exit reason. Signed-off-by: Ahmed Abd El Mawgood <ahmedsoliman@mena.vt.edu> --- arch/x86/kvm/x86.c | 10 +++++++++- include/kvm/roe.h | 12 ++++++++++++ include/uapi/linux/kvm.h | 2 +- virt/kvm/kvm_main.c | 1 + virt/kvm/roe.c | 2 +- virt/kvm/roe_generic.h | 9 +-------- 6 files changed, 25 insertions(+), 11 deletions(-)