コード例 #1
0
ファイル: book3s_xics.c プロジェクト: 0-T-0/ps4-linux
/*
 * Return value ideally indicates how the interrupt was handled, but no
 * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
 * so just return 0.
 */
static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
{
	struct ics_irq_state *state;
	struct kvmppc_ics *ics;
	u16 src;

	XICS_DBG("ics deliver %#x (level: %d)\n", irq, level);

	ics = kvmppc_xics_find_ics(xics, irq, &src);
	if (!ics) {
		XICS_DBG("ics_deliver_irq: IRQ 0x%06x not found !\n", irq);
		return -EINVAL;
	}
	state = &ics->irq_state[src];
	if (!state->exists)
		return -EINVAL;

	/*
	 * We set state->asserted locklessly. This should be fine as
	 * we are the only setter, thus concurrent access is undefined
	 * to begin with.
	 */
	if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL)
		state->asserted = 1;
	else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
		state->asserted = 0;
		return 0;
	}

	/* Attempt delivery */
	icp_deliver_irq(xics, NULL, irq);

	return 0;
}
コード例 #2
0
/*
 * Return value ideally indicates how the interrupt was handled, but no
 * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
 * so just return 0.
 */
static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
{
	struct ics_irq_state *state;
	struct kvmppc_ics *ics;
	u16 src;
	u32 pq_old, pq_new;

	XICS_DBG("ics deliver %#x (level: %d)\n", irq, level);

	ics = kvmppc_xics_find_ics(xics, irq, &src);
	if (!ics) {
		XICS_DBG("ics_deliver_irq: IRQ 0x%06x not found !\n", irq);
		return -EINVAL;
	}
	state = &ics->irq_state[src];
	if (!state->exists)
		return -EINVAL;

	if (level == KVM_INTERRUPT_SET_LEVEL || level == KVM_INTERRUPT_SET)
		level = 1;
	else if (level == KVM_INTERRUPT_UNSET)
		level = 0;
	/*
	 * Take other values the same as 1, consistent with original code.
	 * maybe WARN here?
	 */

	if (!state->lsi && level == 0) /* noop for MSI */
		return 0;

	do {
		pq_old = state->pq_state;
		if (state->lsi) {
			if (level) {
				if (pq_old & PQ_PRESENTED)
					/* Setting already set LSI ... */
					return 0;

				pq_new = PQ_PRESENTED;
			} else
				pq_new = 0;
		} else
			pq_new = ((pq_old << 1) & 3) | PQ_PRESENTED;
	} while (cmpxchg(&state->pq_state, pq_old, pq_new) != pq_old);

	/* Test P=1, Q=0, this is the only case where we present */
	if (pq_new == PQ_PRESENTED)
		icp_deliver_irq(xics, NULL, irq, false);

	/* Record which CPU this arrived on for passed-through interrupts */
	if (state->host_irq)
		state->intr_cpu = raw_smp_processor_id();

	return 0;
}
コード例 #3
0
ファイル: book3s_xics.c プロジェクト: 0-T-0/ps4-linux
int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority)
{
	struct kvmppc_xics *xics = kvm->arch.xics;
	struct kvmppc_icp *icp;
	struct kvmppc_ics *ics;
	struct ics_irq_state *state;
	u16 src;

	if (!xics)
		return -ENODEV;

	ics = kvmppc_xics_find_ics(xics, irq, &src);
	if (!ics)
		return -EINVAL;
	state = &ics->irq_state[src];

	icp = kvmppc_xics_find_server(kvm, server);
	if (!icp)
		return -EINVAL;

	XICS_DBG("set_xive %#x server %#x prio %#x MP:%d RS:%d\n",
		 irq, server, priority,
		 state->masked_pending, state->resend);

	if (write_xive(xics, ics, state, server, priority, priority))
		icp_deliver_irq(xics, icp, irq);

	return 0;
}
コード例 #4
0
ファイル: book3s_xics.c プロジェクト: 0-T-0/ps4-linux
static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
			     struct kvmppc_icp *icp)
{
	int i;

	unsigned long flags;

	local_irq_save(flags);
	arch_spin_lock(&ics->lock);

	for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
		struct ics_irq_state *state = &ics->irq_state[i];

		if (!state->resend)
			continue;

		XICS_DBG("resend %#x prio %#x\n", state->number,
			      state->priority);

		arch_spin_unlock(&ics->lock);
		local_irq_restore(flags);
		icp_deliver_irq(xics, icp, state->number);
		local_irq_save(flags);
		arch_spin_lock(&ics->lock);
	}

	arch_spin_unlock(&ics->lock);
	local_irq_restore(flags);
}
コード例 #5
0
ファイル: book3s_xics.c プロジェクト: KutuSystems/kutu_linux
/*
 * Return value ideally indicates how the interrupt was handled, but no
 * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
 * so just return 0.
 */
static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
{
	struct ics_irq_state *state;
	struct kvmppc_ics *ics;
	u16 src;

	XICS_DBG("ics deliver %#x (level: %d)\n", irq, level);

	ics = kvmppc_xics_find_ics(xics, irq, &src);
	if (!ics) {
		XICS_DBG("ics_deliver_irq: IRQ 0x%06x not found !\n", irq);
		return -EINVAL;
	}
	state = &ics->irq_state[src];
	if (!state->exists)
		return -EINVAL;

	/*
	 * We set state->asserted locklessly. This should be fine as
	 * we are the only setter, thus concurrent access is undefined
	 * to begin with.
	 */
	if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL)
		state->asserted = 1;
	else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
		state->asserted = 0;
		return 0;
	}

	/* Record which CPU this arrived on for passed-through interrupts */
	if (state->host_irq)
		state->intr_cpu = raw_smp_processor_id();

	/* Attempt delivery */
	icp_deliver_irq(xics, NULL, irq);

	return 0;
}
コード例 #6
0
static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
			     struct kvmppc_icp *icp)
{
	int i;

	for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
		struct ics_irq_state *state = &ics->irq_state[i];
		if (state->resend) {
			XICS_DBG("resend %#x prio %#x\n", state->number,
				      state->priority);
			icp_deliver_irq(xics, icp, state->number, true);
		}
	}
}
コード例 #7
0
static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
			     struct kvmppc_icp *icp)
{
	int i;

	mutex_lock(&ics->lock);

	for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
		struct ics_irq_state *state = &ics->irq_state[i];

		if (!state->resend)
			continue;

		XICS_DBG("resend %#x prio %#x\n", state->number,
			      state->priority);

		mutex_unlock(&ics->lock);
		icp_deliver_irq(xics, icp, state->number);
		mutex_lock(&ics->lock);
	}

	mutex_unlock(&ics->lock);
}