bool enable);
int xc_monitor_guest_request(xc_interface *xch, uint32_t domain_id,
bool enable, bool sync, bool allow_userspace);
+/*
+ * Disables page-walk mem_access events by emulating. If the
+ * emulation can not be performed then a VM_EVENT_REASON_EMUL_UNIMPLEMENTED
+ * event will be issued.
+ */
+int xc_monitor_inguest_pagefault(xc_interface *xch, uint32_t domain_id,
+ bool disable);
int xc_monitor_debug_exceptions(xc_interface *xch, uint32_t domain_id,
bool enable, bool sync);
int xc_monitor_cpuid(xc_interface *xch, uint32_t domain_id, bool enable);
return do_domctl(xch, &domctl);
}
+int xc_monitor_inguest_pagefault(xc_interface *xch, uint32_t domain_id,
+ bool disable)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = disable ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT;
+
+ return do_domctl(xch, &domctl);
+}
+
int xc_monitor_emulate_each_rep(xc_interface *xch, uint32_t domain_id,
bool enable)
{
{
fprintf(stderr, "Usage: %s [-m] <domain_id> write|exec", progname);
#if defined(__i386__) || defined(__x86_64__)
- fprintf(stderr, "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid|desc_access|write_ctrlreg_cr4");
+ fprintf(stderr, "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid|desc_access|write_ctrlreg_cr4|altp2m_write_no_gpt");
#elif defined(__arm__) || defined(__aarch64__)
fprintf(stderr, "|privcall");
#endif
int cpuid = 0;
int desc_access = 0;
int write_ctrlreg_cr4 = 0;
+ int altp2m_write_no_gpt = 0;
uint16_t altp2m_view_id = 0;
char* progname = argv[0];
altp2m = 1;
memaccess = 1;
}
+ else if ( !strcmp(argv[0], "altp2m_write_no_gpt") )
+ {
+ default_access = XENMEM_access_rw;
+ altp2m_write_no_gpt = 1;
+ memaccess = 1;
+ altp2m = 1;
+ }
else if ( !strcmp(argv[0], "debug") )
{
debug = 1;
xen_pfn_t gfn = 0;
unsigned long perm_set = 0;
+ if( altp2m_write_no_gpt )
+ {
+ rc = xc_monitor_inguest_pagefault(xch, domain_id, 1);
+ if ( rc < 0 )
+ {
+ ERROR("Error %d setting inguest pagefault\n", rc);
+ goto exit;
+ }
+ rc = xc_monitor_emul_unimplemented(xch, domain_id, 1);
+ if ( rc < 0 )
+ {
+ ERROR("Error %d failed to enable emul unimplemented\n", rc);
+ goto exit;
+ }
+ }
+
rc = xc_altp2m_set_domain_state( xch, domain_id, 1 );
if ( rc < 0 )
{
req.u.write_ctrlreg.old_value,
req.u.write_ctrlreg.new_value);
break;
+ case VM_EVENT_REASON_EMUL_UNIMPLEMENTED:
+ if ( altp2m_write_no_gpt && req.flags & VM_EVENT_FLAG_ALTERNATE_P2M )
+ {
+ DPRINTF("\tSwitching back to default view!\n");
+
+ rsp.flags |= (VM_EVENT_FLAG_ALTERNATE_P2M |
+ VM_EVENT_FLAG_TOGGLE_SINGLESTEP);
+ rsp.altp2m_idx = 0;
+ }
+ break;
default:
fprintf(stderr, "UNKNOWN REASON CODE %d\n", req.reason);
}
#include <public/vm_event.h>
#include <asm/p2m.h>
#include <asm/altp2m.h>
+#include <asm/hvm/emulate.h>
#include <asm/vm_event.h>
#include "mm-locks.h"
return true;
}
}
+ if ( vm_event_check_ring(d->vm_event_monitor) &&
+ d->arch.monitor.inguest_pagefault_disabled &&
+ npfec.kind != npfec_kind_with_gla ) /* don't send a mem_event */
+ {
+ hvm_emulate_one_vm_event(EMUL_KIND_NORMAL, TRAP_invalid_op, X86_EVENT_NO_EC);
+
+ return true;
+ }
*req_ptr = NULL;
req = xzalloc(vm_event_request_t);
break;
}
+ case XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT:
+ {
+ bool old_status = ad->monitor.inguest_pagefault_disabled;
+
+ if ( unlikely(old_status == requested_status) )
+ return -EEXIST;
+
+ domain_pause(d);
+ ad->monitor.inguest_pagefault_disabled = requested_status;
+ domain_unpause(d);
+ break;
+ }
+
case XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS:
{
bool old_status = ad->monitor.descriptor_access_enabled;
unsigned int descriptor_access_enabled : 1;
unsigned int guest_request_userspace_enabled : 1;
unsigned int emul_unimplemented_enabled : 1;
+ /*
+ * By default all events are sent.
+ * This is used to filter out pagefaults.
+ */
+ unsigned int inguest_pagefault_disabled : 1;
struct monitor_msr_bitmap *msr_bitmap;
uint64_t write_ctrlreg_mask[4];
} monitor;
(1U << XEN_DOMCTL_MONITOR_EVENT_CPUID) |
(1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) |
(1U << XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG) |
- (1U << XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED));
+ (1U << XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED) |
+ (1U << XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT));
if ( hvm_is_singlestep_supported() )
capabilities |= (1U << XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP);
#define XEN_DOMCTL_MONITOR_EVENT_INTERRUPT 8
#define XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS 9
#define XEN_DOMCTL_MONITOR_EVENT_EMUL_UNIMPLEMENTED 10
+/* Enabled by default */
+#define XEN_DOMCTL_MONITOR_EVENT_INGUEST_PAGEFAULT 11
struct xen_domctl_monitor_op {
uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */