|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH V3 10/12] xen: Introduce monitor_op domctl
In preparation for allowing for introspecting ARM and PV domains the old
control interface via the hvm_op hypercall is retired. A new control mechanism
is introduced via the domctl hypercall: monitor_op.
This patch aims to establish a base API on which future applications can build
on.
Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Signed-off-by: Tamas K Lengyel <tamas.lengyel@xxxxxxxxxxxx>
---
tools/libxc/Makefile | 1 +
tools/libxc/include/xenctrl.h | 19 ++++
tools/libxc/xc_mem_access.c | 9 +-
tools/libxc/xc_monitor.c | 118 +++++++++++++++++++++
tools/libxc/xc_private.h | 2 +-
tools/libxc/xc_vm_event.c | 7 +-
tools/tests/xen-access/xen-access.c | 14 +--
xen/arch/x86/Makefile | 1 +
xen/arch/x86/hvm/event.c | 41 ++------
xen/arch/x86/hvm/hvm.c | 38 +------
xen/arch/x86/hvm/vmx/vmcs.c | 4 +-
xen/arch/x86/hvm/vmx/vmx.c | 2 +-
xen/arch/x86/mm/p2m.c | 9 --
xen/arch/x86/monitor.c | 197 ++++++++++++++++++++++++++++++++++++
xen/common/domctl.c | 11 ++
xen/common/vm_event.c | 7 --
xen/include/asm-arm/monitor.h | 13 +++
xen/include/asm-x86/domain.h | 45 ++++++++
xen/include/asm-x86/monitor.h | 9 ++
xen/include/public/domctl.h | 55 +++++++++-
xen/include/public/hvm/params.h | 15 ---
xen/include/public/vm_event.h | 2 +-
22 files changed, 495 insertions(+), 124 deletions(-)
create mode 100644 tools/libxc/xc_monitor.c
create mode 100644 xen/arch/x86/monitor.c
create mode 100644 xen/include/asm-arm/monitor.h
create mode 100644 xen/include/asm-x86/monitor.h
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 6ef17ec..2d79e7c 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -27,6 +27,7 @@ CTRL_SRCS-y += xc_cpu_hotplug.c
CTRL_SRCS-y += xc_resume.c
CTRL_SRCS-y += xc_tmem.c
CTRL_SRCS-y += xc_vm_event.c
+CTRL_SRCS-y += xc_monitor.c
CTRL_SRCS-y += xc_mem_paging.c
CTRL_SRCS-y += xc_mem_access.c
CTRL_SRCS-y += xc_memshr.c
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 0ad8b8d..6428365 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2308,6 +2308,25 @@ int xc_get_mem_access(xc_interface *xch, domid_t
domain_id,
uint64_t pfn, xenmem_access_t *access);
/***
+ * Monitor control operations.
+ */
+int xc_monitor_mov_to_cr0(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int sync,
+ unsigned int onchangeonly);
+int xc_monitor_mov_to_cr3(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int sync,
+ unsigned int onchangeonly);
+int xc_monitor_mov_to_cr4(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int sync,
+ unsigned int onchangeonly);
+int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int extended_capture);
+int xc_monitor_singlestep(xc_interface *xch, domid_t domain_id,
+ unsigned int op);
+int xc_monitor_software_breakpoint(xc_interface *xch, domid_t domain_id,
+ unsigned int op);
+
+/***
* Memory sharing operations.
*
* Unles otherwise noted, these calls return 0 on succes, -1 and errno on
diff --git a/tools/libxc/xc_mem_access.c b/tools/libxc/xc_mem_access.c
index aa6e777..70cc8d0 100644
--- a/tools/libxc/xc_mem_access.c
+++ b/tools/libxc/xc_mem_access.c
@@ -27,14 +27,7 @@
void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t
*port)
{
return xc_vm_event_enable(xch, domain_id, HVM_PARAM_MONITOR_RING_PFN,
- port, 0);
-}
-
-void *xc_mem_access_enable_introspection(xc_interface *xch, domid_t domain_id,
- uint32_t *port)
-{
- return xc_vm_event_enable(xch, domain_id, HVM_PARAM_MONITOR_RING_PFN,
- port, 1);
+ port);
}
int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
diff --git a/tools/libxc/xc_monitor.c b/tools/libxc/xc_monitor.c
new file mode 100644
index 0000000..ee5a37b
--- /dev/null
+++ b/tools/libxc/xc_monitor.c
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * xc_monitor.c
+ *
+ * Interface to VM event monitor
+ *
+ * Copyright (c) 2015 Tamas K Lengyel (tamas@xxxxxxxxxxxxx)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
+ */
+
+#include "xc_private.h"
+
+int xc_monitor_mov_to_cr0(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int sync,
+ unsigned int onchangeonly)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.subop = XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR0;
+ domctl.u.monitor_op.options.mov_to_cr0.sync = sync;
+ domctl.u.monitor_op.options.mov_to_cr0.onchangeonly = onchangeonly;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_monitor_mov_to_cr3(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int sync,
+ unsigned int onchangeonly)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.subop = XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR3;
+ domctl.u.monitor_op.options.mov_to_cr3.sync = sync;
+ domctl.u.monitor_op.options.mov_to_cr3.onchangeonly = onchangeonly;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_monitor_mov_to_cr4(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int sync,
+ unsigned int onchangeonly)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.subop = XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR4;
+ domctl.u.monitor_op.options.mov_to_cr4.sync = sync;
+ domctl.u.monitor_op.options.mov_to_cr4.onchangeonly = onchangeonly;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int extended_capture)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.subop = XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_MSR;
+ domctl.u.monitor_op.options.mov_to_msr.extended_capture = extended_capture;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_monitor_software_breakpoint(xc_interface *xch, domid_t domain_id,
+ unsigned int op)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.subop = XEN_DOMCTL_MONITOR_SUBOP_SOFTWARE_BREAKPOINT;
+
+ return do_domctl(xch, &domctl);
+}
+
+int xc_monitor_singlestep(xc_interface *xch, domid_t domain_id,
+ unsigned int op)
+{
+ DECLARE_DOMCTL;
+
+ domctl.cmd = XEN_DOMCTL_monitor_op;
+ domctl.domain = domain_id;
+ domctl.u.monitor_op.op = op ? XEN_DOMCTL_MONITOR_OP_ENABLE
+ : XEN_DOMCTL_MONITOR_OP_DISABLE;
+ domctl.u.monitor_op.subop = XEN_DOMCTL_MONITOR_SUBOP_SINGLESTEP;
+
+ return do_domctl(xch, &domctl);
+}
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 843540c..9f55309 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -430,6 +430,6 @@ int xc_vm_event_control(xc_interface *xch, domid_t
domain_id, unsigned int op,
* param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
*/
void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
- uint32_t *port, int enable_introspection);
+ uint32_t *port);
#endif /* __XC_PRIVATE_H__ */
diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
index bd14c9d..12d2169 100644
--- a/tools/libxc/xc_vm_event.c
+++ b/tools/libxc/xc_vm_event.c
@@ -41,7 +41,7 @@ int xc_vm_event_control(xc_interface *xch, domid_t domain_id,
unsigned int op,
}
void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
- uint32_t *port, int enable_introspection)
+ uint32_t *port)
{
void *ring_page = NULL;
uint64_t pfn;
@@ -104,10 +104,7 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t
domain_id, int param,
break;
case HVM_PARAM_MONITOR_RING_PFN:
- if ( enable_introspection )
- op = XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION;
- else
- op = XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE;
+ op = XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE;
mode = XEN_DOMCTL_VM_EVENT_OP_MONITOR;
break;
diff --git a/tools/tests/xen-access/xen-access.c
b/tools/tests/xen-access/xen-access.c
index c9aaed4..5411eab 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -447,13 +447,13 @@ int main(int argc, char *argv[])
}
if ( int3 )
- rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3,
HVMPME_mode_sync);
- else
- rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3,
HVMPME_mode_disabled);
- if ( rc < 0 )
{
- ERROR("Error %d setting int3 vm_event\n", rc);
- goto exit;
+ rc = xc_monitor_software_breakpoint(xch, domain_id, 1);
+ if ( rc < 0 )
+ {
+ ERROR("Error %d setting int3 vm_event\n", rc);
+ goto exit;
+ }
}
/* Wait for access */
@@ -467,7 +467,7 @@ int main(int argc, char *argv[])
rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, ~0ull,
0);
rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, 0,
xenaccess->domain_info->max_pages);
- rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3,
HVMPME_mode_disabled);
+ rc = xc_monitor_software_breakpoint(xch, domain_id, 0);
shutting_down = 1;
}
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 86ca5f8..37e547c 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -36,6 +36,7 @@ obj-y += microcode_intel.o
# This must come after the vendor specific files.
obj-y += microcode.o
obj-y += mm.o
+obj-y += monitor.o
obj-y += mpparse.o
obj-y += nmi.o
obj-y += numa.o
diff --git a/xen/arch/x86/hvm/event.c b/xen/arch/x86/hvm/event.c
index 65f80a7..34975b4 100644
--- a/xen/arch/x86/hvm/event.c
+++ b/xen/arch/x86/hvm/event.c
@@ -55,15 +55,12 @@ static void hvm_event_fill_regs(vm_event_request_t *req)
req->regs.x86.cr4 = curr->arch.hvm_vcpu.guest_cr[4];
}
-static int hvm_event_traps(long parameters, vm_event_request_t *req)
+static int hvm_event_traps(uint8_t sync, vm_event_request_t *req)
{
int rc;
struct vcpu *curr = current;
struct domain *currd = curr->domain;
- if ( !(parameters & HVMPME_MODE_MASK) )
- return 0;
-
rc = vm_event_claim_slot(currd, &currd->vm_event->monitor);
if ( rc == -ENOSYS )
{
@@ -74,7 +71,7 @@ static int hvm_event_traps(long parameters,
vm_event_request_t *req)
else if ( rc < 0 )
return rc;
- if ( (parameters & HVMPME_MODE_MASK) == HVMPME_mode_sync )
+ if ( sync )
{
req->flags |= VM_EVENT_FLAG_VCPU_PAUSED;
vm_event_vcpu_pause(curr);
@@ -97,12 +94,10 @@ void hvm_event_cr0(unsigned long value, unsigned long old)
.data.mov_to_cr.old_value = old
};
- long params = currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR0];
-
- if ( (params & HVMPME_onchangeonly) && (value == old) )
+ if ( currd->arch.monitor_options.mov_to_cr0.onchangeonly && value == old )
return;
- hvm_event_traps(params, &req);
+ hvm_event_traps(currd->arch.monitor_options.mov_to_cr0.sync, &req);
}
void hvm_event_cr3(unsigned long value, unsigned long old)
@@ -116,12 +111,10 @@ void hvm_event_cr3(unsigned long value, unsigned long old)
.data.mov_to_cr.old_value = old
};
- long params = currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR3];
-
- if ( (params & HVMPME_onchangeonly) && (value == old) )
+ if ( currd->arch.monitor_options.mov_to_cr3.onchangeonly && value == old )
return;
- hvm_event_traps(params, &req);
+ hvm_event_traps(currd->arch.monitor_options.mov_to_cr3.sync, &req);
}
void hvm_event_cr4(unsigned long value, unsigned long old)
@@ -135,18 +128,15 @@ void hvm_event_cr4(unsigned long value, unsigned long old)
.data.mov_to_cr.old_value = old
};
- long params = currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR4];
-
- if ( (params & HVMPME_onchangeonly) && (value == old) )
+ if ( currd->arch.monitor_options.mov_to_cr4.onchangeonly && value == old )
return;
- hvm_event_traps(params, &req);
+ hvm_event_traps(currd->arch.monitor_options.mov_to_cr3.sync, &req);
}
void hvm_event_msr(unsigned long msr, unsigned long value)
{
struct vcpu *curr = current;
- struct domain *currd = curr->domain;
vm_event_request_t req = {
.reason = VM_EVENT_REASON_MOV_TO_MSR,
.vcpu_id = curr->vcpu_id,
@@ -154,42 +144,33 @@ void hvm_event_msr(unsigned long msr, unsigned long value)
.data.mov_to_msr.value = value,
};
- long params = currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_MSR];
-
- hvm_event_traps(params, &req);
+ hvm_event_traps(1, &req);
}
int hvm_event_int3(unsigned long gla)
{
uint32_t pfec = PFEC_page_present;
struct vcpu *curr = current;
- struct domain *currd = curr->domain;
vm_event_request_t req = {
.reason = VM_EVENT_REASON_SOFTWARE_BREAKPOINT,
.vcpu_id = curr->vcpu_id,
.data.software_breakpoint.gfn = paging_gva_to_gfn(curr, gla, &pfec)
};
- long params = currd->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_INT3];
-
- return hvm_event_traps(params, &req);
+ return hvm_event_traps(1, &req);
}
int hvm_event_single_step(unsigned long gla)
{
uint32_t pfec = PFEC_page_present;
struct vcpu *curr = current;
- struct domain *currd = curr->domain;
vm_event_request_t req = {
.reason = VM_EVENT_REASON_SINGLESTEP,
.vcpu_id = curr->vcpu_id,
.data.singlestep.gfn = paging_gva_to_gfn(curr, gla, &pfec)
};
- long params = currd->arch.hvm_domain
- .params[HVM_PARAM_MEMORY_EVENT_SINGLE_STEP];
-
- return hvm_event_traps(params, &req);
+ return hvm_event_traps(1, &req);
}
/*
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 97f769a..0baeee3 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -5727,23 +5727,6 @@ long do_hvm_op(unsigned long op,
XEN_GUEST_HANDLE_PARAM(void) arg)
case HVM_PARAM_ACPI_IOPORTS_LOCATION:
rc = pmtimer_change_ioport(d, a.value);
break;
- case HVM_PARAM_MEMORY_EVENT_CR0:
- case HVM_PARAM_MEMORY_EVENT_CR3:
- case HVM_PARAM_MEMORY_EVENT_CR4:
- if ( d == current->domain )
- rc = -EPERM;
- break;
- case HVM_PARAM_MEMORY_EVENT_INT3:
- case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP:
- case HVM_PARAM_MEMORY_EVENT_MSR:
- if ( d == current->domain )
- {
- rc = -EPERM;
- break;
- }
- if ( a.value & HVMPME_onchangeonly )
- rc = -EINVAL;
- break;
case HVM_PARAM_NESTEDHVM:
rc = xsm_hvm_param_nested(XSM_PRIV, d);
if ( rc )
@@ -5802,29 +5785,10 @@ long do_hvm_op(unsigned long op,
XEN_GUEST_HANDLE_PARAM(void) arg)
}
}
- if ( rc == 0 )
+ if ( rc == 0 )
{
d->arch.hvm_domain.params[a.index] = a.value;
-
- switch( a.index )
- {
- case HVM_PARAM_MEMORY_EVENT_INT3:
- case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP:
- {
- domain_pause(d);
- domain_unpause(d); /* Causes guest to latch new status */
- break;
- }
- case HVM_PARAM_MEMORY_EVENT_CR3:
- {
- for_each_vcpu ( d, v )
- hvm_funcs.update_guest_cr(v, 0); /* Latches new CR3
mask through CR0 code */
- break;
- }
- }
-
}
-
}
else
{
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 0f2b2e6..9787f3f 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -1375,8 +1375,8 @@ void vmx_do_resume(struct vcpu *v)
}
debug_state = v->domain->debugger_attached
- ||
v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_INT3]
- ||
v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_SINGLE_STEP];
+ ||
v->domain->arch.monitor_options.software_breakpoint.enabled
+ || v->domain->arch.monitor_options.singlestep.enabled;
if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) )
{
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index c5e6771..ce3dcbd 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -1232,7 +1232,7 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned
int cr)
v->arch.hvm_vmx.exec_control |= cr3_ctls;
/* Trap CR3 updates if CR3 memory events are enabled. */
- if ( v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_CR3]
)
+ if ( v->domain->arch.monitor_options.mov_to_cr3.enabled )
v->arch.hvm_vmx.exec_control |= CPU_BASED_CR3_LOAD_EXITING;
vmx_update_cpu_exec_control(v);
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index c7a0bde..3b58700 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1445,15 +1445,6 @@ void p2m_vm_event_emulate_check(struct vcpu *v, const
vm_event_response_t *rsp)
}
}
-void p2m_setup_introspection(struct domain *d)
-{
- if ( hvm_funcs.enable_msr_exit_interception )
- {
- d->arch.hvm_domain.introspection_enabled = 1;
- hvm_funcs.enable_msr_exit_interception(d);
- }
-}
-
bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
struct npfec npfec,
vm_event_request_t **req_ptr)
diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
new file mode 100644
index 0000000..c172aaf
--- /dev/null
+++ b/xen/arch/x86/monitor.c
@@ -0,0 +1,197 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include <xen/config.h>
+#include <xen/sched.h>
+#include <xen/mm.h>
+#include <asm/domain.h>
+
+#define DISABLE_OPTION(option) \
+ if ( !option->enabled ) \
+ return -EFAULT; \
+ memset(option, 0, sizeof(*option))
+
+int monitor_domctl(struct xen_domctl_monitor_op *domctl, struct domain *d)
+{
+ /*
+ * At the moment only HVM domains are supported. However, event delivery
+ * could be extended to PV domains. See comments below.
+ */
+ if ( !is_hvm_domain(d) )
+ return -ENOSYS;
+
+ if ( domctl->op != XEN_DOMCTL_MONITOR_OP_ENABLE &&
+ domctl->op != XEN_DOMCTL_MONITOR_OP_DISABLE )
+ return -EFAULT;
+
+ switch ( domctl->subop )
+ {
+ case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR0:
+ {
+ /* Note: could be supported on PV domains. */
+ struct mov_to_cr0 *options = &d->arch.monitor_options.mov_to_cr0;
+
+ if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
+ {
+ if ( options->enabled )
+ return -EBUSY;
+
+ options->enabled = 1;
+ options->sync = domctl->options.mov_to_cr0.sync;
+ options->onchangeonly = domctl->options.mov_to_cr0.onchangeonly;
+ }
+ else
+ {
+ DISABLE_OPTION(options);
+ }
+ break;
+ }
+ case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR3:
+ {
+ /* Note: could be supported on PV domains. */
+ struct vcpu *v;
+ struct mov_to_cr3 *options = &d->arch.monitor_options.mov_to_cr3;
+
+ if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
+ {
+ if ( options->enabled )
+ return -EBUSY;
+
+ options->enabled = 1;
+ options->sync = domctl->options.mov_to_cr3.sync;
+ options->onchangeonly = domctl->options.mov_to_cr3.onchangeonly;
+ }
+ else
+ {
+ DISABLE_OPTION(options);
+ }
+
+ /* Latches new CR3 mask through CR0 code */
+ for_each_vcpu ( d, v )
+ hvm_funcs.update_guest_cr(v, 0);
+ break;
+ }
+
+ case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR4:
+ {
+ /* Note: could be supported on PV domains. */
+ struct mov_to_cr4 *options = &d->arch.monitor_options.mov_to_cr4;
+
+ if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
+ {
+ if ( options->enabled )
+ return -EBUSY;
+
+ options->enabled = 1;
+ options->sync = domctl->options.mov_to_cr4.sync;
+ options->onchangeonly = domctl->options.mov_to_cr4.onchangeonly;
+ }
+ else
+ {
+ DISABLE_OPTION(options);
+ }
+ break;
+ }
+ case XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_MSR:
+ {
+ struct mov_to_msr *options = &d->arch.monitor_options.mov_to_msr;
+
+ if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
+ {
+ if ( options->enabled )
+ return -EBUSY;
+
+ options->enabled = 1;
+
+ if ( domctl->options.mov_to_msr.extended_capture )
+ {
+ if ( hvm_funcs.enable_msr_exit_interception )
+ {
+ options->extended_capture = 1;
+ hvm_funcs.enable_msr_exit_interception(d);
+ }
+ else
+ {
+ return -ENOSYS;
+ }
+ }
+ }
+ else
+ {
+ DISABLE_OPTION(options);
+ }
+
+ break;
+ }
+ case XEN_DOMCTL_MONITOR_SUBOP_SINGLESTEP:
+ {
+ struct singlestep *options = &d->arch.monitor_options.singlestep;
+
+ if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
+ {
+ if ( options->enabled )
+ return -EBUSY;
+
+ options->enabled = 1;
+ }
+ else
+ {
+ DISABLE_OPTION(options);
+ }
+
+ /* Causes guest to latch new status */
+ domain_pause(d);
+ domain_unpause(d);
+ break;
+ }
+ case XEN_DOMCTL_MONITOR_SUBOP_SOFTWARE_BREAKPOINT:
+ {
+ struct software_breakpoint *options =
+ &d->arch.monitor_options.software_breakpoint;
+
+ if ( domctl->op == XEN_DOMCTL_MONITOR_OP_ENABLE )
+ {
+ if ( options->enabled )
+ return -EBUSY;
+
+ options->enabled = 1;
+ }
+ else
+ {
+ DISABLE_OPTION(options);
+ }
+
+ domain_pause(d);
+ domain_unpause(d); /* Causes guest to latch new status */
+ break;
+ }
+
+ default:
+ return -EFAULT;
+
+ };
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 44d45d1..98c2dc6 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -29,6 +29,7 @@
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/p2m.h>
+#include <asm/monitor.h>
#include <public/domctl.h>
#include <xsm/xsm.h>
@@ -1179,6 +1180,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t)
u_domctl)
}
break;
+ case XEN_DOMCTL_monitor_op:
+ {
+ ret = -EPERM;
+ if ( current->domain == d )
+ break;
+
+ ret = monitor_domctl(&op->u.monitor_op, d);
+ }
+ break;
+
default:
ret = arch_do_domctl(op, d, u_domctl);
break;
diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
index 0db899e..0b30750 100644
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -617,16 +617,10 @@ int vm_event_domctl(struct domain *d,
xen_domctl_vm_event_op_t *vec,
switch( vec->op )
{
case XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE:
- case XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION:
{
rc = vm_event_enable(d, vec, ved, _VPF_mem_access,
HVM_PARAM_MONITOR_RING_PFN,
mem_access_notification);
-
- if ( vec->op == XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION
- && !rc )
- p2m_setup_introspection(d);
-
}
break;
@@ -635,7 +629,6 @@ int vm_event_domctl(struct domain *d,
xen_domctl_vm_event_op_t *vec,
if ( ved->ring_page )
{
rc = vm_event_disable(d, ved);
- d->arch.hvm_domain.introspection_enabled = 0;
}
}
break;
diff --git a/xen/include/asm-arm/monitor.h b/xen/include/asm-arm/monitor.h
new file mode 100644
index 0000000..ef8f38a
--- /dev/null
+++ b/xen/include/asm-arm/monitor.h
@@ -0,0 +1,13 @@
+#ifndef __ASM_ARM_MONITOR_H__
+#define __ASM_ARM_MONITOR_H__
+
+#include <xen/config.h>
+#include <public/domctl.h>
+
+static inline
+int monitor_domctl(struct xen_domctl_monitor_op *op, struct domain *d)
+{
+ return -ENOSYS;
+}
+
+#endif /* __ASM_X86_MONITOR_H__ */
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 20ede1e..99fcd94 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -236,6 +236,41 @@ struct time_scale {
u32 mul_frac;
};
+/************************************************/
+/* monitor event options */
+/************************************************/
+struct mov_to_cr0 {
+ uint8_t enabled;
+ uint8_t sync;
+ uint8_t onchangeonly;
+};
+
+struct mov_to_cr3 {
+ uint8_t enabled;
+ uint8_t sync;
+ uint8_t onchangeonly;
+};
+
+struct mov_to_cr4 {
+ uint8_t enabled;
+ uint8_t sync;
+ uint8_t onchangeonly;
+};
+
+struct mov_to_msr {
+ uint8_t enabled;
+ uint8_t extended_capture;
+};
+
+struct singlestep {
+ uint8_t enabled;
+};
+
+struct software_breakpoint {
+ uint8_t enabled;
+};
+
+
struct pv_domain
{
l1_pgentry_t **gdt_ldt_l1tab;
@@ -330,6 +365,16 @@ struct arch_domain
unsigned long pirq_eoi_map_mfn;
unsigned int psr_rmid; /* RMID assigned to the domain for CMT */
+
+ /* Monitor options */
+ struct {
+ struct mov_to_cr0 mov_to_cr0;
+ struct mov_to_cr3 mov_to_cr3;
+ struct mov_to_cr4 mov_to_cr4;
+ struct mov_to_msr mov_to_msr;
+ struct singlestep singlestep;
+ struct software_breakpoint software_breakpoint;
+ } monitor_options;
} __cacheline_aligned;
#define has_arch_pdevs(d) (!list_empty(&(d)->arch.pdev_list))
diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
new file mode 100644
index 0000000..1d7cdd3
--- /dev/null
+++ b/xen/include/asm-x86/monitor.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_X86_MONITOR_H__
+#define __ASM_X86_MONITOR_H__
+
+#include <xen/config.h>
+#include <public/domctl.h>
+
+int monitor_domctl(struct xen_domctl_monitor_op *op, struct domain *d);
+
+#endif /* __ASM_X86_MONITOR_H__ */
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 5d48a4d..4f3b685 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -803,7 +803,6 @@ struct xen_domctl_gdbsx_domstatus {
#define XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE 0
#define XEN_DOMCTL_VM_EVENT_OP_MONITOR_DISABLE 1
-#define XEN_DOMCTL_VM_EVENT_OP_MONITOR_ENABLE_INTROSPECTION 2
/*
* Sharing ENOMEM helper.
@@ -1001,6 +1000,58 @@ struct xen_domctl_psr_cmt_op {
typedef struct xen_domctl_psr_cmt_op xen_domctl_psr_cmt_op_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
+/* XEN_DOMCTL_MONITOR_*
+ *
+ * Enable/disable monitoring various VM events.
+ * This domctl configures what events will be reported to helper apps
+ * via the ring buffer "MONITOR". The ring has to be first enabled
+ * with the domctl XEN_DOMCTL_VM_EVENT_OP_MONITOR.
+ *
+ * NOTICE: mem_access events are also delivered via the "MONITOR" ring buffer;
+ * however, enabling/disabling those events is performed with the use of
+ * memory_op hypercalls!
+ *
+ */
+#define XEN_DOMCTL_MONITOR_OP_ENABLE 0
+#define XEN_DOMCTL_MONITOR_OP_DISABLE 1
+
+#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR0 0
+#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR3 1
+#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_CR4 2
+#define XEN_DOMCTL_MONITOR_SUBOP_MOV_TO_MSR 3
+#define XEN_DOMCTL_MONITOR_SUBOP_SINGLESTEP 4
+#define XEN_DOMCTL_MONITOR_SUBOP_SOFTWARE_BREAKPOINT 5
+
+struct xen_domctl_monitor_op {
+ uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */
+ uint32_t subop; /* XEN_DOMCTL_MONITOR_SUBOP_* */
+
+ /*
+ * Further options when issuing XEN_DOMCTL_MONITOR_OP_ENABLE.
+ */
+ union {
+ struct {
+ uint8_t sync; /* Pause vCPU until response */
+ uint8_t onchangeonly; /* Send event only on a change of value */
+ uint8_t pad[6];
+ } mov_to_cr0, mov_to_cr3, mov_to_cr4;
+
+ /* Enable the capture of msr events on
+ MSR_IA32_SYSENTER_EIP
+ MSR_IA32_SYSENTER_ESP
+ MSR_IA32_SYSENTER_CS
+ MSR_IA32_MC0_CTL
+ MSR_STAR
+ MSR_LSTAR */
+ struct {
+ uint8_t extended_capture;
+ uint8_t pad[7];
+ } mov_to_msr;
+ } options;
+};
+typedef struct xen_domctl__op xen_domctl_monitor_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_monitor_op_t);
+
struct xen_domctl {
uint32_t cmd;
#define XEN_DOMCTL_createdomain 1
@@ -1076,6 +1127,7 @@ struct xen_domctl {
#define XEN_DOMCTL_setvnumainfo 74
#define XEN_DOMCTL_psr_cmt_op 75
#define XEN_DOMCTL_arm_configure_domain 76
+#define XEN_DOMCTL_monitor_op 77
#define XEN_DOMCTL_gdbsx_guestmemio 1000
#define XEN_DOMCTL_gdbsx_pausevcpu 1001
#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -1141,6 +1193,7 @@ struct xen_domctl {
struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
struct xen_domctl_vnuma vnuma;
struct xen_domctl_psr_cmt_op psr_cmt_op;
+ struct xen_domctl_monitor_op monitor_op;
uint8_t pad[128];
} u;
};
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 6efcc0b..5de6a4b 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -162,21 +162,6 @@
*/
#define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
-/* Enable blocking memory events, async or sync (pause vcpu until response)
- * onchangeonly indicates messages only on a change of value */
-#define HVM_PARAM_MEMORY_EVENT_CR0 20
-#define HVM_PARAM_MEMORY_EVENT_CR3 21
-#define HVM_PARAM_MEMORY_EVENT_CR4 22
-#define HVM_PARAM_MEMORY_EVENT_INT3 23
-#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP 25
-#define HVM_PARAM_MEMORY_EVENT_MSR 30
-
-#define HVMPME_MODE_MASK (3 << 0)
-#define HVMPME_mode_disabled 0
-#define HVMPME_mode_async 1
-#define HVMPME_mode_sync 2
-#define HVMPME_onchangeonly (1 << 2)
-
/* Boolean: Enable nestedhvm (hvm only) */
#define HVM_PARAM_NESTEDHVM 24
diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
index 8fba3d1b..a057608 100644
--- a/xen/include/public/vm_event.h
+++ b/xen/include/public/vm_event.h
@@ -67,7 +67,7 @@
#define VM_EVENT_REASON_MOV_TO_CR3 5
/* CR4 was updated */
#define VM_EVENT_REASON_MOV_TO_CR4 6
-/* An MSR was updated. Does NOT honour HVMPME_onchangeonly */
+/* An MSR was updated. */
#define VM_EVENT_REASON_MOV_TO_MSR 9
/* Debug operation executed (int3) */
#define VM_EVENT_REASON_SOFTWARE_BREAKPOINT 7
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |