Make PCI interupts allocation static when using bootrom (UEFI).

This makes factual interrupt routing match one shipped with UEFI firmware.
With old firmware this make legacy interrupts work reliable for functions 0
of PCI slots 3-6.  Updated UEFI image fixes problem completely.
This commit is contained in:
Alexander Motin 2016-07-14 17:16:10 +00:00
parent a509d56d7f
commit 1b4496d043
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=302850
5 changed files with 28 additions and 13 deletions

View File

@ -29,11 +29,14 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <stdio.h>
#include <machine/vmm.h>
#include <vmmapi.h>
#include "ioapic.h"
#include "pci_emul.h"
#include "pci_lpc.h"
/*
* Assign PCI INTx interrupts to I/O APIC pins in a round-robin
@ -64,11 +67,15 @@ ioapic_init(struct vmctx *ctx)
}
int
ioapic_pci_alloc_irq(void)
ioapic_pci_alloc_irq(struct pci_devinst *pi)
{
static int last_pin;
if (pci_pins == 0)
return (-1);
if (lpc_bootrom()) {
/* For external bootrom use fixed mapping. */
return (16 + (4 + pi->pi_slot + pi->pi_lintr.pin) % 8);
}
return (16 + (last_pin++ % pci_pins));
}

View File

@ -30,10 +30,12 @@
#ifndef _IOAPIC_H_
#define _IOAPIC_H_
struct pci_devinst;
/*
* Allocate a PCI IRQ from the I/O APIC.
*/
void ioapic_init(struct vmctx *ctx);
int ioapic_pci_alloc_irq(void);
int ioapic_pci_alloc_irq(struct pci_devinst *pi);
#endif

View File

@ -1504,7 +1504,7 @@ pci_lintr_route(struct pci_devinst *pi)
* is not yet assigned.
*/
if (ii->ii_ioapic_irq == 0)
ii->ii_ioapic_irq = ioapic_pci_alloc_irq();
ii->ii_ioapic_irq = ioapic_pci_alloc_irq(pi);
assert(ii->ii_ioapic_irq > 0);
/*
@ -1512,7 +1512,7 @@ pci_lintr_route(struct pci_devinst *pi)
* not yet assigned.
*/
if (ii->ii_pirq_pin == 0)
ii->ii_pirq_pin = pirq_alloc_pin(pi->pi_vmctx);
ii->ii_pirq_pin = pirq_alloc_pin(pi);
assert(ii->ii_pirq_pin > 0);
pi->pi_lintr.ioapic_irq = ii->ii_ioapic_irq;

View File

@ -193,19 +193,25 @@ pci_irq_deassert(struct pci_devinst *pi)
}
int
pirq_alloc_pin(struct vmctx *ctx)
pirq_alloc_pin(struct pci_devinst *pi)
{
struct vmctx *ctx = pi->pi_vmctx;
int best_count, best_irq, best_pin, irq, pin;
pirq_cold = 0;
/* First, find the least-used PIRQ pin. */
best_pin = 0;
best_count = pirqs[0].use_count;
for (pin = 1; pin < nitems(pirqs); pin++) {
if (pirqs[pin].use_count < best_count) {
best_pin = pin;
best_count = pirqs[pin].use_count;
if (lpc_bootrom()) {
/* For external bootrom use fixed mapping. */
best_pin = (4 + pi->pi_slot + pi->pi_lintr.pin) % 8;
} else {
/* Find the least-used PIRQ pin. */
best_pin = 0;
best_count = pirqs[0].use_count;
for (pin = 1; pin < nitems(pirqs); pin++) {
if (pirqs[pin].use_count < best_count) {
best_pin = pin;
best_count = pirqs[pin].use_count;
}
}
}
pirqs[best_pin].use_count++;

View File

@ -37,7 +37,7 @@ void pci_irq_deassert(struct pci_devinst *pi);
void pci_irq_init(struct vmctx *ctx);
void pci_irq_reserve(int irq);
void pci_irq_use(int irq);
int pirq_alloc_pin(struct vmctx *ctx);
int pirq_alloc_pin(struct pci_devinst *pi);
int pirq_irq(int pin);
uint8_t pirq_read(int pin);
void pirq_write(struct vmctx *ctx, int pin, uint8_t val);