From owner-p4-projects@FreeBSD.ORG Fri Oct 10 17:06:36 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id F0EB216A4C0; Fri, 10 Oct 2003 17:06:35 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id CA11616A4B3 for ; Fri, 10 Oct 2003 17:06:35 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 95F0F43FA3 for ; Fri, 10 Oct 2003 17:06:34 -0700 (PDT) (envelope-from peter@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.9/8.12.9) with ESMTP id h9B06YXJ042836 for ; Fri, 10 Oct 2003 17:06:34 -0700 (PDT) (envelope-from peter@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.9/8.12.9/Submit) id h9B06YeQ042833 for perforce@freebsd.org; Fri, 10 Oct 2003 17:06:34 -0700 (PDT) (envelope-from peter@freebsd.org) Date: Fri, 10 Oct 2003 17:06:34 -0700 (PDT) Message-Id: <200310110006.h9B06YeQ042833@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to peter@freebsd.org using -f From: Peter Wemm To: Perforce Change Reviews Subject: PERFORCE change 39483 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 11 Oct 2003 00:06:36 -0000 http://perforce.freebsd.org/chv.cgi?CH=39483 Change 39483 by peter@peter_daintree on 2003/10/10 17:06:04 p4 integ -I smp_hammer branch (ie: suck in jhb's current changes) (wow! conflict city!) Affected files ... .. //depot/projects/hammer/sys/amd64/acpica/madt.c#3 integrate .. //depot/projects/hammer/sys/amd64/amd64/apic_vector.s#7 integrate .. //depot/projects/hammer/sys/amd64/amd64/intr_machdep.c#3 integrate .. //depot/projects/hammer/sys/amd64/amd64/io_apic.c#8 integrate .. //depot/projects/hammer/sys/amd64/amd64/local_apic.c#11 integrate .. //depot/projects/hammer/sys/amd64/amd64/mp_machdep.c#15 integrate .. //depot/projects/hammer/sys/amd64/amd64/mpboot.s#8 integrate .. //depot/projects/hammer/sys/amd64/include/apicvar.h#6 integrate .. //depot/projects/hammer/sys/amd64/include/intr_machdep.h#4 integrate .. //depot/projects/hammer/sys/amd64/isa/atpic.c#6 integrate .. //depot/projects/hammer/sys/amd64/isa/atpic_vector.s#5 integrate .. //depot/projects/hammer/sys/jhb_notes#5 integrate Differences ... ==== //depot/projects/hammer/sys/amd64/acpica/madt.c#3 (text+ko) ==== @@ -62,8 +62,8 @@ struct lapic_info { int la_present:1; int la_enabled:1; - int la_acpi_id:8; -} lapics[NLAPICS]; + int la_apic_id:8; +} lapics[NLAPICS + 1]; static APIC_TABLE *madt; static vm_paddr_t madt_physaddr; @@ -338,9 +338,6 @@ madt_setup_io(void) { int i; -#if 0 - u_char byte; -#endif /* First, we run through adding I/O APIC's. */ madt_walk_table(madt_parse_apics, NULL); @@ -355,15 +352,6 @@ /* Finally, we throw the switch to enable the I/O APIC's. */ acpi_SetDefaultIntrModel(ACPI_INTR_APIC); -#if 0 - /* XXX: how are we supposed to do this now? does _PIC do this for us? */ - if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) { - outb(0x22, 0x70); /* select IMCR */ - byte = inb(0x23); /* current contents */ - byte |= 0x01; /* mask external INTR */ - outb(0x23, byte); /* disconnect 8259s/NMI */ - } -#endif return (0); } @@ -408,19 +396,24 @@ * its own. */ proc = (PROCESSOR_APIC *)entry; - la = &lapics[proc->LocalApicId]; +#if 0 + if (bootverbose) +#endif + printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n", + proc->LocalApicId, proc->ProcessorApicId, + proc->ProcessorEnabled ? "enabled" : "disabled"); + if (proc->ProcessorApicId > NLAPICS) + panic("%s: CPU ID %d too high", __func__, + proc->ProcessorApicId); + la = &lapics[proc->ProcessorApicId]; KASSERT(la->la_present == 0, - ("Duplicate local APIC ID %d", proc->LocalApicId)); + ("Duplicate local ACPI ID %d", proc->ProcessorApicId)); la->la_present = 1; - la->la_acpi_id = proc->ProcessorApicId; + la->la_apic_id = proc->LocalApicId; if (proc->ProcessorEnabled) { la->la_enabled = 1; lapic_create(proc->LocalApicId, 0); } - /* XXXTEST */ - printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n", - proc->LocalApicId, proc->ProcessorApicId, - proc->ProcessorEnabled ? "enabled" : "disabled"); break; } } @@ -438,6 +431,12 @@ switch (entry->Type) { case APIC_IO: apic = (IO_APIC *)entry; +#if 0 + if (bootverbose) +#endif + printf("MADT: Found IO APIC ID %d, Vector %d at %p\n", + apic->IoApicId, apic->Vector, + (void *)apic->IoApicAddress); if (apic->IoApicId >= NIOAPICS) panic("%s: I/O APIC ID %d too high", __func__, apic->IoApicId); @@ -448,9 +447,6 @@ (uintptr_t)apic->IoApicAddress, apic->IoApicId, apic->Vector); ioapics[apic->IoApicId].io_vector = apic->Vector; - /* XXXTEST */ - printf("MADT: Found IO APIC ID %d, Vector %d at %p\n", - apic->IoApicId, apic->Vector, (void *)(uintptr_t)apic->IoApicAddress); break; default: break; @@ -498,18 +494,14 @@ static int madt_find_cpu(u_int acpi_id, u_int *apic_id) { - int i; - for (i = 0; i < NLAPICS; i++) - if (lapics[i].la_present && lapics[i].la_acpi_id == acpi_id) { - if (apic_id != NULL) - *apic_id = i; - if (lapics[i].la_enabled) - return (0); - else - return (ENXIO); - } - return (ENOENT); + if (!lapics[acpi_id].la_present) + return (ENOENT); + *apic_id = lapics[acpi_id].la_apic_id; + if (lapics[acpi_id].la_enabled) + return (0); + else + return (ENXIO); } /* @@ -602,9 +594,12 @@ if (nmi->ProcessorApicId == 0xff) apic_id = APIC_ID_ALL; - else if (madt_find_cpu(nmi->ProcessorApicId, &apic_id) == ENOENT) { - printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n", - nmi->ProcessorApicId); + else if (madt_find_cpu(nmi->ProcessorApicId, &apic_id) != 0) { +#if 0 + if (bootverbose) +#endif + printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n", + nmi->ProcessorApicId); return; } if (nmi->LINTPin == 0) ==== //depot/projects/hammer/sys/amd64/amd64/apic_vector.s#7 (text+ko) ==== @@ -127,7 +127,7 @@ incl TD_INTR_NESTING_LEVEL(%rbx) ; \ bsrl %eax, %eax ; /* index of highset set bit in ISR */ \ jz 2f ; \ - addl $(32 * (index - 1)),%eax ; \ + addl $(32 * index),%eax ; \ 1: ; \ FAKE_MCOUNT(13*4(%esp)) ; /* XXX avoid double count */ \ movq %rax, %rdi ; /* pass the IRQ */ \ @@ -153,13 +153,13 @@ iretq -MCOUNT_LABEL(bintr) +MCOUNT_LABEL(bintr2) ISR_VEC(1,apic_isr1) ISR_VEC(2,apic_isr2) ISR_VEC(3,apic_isr3) ISR_VEC(4,apic_isr4) ISR_VEC(5,apic_isr5) -MCOUNT_LABEL(eintr) +MCOUNT_LABEL(eintr2) #ifdef SMP /* ==== //depot/projects/hammer/sys/amd64/amd64/intr_machdep.c#3 (text+ko) ==== @@ -294,91 +294,3 @@ db_dump_ithread((*isrc)->is_ithread, verbose); } #endif - -/* XXX: this does not belong here */ - -#include "opt_mca.h" - -#include -#include - -#ifdef PC98 -#define NMI_PARITY 0x04 -#define NMI_EPARITY 0x02 -#else -#define NMI_PARITY (1 << 7) -#define NMI_IOCHAN (1 << 6) -#define ENMI_WATCHDOG (1 << 7) -#define ENMI_BUSTIMER (1 << 6) -#define ENMI_IOSTATUS (1 << 5) -#endif - -/* - * Handle a NMI, possibly a machine check. - * return true to panic system, false to ignore. - */ -int -isa_nmi(cd) - int cd; -{ - int retval = 0; -#ifdef PC98 - int port = inb(0x33); - - log(LOG_CRIT, "NMI PC98 port = %x\n", port); - if (epson_machine_id == 0x20) - epson_outb(0xc16, epson_inb(0xc16) | 0x1); - if (port & NMI_PARITY) { - log(LOG_CRIT, "BASE RAM parity error, likely hardware failure."); - retval = 1; - } else if (port & NMI_EPARITY) { - log(LOG_CRIT, "EXTENDED RAM parity error, likely hardware failure."); - retval = 1; - } else { - log(LOG_CRIT, "\nNMI Resume ??\n"); - } -#else /* IBM-PC */ - int isa_port = inb(0x61); - int eisa_port = inb(0x461); - - log(LOG_CRIT, "NMI ISA %x, EISA %x\n", isa_port, eisa_port); -#ifdef DEV_MCA - if (MCA_system && mca_bus_nmi()) - return(0); -#endif - - if (isa_port & NMI_PARITY) { - log(LOG_CRIT, "RAM parity error, likely hardware failure."); - retval = 1; - } - - if (isa_port & NMI_IOCHAN) { - log(LOG_CRIT, "I/O channel check, likely hardware failure."); - retval = 1; - } - - /* - * On a real EISA machine, this will never happen. However it can - * happen on ISA machines which implement XT style floating point - * error handling (very rare). Save them from a meaningless panic. - */ - if (eisa_port == 0xff) - return(retval); - - if (eisa_port & ENMI_WATCHDOG) { - log(LOG_CRIT, "EISA watchdog timer expired, likely hardware failure."); - retval = 1; - } - - if (eisa_port & ENMI_BUSTIMER) { - log(LOG_CRIT, "EISA bus timeout, likely hardware failure."); - retval = 1; - } - - if (eisa_port & ENMI_IOSTATUS) { - log(LOG_CRIT, "EISA I/O port status error."); - retval = 1; - } -#endif - return(retval); -} ==== //depot/projects/hammer/sys/amd64/amd64/io_apic.c#8 (text+ko) ==== @@ -30,6 +30,7 @@ */ #include "opt_isa.h" +#include "opt_no_mixed_mode.h" #include #include @@ -48,7 +49,7 @@ #include #include -#ifdef DEV_ISA +#if defined(DEV_ISA) && !defined(NO_MIXED_MODE) #define MIXED_MODE #endif @@ -175,7 +176,7 @@ uint32_t flags; mtx_lock_spin(&icu_lock); - if (!intpin->io_masked) { + if (!intpin->io_masked && !intpin->io_edgetrigger) { flags = ioapic_read(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin)); flags |= IOART_INTMSET; @@ -251,11 +252,6 @@ { struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; - if (intpin->io_vector == IDT_TO_IRQ(IDT_SYSCALL)) { - printf("WARNING: IRQ %d is not routed!\n", - IDT_TO_IRQ(IDT_SYSCALL)); - return; - } KASSERT(intpin->io_dest != DEST_EXTINT, ("ExtINT pin trying to use ioapic enable_intr method")); if (intpin->io_dest == DEST_NONE) { @@ -392,7 +388,7 @@ * logical cluster destination until it is enabled. */ intpin->io_masked = 1; - intpin->io_dest = -1; + intpin->io_dest = DEST_NONE; if (bootverbose) { printf("ioapic%u: intpin %d -> ", io->io_id, i); if (intpin->io_vector == VECTOR_EXTINT) @@ -611,7 +607,7 @@ break; default: flags |= IOART_DELLOPRI | - IRQ_TO_IDT(pin->io_vector); + apic_irq_to_idt(pin->io_vector); } mtx_lock_spin(&icu_lock); ioapic_write(apic, IOAPIC_REDTBL_LO(i), flags); @@ -654,7 +650,8 @@ STAILQ_FOREACH(io, &ioapic_list, io_next) for (i = 0; i < io->io_numintr; i++) if (io->io_pins[i].io_dest != DEST_NONE && - io->io_pins[i].io_dest != DEST_EXTINT) + io->io_pins[i].io_dest != DEST_EXTINT && + io->io_pins[i].io_vector != VECTOR_EXTINT /* XXXTEST */) ioapic_program_destination(&io->io_pins[i]); } SYSINIT(ioapic_destinations, SI_SUB_SMP, SI_ORDER_SECOND, @@ -684,10 +681,12 @@ if (extint->io_vector != VECTOR_EXTINT) panic("Can't find ExtINT pin to route through!"); if (extint->io_dest == DEST_NONE) { +#if 0 + /* XXXTEST? */ ioapic_assign_cluster(extint); +#endif ioapic_enable_source(&extint->io_intsrc); } - } #endif /* MIXED_MODE */ ==== //depot/projects/hammer/sys/amd64/amd64/local_apic.c#11 (text+ko) ==== @@ -75,6 +75,7 @@ struct lapic { struct lvt la_lvts[LVT_MAX + 1]; + int la_id:8; int la_cluster:4; int la_cluster_id:2; int la_present:1; @@ -85,7 +86,7 @@ /* Global defaults for local APIC LVT entries. */ static struct lvt lvts[LVT_MAX + 1] = { { 1, 1, 1, 1, APIC_LVT_DM_EXTINT, 0 }, /* LINT0: masked ExtINT */ - { 1, 1, 1, 1, APIC_LVT_DM_NMI, 0 }, /* LINT1: NMI */ + { 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 }, /* LINT1: NMI */ { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* Timer: needs a vector */ { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* Error: needs a vector */ { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* PMC */ @@ -130,10 +131,11 @@ case APIC_LVT_DM_SMI: case APIC_LVT_DM_INIT: case APIC_LVT_DM_EXTINT: - KASSERT(lvt->lvt_edgetrigger == 1, - ("LVT with mode %#x must be edge triggered", - lvt->lvt_mode)); - /* FALLTHROUGH */ + if (!lvt->lvt_edgetrigger) { + printf("lapic%u: Forcing LINT%u to edge trigger\n", + la->la_id, pin); + value |= APIC_LVT_TM; + } /* Use a vector of 0. */ break; case APIC_LVT_DM_FIXED: @@ -197,6 +199,7 @@ * intra-cluster ID of 0. */ lapics[apic_id].la_present = 1; + lapics[apic_id].la_id = apic_id; for (i = 0; i < LVT_MAX; i++) { lapics[apic_id].la_lvts[i] = lvts[i]; lapics[apic_id].la_lvts[i].lvt_active = 0; @@ -222,14 +225,14 @@ } void -lapic_enable_intr(u_int vector) +lapic_enable_intr(u_int irq) { + u_int vector; - /* Convert to IDT vector. */ - vector = IRQ_TO_IDT(vector); + vector = apic_irq_to_idt(irq); KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry")); KASSERT(ioint_handlers[vector / 32] != NULL, - ("No ISR handler for IRQ %d", IDT_TO_IRQ(vector))); + ("No ISR handler for IRQ %u", irq)); setidt(vector, ioint_handlers[vector / 32], SDT_SYSIGT, SEL_KPL, 0); } @@ -283,19 +286,12 @@ void lapic_disable(void) { - struct lapic *la; - u_int32_t value; - register_t eflags; + uint32_t value; - la = &lapics[lapic_id()]; - KASSERT(la->la_present, ("missing APIC structure")); - eflags = intr_disable(); - - /* Disable local APIC to be safe during boot */ + /* Software disable the local APIC. */ value = lapic->svr; value &= ~APIC_SVR_SWEN; lapic->svr = value; - intr_restore(eflags); } int @@ -341,88 +337,114 @@ } int -lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked) +lapic_set_lvt_mask(u_int apic_id, u_int pin, u_char masked) { - if (lvt > LVT_MAX) + if (pin > LVT_MAX) return (EINVAL); if (apic_id == APIC_ID_ALL) - lvts[lvt].lvt_masked = masked; + lvts[pin].lvt_masked = masked; else { KASSERT(lapics[apic_id].la_present, ("%s: missing APIC %u", __func__, apic_id)); - lapics[apic_id].la_lvts[lvt].lvt_masked = masked; - lapics[apic_id].la_lvts[lvt].lvt_active = 1; + lapics[apic_id].la_lvts[pin].lvt_masked = masked; + lapics[apic_id].la_lvts[pin].lvt_active = 1; } + /* XXXTEST */ + printf("lapic%u: LINT%u %s\n", apic_id, pin, + masked ? "masked" : "unmasked"); return (0); } int -lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode) +lapic_set_lvt_mode(u_int apic_id, u_int pin, u_int32_t mode) { - struct lvt *lv; + struct lvt *lvt; - if (lvt > LVT_MAX) + if (pin > LVT_MAX) return (EINVAL); if (apic_id == APIC_ID_ALL) - lv = &lvts[lvt]; + lvt = &lvts[pin]; else { KASSERT(lapics[apic_id].la_present, ("%s: missing APIC %u", __func__, apic_id)); - lv = &lapics[apic_id].la_lvts[lvt]; - lv->lvt_active = 1; + lvt = &lapics[apic_id].la_lvts[pin]; + lvt->lvt_active = 1; } - lv->lvt_mode = mode; + lvt->lvt_mode = mode; switch (mode) { case APIC_LVT_DM_NMI: case APIC_LVT_DM_SMI: case APIC_LVT_DM_INIT: case APIC_LVT_DM_EXTINT: - lv->lvt_edgetrigger = 1; - lv->lvt_activehi = 1; + lvt->lvt_edgetrigger = 1; + lvt->lvt_activehi = 1; if (mode == APIC_LVT_DM_EXTINT) - lv->lvt_masked = 1; + lvt->lvt_masked = 1; else - lv->lvt_masked = 0; + lvt->lvt_masked = 0; break; default: panic("Unsupported delivery mode: 0x%x\n", mode); - } + } + /* XXXTEST */ + printf("lapic%u: Routing ", apic_id); + switch (mode) { + case APIC_LVT_DM_NMI: + printf("NMI"); + break; + case APIC_LVT_DM_SMI: + printf("SMI"); + break; + case APIC_LVT_DM_INIT: + printf("INIT"); + break; + case APIC_LVT_DM_EXTINT: + printf("ExtINT"); + break; + } + printf(" -> LINT%u\n", pin); return (0); } int -lapic_set_lvt_polarity(u_int apic_id, u_int lvt, u_char activehi) +lapic_set_lvt_polarity(u_int apic_id, u_int pin, u_char activehi) { - if (lvt > LVT_MAX) + if (pin > LVT_MAX) return (EINVAL); if (apic_id == APIC_ID_ALL) - lvts[lvt].lvt_activehi = activehi; + lvts[pin].lvt_activehi = activehi; else { KASSERT(lapics[apic_id].la_present, ("%s: missing APIC %u", __func__, apic_id)); - lapics[apic_id].la_lvts[lvt].lvt_active = 1; - lapics[apic_id].la_lvts[lvt].lvt_activehi = activehi; + lapics[apic_id].la_lvts[pin].lvt_active = 1; + lapics[apic_id].la_lvts[pin].lvt_activehi = activehi; } + /* XXXTEST */ + printf("lapic%u: LINT%u polarity: active-%s\n", apic_id, pin, + activehi ? "hi" : "lo"); return (0); } int -lapic_set_lvt_triggermode(u_int apic_id, u_int lvt, u_char edgetrigger) +lapic_set_lvt_triggermode(u_int apic_id, u_int pin, u_char edgetrigger) { - if (lvt > LVT_MAX) + if (pin > LVT_MAX) return (EINVAL); if (apic_id == APIC_ID_ALL) - lvts[lvt].lvt_edgetrigger = edgetrigger; + lvts[pin].lvt_edgetrigger = edgetrigger; else { KASSERT(lapics[apic_id].la_present, ("%s: missing APIC %u", __func__, apic_id)); - lapics[apic_id].la_lvts[lvt].lvt_edgetrigger = edgetrigger; - lapics[apic_id].la_lvts[lvt].lvt_active = 1; + lapics[apic_id].la_lvts[pin].lvt_edgetrigger = edgetrigger; + lapics[apic_id].la_lvts[pin].lvt_active = 1; } + /* XXXTEST */ + printf("lapic%u: LINT%u trigger: %s\n", apic_id, pin, + edgetrigger ? "edge" : "level"); return (0); } @@ -434,12 +456,37 @@ if (vec == -1) panic("Couldn't get vector from ISR!"); - isrc = intr_lookup_source(vec); + isrc = intr_lookup_source(apic_idt_to_irq(vec)); isrc->is_pic->pic_disable_source(isrc); lapic->eoi = 0; intr_execute_handlers(isrc, &frame); } +/* Translate between IDT vectors and IRQ vectors. */ +u_int +apic_irq_to_idt(u_int irq) +{ + u_int vector; + + KASSERT(irq < NUM_IO_INTS, ("Invalid IRQ %u", irq)); + vector = irq + IDT_IO_INTS; + if (vector >= IDT_SYSCALL) + vector++; + return (vector); +} + +u_int +apic_idt_to_irq(u_int vector) +{ + + KASSERT(vector >= IDT_IO_INTS && vector != IDT_SYSCALL && + vector <= IDT_IO_INTS + NUM_IO_INTS, + ("Vector %u does not map to an IRQ line", vector)); + if (vector > IDT_SYSCALL) + vector--; + return (vector - IDT_IO_INTS); +} + /* * APIC probing support code. This includes code to manage enumerators. */ ==== //depot/projects/hammer/sys/amd64/amd64/mp_machdep.c#15 (text+ko) ==== @@ -76,29 +76,9 @@ #define BIOS_RESET (0x0f) #define BIOS_WARM (0x0a) -/* - * Values to send to the POST hardware. - */ -#define MP_BOOTADDRESS_POST 0x10 -#define MP_PROBE_POST 0x11 -#define MPTABLE_PASS1_POST 0x12 - -#define MP_START_POST 0x13 -#define MP_ENABLE_POST 0x14 -#define MPTABLE_PASS2_POST 0x15 - -#define START_ALL_APS_POST 0x16 -#define INSTALL_AP_TRAMP_POST 0x17 -#define START_AP_POST 0x18 - -#define MP_ANNOUNCE_POST 0x19 - /* lock region used by kernel profiling */ int mcount_lock; -/** XXX FIXME: where does this really belong, isa.h/isa.c perhaps? */ -int current_postcode; - int mp_naps; /* # of Applications processors */ int boot_cpu_id = -1; /* designated BSP */ extern int nkpt; @@ -160,7 +140,6 @@ static int start_all_aps(u_int boot_addr); static void install_ap_tramp(u_int boot_addr); static int start_ap(int apic_id, u_int boot_addr); -void ap_init(void); static void release_aps(void *dummy); static int hlt_cpus_mask; @@ -233,6 +212,16 @@ } /* At least one CPU was found. */ + if (mp_ncpus == 1) { + /* + * One CPU was found, so this must be a UP system with + * an I/O APIC. + */ + mp_maxid = 0; + return (0); + } + + /* At least two CPUs were found. */ KASSERT(mp_maxid >= mp_ncpus - 1, ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid, mp_ncpus)); @@ -311,21 +300,21 @@ printf(" cpu%d (AP): APIC ID: %2d\n", i++, x); } } - - /* XXX: List I/O APICs? They are done differently now. */ } /* - * AP cpu's call this to sync up protected mode. + * AP CPU's call this to initialize themselves. */ void init_secondary(void) { int gsel_tss; - int myid = bootAP; + int myid; u_int64_t cr0; struct pcpu *pc; + /* bootAP is set in start_ap() to our ID. */ + myid = bootAP; lgdt(&r_gdt); /* does magic intra-segment return */ pc = &__pcpu[myid]; @@ -354,7 +343,74 @@ mp_naps++; - ap_init(); /* kick things off, this does not return */ + /* spin until all the AP's are ready */ + while (!aps_ready) + ia32_pause(); + + /* set up CPU registers and state */ + cpu_setregs(); + + /* set up FPU state on the AP */ + npxinit(__INITIAL_NPXCW__); + + /* set up SSE registers */ + enable_sse(); + + /* A quick check from sanity claus */ + if (PCPU_GET(apic_id) != lapic_id()) { + printf("SMP: cpuid = %d\n", PCPU_GET(cpuid)); + printf("SMP: actual apic_id = %d\n", lapic_id()); + printf("SMP: correct apic_id = %d\n", PCPU_GET(apic_id)); + panic("cpuid mismatch! boom!!"); + } + + /* Init local apic for irq's */ + lapic_setup(); + + /* Set memory range attributes for this CPU to match the BSP */ + mem_range_AP_init(); + + mtx_lock_spin(&ap_boot_mtx); + + smp_cpus++; + + CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", PCPU_GET(cpuid)); + printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid)); + + /* Determine if we are a logical CPU. */ + if (logical_cpus > 1 && PCPU_GET(apic_id) % logical_cpus != 0) + logical_cpus_mask |= PCPU_GET(cpumask); + + /* Build our map of 'other' CPUs. */ + PCPU_SET(other_cpus, all_cpus & ~PCPU_GET(cpumask)); + +#if 0 + if (bootverbose) +#endif + lapic_dump("AP"); + + if (smp_cpus == mp_ncpus) { + /* enable IPI's, tlb shootdown, freezes etc */ + atomic_store_rel_int(&smp_started, 1); + smp_active = 1; /* historic */ + } + + mtx_unlock_spin(&ap_boot_mtx); + + /* wait until all the AP's are up */ + while (smp_started == 0) + ia32_pause(); + + /* ok, now grab sched_lock and enter the scheduler */ + mtx_lock_spin(&sched_lock); + + binuptime(PCPU_PTR(switchtime)); + PCPU_SET(switchticks, ticks); + + cpu_throw(NULL, choosethread()); /* doesn't return */ + + panic("scheduler returned us to %s", __func__); + /* NOTREACHED */ } /******************************************************************* @@ -781,83 +837,6 @@ /* - * This is called once the rest of the system is up and running and we're - * ready to let the AP's out of the pen. - */ -void -ap_init(void) -{ - - /* spin until all the AP's are ready */ - while (!aps_ready) - ia32_pause(); - - /* set up CPU registers and state */ - cpu_setregs(); - - /* set up FPU state on the AP */ - npxinit(__INITIAL_NPXCW__); - - /* set up SSE registers */ - enable_sse(); - - /* A quick check from sanity claus */ - if (PCPU_GET(apic_id) != lapic_id()) { - printf("SMP: cpuid = %d\n", PCPU_GET(cpuid)); - printf("SMP: actual apic_id = %d\n", lapic_id()); - printf("SMP: correct apic_id = %d\n", PCPU_GET(apic_id)); - panic("cpuid mismatch! boom!!"); - } - - /* Init local apic for irq's */ - lapic_setup(); - - /* Set memory range attributes for this CPU to match the BSP */ - mem_range_AP_init(); - - mtx_lock_spin(&ap_boot_mtx); - - smp_cpus++; - - CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", PCPU_GET(cpuid)); - printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid)); - - /* Determine if we are a logical CPU. */ - if (logical_cpus > 1 && PCPU_GET(apic_id) % logical_cpus != 0) - logical_cpus_mask |= PCPU_GET(cpumask); - - /* Build our map of 'other' CPUs. */ - PCPU_SET(other_cpus, all_cpus & ~PCPU_GET(cpumask)); - -#if 0 - if (bootverbose) -#endif - lapic_dump("AP"); - - if (smp_cpus == mp_ncpus) { - /* enable IPI's, tlb shootdown, freezes etc */ - atomic_store_rel_int(&smp_started, 1); - smp_active = 1; /* historic */ - } - - mtx_unlock_spin(&ap_boot_mtx); - - /* wait until all the AP's are up */ - while (smp_started == 0) - ia32_pause(); - - /* ok, now grab sched_lock and enter the scheduler */ - mtx_lock_spin(&sched_lock); - - binuptime(PCPU_PTR(switchtime)); - PCPU_SET(switchticks, ticks); - - cpu_throw(NULL, choosethread()); /* doesn't return */ - - panic("scheduler returned us to %s", __func__); -} - -/* * For statclock, we send an IPI to all CPU's to have them call this * function. */ @@ -966,6 +945,10 @@ lapic_ipi_vectored(ipi, APIC_IPI_DEST_SELF); } +/* + * This is called once the rest of the system is up and running and we're + * ready to let the AP's out of the pen. + */ static void release_aps(void *dummy __unused) { @@ -978,7 +961,6 @@ ia32_pause(); mtx_unlock_spin(&sched_lock); } - SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL); static int ==== //depot/projects/hammer/sys/amd64/amd64/mpboot.s#8 (text+ko) ==== ==== //depot/projects/hammer/sys/amd64/include/apicvar.h#6 (text+ko) ==== @@ -131,19 +131,22 @@ IDTVEC(apic_isr1), IDTVEC(apic_isr2), IDTVEC(apic_isr3), IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(spuriousint); +u_int apic_irq_to_idt(u_int irq); +u_int apic_idt_to_irq(u_int vector); void apic_register_enumerator(struct apic_enumerator *enumerator); void *ioapic_create(uintptr_t addr, int32_t id, int intbase); int ioapic_disable_pin(void *cookie, u_int pin); int ioapic_get_vector(void *cookie, u_int pin); int ioapic_next_logical_cluster(void); +void ioapic_register(void *cookie); +int ioapic_remap_vector(void *cookie, u_int pin, int vector); int ioapic_set_extint(void *cookie, u_int pin); int ioapic_set_nmi(void *cookie, u_int pin); int ioapic_set_polarity(void *cookie, u_int pin, char activehi); int ioapic_set_triggermode(void *cookie, u_int pin, char edgetrigger); int ioapic_set_smi(void *cookie, u_int pin); -int ioapic_remap_vector(void *cookie, u_int pin, int vector); -void ioapic_register(void *cookie); void lapic_create(u_int apic_id, int boot_cpu); +void lapic_disable(void); void lapic_dump(const char *str); void lapic_enable_intr(u_int vector); int lapic_id(void); ==== //depot/projects/hammer/sys/amd64/include/intr_machdep.h#4 (text+ko) ==== @@ -31,8 +31,8 @@ #ifdef _KERNEL -/* With I/O APIC's we can have up to 160 interrupts. */ -#define NUM_IO_INTS 160 +/* With I/O APIC's we can have up to 159 interrupts. */ +#define NUM_IO_INTS 159 #define INTRCNT_COUNT (1 + NUM_IO_INTS * 2) #ifndef LOCORE @@ -77,9 +77,6 @@ extern struct mtx icu_lock; -/* XXX: Does this belong in icu.h? */ -void atpic_startup(void); - int intr_add_handler(const char *name, int vector, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep); void intr_execute_handlers(struct intsrc *isrc, struct intrframe *iframe); @@ -89,8 +86,6 @@ void intr_resume(void); void intr_suspend(void); -int isa_nmi(int cd); - #endif /* !LOCORE */ #endif /* _KERNEL */ #endif /* !__MACHINE_INTR_MACHDEP_H__ */ ==== //depot/projects/hammer/sys/amd64/isa/atpic.c#6 (text+ko) ==== @@ -65,16 +65,6 @@ unsigned int imen; /* XXX */ inthand_t - IDTVEC(atpic_fastintr0), IDTVEC(atpic_fastintr1), - IDTVEC(atpic_fastintr2), IDTVEC(atpic_fastintr3), - IDTVEC(atpic_fastintr4), IDTVEC(atpic_fastintr5), - IDTVEC(atpic_fastintr6), IDTVEC(atpic_fastintr7), - IDTVEC(atpic_fastintr8), IDTVEC(atpic_fastintr9), - IDTVEC(atpic_fastintr10), IDTVEC(atpic_fastintr11), - IDTVEC(atpic_fastintr12), IDTVEC(atpic_fastintr13), - IDTVEC(atpic_fastintr14), IDTVEC(atpic_fastintr15); - -inthand_t IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2), IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5), IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8), @@ -87,35 +77,26 @@ #define ATPIC(io, base, eoi, imenptr) \ { { atpic_enable_source, atpic_disable_source, (eoi), \ atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \ - atpic_resume }, (io), (base), IRQ_TO_IDT(base), (imenptr) } + atpic_resume }, (io), (base), IDT_IO_INTS + (base), (imenptr) } #define INTSRC(irq) \ - { { (struct pic *)(&atpics[(irq) / 8]) }, (irq) % 8, \ - IDTVEC(atpic_fastintr ## irq ), IDTVEC(atpic_intr ## irq ) } + { { &atpics[(irq) / 8].at_pic }, (irq) % 8, \ + IDTVEC(atpic_intr ## irq ) } struct atpic { struct pic at_pic; int at_ioaddr; int at_irqbase; - uint16_t at_intbase; + uint8_t at_intbase; uint8_t *at_imen; }; struct atpic_intsrc { >>> TRUNCATED FOR MAIL (1000 lines) <<<