diff options
Diffstat (limited to 'sys/kern/subr_smp.c')
-rw-r--r-- | sys/kern/subr_smp.c | 154 |
1 files changed, 109 insertions, 45 deletions
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index a27cf86..c817925 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -22,11 +22,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.16 1997/05/29 05:58:41 fsmp Exp $ + * $Id: mp_machdep.c,v 1.17 1997/06/02 10:44:08 dfr Exp $ */ #include "opt_smp.h" -#include "opt_serial.h" #include <sys/param.h> /* for KERNBASE */ #include <sys/types.h> @@ -38,18 +37,21 @@ #include <vm/vm_param.h> /* for KERNBASE */ #include <vm/pmap.h> /* for KERNBASE */ #include <machine/pmap.h> /* for KERNBASE */ +#include <vm/vm_kern.h> +#include <vm/vm_extern.h> #include <machine/smp.h> #include <machine/apic.h> #include <machine/mpapic.h> #include <machine/cpufunc.h> #include <machine/segments.h> -#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, LATE_START */ +#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */ +#include <machine/tss.h> #include <i386/i386/cons.h> /* cngetc() */ #if defined(APIC_IO) -#include <i386/include/md_var.h> /* setidt() */ +#include <machine/md_var.h> /* setidt() */ #include <i386/isa/icu.h> /* Xinvltlb() */ #include <i386/isa/intr_machdep.h> /* Xinvltlb() */ #endif /* APIC_IO */ @@ -186,11 +188,6 @@ typedef struct BASETABLE_ENTRY { /** FIXME: what system files declare these??? */ extern struct region_descriptor r_gdt, r_idt; -/* global data */ -struct proc *SMPcurproc[NCPU]; -struct pcb *SMPcurpcb[NCPU]; -struct timeval SMPruntime[NCPU]; - int mp_ncpus; /* # of CPUs, including BSP */ int mp_naps; /* # of Applications processors */ int mp_nbusses; /* # of busses */ @@ -210,6 +207,15 @@ int cpu_num_to_apic_id[NAPICID]; int io_num_to_apic_id[NAPICID]; int apic_id_to_logical[NAPICID]; +/* Boot of AP uses this PTD */ +u_int *bootPTD; + +/* Hotwire a 0->4MB V==P mapping */ +extern pt_entry_t KPTphys; + +/* virtual address of per-cpu common_tss */ +extern struct i386tss common_tss; + /* * look for MP compliant motherboard. */ @@ -283,11 +289,6 @@ found: /* please forgive the 'goto'! */ if (mptable_pass1()) panic("you must reconfigure your kernel"); -#if defined(LATE_START) - /* create pages for (address common) cpu APIC and each IO APIC */ - pmap_bootstrap_apics(); -#endif /* LATE_START */ - /* flag fact that we are running multiple processors */ mp_capable = 1; return 1; @@ -305,9 +306,6 @@ mp_start(void) mp_enable(boot_address); else panic("MP hardware not found!"); - - /* finish pmap initialization - turn off V==P mapping at zero */ - pmap_bootstrap2(); } @@ -321,23 +319,25 @@ mp_announce(void) printf("FreeBSD/SMP: Multiprocessor motherboard\n"); printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0)); - printf(", version: 0x%08x\n", cpu_apic_versions[0]); + printf(", version: 0x%08x", cpu_apic_versions[0]); + printf(", at 0x%08x\n", cpu_apic_address); for (x = 1; x <= mp_naps; ++x) { printf(" cpu%d (AP): apic id: %d", x, CPU_TO_ID(x)); - printf(", version: 0x%08x\n", cpu_apic_versions[x]); + printf(", version: 0x%08x", cpu_apic_versions[x]); + printf(", at 0x%08x\n", cpu_apic_address); } #if defined(APIC_IO) for (x = 0; x < mp_napics; ++x) { printf(" io%d (APIC): apic id: %d", x, IO_TO_ID(x)); - printf(", version: 0x%08x\n", io_apic_versions[x]); + printf(", version: 0x%08x", io_apic_versions[x]); + printf(", at 0x%08x\n", io_apic_address[x]); } #else printf(" Warning: APIC I/O disabled\n"); #endif /* APIC_IO */ } - /* * AP cpu's call this to sync up protected mode. */ @@ -352,12 +352,18 @@ init_secondary(void) lidt(&r_idt); lldt(_default_ldt); - slot = NGDT + cpunumber(); + slot = NGDT + cpuid; gsel_tss = GSEL(slot, SEL_KPL); gdt[slot].sd.sd_type = SDT_SYS386TSS; + common_tss.tss_esp0 = 0; /* not used until after switch */ + common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); + common_tss.tss_ioopt = (sizeof common_tss) << 16; ltr(gsel_tss); load_cr0(0x8005003b); /* XXX! */ + + PTD[0] = 0; + invltlb(); } @@ -375,9 +381,9 @@ configure_local_apic(void) outb(0x23, byte); /* disconnect 8259s/NMI */ } /* mask the LVT1 */ - temp = lapic__lvt_lint0; + temp = lapic.lvt_lint0; temp |= APIC_LVT_M; - lapic__lvt_lint0 = temp; + lapic.lvt_lint0 = temp; } #endif /* APIC_IO */ @@ -398,13 +404,15 @@ mp_enable(u_int boot_addr) u_int ux; #endif /* APIC_IO */ - /* examine the MP table for needed info */ + /* Turn on 4MB of V == P addressing so we can get to MP table */ + *(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME); + invltlb(); + + /* examine the MP table for needed info, uses physical addresses */ x = mptable_pass2(); -#if !defined(LATE_START) - /* create pages for (address common) cpu APIC and each IO APIC */ - pmap_bootstrap_apics(); -#endif /* LATE_START */ + *(int *)PTD = 0; + invltlb(); /* can't process default configs till the CPU APIC is pmapped */ if (x) @@ -832,7 +840,7 @@ fix_mp_table(void) for (x = 0; x < mp_nbusses; ++x) { if (bus_data[x].bus_type != PCI) continue; - if (bus_data[x].bus_id >= num_pci_bus ) + if (bus_data[x].bus_id >= num_pci_bus) panic("bad PCI bus numbering"); } } @@ -1258,7 +1266,7 @@ default_mp_table(int type) } #endif /* 0 */ - boot_cpu_id = (lapic__id & APIC_ID_MASK) >> 24; + boot_cpu_id = (lapic.id & APIC_ID_MASK) >> 24; ap_cpu_id = (boot_cpu_id == 0) ? 1 : 0; /* BSP */ @@ -1351,9 +1359,12 @@ default_mp_table(int type) static int start_all_aps(u_int boot_addr) { - int x; + int x, i; u_char mpbiosreason; u_long mpbioswarmvec; + pd_entry_t newptd; + pt_entry_t newpt; + int *newpp; /** * NOTE: this needs further thought: @@ -1362,7 +1373,7 @@ start_all_aps(u_int boot_addr) * * get the initial mp_lock with a count of 1 for the BSP */ - mp_lock = (lapic__id & APIC_ID_MASK) + 1; + mp_lock = (lapic.id & APIC_ID_MASK) + 1; /* initialize BSP's local APIC */ apic_initialize(1); @@ -1370,6 +1381,7 @@ start_all_aps(u_int boot_addr) /* install the AP 1st level boot code */ install_ap_tramp(boot_addr); + /* save the current value of the warm-start vector */ mpbioswarmvec = *((u_long *) WARMBOOT_OFF); outb(CMOS_REG, BIOS_RESET); @@ -1378,6 +1390,58 @@ start_all_aps(u_int boot_addr) /* start each AP */ for (x = 1; x <= mp_naps; ++x) { + /* HACK HACK HACK !!! */ + + /* alloc new page table directory */ + newptd = (pd_entry_t)(kmem_alloc(kernel_map, PAGE_SIZE)); + + /* clone currently active one (ie: IdlePTD) */ + bcopy(PTD, newptd, PAGE_SIZE); /* inc prv page pde */ + + /* set up 0 -> 4MB P==V mapping for AP boot */ + newptd[0] = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME); + + /* store PTD for this AP */ + bootPTD = (pd_entry_t)vtophys(newptd); + + /* alloc new page table page */ + newpt = (pt_entry_t)(kmem_alloc(kernel_map, PAGE_SIZE)); + + /* set the new PTD's private page to point there */ + newptd[MPPTDI] = PG_V | PG_RW | vtophys(newpt); + + /* install self referential entry */ + newptd[PTDPTDI] = PG_V | PG_RW | vtophys(newptd); + + /* get a new private data page */ + newpp = (int *)kmem_alloc(kernel_map, PAGE_SIZE); + + /* wire it into the private page table page */ + newpt[0] = PG_V | PG_RW | vtophys(newpp); + + /* wire the ptp into itself for access */ + newpt[1] = PG_V | PG_RW | vtophys(newpt); + + /* and the local apic */ + newpt[2] = SMP_prvpt[2]; + + /* and the IO apic mapping[s] */ + for (i = 16; i < 32; i++) + newpt[i] = SMP_prvpt[i]; + + /* prime data page for it to use */ + newpp[0] = x; /* cpuid */ + newpp[1] = 0; /* curproc */ + newpp[2] = 0; /* curpcb */ + newpp[3] = 0; /* npxproc */ + newpp[4] = 0; /* runtime.tv_sec */ + newpp[5] = 0; /* runtime.tv_usec */ + newpp[6] = x << 24; /* cpu_lockid */ + + /* XXX NOTE: ABANDON bootPTD for now!!!! */ + + /* END REVOLTING HACKERY */ + /* setup a vector to our boot code */ *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET; *((volatile u_short *) WARMBOOT_SEG) = (boot_addr >> 4); @@ -1401,7 +1465,7 @@ start_all_aps(u_int boot_addr) } /* fill in our (BSP) APIC version */ - cpu_apic_versions[0] = lapic__version; + cpu_apic_versions[0] = lapic.version; /* restore the warmstart vector */ *(u_long *) WARMBOOT_OFF = mpbioswarmvec; @@ -1503,24 +1567,24 @@ start_ap(int logical_cpu, u_int boot_addr) */ /* setup the address for the target AP */ - icr_hi = lapic__icr_hi & ~APIC_ID_MASK; + icr_hi = lapic.icr_hi & ~APIC_ID_MASK; icr_hi |= (physical_cpu << 24); - lapic__icr_hi = icr_hi; + lapic.icr_hi = icr_hi; /* do an INIT IPI: assert RESET */ - icr_lo = lapic__icr_lo & 0xfff00000; - lapic__icr_lo = icr_lo | 0x0000c500; + icr_lo = lapic.icr_lo & 0xfff00000; + lapic.icr_lo = icr_lo | 0x0000c500; /* wait for pending status end */ - while (lapic__icr_lo & APIC_DELSTAT_MASK) + while (lapic.icr_lo & APIC_DELSTAT_MASK) /* spin */ ; /* do an INIT IPI: deassert RESET */ - lapic__icr_lo = icr_lo | 0x00008500; + lapic.icr_lo = icr_lo | 0x00008500; /* wait for pending status end */ u_sleep(10000); /* wait ~10mS */ - while (lapic__icr_lo & APIC_DELSTAT_MASK) + while (lapic.icr_lo & APIC_DELSTAT_MASK) /* spin */ ; /* @@ -1533,8 +1597,8 @@ start_ap(int logical_cpu, u_int boot_addr) */ /* do a STARTUP IPI */ - lapic__icr_lo = icr_lo | 0x00000600 | vector; - while (lapic__icr_lo & APIC_DELSTAT_MASK) + lapic.icr_lo = icr_lo | 0x00000600 | vector; + while (lapic.icr_lo & APIC_DELSTAT_MASK) /* spin */ ; u_sleep(200); /* wait ~200uS */ @@ -1545,8 +1609,8 @@ start_ap(int logical_cpu, u_int boot_addr) * recognized after hardware RESET or INIT IPI. */ - lapic__icr_lo = icr_lo | 0x00000600 | vector; - while (lapic__icr_lo & APIC_DELSTAT_MASK) + lapic.icr_lo = icr_lo | 0x00000600 | vector; + while (lapic.icr_lo & APIC_DELSTAT_MASK) /* spin */ ; u_sleep(200); /* wait ~200uS */ |