Note that this retains the hvmop interface definitions as those had (wrongly) been exposed to non-tool stack consumers (albeit the operation wouldn't have succeeded when requested by a domain for itself). 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 @@ -488,27 +488,11 @@ int xc_hvm_set_isa_irq_level( uint8_t isa_irq, unsigned int level) { - DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_isa_irq_level, arg); - int rc; + DECLARE_HVMCTL(set_isa_irq_level, dom, + .isa_irq = isa_irq, + .level = level); - arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg)); - if ( arg == NULL ) - { - PERROR("Could not allocate memory for xc_hvm_set_isa_irq_level hypercall"); - return -1; - } - - arg->domid = dom; - arg->isa_irq = isa_irq; - arg->level = level; - - rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op, - HVMOP_set_isa_irq_level, - HYPERCALL_BUFFER_AS_ARG(arg)); - - xc_hypercall_buffer_free(xch, arg); - - return rc; + return do_hvmctl(xch, &hvmctl); } int xc_hvm_set_pci_link_route( --- a/xen/arch/x86/hvm/control.c +++ b/xen/arch/x86/hvm/control.c @@ -43,6 +43,30 @@ static int set_pci_intx_level(struct dom return 0; } +static int set_isa_irq_level(struct domain *d, + const struct xen_hvm_set_isa_irq_level *op) +{ + if ( op->isa_irq > 15 ) + return -EINVAL; + + if ( !is_hvm_domain(d) ) + return -EINVAL; + + switch ( op->level ) + { + case 0: + hvm_isa_irq_deassert(d, op->isa_irq); + break; + case 1: + hvm_isa_irq_assert(d, op->isa_irq); + break; + default: + return -EINVAL; + } + + return 0; +} + long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xen_hvmctl_t) u_hvmctl) { xen_hvmctl_t op; @@ -80,6 +104,10 @@ long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xe rc = set_pci_intx_level(d, &op.u.set_pci_intx_level); break; + case XEN_HVMCTL_set_isa_irq_level: + rc = set_isa_irq_level(d, &op.u.set_isa_irq_level); + break; + default: rc = -EOPNOTSUPP; break; --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -4446,50 +4446,6 @@ static void hvm_s3_resume(struct domain } } -static int hvmop_set_isa_irq_level( - XEN_GUEST_HANDLE_PARAM(xen_hvm_set_isa_irq_level_t) uop) -{ - struct xen_hvm_set_isa_irq_level op; - struct domain *d; - int rc; - - if ( copy_from_guest(&op, uop, 1) ) - return -EFAULT; - - if ( op.isa_irq > 15 ) - return -EINVAL; - - rc = rcu_lock_remote_domain_by_id(op.domid, &d); - if ( rc != 0 ) - return rc; - - rc = -EINVAL; - if ( !is_hvm_domain(d) ) - goto out; - - rc = xsm_hvm_set_isa_irq_level(XSM_DM_PRIV, d); - if ( rc ) - goto out; - - rc = 0; - switch ( op.level ) - { - case 0: - hvm_isa_irq_deassert(d, op.isa_irq); - break; - case 1: - hvm_isa_irq_assert(d, op.isa_irq); - break; - default: - rc = -EINVAL; - break; - } - - out: - rcu_unlock_domain(d); - return rc; -} - static int hvmop_set_pci_link_route( XEN_GUEST_HANDLE_PARAM(xen_hvm_set_pci_link_route_t) uop) { @@ -5364,11 +5320,6 @@ long do_hvm_op(unsigned long op, XEN_GUE guest_handle_cast(arg, xen_hvm_param_t)); break; - case HVMOP_set_isa_irq_level: - rc = hvmop_set_isa_irq_level( - guest_handle_cast(arg, xen_hvm_set_isa_irq_level_t)); - break; - case HVMOP_inject_msi: rc = hvmop_inject_msi( guest_handle_cast(arg, xen_hvm_inject_msi_t)); --- a/xen/include/public/hvm/control.h +++ b/xen/include/public/hvm/control.h @@ -38,14 +38,25 @@ struct xen_hvm_set_pci_intx_level { uint8_t level; }; +/* XEN_HVMCTL_set_isa_irq_level */ +/* Set the logical level of one of a domain's ISA IRQ wires. */ +struct xen_hvm_set_isa_irq_level { + /* ISA device identification, by ISA IRQ (0-15). */ + uint8_t isa_irq; + /* Assertion level (0 = unasserted, 1 = asserted). */ + uint8_t level; +}; + struct xen_hvmctl { uint16_t interface_version; /* XEN_HVMCTL_INTERFACE_VERSION */ domid_t domain; uint32_t cmd; #define XEN_HVMCTL_set_pci_intx_level 1 +#define XEN_HVMCTL_set_isa_irq_level 2 uint64_t opaque; /* Must be zero on initial invocation. */ union { struct xen_hvm_set_pci_intx_level set_pci_intx_level; + struct xen_hvm_set_isa_irq_level set_isa_irq_level; uint8_t pad[120]; } u; }; --- a/xen/include/public/hvm/hvm_op.h +++ b/xen/include/public/hvm/hvm_op.h @@ -53,8 +53,6 @@ struct xen_hvm_set_pci_intx_level { typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t; DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t); -#endif - /* Set the logical level of one of a domain's ISA IRQ wires. */ #define HVMOP_set_isa_irq_level 3 struct xen_hvm_set_isa_irq_level { @@ -68,6 +66,8 @@ struct xen_hvm_set_isa_irq_level { typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t; DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t); +#endif + #define HVMOP_set_pci_link_route 4 struct xen_hvm_set_pci_link_route { /* Domain to be updated. */ --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -609,12 +609,6 @@ static XSM_INLINE int xsm_shadow_control return xsm_default_action(action, current->domain, d); } -static XSM_INLINE int xsm_hvm_set_isa_irq_level(XSM_DEFAULT_ARG struct domain *d) -{ - XSM_ASSERT_ACTION(XSM_DM_PRIV); - return xsm_default_action(action, current->domain, d); -} - static XSM_INLINE int xsm_hvm_set_pci_link_route(XSM_DEFAULT_ARG struct domain *d) { XSM_ASSERT_ACTION(XSM_DM_PRIV); --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -173,7 +173,6 @@ struct xsm_operations { #ifdef CONFIG_X86 int (*do_mca) (void); int (*shadow_control) (struct domain *d, uint32_t op); - int (*hvm_set_isa_irq_level) (struct domain *d); int (*hvm_set_pci_link_route) (struct domain *d); int (*hvm_inject_msi) (struct domain *d); int (*hvm_ioreq_server) (struct domain *d, int op); @@ -645,11 +644,6 @@ static inline int xsm_shadow_control (xs return xsm_ops->shadow_control(d, op); } -static inline int xsm_hvm_set_isa_irq_level (xsm_default_t def, struct domain *d) -{ - return xsm_ops->hvm_set_isa_irq_level(d); -} - static inline int xsm_hvm_set_pci_link_route (xsm_default_t def, struct domain *d) { return xsm_ops->hvm_set_pci_link_route(d); --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -145,7 +145,6 @@ void xsm_fixup_ops (struct xsm_operation #ifdef CONFIG_X86 set_to_dummy_if_null(ops, do_mca); set_to_dummy_if_null(ops, shadow_control); - set_to_dummy_if_null(ops, hvm_set_isa_irq_level); set_to_dummy_if_null(ops, hvm_set_pci_link_route); set_to_dummy_if_null(ops, hvm_inject_msi); set_to_dummy_if_null(ops, hvm_ioreq_server); --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -1193,6 +1193,9 @@ static int flask_hvm_control(struct doma case XEN_HVMCTL_set_pci_intx_level: perm = HVM__PCILEVEL; break; + case XEN_HVMCTL_set_isa_irq_level: + perm = HVM__IRQLEVEL; + break; default: perm = HVM__HVMCTL; break; @@ -1517,11 +1520,6 @@ static int flask_ioport_mapping(struct d return flask_ioport_permission(d, start, end, access); } -static int flask_hvm_set_isa_irq_level(struct domain *d) -{ - return current_has_perm(d, SECCLASS_HVM, HVM__IRQLEVEL); -} - static int flask_hvm_set_pci_link_route(struct domain *d) { return current_has_perm(d, SECCLASS_HVM, HVM__PCIROUTE); @@ -1805,7 +1803,6 @@ static struct xsm_operations flask_ops = #ifdef CONFIG_X86 .do_mca = flask_do_mca, .shadow_control = flask_shadow_control, - .hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level, .hvm_set_pci_link_route = flask_hvm_set_pci_link_route, .hvm_inject_msi = flask_hvm_inject_msi, .hvm_ioreq_server = flask_hvm_ioreq_server, --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -263,7 +263,7 @@ class hvm getparam # XEN_HVMCTL_set_pci_intx_level pcilevel -# HVMOP_set_isa_irq_level +# XEN_HVMCTL_set_isa_irq_level irqlevel # HVMOP_set_pci_link_route pciroute