| 2543 | } |
| 2544 | |
| 2545 | int |
| 2546 | vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest, |
| 2547 | vm_rendezvous_func_t func, void *arg) |
| 2548 | { |
| 2549 | int error, i; |
| 2550 | |
| 2551 | /* |
| 2552 | * Enforce that this function is called without any locks |
| 2553 | */ |
| 2554 | WITNESS_WARN(WARN_PANIC, NULL, "vm_smp_rendezvous"); |
| 2555 | KASSERT(vcpuid == -1 || (vcpuid >= 0 && vcpuid < vm->maxcpus), |
| 2556 | ("vm_smp_rendezvous: invalid vcpuid %d", vcpuid)); |
| 2557 | |
| 2558 | restart: |
| 2559 | mtx_lock(&vm->rendezvous_mtx); |
| 2560 | if (vm->rendezvous_func != NULL) { |
| 2561 | /* |
| 2562 | * If a rendezvous is already in progress then we need to |
| 2563 | * call the rendezvous handler in case this 'vcpuid' is one |
| 2564 | * of the targets of the rendezvous. |
| 2565 | */ |
| 2566 | RENDEZVOUS_CTR0(vm, vcpuid, "Rendezvous already in progress"); |
| 2567 | mtx_unlock(&vm->rendezvous_mtx); |
| 2568 | error = vm_handle_rendezvous(vm, vcpuid); |
| 2569 | if (error != 0) |
| 2570 | return (error); |
| 2571 | goto restart; |
| 2572 | } |
| 2573 | KASSERT(vm->rendezvous_func == NULL, ("vm_smp_rendezvous: previous " |
| 2574 | "rendezvous is still in progress")); |
| 2575 | |
| 2576 | RENDEZVOUS_CTR0(vm, vcpuid, "Initiating rendezvous"); |
| 2577 | vm->rendezvous_req_cpus = dest; |
| 2578 | CPU_ZERO(&vm->rendezvous_done_cpus); |
| 2579 | vm->rendezvous_arg = arg; |
| 2580 | vm->rendezvous_func = func; |
| 2581 | mtx_unlock(&vm->rendezvous_mtx); |
| 2582 | |
| 2583 | /* |
| 2584 | * Wake up any sleeping vcpus and trigger a VM-exit in any running |
| 2585 | * vcpus so they handle the rendezvous as soon as possible. |
| 2586 | */ |
| 2587 | for (i = 0; i < vm->maxcpus; i++) { |
| 2588 | if (CPU_ISSET(i, &dest)) |
| 2589 | vcpu_notify_event(vm, i, false); |
| 2590 | } |
| 2591 | |
| 2592 | return (vm_handle_rendezvous(vm, vcpuid)); |
| 2593 | } |
| 2594 | |
| 2595 | struct vatpic * |
| 2596 | vm_atpic(struct vm *vm) |
no test coverage detected