// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2023, Microsoft Corporation. * * mshv_root module's main interrupt handler and associated functionality. * * Authors: Microsoft Linux virtualization team
*/
if (unlikely(!*synic_eventring_tail)) {
pr_debug("Missing synic event ring tail!\n"); return 0;
}
tail = (*synic_eventring_tail)[sint_index];
if (unlikely(!*event_ring_page)) {
pr_debug("Missing synic event ring page!\n"); return 0;
}
ring = &(*event_ring_page)->sint_event_ring[sint_index];
/* * Get the message.
*/
message = ring->data[tail];
if (!message) { if (ring->ring_full) { /* * Ring is marked full, but we would have consumed all * the messages. Notify the hypervisor that ring is now * empty and check again.
*/
ring->ring_full = 0;
hv_call_notify_port_ring_empty(sint_index);
message = ring->data[tail];
}
if (!message) {
ring->signal_masked = 0; /* * Unmask the signal and sync with hypervisor * before one last check for any message.
*/
mb();
message = ring->data[tail];
/* * Hold this lock for the rest of the isr, because the partition could * be released anytime. * e.g. the MSHV_RUN_VP thread could wake on another cpu; it could * release the partition unless we hold this!
*/
rcu_read_lock();
partition = mshv_partition_find(partition_id);
if (unlikely(!partition)) {
pr_debug("failed to find partition %llu\n", partition_id); goto unlock_out;
}
/* This shouldn't happen, but just in case. */ if (unlikely(vp_index >= MSHV_MAX_VPS)) {
pr_debug("VP index %u out of bounds\n",
vp_index); goto unlock_out;
}
vp = partition->pt_vp_array[vp_index]; if (unlikely(!vp)) {
pr_debug("failed to find VP %u\n", vp_index); goto unlock_out;
}
kick_vp(vp);
vps_signaled++;
}
bank_contents++;
}
unlock_out:
rcu_read_unlock();
if (vps_signaled != msg->vp_count)
pr_debug("asked to signal %u VPs but only did %u\n",
msg->vp_count, vps_signaled);
}
partition = mshv_partition_find(partition_id); if (unlikely(!partition)) {
pr_debug("failed to find partition %llu\n",
partition_id); goto unlock_out;
}
if (msg->header.message_type == HVMSG_X64_APIC_EOI) { /* * Check if this gsi is registered in the * ack_notifier list and invoke the callback * if registered.
*/
/* * If there is a notifier, the ack callback is supposed * to handle the VMEXIT. So we need not pass this message * to vcpu thread.
*/ struct hv_x64_apic_eoi_message *eoi_msg =
(struct hv_x64_apic_eoi_message *)&msg->u.payload[0];
/* * We should get an opaque intercept message here for all intercept * messages, since we're using the mapped VP intercept message page. * * The intercept message will have been placed in intercept message * page at this point. * * Make sure the message type matches our expectation.
*/ if (msg->header.message_type != HVMSG_OPAQUE_INTERCEPT) {
pr_debug("wrong message type %d", msg->header.message_type); goto unlock_out;
}
/* * Since we directly index the vp, and it has to exist for us to be here * (because the vp is only deleted when the partition is), no additional * locking is needed here
*/
vp_index =
((struct hv_opaque_intercept_message *)msg->u.payload)->vp_index;
vp = partition->pt_vp_array[vp_index]; if (unlikely(!vp)) {
pr_debug("failed to find VP %u\n", vp_index); goto unlock_out;
}
/* * If the type isn't set, there isn't really a message; * it may be some other hyperv interrupt
*/ if (msg->header.message_type == HVMSG_NONE) return;
handled = mshv_doorbell_isr(msg);
if (!handled)
handled = mshv_scheduler_isr(msg);
if (!handled)
handled = mshv_async_call_completion_isr(msg);
if (!handled)
handled = mshv_intercept_isr(msg);
if (handled) { /* * Acknowledge message with hypervisor if another message is * pending.
*/
msg->header.message_type = HVMSG_NONE; /* * Ensure the write is complete so the hypervisor will deliver * the next message if available.
*/
mb(); if (msg->header.message_flags.msg_pending)
hv_set_non_nested_msr(HV_MSR_EOM, 0);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.