Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xen/evtchn: Introduce new IOCTL to bind static evtchn

Xen 4.17 supports the creation of static evtchns. To allow user space
application to bind static evtchns introduce new ioctl
"IOCTL_EVTCHN_BIND_STATIC". Existing IOCTL doing more than binding
that’s why we need to introduce the new IOCTL to only bind the static
event channels.

Static evtchns to be available for use during the lifetime of the
guest. When the application exits, __unbind_from_irq() ends up being
called from release() file operations because of that static evtchns
are getting closed. To avoid closing the static event channel, add the
new bool variable "is_static" in "struct irq_info" to mark the event
channel static when creating the event channel to avoid closing the
static evtchn.

Also, take this opportunity to remove the open-coded version of the
evtchn close in drivers/xen/evtchn.c file and use xen_evtchn_close().

Signed-off-by: Rahul Singh <rahul.singh@arm.com>
Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
Link: https://lore.kernel.org/r/ae7329bf1713f83e4aad4f3fa0f316258c40a3e9.1689677042.git.rahul.singh@arm.com
Signed-off-by: Juergen Gross <jgross@suse.com>

authored by

Rahul Singh and committed by
Juergen Gross
58f6259b 0d8f7cc8

+50 -21
+5 -11
drivers/xen/events/events_base.c
··· 112 112 unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */ 113 113 u64 eoi_time; /* Time in jiffies when to EOI. */ 114 114 raw_spinlock_t lock; 115 + bool is_static; /* Is event channel static */ 115 116 116 117 union { 117 118 unsigned short virq; ··· 816 815 irq_free_desc(irq); 817 816 } 818 817 819 - static void xen_evtchn_close(evtchn_port_t port) 820 - { 821 - struct evtchn_close close; 822 - 823 - close.port = port; 824 - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) 825 - BUG(); 826 - } 827 - 828 818 /* Not called for lateeoi events. */ 829 819 static void event_handler_exit(struct irq_info *info) 830 820 { ··· 974 982 unsigned int cpu = cpu_from_irq(irq); 975 983 struct xenbus_device *dev; 976 984 977 - xen_evtchn_close(evtchn); 985 + if (!info->is_static) 986 + xen_evtchn_close(evtchn); 978 987 979 988 switch (type_from_irq(irq)) { 980 989 case IRQT_VIRQ: ··· 1567 1574 } 1568 1575 EXPORT_SYMBOL_GPL(xen_set_irq_priority); 1569 1576 1570 - int evtchn_make_refcounted(evtchn_port_t evtchn) 1577 + int evtchn_make_refcounted(evtchn_port_t evtchn, bool is_static) 1571 1578 { 1572 1579 int irq = get_evtchn_to_irq(evtchn); 1573 1580 struct irq_info *info; ··· 1583 1590 WARN_ON(info->refcnt != -1); 1584 1591 1585 1592 info->refcnt = 1; 1593 + info->is_static = is_static; 1586 1594 1587 1595 return 0; 1588 1596 }
+26 -9
drivers/xen/evtchn.c
··· 366 366 return 0; 367 367 } 368 368 369 - static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port) 369 + static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port, 370 + bool is_static) 370 371 { 371 372 struct user_evtchn *evtchn; 372 - struct evtchn_close close; 373 373 int rc = 0; 374 374 375 375 /* ··· 402 402 if (rc < 0) 403 403 goto err; 404 404 405 - rc = evtchn_make_refcounted(port); 405 + rc = evtchn_make_refcounted(port, is_static); 406 406 return rc; 407 407 408 408 err: 409 409 /* bind failed, should close the port now */ 410 - close.port = port; 411 - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) 412 - BUG(); 410 + if (!is_static) 411 + xen_evtchn_close(port); 412 + 413 413 del_evtchn(u, evtchn); 414 414 return rc; 415 415 } ··· 456 456 if (rc != 0) 457 457 break; 458 458 459 - rc = evtchn_bind_to_user(u, bind_virq.port); 459 + rc = evtchn_bind_to_user(u, bind_virq.port, false); 460 460 if (rc == 0) 461 461 rc = bind_virq.port; 462 462 break; ··· 482 482 if (rc != 0) 483 483 break; 484 484 485 - rc = evtchn_bind_to_user(u, bind_interdomain.local_port); 485 + rc = evtchn_bind_to_user(u, bind_interdomain.local_port, false); 486 486 if (rc == 0) 487 487 rc = bind_interdomain.local_port; 488 488 break; ··· 507 507 if (rc != 0) 508 508 break; 509 509 510 - rc = evtchn_bind_to_user(u, alloc_unbound.port); 510 + rc = evtchn_bind_to_user(u, alloc_unbound.port, false); 511 511 if (rc == 0) 512 512 rc = alloc_unbound.port; 513 513 break; ··· 533 533 disable_irq(irq_from_evtchn(unbind.port)); 534 534 evtchn_unbind_from_user(u, evtchn); 535 535 rc = 0; 536 + break; 537 + } 538 + 539 + case IOCTL_EVTCHN_BIND_STATIC: { 540 + struct ioctl_evtchn_bind bind; 541 + struct user_evtchn *evtchn; 542 + 543 + rc = -EFAULT; 544 + if (copy_from_user(&bind, uarg, sizeof(bind))) 545 + break; 546 + 547 + rc = -EISCONN; 548 + evtchn = find_evtchn(u, bind.port); 549 + if (evtchn) 550 + break; 551 + 552 + rc = evtchn_bind_to_user(u, bind.port, true); 536 553 break; 537 554 } 538 555
+9
include/uapi/xen/evtchn.h
··· 101 101 domid_t domid; 102 102 }; 103 103 104 + /* 105 + * Bind statically allocated @port. 106 + */ 107 + #define IOCTL_EVTCHN_BIND_STATIC \ 108 + _IOC(_IOC_NONE, 'E', 7, sizeof(struct ioctl_evtchn_bind)) 109 + struct ioctl_evtchn_bind { 110 + unsigned int port; 111 + }; 112 + 104 113 #endif /* __LINUX_PUBLIC_EVTCHN_H__ */
+10 -1
include/xen/events.h
··· 69 69 /* 70 70 * Allow extra references to event channels exposed to userspace by evtchn 71 71 */ 72 - int evtchn_make_refcounted(evtchn_port_t evtchn); 72 + int evtchn_make_refcounted(evtchn_port_t evtchn, bool is_static); 73 73 int evtchn_get(evtchn_port_t evtchn); 74 74 void evtchn_put(evtchn_port_t evtchn); 75 75 ··· 140 140 void xen_init_IRQ(void); 141 141 142 142 irqreturn_t xen_debug_interrupt(int irq, void *dev_id); 143 + 144 + static inline void xen_evtchn_close(evtchn_port_t port) 145 + { 146 + struct evtchn_close close; 147 + 148 + close.port = port; 149 + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) 150 + BUG(); 151 + } 143 152 144 153 #endif /* _XEN_EVENTS_H */