hvmctl: convert HVMOP_inject_trap Signed-off-by: Jan Beulich Reviewed-by: Wei Liu Reviewed-by: Andrew Cooper --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -584,31 +584,15 @@ int xc_hvm_inject_trap( uint32_t type, uint32_t error_code, uint32_t insn_len, uint64_t cr2) { - DECLARE_HYPERCALL_BUFFER(struct xen_hvm_inject_trap, arg); - int rc; + DECLARE_HVMCTL(inject_trap, dom, + .vcpuid = vcpu, + .type = type, + .vector = vector, + .insn_len = insn_len, + .error_code = error_code, + .cr2 = cr2); - arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg)); - if ( arg == NULL ) - { - PERROR("Could not allocate memory for xc_hvm_inject_trap hypercall"); - return -1; - } - - arg->domid = dom; - arg->vcpuid = vcpu; - arg->vector = vector; - arg->type = type; - arg->error_code = error_code; - arg->insn_len = insn_len; - arg->cr2 = cr2; - - rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op, - HVMOP_inject_trap, - HYPERCALL_BUFFER_AS_ARG(arg)); - - xc_hypercall_buffer_free(xch, arg); - - return rc; + return do_hvmctl(xch, &hvmctl); } int xc_livepatch_upload(xc_interface *xch, --- a/tools/tests/xen-access/xen-access.c +++ b/tools/tests/xen-access/xen-access.c @@ -41,6 +41,7 @@ #include #include #include +#include #if defined(__arm__) || defined(__aarch64__) #include @@ -643,7 +644,7 @@ int main(int argc, char *argv[]) /* Reinject */ rc = xc_hvm_inject_trap( xch, domain_id, req.vcpu_id, 3, - HVMOP_TRAP_sw_exc, -1, 0, 0); + XEN_HVMCTL_TRAP_sw_exc, -1, 0, 0); if (rc < 0) { ERROR("Error %d injecting breakpoint\n", rc); --- a/xen/arch/x86/hvm/control.c +++ b/xen/arch/x86/hvm/control.c @@ -200,6 +200,32 @@ static int set_mem_type(struct domain *d return 0; } +static int inject_trap(struct domain *d, + const struct xen_hvm_inject_trap *op) +{ + struct vcpu *v; + + if ( !is_hvm_domain(d) ) + return -EINVAL; + + if ( op->rsvd8 || op->rsvd32 ) + return -EINVAL; + + if ( op->vcpuid >= d->max_vcpus || (v = d->vcpu[op->vcpuid]) == NULL ) + return -ENOENT; + + if ( v->arch.hvm_vcpu.inject_trap.vector != -1 ) + return -EBUSY; + + v->arch.hvm_vcpu.inject_trap.vector = op->vector; + v->arch.hvm_vcpu.inject_trap.type = op->type; + v->arch.hvm_vcpu.inject_trap.error_code = op->error_code; + v->arch.hvm_vcpu.inject_trap.insn_len = op->insn_len; + v->arch.hvm_vcpu.inject_trap.cr2 = op->cr2; + + return 0; +} + long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xen_hvmctl_t) u_hvmctl) { xen_hvmctl_t op; @@ -258,6 +284,10 @@ long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xe rc = set_mem_type(d, &op.u.set_mem_type, &op.opaque); break; + case XEN_HVMCTL_inject_trap: + rc = inject_trap(d, &op.u.inject_trap); + break; + default: rc = -EOPNOTSUPP; break; --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -5366,48 +5366,6 @@ long do_hvm_op(unsigned long op, XEN_GUE break; } - case HVMOP_inject_trap: - { - xen_hvm_inject_trap_t tr; - struct domain *d; - struct vcpu *v; - - if ( copy_from_guest(&tr, arg, 1 ) ) - return -EFAULT; - - rc = rcu_lock_remote_domain_by_id(tr.domid, &d); - if ( rc != 0 ) - return rc; - - rc = -EINVAL; - if ( !is_hvm_domain(d) ) - goto injtrap_fail; - - rc = xsm_hvm_control(XSM_DM_PRIV, d, op); - if ( rc ) - goto injtrap_fail; - - rc = -ENOENT; - if ( tr.vcpuid >= d->max_vcpus || (v = d->vcpu[tr.vcpuid]) == NULL ) - goto injtrap_fail; - - if ( v->arch.hvm_vcpu.inject_trap.vector != -1 ) - rc = -EBUSY; - else - { - v->arch.hvm_vcpu.inject_trap.vector = tr.vector; - v->arch.hvm_vcpu.inject_trap.type = tr.type; - v->arch.hvm_vcpu.inject_trap.error_code = tr.error_code; - v->arch.hvm_vcpu.inject_trap.insn_len = tr.insn_len; - v->arch.hvm_vcpu.inject_trap.cr2 = tr.cr2; - rc = 0; - } - - injtrap_fail: - rcu_unlock_domain(d); - break; - } - case HVMOP_guest_request_vm_event: if ( guest_handle_is_null(arg) ) vm_event_monitor_guest_request(); --- a/xen/include/public/hvm/control.h +++ b/xen/include/public/hvm/control.h @@ -89,6 +89,37 @@ struct xen_hvm_set_mem_type { uint64_aligned_t first_gfn; }; +/* XEN_HVMCTL_inject_trap */ +/* + * Inject a trap into a VCPU, which will get taken up on the next + * scheduling of it. Note that the caller should know enough of the + * state of the CPU before injecting, to know what the effect of + * injecting the trap will be. + */ +struct xen_hvm_inject_trap { + /* VCPU */ + uint32_t vcpuid; + /* Trap type (XEN_HVMCTL_TRAP_*). */ + uint8_t type; +/* NB. This enumeration precisely matches hvm.h:X86_EVENTTYPE_*. */ +#define XEN_HVMCTL_TRAP_ext_int 0 /* external interrupt */ +#define XEN_HVMCTL_TRAP_nmi 2 /* NMI */ +#define XEN_HVMCTL_TRAP_hw_exc 3 /* hardware exception */ +#define XEN_HVMCTL_TRAP_sw_int 4 /* software interrupt (CD nn) */ +#define XEN_HVMCTL_TRAP_pri_sw_exc 5 /* ICEBP (F1) */ +#define XEN_HVMCTL_TRAP_sw_exc 6 /* INT3 (CC), INTO (CE) */ + /* Vector number. */ + uint8_t vector; + /* Instruction length. */ + uint8_t insn_len; + uint8_t rsvd8; + /* Error code, or ~0u to skip. */ + uint32_t error_code; + uint32_t rsvd32; + /* CR2 for page faults. */ + uint64_aligned_t cr2; +}; + struct xen_hvmctl { uint16_t interface_version; /* XEN_HVMCTL_INTERFACE_VERSION */ domid_t domain; @@ -99,6 +130,7 @@ struct xen_hvmctl { #define XEN_HVMCTL_track_dirty_vram 4 #define XEN_HVMCTL_modified_memory 5 #define XEN_HVMCTL_set_mem_type 6 +#define XEN_HVMCTL_inject_trap 7 uint64_t opaque; /* Must be zero on initial invocation. */ union { struct xen_hvm_set_pci_intx_level set_pci_intx_level; @@ -107,6 +139,7 @@ struct xen_hvmctl { struct xen_hvm_track_dirty_vram track_dirty_vram; struct xen_hvm_modified_memory modified_memory; struct xen_hvm_set_mem_type set_mem_type; + struct xen_hvm_inject_trap inject_trap; uint8_t pad[120]; } u; }; --- a/xen/include/public/hvm/hvm_op.h +++ b/xen/include/public/hvm/hvm_op.h @@ -123,49 +123,6 @@ struct xen_hvm_xentrace { typedef struct xen_hvm_xentrace xen_hvm_xentrace_t; DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t); -/* Following tools-only interfaces may change in future. */ -#if defined(__XEN__) || defined(__XEN_TOOLS__) - -/* Deprecated by XENMEM_access_op_set_access */ -#define HVMOP_set_mem_access 12 - -/* Deprecated by XENMEM_access_op_get_access */ -#define HVMOP_get_mem_access 13 - -#define HVMOP_inject_trap 14 -/* Inject a trap into a VCPU, which will get taken up on the next - * scheduling of it. Note that the caller should know enough of the - * state of the CPU before injecting, to know what the effect of - * injecting the trap will be. - */ -struct xen_hvm_inject_trap { - /* Domain to be queried. */ - domid_t domid; - /* VCPU */ - uint32_t vcpuid; - /* Vector number */ - uint32_t vector; - /* Trap type (HVMOP_TRAP_*) */ - uint32_t type; -/* NB. This enumeration precisely matches hvm.h:X86_EVENTTYPE_* */ -# define HVMOP_TRAP_ext_int 0 /* external interrupt */ -# define HVMOP_TRAP_nmi 2 /* nmi */ -# define HVMOP_TRAP_hw_exc 3 /* hardware exception */ -# define HVMOP_TRAP_sw_int 4 /* software interrupt (CD nn) */ -# define HVMOP_TRAP_pri_sw_exc 5 /* ICEBP (F1) */ -# define HVMOP_TRAP_sw_exc 6 /* INT3 (CC), INTO (CE) */ - /* Error code, or ~0u to skip */ - uint32_t error_code; - /* Intruction length */ - uint32_t insn_len; - /* CR2 for page faults */ - uint64_aligned_t cr2; -}; -typedef struct xen_hvm_inject_trap xen_hvm_inject_trap_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t); - -#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ - #define HVMOP_get_mem_type 15 /* Return hvmmem_type_t for the specified pfn. */ struct xen_hvm_get_mem_type { --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -273,8 +273,7 @@ class hvm # XEN_HVMCTL_track_dirty_vram trackdirtyvram # XEN_HVMCTL_modified_memory, HVMOP_get_mem_type, XEN_HVMCTL_set_mem_type, -# HVMOP_set_mem_access, HVMOP_get_mem_access, HVMOP_pagetable_dying, -# HVMOP_inject_trap +# HVMOP_pagetable_dying, XEN_HVMCTL_inject_trap hvmctl # XEN_DOMCTL_mem_sharing_op and XENMEM_sharing_op_{share,add_physmap} with: # source = the domain making the hypercall