[BACK]Return to cpu.c CVS log [TXT][DIR] Up to [local] / sys / arch / amd64 / amd64

Annotation of sys/arch/amd64/amd64/cpu.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: cpu.c,v 1.13 2007/08/02 16:40:27 deraadt Exp $        */
                      2: /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by RedBack Networks Inc.
                     10:  *
                     11:  * Author: Bill Sommerfeld
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. All advertising materials mentioning features or use of this software
                     22:  *    must display the following acknowledgement:
                     23:  *        This product includes software developed by the NetBSD
                     24:  *        Foundation, Inc. and its contributors.
                     25:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     26:  *    contributors may be used to endorse or promote products derived
                     27:  *    from this software without specific prior written permission.
                     28:  *
                     29:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     39:  * POSSIBILITY OF SUCH DAMAGE.
                     40:  */
                     41:
                     42: /*
                     43:  * Copyright (c) 1999 Stefan Grefen
                     44:  *
                     45:  * Redistribution and use in source and binary forms, with or without
                     46:  * modification, are permitted provided that the following conditions
                     47:  * are met:
                     48:  * 1. Redistributions of source code must retain the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer.
                     50:  * 2. Redistributions in binary form must reproduce the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer in the
                     52:  *    documentation and/or other materials provided with the distribution.
                     53:  * 3. All advertising materials mentioning features or use of this software
                     54:  *    must display the following acknowledgement:
                     55:  *      This product includes software developed by the NetBSD
                     56:  *      Foundation, Inc. and its contributors.
                     57:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     58:  *    contributors may be used to endorse or promote products derived
                     59:  *    from this software without specific prior written permission.
                     60:  *
                     61:  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
                     62:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     63:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     64:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
                     65:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     66:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     67:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     68:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     69:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     70:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     71:  * SUCH DAMAGE.
                     72:  */
                     73:
                     74: #include "lapic.h"
                     75: #include "ioapic.h"
                     76:
                     77: #include <sys/param.h>
                     78: #include <sys/proc.h>
                     79: #include <sys/user.h>
                     80: #include <sys/systm.h>
                     81: #include <sys/device.h>
                     82: #include <sys/malloc.h>
                     83:
                     84: #include <uvm/uvm_extern.h>
                     85:
                     86: #include <machine/cpu.h>
                     87: #include <machine/cpufunc.h>
                     88: #include <machine/cpuvar.h>
                     89: #include <machine/pmap.h>
                     90: #include <machine/vmparam.h>
                     91: #include <machine/mpbiosvar.h>
                     92: #include <machine/pcb.h>
                     93: #include <machine/specialreg.h>
                     94: #include <machine/segments.h>
                     95: #include <machine/gdt.h>
                     96: #include <machine/mtrr.h>
                     97: #include <machine/pio.h>
                     98:
                     99: #if NLAPIC > 0
                    100: #include <machine/apicvar.h>
                    101: #include <machine/i82489reg.h>
                    102: #include <machine/i82489var.h>
                    103: #endif
                    104:
                    105: #if NIOAPIC > 0
                    106: #include <machine/i82093var.h>
                    107: #endif
                    108:
                    109: #include <dev/ic/mc146818reg.h>
                    110: #include <amd64/isa/nvram.h>
                    111: #include <dev/isa/isareg.h>
                    112:
                    113: int     cpu_match(struct device *, void *, void *);
                    114: void    cpu_attach(struct device *, struct device *, void *);
                    115:
                    116: struct cpu_softc {
                    117:        struct device sc_dev;           /* device tree glue */
                    118:        struct cpu_info *sc_info;       /* pointer to CPU info */
                    119: };
                    120:
                    121: #ifdef MULTIPROCESSOR
                    122: int mp_cpu_start(struct cpu_info *);
                    123: void mp_cpu_start_cleanup(struct cpu_info *);
                    124: struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,
                    125:                                      mp_cpu_start_cleanup };
                    126: #endif /* MULTIPROCESSOR */
                    127:
                    128: struct cfattach cpu_ca = {
                    129:        sizeof(struct cpu_softc), cpu_match, cpu_attach
                    130: };
                    131:
                    132: struct cfdriver cpu_cd = {
                    133:        NULL, "cpu", DV_DULL
                    134: };
                    135:
                    136: /*
                    137:  * Statically-allocated CPU info for the primary CPU (or the only
                    138:  * CPU, on uniprocessors).  The CPU info list is initialized to
                    139:  * point at it.
                    140:  */
                    141: struct cpu_info cpu_info_primary = { 0, &cpu_info_primary };
                    142:
                    143: struct cpu_info *cpu_info_list = &cpu_info_primary;
                    144:
                    145: u_int32_t cpus_attached = 0;
                    146:
                    147: #ifdef MULTIPROCESSOR
                    148: /*
                    149:  * Array of CPU info structures.  Must be statically-allocated because
                    150:  * curproc, etc. are used early.
                    151:  */
                    152: struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary };
                    153:
                    154: u_int32_t cpus_running = 0;
                    155:
                    156: void           cpu_hatch(void *);
                    157: static void            cpu_boot_secondary(struct cpu_info *ci);
                    158: static void            cpu_start_secondary(struct cpu_info *ci);
                    159: static void    cpu_copy_trampoline(void);
                    160:
                    161: /*
                    162:  * Runs once per boot once multiprocessor goo has been detected and
                    163:  * the local APIC on the boot processor has been mapped.
                    164:  *
                    165:  * Called from lapic_boot_init() (from mpbios_scan()).
                    166:  */
                    167: void
                    168: cpu_init_first(void)
                    169: {
                    170:        int cpunum = lapic_cpu_number();
                    171:
                    172:        if (cpunum != 0) {
                    173:                cpu_info[0] = NULL;
                    174:                cpu_info[cpunum] = &cpu_info_primary;
                    175:        }
                    176:
                    177:        cpu_copy_trampoline();
                    178: }
                    179: #endif
                    180:
                    181: int
                    182: cpu_match(struct device *parent, void *match, void *aux)
                    183: {
                    184:        struct cfdata *cf = match;
                    185:        struct cpu_attach_args *caa = aux;
                    186:
                    187:        if (strcmp(caa->caa_name, cf->cf_driver->cd_name) == 0)
                    188:                return 1;
                    189:        return 0;
                    190: }
                    191:
                    192: static void
                    193: cpu_vm_init(struct cpu_info *ci)
                    194: {
                    195:        int ncolors = 2, i;
                    196:
                    197:        for (i = CAI_ICACHE; i <= CAI_L2CACHE; i++) {
                    198:                struct x86_cache_info *cai;
                    199:                int tcolors;
                    200:
                    201:                cai = &ci->ci_cinfo[i];
                    202:
                    203:                tcolors = atop(cai->cai_totalsize);
                    204:                switch(cai->cai_associativity) {
                    205:                case 0xff:
                    206:                        tcolors = 1; /* fully associative */
                    207:                        break;
                    208:                case 0:
                    209:                case 1:
                    210:                        break;
                    211:                default:
                    212:                        tcolors /= cai->cai_associativity;
                    213:                }
                    214:                ncolors = max(ncolors, tcolors);
                    215:        }
                    216:
                    217: #ifdef notyet
                    218:        /*
                    219:         * Knowing the size of the largest cache on this CPU, re-color
                    220:         * our pages.
                    221:         */
                    222:        if (ncolors <= uvmexp.ncolors)
                    223:                return;
                    224:        printf("%s: %d page colors\n", ci->ci_dev->dv_xname, ncolors);
                    225:        uvm_page_recolor(ncolors);
                    226: #endif
                    227: }
                    228:
                    229:
                    230: void
                    231: cpu_attach(struct device *parent, struct device *self, void *aux)
                    232: {
                    233:        struct cpu_softc *sc = (void *) self;
                    234:        struct cpu_attach_args *caa = aux;
                    235:        struct cpu_info *ci;
                    236: #if defined(MULTIPROCESSOR)
                    237:        int cpunum = caa->cpu_number;
                    238:        vaddr_t kstack;
                    239:        struct pcb *pcb;
                    240: #endif
                    241:
                    242:        /*
                    243:         * If we're an Application Processor, allocate a cpu_info
                    244:         * structure, otherwise use the primary's.
                    245:         */
                    246:        if (caa->cpu_role == CPU_ROLE_AP) {
                    247:                ci = malloc(sizeof(*ci), M_DEVBUF, M_WAITOK);
                    248:                memset(ci, 0, sizeof(*ci));
                    249: #if defined(MULTIPROCESSOR)
                    250:                if (cpu_info[cpunum] != NULL)
                    251:                        panic("cpu at apic id %d already attached?", cpunum);
                    252:                cpu_info[cpunum] = ci;
                    253: #endif
                    254: #ifdef TRAPLOG
                    255:                ci->ci_tlog_base = malloc(sizeof(struct tlog),
                    256:                    M_DEVBUF, M_WAITOK);
                    257: #endif
                    258:        } else {
                    259:                ci = &cpu_info_primary;
                    260: #if defined(MULTIPROCESSOR)
                    261:                if (cpunum != lapic_cpu_number()) {
                    262:                        panic("%s: running cpu is at apic %d"
                    263:                            " instead of at expected %d",
                    264:                            sc->sc_dev.dv_xname, lapic_cpu_number(), cpunum);
                    265:                }
                    266: #endif
                    267:        }
                    268:
                    269:        ci->ci_self = ci;
                    270:        sc->sc_info = ci;
                    271:
                    272:        ci->ci_dev = self;
                    273:        ci->ci_apicid = caa->cpu_number;
                    274: #ifdef MULTIPROCESSOR
                    275:        ci->ci_cpuid = ci->ci_apicid;
                    276: #else
                    277:        ci->ci_cpuid = 0;       /* False for APs, but they're not used anyway */
                    278: #endif
                    279:        ci->ci_func = caa->cpu_func;
                    280:
                    281:        simple_lock_init(&ci->ci_slock);
                    282:
                    283: #if defined(MULTIPROCESSOR)
                    284:        /*
                    285:         * Allocate UPAGES contiguous pages for the idle PCB and stack.
                    286:         */
                    287:        kstack = uvm_km_alloc (kernel_map, USPACE);
                    288:        if (kstack == 0) {
                    289:                if (caa->cpu_role != CPU_ROLE_AP) {
                    290:                        panic("cpu_attach: unable to allocate idle stack for"
                    291:                            " primary");
                    292:                }
                    293:                printf("%s: unable to allocate idle stack\n",
                    294:                    sc->sc_dev.dv_xname);
                    295:                return;
                    296:        }
                    297:        pcb = ci->ci_idle_pcb = (struct pcb *) kstack;
                    298:        memset(pcb, 0, USPACE);
                    299:
                    300:        pcb->pcb_tss.tss_rsp0 = kstack + USPACE - 16;
                    301:        pcb->pcb_rbp = pcb->pcb_rsp = kstack + USPACE - 16;
                    302:        pcb->pcb_tss.tss_ist[0] = kstack + PAGE_SIZE - 16;
                    303:        pcb->pcb_pmap = pmap_kernel();
                    304:        pcb->pcb_cr0 = rcr0();
                    305:        pcb->pcb_cr3 = pcb->pcb_pmap->pm_pdirpa;
                    306: #endif
                    307:
                    308:        /* further PCB init done later. */
                    309:
                    310:        printf(": ");
                    311:
                    312:        switch (caa->cpu_role) {
                    313:        case CPU_ROLE_SP:
                    314:                printf("(uniprocessor)\n");
                    315:                ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY;
                    316:                cpu_intr_init(ci);
                    317:                identifycpu(ci);
                    318:                cpu_init(ci);
                    319:                break;
                    320:
                    321:        case CPU_ROLE_BP:
                    322:                printf("apid %d (boot processor)\n", caa->cpu_number);
                    323:                ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY;
                    324:                cpu_intr_init(ci);
                    325:                identifycpu(ci);
                    326:                cpu_init(ci);
                    327:
                    328: #if NLAPIC > 0
                    329:                /*
                    330:                 * Enable local apic
                    331:                 */
                    332:                lapic_enable();
                    333:                lapic_calibrate_timer(ci);
                    334: #endif
                    335: #if NIOAPIC > 0
                    336:                ioapic_bsp_id = caa->cpu_number;
                    337: #endif
                    338:                break;
                    339:
                    340:        case CPU_ROLE_AP:
                    341:                /*
                    342:                 * report on an AP
                    343:                 */
                    344:                printf("apid %d (application processor)\n", caa->cpu_number);
                    345:
                    346: #if defined(MULTIPROCESSOR)
                    347:                cpu_intr_init(ci);
                    348:                gdt_alloc_cpu(ci);
                    349:                cpu_start_secondary(ci);
                    350:                ncpus++;
                    351:                if (ci->ci_flags & CPUF_PRESENT) {
                    352:                        identifycpu(ci);
                    353:                        ci->ci_next = cpu_info_list->ci_next;
                    354:                        cpu_info_list->ci_next = ci;
                    355:                }
                    356: #else
                    357:                printf("%s: not started\n", sc->sc_dev.dv_xname);
                    358: #endif
                    359:                break;
                    360:
                    361:        default:
                    362:                panic("unknown processor type??");
                    363:        }
                    364:        cpu_vm_init(ci);
                    365:
                    366:        cpus_attached |= (1 << ci->ci_cpuid);
                    367:
                    368: #if defined(MULTIPROCESSOR)
                    369:        if (mp_verbose) {
                    370:                printf("%s: kstack at 0x%lx for %d bytes\n",
                    371:                    sc->sc_dev.dv_xname, kstack, USPACE);
                    372:                printf("%s: idle pcb at %p, idle sp at 0x%lx\n",
                    373:                    sc->sc_dev.dv_xname, pcb, pcb->pcb_rsp);
                    374:        }
                    375: #endif
                    376: }
                    377:
                    378: /*
                    379:  * Initialize the processor appropriately.
                    380:  */
                    381:
                    382: void
                    383: cpu_init(struct cpu_info *ci)
                    384: {
                    385:        /* configure the CPU if needed */
                    386:        if (ci->cpu_setup != NULL)
                    387:                (*ci->cpu_setup)(ci);
                    388:
                    389:        lcr0(rcr0() | CR0_WP);
                    390:        lcr4(rcr4() | CR4_DEFAULT);
                    391:
                    392: #ifdef MTRR
                    393:        if ((ci->ci_flags & CPUF_AP) == 0)
                    394:                i686_mtrr_init_first();
                    395:        mtrr_init_cpu(ci);
                    396: #endif
                    397:
                    398: #ifdef MULTIPROCESSOR
                    399:        ci->ci_flags |= CPUF_RUNNING;
                    400:        cpus_running |= 1 << ci->ci_cpuid;
                    401: #endif
                    402: }
                    403:
                    404:
                    405: #ifdef MULTIPROCESSOR
                    406: void
                    407: cpu_boot_secondary_processors(void)
                    408: {
                    409:        struct cpu_info *ci;
                    410:        u_long i;
                    411:
                    412:        for (i=0; i < X86_MAXPROCS; i++) {
                    413:                ci = cpu_info[i];
                    414:                if (ci == NULL)
                    415:                        continue;
                    416:                if (ci->ci_idle_pcb == NULL)
                    417:                        continue;
                    418:                if ((ci->ci_flags & CPUF_PRESENT) == 0)
                    419:                        continue;
                    420:                if (ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY))
                    421:                        continue;
                    422:                cpu_boot_secondary(ci);
                    423:        }
                    424: }
                    425:
                    426: void
                    427: cpu_init_idle_pcbs(void)
                    428: {
                    429:        struct cpu_info *ci;
                    430:        u_long i;
                    431:
                    432:        for (i=0; i < X86_MAXPROCS; i++) {
                    433:                ci = cpu_info[i];
                    434:                if (ci == NULL)
                    435:                        continue;
                    436:                if (ci->ci_idle_pcb == NULL)
                    437:                        continue;
                    438:                if ((ci->ci_flags & CPUF_PRESENT) == 0)
                    439:                        continue;
                    440:                x86_64_init_pcb_tss_ldt(ci);
                    441:        }
                    442: }
                    443:
                    444: void
                    445: cpu_start_secondary(struct cpu_info *ci)
                    446: {
                    447:        struct pcb *pcb;
                    448:        int i;
                    449:
                    450:        pcb = ci->ci_idle_pcb;
                    451:
                    452:        ci->ci_flags |= CPUF_AP;
                    453:
                    454:        CPU_STARTUP(ci);
                    455:
                    456:        /*
                    457:         * wait for it to become ready
                    458:         */
                    459:        for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {
                    460:                delay(10);
                    461:        }
                    462:        if (! (ci->ci_flags & CPUF_PRESENT)) {
                    463:                printf("%s: failed to become ready\n", ci->ci_dev->dv_xname);
                    464: #if defined(MPDEBUG) && defined(DDB)
                    465:                printf("dropping into debugger; continue from here to resume boot\n");
                    466:                Debugger();
                    467: #endif
                    468:        }
                    469:
                    470:        CPU_START_CLEANUP(ci);
                    471: }
                    472:
                    473: void
                    474: cpu_boot_secondary(struct cpu_info *ci)
                    475: {
                    476:        int i;
                    477:
                    478:        ci->ci_flags |= CPUF_GO; /* XXX atomic */
                    479:
                    480:        for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) {
                    481:                delay(10);
                    482:        }
                    483:        if (! (ci->ci_flags & CPUF_RUNNING)) {
                    484:                printf("cpu failed to start\n");
                    485: #if defined(MPDEBUG) && defined(DDB)
                    486:                printf("dropping into debugger; continue from here to resume boot\n");
                    487:                Debugger();
                    488: #endif
                    489:        }
                    490: }
                    491:
                    492: /*
                    493:  * The CPU ends up here when its ready to run
                    494:  * This is called from code in mptramp.s; at this point, we are running
                    495:  * in the idle pcb/idle stack of the new cpu.  When this function returns,
                    496:  * this processor will enter the idle loop and start looking for work.
                    497:  *
                    498:  * XXX should share some of this with init386 in machdep.c
                    499:  */
                    500: void
                    501: cpu_hatch(void *v)
                    502: {
                    503:        struct cpu_info *ci = (struct cpu_info *)v;
                    504:        int s;
                    505:
                    506:        cpu_init_msrs(ci);
                    507:
                    508:        cpu_probe_features(ci);
                    509:        cpu_feature &= ci->ci_feature_flags;
                    510:
                    511: #ifdef DEBUG
                    512:        if (ci->ci_flags & CPUF_PRESENT)
                    513:                panic("%s: already running!?", ci->ci_dev->dv_xname);
                    514: #endif
                    515:
                    516:        ci->ci_flags |= CPUF_PRESENT;
                    517:
                    518:        lapic_enable();
                    519:        lapic_initclocks();
                    520:
                    521:        while ((ci->ci_flags & CPUF_GO) == 0)
                    522:                delay(10);
                    523: #ifdef DEBUG
                    524:        if (ci->ci_flags & CPUF_RUNNING)
                    525:                panic("%s: already running!?", ci->ci_dev->dv_xname);
                    526: #endif
                    527:
                    528:        lcr0(ci->ci_idle_pcb->pcb_cr0);
                    529:        cpu_init_idt();
                    530:        lapic_set_lvt();
                    531:        gdt_init_cpu(ci);
                    532:        fpuinit(ci);
                    533:
                    534:        lldt(GSYSSEL(GLDT_SEL, SEL_KPL));
                    535:
                    536:        cpu_init(ci);
                    537:
                    538:        s = splhigh();
                    539:        lcr8(0);
                    540:        enable_intr();
                    541:
                    542:        microuptime(&ci->ci_schedstate.spc_runtime);
                    543:        splx(s);
                    544: }
                    545:
                    546: #if defined(DDB)
                    547:
                    548: #include <ddb/db_output.h>
                    549: #include <machine/db_machdep.h>
                    550:
                    551: /*
                    552:  * Dump cpu information from ddb.
                    553:  */
                    554: void
                    555: cpu_debug_dump(void)
                    556: {
                    557:        struct cpu_info *ci;
                    558:        CPU_INFO_ITERATOR cii;
                    559:
                    560:        db_printf("addr         dev     id      flags   ipis    curproc         fpcurproc\n");
                    561:        CPU_INFO_FOREACH(cii, ci) {
                    562:                db_printf("%p   %s      %u      %x      %x      %10p    %10p\n",
                    563:                    ci,
                    564:                    ci->ci_dev == NULL ? "BOOT" : ci->ci_dev->dv_xname,
                    565:                    ci->ci_cpuid,
                    566:                    ci->ci_flags, ci->ci_ipis,
                    567:                    ci->ci_curproc,
                    568:                    ci->ci_fpcurproc);
                    569:        }
                    570: }
                    571: #endif
                    572:
                    573: static void
                    574: cpu_copy_trampoline(void)
                    575: {
                    576:        /*
                    577:         * Copy boot code.
                    578:         */
                    579:        extern u_char cpu_spinup_trampoline[];
                    580:        extern u_char cpu_spinup_trampoline_end[];
                    581:
                    582:        struct pmap *kmp = pmap_kernel();
                    583:        extern u_int32_t mp_pdirpa;
                    584:        extern vaddr_t lo32_vaddr;
                    585:        extern paddr_t lo32_paddr;
                    586:
                    587:        pmap_kenter_pa((vaddr_t)MP_TRAMPOLINE,  /* virtual */
                    588:            (paddr_t)MP_TRAMPOLINE,     /* physical */
                    589:            VM_PROT_ALL);               /* protection */
                    590:        memcpy((caddr_t)MP_TRAMPOLINE,
                    591:            cpu_spinup_trampoline,
                    592:            cpu_spinup_trampoline_end-cpu_spinup_trampoline);
                    593:
                    594:        /*
                    595:         * The initial PML4 pointer must be below 4G, so if the
                    596:         * current one isn't, use a "bounce buffer"
                    597:         * We need to patch this after we copy the trampoline,
                    598:         * the symbol points into the copied trampoline.
                    599:         */
                    600:        if (kmp->pm_pdirpa > 0xffffffff) {
                    601:                memcpy((void *)lo32_vaddr, kmp->pm_pdir, PAGE_SIZE);
                    602:                mp_pdirpa = lo32_paddr;
                    603:        } else
                    604:                mp_pdirpa = kmp->pm_pdirpa;
                    605: }
                    606:
                    607:
                    608: int
                    609: mp_cpu_start(struct cpu_info *ci)
                    610: {
                    611: #if NLAPIC > 0
                    612:        int error;
                    613: #endif
                    614:        unsigned short dwordptr[2];
                    615:
                    616:        /*
                    617:         * "The BSP must initialize CMOS shutdown code to 0Ah ..."
                    618:         */
                    619:
                    620:        outb(IO_RTC, NVRAM_RESET);
                    621:        outb(IO_RTC+1, NVRAM_RESET_JUMP);
                    622:
                    623:        /*
                    624:         * "and the warm reset vector (DWORD based at 40:67) to point
                    625:         * to the AP startup code ..."
                    626:         */
                    627:
                    628:        dwordptr[0] = 0;
                    629:        dwordptr[1] = MP_TRAMPOLINE >> 4;
                    630:
                    631:        pmap_kenter_pa(0, 0, VM_PROT_READ|VM_PROT_WRITE);
                    632:        memcpy((u_int8_t *) 0x467, dwordptr, 4);
                    633:        pmap_kremove(0, PAGE_SIZE);
                    634:
                    635: #if NLAPIC > 0
                    636:        /*
                    637:         * ... prior to executing the following sequence:"
                    638:         */
                    639:
                    640:        if (ci->ci_flags & CPUF_AP) {
                    641:                if ((error = x86_ipi_init(ci->ci_apicid)) != 0)
                    642:                        return error;
                    643:
                    644:                delay(10000);
                    645:
                    646:                if (cpu_feature & CPUID_APIC) {
                    647:                        if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
                    648:                                             ci->ci_apicid,
                    649:                                             LAPIC_DLMODE_STARTUP)) != 0)
                    650:                                return error;
                    651:                        delay(200);
                    652:
                    653:                        if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
                    654:                                             ci->ci_apicid,
                    655:                                             LAPIC_DLMODE_STARTUP)) != 0)
                    656:                                return error;
                    657:                        delay(200);
                    658:                }
                    659:        }
                    660: #endif
                    661:        return 0;
                    662: }
                    663:
                    664: void
                    665: mp_cpu_start_cleanup(struct cpu_info *ci)
                    666: {
                    667:        /*
                    668:         * Ensure the NVRAM reset byte contains something vaguely sane.
                    669:         */
                    670:
                    671:        outb(IO_RTC, NVRAM_RESET);
                    672:        outb(IO_RTC+1, NVRAM_RESET_RST);
                    673: }
                    674: #endif /* MULTIPROCESSOR */
                    675:
                    676: typedef void (vector)(void);
                    677: extern vector Xsyscall, Xsyscall32;
                    678:
                    679: void
                    680: cpu_init_msrs(struct cpu_info *ci)
                    681: {
                    682:        wrmsr(MSR_STAR,
                    683:            ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
                    684:            ((uint64_t)LSEL(LSYSRETBASE_SEL, SEL_UPL) << 48));
                    685:        wrmsr(MSR_LSTAR, (uint64_t)Xsyscall);
                    686:        wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32);
                    687:        wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C);
                    688:
                    689:        wrmsr(MSR_FSBASE, 0);
                    690:        wrmsr(MSR_GSBASE, (u_int64_t)ci);
                    691:        wrmsr(MSR_KERNELGSBASE, 0);
                    692:
                    693:        if (cpu_feature & CPUID_NXE)
                    694:                wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NXE);
                    695: }

CVSweb