| 425 | SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_sysinit, NULL); |
| 426 | |
| 427 | static void |
| 428 | xen_hvm_cpu_init(void) |
| 429 | { |
| 430 | struct vcpu_register_vcpu_info info; |
| 431 | struct vcpu_info *vcpu_info; |
| 432 | uint32_t regs[4]; |
| 433 | int cpu, rc; |
| 434 | |
| 435 | if (!xen_domain()) |
| 436 | return; |
| 437 | |
| 438 | if (DPCPU_GET(vcpu_info) != NULL) { |
| 439 | /* |
| 440 | * vcpu_info is already set. We're resuming |
| 441 | * from a failed migration and our pre-suspend |
| 442 | * configuration is still valid. |
| 443 | */ |
| 444 | return; |
| 445 | } |
| 446 | |
| 447 | /* |
| 448 | * Set vCPU ID. If available fetch the ID from CPUID, if not just use |
| 449 | * the ACPI ID. |
| 450 | */ |
| 451 | KASSERT(cpuid_base != 0, ("Invalid base Xen CPUID leaf")); |
| 452 | cpuid_count(cpuid_base + 4, 0, regs); |
| 453 | KASSERT((regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) || |
| 454 | !xen_pv_domain(), |
| 455 | ("Xen PV domain without vcpu_id in cpuid")); |
| 456 | PCPU_SET(vcpu_id, (regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) ? |
| 457 | regs[1] : PCPU_GET(acpi_id)); |
| 458 | |
| 459 | if (xen_evtchn_needs_ack && !IS_BSP()) { |
| 460 | /* |
| 461 | * Setup the per-vpcu event channel upcall vector. This is only |
| 462 | * required when using the new HVMOP_set_evtchn_upcall_vector |
| 463 | * hypercall, which allows using a different vector for each |
| 464 | * vCPU. Note that FreeBSD uses the same vector for all vCPUs |
| 465 | * because it's not dynamically allocated. |
| 466 | */ |
| 467 | rc = set_percpu_callback(PCPU_GET(vcpu_id)); |
| 468 | if (rc != 0) |
| 469 | panic("Event channel upcall vector setup failed: %d", |
| 470 | rc); |
| 471 | } |
| 472 | |
| 473 | /* |
| 474 | * Set the vCPU info. |
| 475 | * |
| 476 | * NB: the vCPU info for vCPUs < 32 can be fetched from the shared info |
| 477 | * page, but in order to make sure the mapping code is correct always |
| 478 | * attempt to map the vCPU info at a custom place. |
| 479 | */ |
| 480 | vcpu_info = DPCPU_PTR(vcpu_local_info); |
| 481 | cpu = PCPU_GET(vcpu_id); |
| 482 | info.mfn = vtophys(vcpu_info) >> PAGE_SHIFT; |
| 483 | info.offset = vtophys(vcpu_info) - trunc_page(vtophys(vcpu_info)); |
| 484 |
no test coverage detected