Exemple #1
0
static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
			struct kvm *kvm, int level)
{
	int vcpu_id;
	struct kvm_vcpu *vcpu;
	struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
	int dest_id = (e->msi.address_lo & MSI_ADDR_DEST_ID_MASK)
			>> MSI_ADDR_DEST_ID_SHIFT;
	int vector = (e->msi.data & MSI_DATA_VECTOR_MASK)
			>> MSI_DATA_VECTOR_SHIFT;
	int dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
				(unsigned long *)&e->msi.address_lo);
	int trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
				(unsigned long *)&e->msi.data);
	int delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
				(unsigned long *)&e->msi.data);
	u32 deliver_bitmask;

	BUG_ON(!ioapic);

	deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic,
				dest_id, dest_mode);
	/* IOAPIC delivery mode value is the same as MSI here */
	switch (delivery_mode) {
	case IOAPIC_LOWEST_PRIORITY:
		vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
				deliver_bitmask);
		if (vcpu != NULL)
			kvm_apic_set_irq(vcpu, vector, trig_mode);
		else
			printk(KERN_INFO "kvm: null lowest priority vcpu!\n");
		break;
	case IOAPIC_FIXED:
		for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
			if (!(deliver_bitmask & (1 << vcpu_id)))
				continue;
			deliver_bitmask &= ~(1 << vcpu_id);
			vcpu = ioapic->kvm->vcpus[vcpu_id];
			if (vcpu)
				kvm_apic_set_irq(vcpu, vector, trig_mode);
		}
		break;
	default:
		break;
	}
}
Exemple #2
0
static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
{
	u8 dest = ioapic->redirtbl[irq].fields.dest_id;
	u8 dest_mode = ioapic->redirtbl[irq].fields.dest_mode;
	u8 delivery_mode = ioapic->redirtbl[irq].fields.delivery_mode;
	u8 vector = ioapic->redirtbl[irq].fields.vector;
	u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
	u32 deliver_bitmask;
	struct kvm_vcpu *vcpu;
	int vcpu_id;

	ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
		     "vector=%x trig_mode=%x\n",
		     dest, dest_mode, delivery_mode, vector, trig_mode);

	deliver_bitmask = ioapic_get_delivery_bitmask(ioapic, dest, dest_mode);
	if (!deliver_bitmask) {
		ioapic_debug("no target on destination\n");
		return;
	}

	switch (delivery_mode) {
	case IOAPIC_LOWEST_PRIORITY:
		vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
				deliver_bitmask);
#ifdef CONFIG_X86
		if (irq == 0)
			vcpu = ioapic->kvm->vcpus[0];
#endif
		if (vcpu != NULL)
			ioapic_inj_irq(ioapic, vcpu, vector,
				       trig_mode, delivery_mode);
		else
			ioapic_debug("null lowest prio vcpu: "
				     "mask=%x vector=%x delivery_mode=%x\n",
				     deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY);
		break;
	case IOAPIC_FIXED:
#ifdef CONFIG_X86
		if (irq == 0)
			deliver_bitmask = 1;
#endif
		for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
			if (!(deliver_bitmask & (1 << vcpu_id)))
				continue;
			deliver_bitmask &= ~(1 << vcpu_id);
			vcpu = ioapic->kvm->vcpus[vcpu_id];
			if (vcpu) {
				ioapic_inj_irq(ioapic, vcpu, vector,
					       trig_mode, delivery_mode);
			}
		}
		break;

		/* TODO: NMI */
	default:
		printk(KERN_WARNING "Unsupported delivery mode %d\n",
		       delivery_mode);
		break;
	}
}