[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH V3 10/12] xen: Introduce monitor_op domctl
> From: Tamas K Lengyel [mailto:tamas.lengyel@xxxxxxxxxxxx] > Sent: Friday, January 30, 2015 5:47 AM > > 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> for VMX changes: Acked-by: Kevin Tian <kevin.tian@xxxxxxxxx> > --- > 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_ST > EP]; > - > - 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_SING > LE_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 |