events.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
  4. * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
  5. * (C) 2020 - EPAM Systems Inc.
  6. *
  7. * File: events.c [1]
  8. * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
  9. * Changes: Grzegorz Milos (gm281@cam.ac.uk)
  10. *
  11. * Date: Jul 2003, changes Jun 2005
  12. *
  13. * Description: Deals with events received on event channels
  14. *
  15. * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary
  16. */
  17. #include <common.h>
  18. #include <log.h>
  19. #include <asm/io.h>
  20. #include <asm/xen/system.h>
  21. #include <xen/events.h>
  22. #include <xen/hvm.h>
  23. extern u32 console_evtchn;
  24. #define NR_EVS 1024
  25. /**
  26. * struct _ev_action - represents a event handler.
  27. *
  28. * Chaining or sharing is not allowed
  29. */
  30. struct _ev_action {
  31. void (*handler)(evtchn_port_t port, struct pt_regs *regs, void *data);
  32. void *data;
  33. u32 count;
  34. };
  35. static struct _ev_action ev_actions[NR_EVS];
  36. void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
  37. static unsigned long bound_ports[NR_EVS / (8 * sizeof(unsigned long))];
  38. void unbind_all_ports(void)
  39. {
  40. int i;
  41. int cpu = 0;
  42. struct shared_info *s = HYPERVISOR_shared_info;
  43. struct vcpu_info *vcpu_info = &s->vcpu_info[cpu];
  44. for (i = 0; i < NR_EVS; i++) {
  45. if (i == console_evtchn)
  46. continue;
  47. if (test_and_clear_bit(i, bound_ports)) {
  48. printf("port %d still bound!\n", i);
  49. unbind_evtchn(i);
  50. }
  51. }
  52. vcpu_info->evtchn_upcall_pending = 0;
  53. vcpu_info->evtchn_pending_sel = 0;
  54. }
  55. int do_event(evtchn_port_t port, struct pt_regs *regs)
  56. {
  57. struct _ev_action *action;
  58. clear_evtchn(port);
  59. if (port >= NR_EVS) {
  60. printk("WARN: do_event(): Port number too large: %d\n", port);
  61. return 1;
  62. }
  63. action = &ev_actions[port];
  64. action->count++;
  65. /* call the handler */
  66. action->handler(port, regs, action->data);
  67. return 1;
  68. }
  69. evtchn_port_t bind_evtchn(evtchn_port_t port,
  70. void (*handler)(evtchn_port_t, struct pt_regs *, void *),
  71. void *data)
  72. {
  73. if (ev_actions[port].handler != default_handler)
  74. printf("WARN: Handler for port %d already registered, replacing\n",
  75. port);
  76. ev_actions[port].data = data;
  77. wmb();
  78. ev_actions[port].handler = handler;
  79. synch_set_bit(port, bound_ports);
  80. return port;
  81. }
  82. /**
  83. * unbind_evtchn() - Unbind event channel for selected port
  84. */
  85. void unbind_evtchn(evtchn_port_t port)
  86. {
  87. struct evtchn_close close;
  88. int rc;
  89. if (ev_actions[port].handler == default_handler)
  90. debug("Default handler for port %d when unbinding\n", port);
  91. mask_evtchn(port);
  92. clear_evtchn(port);
  93. ev_actions[port].handler = default_handler;
  94. wmb();
  95. ev_actions[port].data = NULL;
  96. synch_clear_bit(port, bound_ports);
  97. close.port = port;
  98. rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
  99. if (rc)
  100. printf("WARN: close_port %d failed rc=%d. ignored\n", port, rc);
  101. }
  102. void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
  103. {
  104. debug("[Port %d] - event received\n", port);
  105. }
  106. /**
  107. * evtchn_alloc_unbound() - Create a port available to the pal for
  108. * exchanging notifications.
  109. *
  110. * Unfortunate confusion of terminology: the port is unbound as far
  111. * as Xen is concerned, but we automatically bind a handler to it.
  112. *
  113. * Return: The result of the hypervisor call.
  114. */
  115. int evtchn_alloc_unbound(domid_t pal,
  116. void (*handler)(evtchn_port_t, struct pt_regs *, void *),
  117. void *data, evtchn_port_t *port)
  118. {
  119. int rc;
  120. struct evtchn_alloc_unbound op;
  121. op.dom = DOMID_SELF;
  122. op.remote_dom = pal;
  123. rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
  124. if (rc) {
  125. printf("ERROR: alloc_unbound failed with rc=%d", rc);
  126. return rc;
  127. }
  128. if (!handler)
  129. handler = default_handler;
  130. *port = bind_evtchn(op.port, handler, data);
  131. return rc;
  132. }
  133. /**
  134. * eventchn_poll() - Event channel polling function
  135. *
  136. * Check and process any pending events
  137. */
  138. void eventchn_poll(void)
  139. {
  140. do_hypervisor_callback(NULL);
  141. }
  142. /**
  143. * init_events() - Initialize event handler
  144. *
  145. * Initially all events are without a handler and disabled.
  146. */
  147. void init_events(void)
  148. {
  149. int i;
  150. debug("%s\n", __func__);
  151. for (i = 0; i < NR_EVS; i++) {
  152. ev_actions[i].handler = default_handler;
  153. mask_evtchn(i);
  154. }
  155. }
  156. /**
  157. * fini_events() - Close all ports
  158. *
  159. * Mask and clear event channels. Close port using EVTCHNOP_close
  160. * hypercall.
  161. */
  162. void fini_events(void)
  163. {
  164. debug("%s\n", __func__);
  165. /* Dealloc all events */
  166. unbind_all_ports();
  167. }