Utility to choose good IRQ numbers
This commit is contained in:
parent
ac00d1c031
commit
2abd221789
5 changed files with 57 additions and 6 deletions
|
|
@ -17,7 +17,6 @@ unsigned int cpu_get_core_id(void);
|
|||
void write_gs_base(uint64_t base);
|
||||
|
||||
|
||||
#define LINEBUF_SIZE 256
|
||||
struct cpu_info {
|
||||
// first member of struct is pointer to itself, for easier loading
|
||||
struct cpu_info* cpu_info;
|
||||
|
|
@ -35,4 +34,14 @@ static inline struct cpu_info *local_cpu_data(void) {
|
|||
|
||||
void interrupt_handler_register(unsigned int vector, void (*handler)(void));
|
||||
|
||||
/** Choose one of the 223 interrupt numbers available for Hardware IRQs.
|
||||
* This function is useful for drivers that can control the IRQ numbers they are assigned
|
||||
* (e.g. hardware using MSI, MSI-X or the IOAPIC).
|
||||
* Interrupt numbers are chosen based on a hash of the arguments given to the function.
|
||||
* This ensures evenly spread interrupt numbers, that are stable across
|
||||
* multiple boots, kernel changes, and different computers.
|
||||
*/
|
||||
unsigned int choose_irq_vector(const char *system_name,
|
||||
uint64_t instance_idx, uint64_t subinstance_idx);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LAPIC_SPURIOUS_VECTOR_NUMBER 0xFF
|
||||
|
||||
void lapic_init(void);
|
||||
unsigned lapic_get_id(void);
|
||||
void lapic_eoi(void);
|
||||
|
|
|
|||
|
|
@ -620,3 +620,36 @@ void cpu_init_ap_1(uint8_t core_id) {
|
|||
main();
|
||||
PANIC("return from main?");
|
||||
}
|
||||
|
||||
/* Fowler-Noll-Vo Hash Function (Alternate) */
|
||||
|
||||
#define FNV32_PRIME 16777619u
|
||||
#define FNV32_OFFSET_BASIS 2166136261u
|
||||
|
||||
static void
|
||||
hash32_fnv1a(uint32_t *hash, const void *d, unsigned n)
|
||||
{
|
||||
const uint8_t *c = d;
|
||||
uint32_t h = *hash;
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
h ^= *c;
|
||||
h *= FNV32_PRIME;
|
||||
c++;
|
||||
}
|
||||
*hash = h;
|
||||
}
|
||||
|
||||
unsigned int choose_irq_vector(const char *system_name,
|
||||
uint64_t instance_idx, uint64_t subinstance_idx)
|
||||
{
|
||||
uint32_t hash = FNV32_OFFSET_BASIS;
|
||||
hash32_fnv1a(&hash, system_name, strlen(system_name));
|
||||
hash32_fnv1a(&hash, &instance_idx, sizeof instance_idx);
|
||||
hash32_fnv1a(&hash, &subinstance_idx, sizeof subinstance_idx);
|
||||
hash &= 0xFF;
|
||||
// TODO this biases IRQ vectors into specific numbers, fix it
|
||||
if (hash < 32) hash += 32;
|
||||
if (hash == LAPIC_SPURIOUS_VECTOR_NUMBER) hash ^= 1;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ void lapic_init(void)
|
|||
{
|
||||
ASSERT((LAPIC_ADDR->lapic_version.value & 0xff) <= 0x15);
|
||||
|
||||
LAPIC_ADDR->spurious_vector.value = SPURIOUS_VECTOR_APIC_ENABLE | 0xff;
|
||||
LAPIC_ADDR->spurious_vector.value = SPURIOUS_VECTOR_APIC_ENABLE | LAPIC_SPURIOUS_VECTOR_NUMBER;
|
||||
wbinvd();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,13 +382,20 @@ void ps2_init() {
|
|||
}
|
||||
|
||||
/* register interrupt handlers */
|
||||
interrupt_handler_register(101, port1_handler);
|
||||
interrupt_handler_register(102, port2_handler);
|
||||
|
||||
unsigned port1_irq = choose_irq_vector("ps2", 0, 1);
|
||||
unsigned port2_irq = choose_irq_vector("ps2", 0, 2);
|
||||
|
||||
printlinef("port1_irq = %d", port1_irq);
|
||||
printlinef("port2_irq = %d", port2_irq);
|
||||
|
||||
interrupt_handler_register(port1_irq, port1_handler);
|
||||
interrupt_handler_register(port2_irq, port2_handler);
|
||||
|
||||
bool success;
|
||||
success = ioapic_configure_irq(1, 101 | IORED_DELIVERY_NORMAL | ((uint64_t)lapic_get_id() << IORED_DESTINATION_SHIFT));
|
||||
success = ioapic_configure_irq(1, port1_irq | IORED_DELIVERY_NORMAL | ((uint64_t)lapic_get_id() << IORED_DESTINATION_SHIFT));
|
||||
ASSERT(success);
|
||||
success = ioapic_configure_irq(12, 102 | IORED_DELIVERY_NORMAL | ((uint64_t)lapic_get_id() << IORED_DESTINATION_SHIFT));
|
||||
success = ioapic_configure_irq(12, port2_irq | IORED_DELIVERY_NORMAL | ((uint64_t)lapic_get_id() << IORED_DESTINATION_SHIFT));
|
||||
ASSERT(success);
|
||||
|
||||
ps2_cmd_with_data(CMD_TO_CNTRL_OUTPUT, 0x03);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue