* Tell the hypervisor how to contact us for event channel callbacks. */
| 247 | * Tell the hypervisor how to contact us for event channel callbacks. |
| 248 | */ |
| 249 | void |
| 250 | xen_hvm_set_callback(device_t dev) |
| 251 | { |
| 252 | struct xen_hvm_param xhp; |
| 253 | int irq; |
| 254 | |
| 255 | if (xen_vector_callback_enabled) |
| 256 | return; |
| 257 | |
| 258 | xhp.domid = DOMID_SELF; |
| 259 | xhp.index = HVM_PARAM_CALLBACK_IRQ; |
| 260 | if (xen_feature(XENFEAT_hvm_callback_vector) != 0) { |
| 261 | int error; |
| 262 | |
| 263 | error = set_percpu_callback(0); |
| 264 | if (error == 0) { |
| 265 | xen_evtchn_needs_ack = true; |
| 266 | /* Trick toolstack to think we are enlightened */ |
| 267 | xhp.value = 1; |
| 268 | } else |
| 269 | xhp.value = HVM_CALLBACK_VECTOR(IDT_EVTCHN); |
| 270 | error = HYPERVISOR_hvm_op(HVMOP_set_param, &xhp); |
| 271 | if (error == 0) { |
| 272 | xen_vector_callback_enabled = 1; |
| 273 | return; |
| 274 | } else if (xen_evtchn_needs_ack) |
| 275 | panic("Unable to setup fake HVM param: %d", error); |
| 276 | |
| 277 | printf("Xen HVM callback vector registration failed (%d). " |
| 278 | "Falling back to emulated device interrupt\n", error); |
| 279 | } |
| 280 | xen_vector_callback_enabled = 0; |
| 281 | if (dev == NULL) { |
| 282 | /* |
| 283 | * Called from early boot or resume. |
| 284 | * xenpci will invoke us again later. |
| 285 | */ |
| 286 | return; |
| 287 | } |
| 288 | |
| 289 | irq = pci_get_irq(dev); |
| 290 | if (irq < 16) { |
| 291 | xhp.value = HVM_CALLBACK_GSI(irq); |
| 292 | } else { |
| 293 | u_int slot; |
| 294 | u_int pin; |
| 295 | |
| 296 | slot = pci_get_slot(dev); |
| 297 | pin = pci_get_intpin(dev) - 1; |
| 298 | xhp.value = HVM_CALLBACK_PCI_INTX(slot, pin); |
| 299 | } |
| 300 | |
| 301 | if (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp) != 0) |
| 302 | panic("Can't set evtchn callback"); |
| 303 | } |
| 304 | |
| 305 | #define XEN_MAGIC_IOPORT 0x10 |
| 306 | enum { |
no test coverage detected