--- //depot/vendor/freebsd/src/sys/amd64/amd64/io_apic.c 2007/03/05 20:41:29 +++ //depot/user/jhb/acpipci/amd64/amd64/io_apic.c 2007/03/06 15:28:38 @@ -52,6 +52,7 @@ #include #include #include +#include #include #define IOAPIC_ISA_INTS 16 @@ -100,6 +101,7 @@ u_int io_intbase:8; /* System Interrupt base */ u_int io_numintr:8; volatile ioapic_t *io_addr; /* XXX: should use bus_space */ + vm_paddr_t io_paddr; STAILQ_ENTRY(ioapic) io_next; struct ioapic_intsrc io_pins[0]; }; @@ -479,6 +481,7 @@ next_ioapic_base = intbase + numintr; io->io_numintr = numintr; io->io_addr = apic; + io->io_paddr = addr; /* * Initialize pins. Start off with interrupts disabled. Default @@ -774,3 +777,73 @@ static devclass_t ioapic_devclass; DRIVER_MODULE(ioapic, pci, ioapic_pci_driver, ioapic_devclass, 0, 0); + +/* + * A new-bus driver to consume the memory resources associated with + * the APICs in the system. On some systems ACPI or PnPBIOS system + * resource devices may already claim these resources. To keep from + * breaking those devices, we attach ourself to the nexus device after + * legacy0 and acpi0 and ignore any allocation failures. + */ +static void +apic_identify(driver_t *driver, device_t parent) +{ + + /* + * Add at order 12. acpi0 is probed at order 10 and legacy0 + * is probed at order 11. + */ + if (lapic_paddr != 0) + BUS_ADD_CHILD(parent, 12, "apic", 0); +} + +static int +apic_probe(device_t dev) +{ + + device_set_desc(dev, "APIC resources"); + device_quiet(dev); + return (0); +} + +static void +apic_add_resource(device_t dev, int rid, vm_paddr_t base, size_t length) +{ + int error; + + error = bus_set_resource(dev, SYS_RES_MEMORY, rid, base, length); + if (error) + panic("apic_add_resource: resource %d failed set with %d", rid, + error); + bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0); +} + +static int +apic_attach(device_t dev) +{ + struct ioapic *io; + int i; + + /* Reserve the local APIC. */ + apic_add_resource(dev, 0, lapic_paddr, sizeof(lapic_t)); + i = 1; + STAILQ_FOREACH(io, &ioapic_list, io_next) { + apic_add_resource(dev, i, io->io_paddr, IOAPIC_MEM_REGION); + i++; + } + return (0); +} + +static device_method_t apic_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, apic_identify), + DEVMETHOD(device_probe, apic_probe), + DEVMETHOD(device_attach, apic_attach), + + { 0, 0 } +}; + +DEFINE_CLASS_0(apic, apic_driver, apic_methods, 0); + +static devclass_t apic_devclass; +DRIVER_MODULE(apic, nexus, apic_driver, apic_devclass, 0, 0); --- //depot/vendor/freebsd/src/sys/amd64/amd64/local_apic.c 2007/03/05 20:41:29 +++ //depot/user/jhb/acpipci/amd64/amd64/local_apic.c 2007/03/06 15:28:38 @@ -148,6 +148,7 @@ }; volatile lapic_t *lapic; +vm_paddr_t lapic_paddr; static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz; static void lapic_enable(void); @@ -212,6 +213,7 @@ KASSERT(trunc_page(addr) == addr, ("local APIC not aligned on a page boundary")); lapic = pmap_mapdev(addr, sizeof(lapic_t)); + lapic_paddr = addr; setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0); /* Perform basic initialization of the BSP's local APIC. */ --- //depot/vendor/freebsd/src/sys/amd64/include/apicvar.h 2007/03/05 20:41:29 +++ //depot/user/jhb/acpipci/amd64/include/apicvar.h 2007/03/06 15:28:38 @@ -174,6 +174,8 @@ IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6), IDTVEC(apic_isr7), IDTVEC(spuriousint), IDTVEC(timerint); +extern vm_paddr_t lapic_paddr; + u_int apic_alloc_vector(u_int irq); u_int apic_alloc_vectors(u_int *irqs, u_int count, u_int align); void apic_enable_vector(u_int vector); --- //depot/vendor/freebsd/src/sys/i386/i386/io_apic.c 2007/03/05 20:36:22 +++ //depot/user/jhb/acpipci/i386/i386/io_apic.c 2007/03/06 15:28:38 @@ -52,6 +52,7 @@ #include #include #include +#include #include #define IOAPIC_ISA_INTS 16 @@ -100,6 +101,7 @@ u_int io_intbase:8; /* System Interrupt base */ u_int io_numintr:8; volatile ioapic_t *io_addr; /* XXX: should use bus_space */ + vm_paddr_t io_paddr; STAILQ_ENTRY(ioapic) io_next; struct ioapic_intsrc io_pins[0]; }; @@ -479,6 +481,7 @@ next_ioapic_base = intbase + numintr; io->io_numintr = numintr; io->io_addr = apic; + io->io_paddr = addr; /* * Initialize pins. Start off with interrupts disabled. Default @@ -774,3 +777,81 @@ static devclass_t ioapic_devclass; DRIVER_MODULE(ioapic, pci, ioapic_pci_driver, ioapic_devclass, 0, 0); + +/* + * A new-bus driver to consume the memory resources associated with + * the APICs in the system. On some systems ACPI or PnPBIOS system + * resource devices may already claim these resources. To keep from + * breaking those devices, we attach ourself to the nexus device after + * legacy0 and acpi0 and ignore any allocation failures. + */ +static void +apic_identify(driver_t *driver, device_t parent) +{ + + /* + * Add at order 12. acpi0 is probed at order 10 and legacy0 + * is probed at order 11. + */ + if (lapic_paddr != 0) + BUS_ADD_CHILD(parent, 12, "apic", 0); +} + +static int +apic_probe(device_t dev) +{ + + device_set_desc(dev, "APIC resources"); + device_quiet(dev); + return (0); +} + +static void +apic_add_resource(device_t dev, int rid, vm_paddr_t base, size_t length) +{ + int error; + +#ifdef PAE + /* + * Resources use long's to track resources, so we can't + * include memory regions above 4GB. + */ + if (base >= ~0ul) + return; +#endif + error = bus_set_resource(dev, SYS_RES_MEMORY, rid, base, length); + if (error) + panic("apic_add_resource: resource %d failed set with %d", rid, + error); + bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0); +} + +static int +apic_attach(device_t dev) +{ + struct ioapic *io; + int i; + + /* Reserve the local APIC. */ + apic_add_resource(dev, 0, lapic_paddr, sizeof(lapic_t)); + i = 1; + STAILQ_FOREACH(io, &ioapic_list, io_next) { + apic_add_resource(dev, i, io->io_paddr, IOAPIC_MEM_REGION); + i++; + } + return (0); +} + +static device_method_t apic_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, apic_identify), + DEVMETHOD(device_probe, apic_probe), + DEVMETHOD(device_attach, apic_attach), + + { 0, 0 } +}; + +DEFINE_CLASS_0(apic, apic_driver, apic_methods, 0); + +static devclass_t apic_devclass; +DRIVER_MODULE(apic, nexus, apic_driver, apic_devclass, 0, 0); --- //depot/vendor/freebsd/src/sys/i386/i386/local_apic.c 2007/03/05 20:36:22 +++ //depot/user/jhb/acpipci/i386/i386/local_apic.c 2007/03/06 15:28:38 @@ -148,6 +148,7 @@ }; volatile lapic_t *lapic; +vm_paddr_t lapic_paddr; static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz; static void lapic_enable(void); @@ -212,6 +213,7 @@ KASSERT(trunc_page(addr) == addr, ("local APIC not aligned on a page boundary")); lapic = pmap_mapdev(addr, sizeof(lapic_t)); + lapic_paddr = addr; setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); --- //depot/vendor/freebsd/src/sys/i386/include/apicvar.h 2007/03/05 20:36:22 +++ //depot/user/jhb/acpipci/i386/include/apicvar.h 2007/03/06 15:28:38 @@ -173,6 +173,8 @@ IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6), IDTVEC(apic_isr7), IDTVEC(spuriousint), IDTVEC(timerint); +extern vm_paddr_t lapic_paddr; + u_int apic_alloc_vector(u_int irq); u_int apic_alloc_vectors(u_int *irqs, u_int count, u_int align); void apic_enable_vector(u_int vector);