drivers/hv/mshv_irq.c

Source file repositories/reference/linux-study-clean/drivers/hv/mshv_irq.c

File Facts

System
Linux kernel
Corpus path
drivers/hv/mshv_irq.c
Extension
.c
Size
3305 bytes
Lines
133
Domain
Driver Families
Bucket
drivers/hv
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (girq->guest_irq_num != 0) {
			r = -EINVAL;
			goto out;
		}

		girq->guest_irq_num = ue[i].gsi;
		girq->girq_addr_lo = ue[i].address_lo;
		girq->girq_addr_hi = ue[i].address_hi;
		girq->girq_irq_data = ue[i].data;
		girq->girq_entry_valid = true;
	}

swap_routes:
	mutex_lock(&partition->pt_irq_lock);
	old = rcu_dereference_protected(partition->pt_girq_tbl, 1);
	rcu_assign_pointer(partition->pt_girq_tbl, new);
	mshv_irqfd_routing_update(partition);
	mutex_unlock(&partition->pt_irq_lock);

	synchronize_srcu_expedited(&partition->pt_irq_srcu);

	trace_mshv_update_routing_table(partition->pt_id,
					old, new, numents);

	new = old;

out:
	kfree(new);

	return r;
}

/* vm is going away, kfree the irq routing table */
void mshv_free_routing_table(struct mshv_partition *partition)
{
	struct mshv_girq_routing_table *rt =
				   rcu_access_pointer(partition->pt_girq_tbl);

	kfree(rt);
}

struct mshv_guest_irq_ent
mshv_ret_girq_entry(struct mshv_partition *partition, u32 irqnum)
{
	struct mshv_guest_irq_ent entry = { 0 };
	struct mshv_girq_routing_table *girq_tbl;

	girq_tbl = srcu_dereference_check(partition->pt_girq_tbl,
					  &partition->pt_irq_srcu,
					  lockdep_is_held(&partition->pt_irq_lock));
	if (!girq_tbl || irqnum >= girq_tbl->num_rt_entries) {
		/*
		 * Premature register_irqfd, setting valid_entry = 0
		 * would ignore this entry anyway
		 */
		entry.guest_irq_num = irqnum;
		return entry;
	}

	return girq_tbl->mshv_girq_info_tbl[irqnum];
}

void mshv_copy_girq_info(struct mshv_guest_irq_ent *ent,
			 struct mshv_lapic_irq *lirq)
{
	memset(lirq, 0, sizeof(*lirq));
	if (!ent || !ent->girq_entry_valid)
		return;

	lirq->lapic_vector = ent->girq_irq_data & 0xFF;
	lirq->lapic_apic_id = (ent->girq_addr_lo >> 12) & 0xFF;
	lirq->lapic_control.interrupt_type = (ent->girq_irq_data & 0x700) >> 8;
#if IS_ENABLED(CONFIG_X86)
	lirq->lapic_control.level_triggered = (ent->girq_irq_data >> 15) & 0x1;
	lirq->lapic_control.logical_dest_mode = (ent->girq_addr_lo >> 2) & 0x1;
#elif IS_ENABLED(CONFIG_ARM64)
	lirq->lapic_control.asserted = 1;
#endif
}

Annotation

Implementation Notes