[BACK]Return to integrator_machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / evbarm / integrator

Annotation of src/sys/arch/evbarm/integrator/integrator_machdep.c, Revision 1.47

1.47    ! rearnsha    1: /*     $NetBSD: integrator_machdep.c,v 1.46 2003/09/06 10:28:26 rearnsha Exp $ */
1.1       rearnsha    2:
                      3: /*
1.23      rearnsha    4:  * Copyright (c) 2001,2002 ARM Ltd
1.1       rearnsha    5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the company may not be used to endorse or promote
                     16:  *    products derived from this software without specific prior written
                     17:  *    permission.
                     18:  *
1.23      rearnsha   19:  * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ARM LTD
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
1.1       rearnsha   33:  * Copyright (c) 1997,1998 Mark Brinicombe.
                     34:  * Copyright (c) 1997,1998 Causality Limited.
                     35:  * All rights reserved.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
                     45:  * 3. All advertising materials mentioning features or use of this software
                     46:  *    must display the following acknowledgement:
                     47:  *     This product includes software developed by Mark Brinicombe
                     48:  *     for the NetBSD Project.
                     49:  * 4. The name of the company nor the name of the author may be used to
                     50:  *    endorse or promote products derived from this software without specific
                     51:  *    prior written permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     54:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     55:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     56:  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     57:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     58:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     59:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     60:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     61:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     62:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     63:  * SUCH DAMAGE.
                     64:  *
                     65:  * Machine dependant functions for kernel setup for integrator board
                     66:  *
                     67:  * Created      : 24/11/97
                     68:  */
1.43      lukem      69:
                     70: #include <sys/cdefs.h>
1.47    ! rearnsha   71: __KERNEL_RCSID(0, "$NetBSD: integrator_machdep.c,v 1.46 2003/09/06 10:28:26 rearnsha Exp $");
1.1       rearnsha   72:
                     73: #include "opt_ddb.h"
                     74: #include "opt_pmap_debug.h"
                     75:
                     76: #include <sys/param.h>
                     77: #include <sys/device.h>
                     78: #include <sys/systm.h>
                     79: #include <sys/kernel.h>
                     80: #include <sys/exec.h>
                     81: #include <sys/proc.h>
                     82: #include <sys/msgbuf.h>
                     83: #include <sys/reboot.h>
                     84: #include <sys/termios.h>
1.32      ragge      85: #include <sys/ksyms.h>
1.1       rearnsha   86:
1.31      thorpej    87: #include <uvm/uvm_extern.h>
                     88:
1.1       rearnsha   89: #include <dev/cons.h>
                     90:
                     91: #include <machine/db_machdep.h>
                     92: #include <ddb/db_sym.h>
                     93: #include <ddb/db_extern.h>
                     94:
                     95: #include <machine/bootconfig.h>
                     96: #include <machine/bus.h>
                     97: #include <machine/cpu.h>
                     98: #include <machine/frame.h>
                     99: #include <machine/intr.h>
1.8       thorpej   100: #include <evbarm/ifpga/irqhandler.h>   /* XXX XXX XXX */
1.6       thorpej   101: #include <arm/undefined.h>
1.1       rearnsha  102:
1.23      rearnsha  103: #include <arm/arm32/machdep.h>
                    104:
1.1       rearnsha  105: #include <evbarm/integrator/integrator_boot.h>
                    106:
                    107: #include "opt_ipkdb.h"
                    108: #include "pci.h"
1.32      ragge     109: #include "ksyms.h"
1.1       rearnsha  110:
                    111: void ifpga_reset(void) __attribute__((noreturn));
1.36      thorpej   112:
                    113: /* Kernel text starts 2MB in from the bottom of the kernel address space. */
                    114: #define        KERNEL_TEXT_BASE        (KERNEL_BASE + 0x00200000)
1.39      thorpej   115: #define        KERNEL_VM_BASE          (KERNEL_BASE + 0x01000000)
1.40      thorpej   116:
                    117: /*
                    118:  * The range 0xc1000000 - 0xccffffff is available for kernel VM space
                    119:  * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff
                    120:  */
                    121: #define KERNEL_VM_SIZE         0x0C000000
1.36      thorpej   122:
1.1       rearnsha  123: /*
                    124:  * Address to call from cpu_reset() to reset the machine.
                    125:  * This is machine architecture dependant as it varies depending
                    126:  * on where the ROM appears when you turn the MMU off.
                    127:  */
                    128:
                    129: u_int cpu_reset_address = (u_int) ifpga_reset;
                    130:
                    131: /* Define various stack sizes in pages */
                    132: #define IRQ_STACK_SIZE 1
                    133: #define ABT_STACK_SIZE 1
                    134: #ifdef IPKDB
                    135: #define UND_STACK_SIZE 2
                    136: #else
                    137: #define UND_STACK_SIZE 1
                    138: #endif
                    139:
                    140: BootConfig bootconfig;         /* Boot config storage */
                    141: char *boot_args = NULL;
                    142: char *boot_file = NULL;
                    143:
                    144: vm_offset_t physical_start;
                    145: vm_offset_t physical_end;
                    146: vm_offset_t pagetables_start;
                    147: int physmem = 0;
                    148:
                    149: /*int debug_flags;*/
                    150: #ifndef PMAP_STATIC_L1S
                    151: int max_processes = 64;                        /* Default number */
                    152: #endif /* !PMAP_STATIC_L1S */
                    153:
                    154: /* Physical and virtual addresses for some global pages */
                    155: pv_addr_t systempage;
                    156: pv_addr_t irqstack;
                    157: pv_addr_t undstack;
                    158: pv_addr_t abtstack;
                    159: pv_addr_t kernelstack;
                    160:
                    161: vm_offset_t msgbufphys;
                    162:
                    163: extern u_int data_abort_handler_address;
                    164: extern u_int prefetch_abort_handler_address;
                    165: extern u_int undefined_handler_address;
                    166:
                    167: #ifdef PMAP_DEBUG
                    168: extern int pmap_debug_level;
                    169: #endif
                    170:
1.23      rearnsha  171: #define KERNEL_PT_SYS          0       /* L2 table for mapping zero page */
                    172:
                    173: #define KERNEL_PT_KERNEL       1       /* L2 table for mapping kernel */
                    174: #define        KERNEL_PT_KERNEL_NUM    2
                    175:                                        /* L2 tables for mapping kernel VM */
                    176: #define KERNEL_PT_VMDATA       (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
1.17      chris     177: #define        KERNEL_PT_VMDATA_NUM    4       /* start with 16MB of KVM */
1.1       rearnsha  178: #define NUM_KERNEL_PTS         (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
                    179:
1.14      thorpej   180: pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
1.1       rearnsha  181:
                    182: struct user *proc0paddr;
                    183:
                    184: /* Prototypes */
                    185:
1.23      rearnsha  186: static void    integrator_sdram_bounds (paddr_t *, psize_t *);
1.1       rearnsha  187:
1.23      rearnsha  188: void   consinit(void);
1.1       rearnsha  189:
                    190: /* A load of console goo. */
                    191: #include "vga.h"
1.23      rearnsha  192: #if NVGA > 0
1.1       rearnsha  193: #include <dev/ic/mc6845reg.h>
                    194: #include <dev/ic/pcdisplayvar.h>
                    195: #include <dev/ic/vgareg.h>
                    196: #include <dev/ic/vgavar.h>
                    197: #endif
                    198:
                    199: #include "pckbc.h"
1.23      rearnsha  200: #if NPCKBC > 0
1.1       rearnsha  201: #include <dev/ic/i8042reg.h>
                    202: #include <dev/ic/pckbcvar.h>
                    203: #endif
                    204:
                    205: #include "com.h"
1.23      rearnsha  206: #if NCOM > 0
1.1       rearnsha  207: #include <dev/ic/comreg.h>
                    208: #include <dev/ic/comvar.h>
                    209: #ifndef CONCOMADDR
                    210: #define CONCOMADDR 0x3f8
                    211: #endif
                    212: #endif
                    213:
1.23      rearnsha  214: /*
                    215:  * Define the default console speed for the board.  This is generally
                    216:  * what the firmware provided with the board defaults to.
                    217:  */
1.30      mycroft   218: #ifndef CONSPEED
1.1       rearnsha  219: #define CONSPEED B115200
                    220: #endif
                    221: #ifndef CONMODE
                    222: #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    223: #endif
                    224:
                    225: int comcnspeed = CONSPEED;
                    226: int comcnmode = CONMODE;
                    227:
                    228: #include "plcom.h"
                    229: #if (NPLCOM > 0)
                    230: #include <evbarm/dev/plcomreg.h>
                    231: #include <evbarm/dev/plcomvar.h>
                    232:
                    233: #include <evbarm/ifpga/ifpgamem.h>
                    234: #include <evbarm/ifpga/ifpgareg.h>
                    235: #include <evbarm/ifpga/ifpgavar.h>
                    236: #endif
                    237:
                    238: #ifndef CONSDEVNAME
                    239: #define CONSDEVNAME "plcom"
                    240: #endif
                    241:
                    242: #ifndef PLCONSPEED
                    243: #define PLCONSPEED B38400
                    244: #endif
                    245: #ifndef PLCONMODE
                    246: #define PLCONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    247: #endif
                    248: #ifndef PLCOMCNUNIT
                    249: #define PLCOMCNUNIT -1
                    250: #endif
                    251:
                    252: int plcomcnspeed = PLCONSPEED;
                    253: int plcomcnmode = PLCONMODE;
                    254:
                    255: #if 0
                    256: extern struct consdev kcomcons;
                    257: static void kcomcnputc(dev_t, int);
                    258: #endif
                    259:
                    260: /*
                    261:  * void cpu_reboot(int howto, char *bootstr)
                    262:  *
                    263:  * Reboots the system
                    264:  *
                    265:  * Deal with any syncing, unmounting, dumping and shutdown hooks,
                    266:  * then reset the CPU.
                    267:  */
                    268: void
1.23      rearnsha  269: cpu_reboot(int howto, char *bootstr)
1.1       rearnsha  270: {
                    271:
                    272:        /*
                    273:         * If we are still cold then hit the air brakes
                    274:         * and crash to earth fast
                    275:         */
                    276:        if (cold) {
                    277:                doshutdownhooks();
                    278:                printf("The operating system has halted.\n");
                    279:                printf("Please press any key to reboot.\n\n");
                    280:                cngetc();
                    281:                printf("rebooting...\n");
                    282:                ifpga_reset();
                    283:                /*NOTREACHED*/
                    284:        }
                    285:
                    286:        /* Disable console buffering */
                    287:
                    288:        /*
                    289:         * If RB_NOSYNC was not specified sync the discs.
1.23      rearnsha  290:         * Note: Unless cold is set to 1 here, syslogd will die during the
                    291:         * unmount.  It looks like syslogd is getting woken up only to find
                    292:         * that it cannot page part of the binary in as the filesystem has
                    293:         * been unmounted.
1.1       rearnsha  294:         */
                    295:        if (!(howto & RB_NOSYNC))
                    296:                bootsync();
                    297:
                    298:        /* Say NO to interrupts */
                    299:        splhigh();
                    300:
                    301:        /* Do a dump if requested. */
                    302:        if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
                    303:                dumpsys();
                    304:
                    305:        /* Run any shutdown hooks */
                    306:        doshutdownhooks();
                    307:
                    308:        /* Make sure IRQ's are disabled */
                    309:        IRQdisable;
                    310:
                    311:        if (howto & RB_HALT) {
                    312:                printf("The operating system has halted.\n");
                    313:                printf("Please press any key to reboot.\n\n");
                    314:                cngetc();
                    315:        }
                    316:
                    317:        printf("rebooting...\n");
                    318:        ifpga_reset();
                    319:        /*NOTREACHED*/
                    320: }
                    321:
1.42      thorpej   322: /* Statically mapped devices. */
                    323: static const struct pmap_devmap integrator_devmap[] = {
1.1       rearnsha  324: #if NPLCOM > 0 && defined(PLCONSOLE)
1.23      rearnsha  325:        {
                    326:                UART0_BOOT_BASE,
                    327:                IFPGA_IO_BASE + IFPGA_UART0,
                    328:                1024 * 1024,
                    329:                VM_PROT_READ|VM_PROT_WRITE,
                    330:                PTE_NOCACHE
                    331:        },
                    332:
                    333:        {
                    334:                UART1_BOOT_BASE,
                    335:                IFPGA_IO_BASE + IFPGA_UART1,
                    336:                1024 * 1024,
                    337:                VM_PROT_READ|VM_PROT_WRITE,
                    338:                PTE_NOCACHE
                    339:        },
1.1       rearnsha  340: #endif
                    341: #if NPCI > 0
1.23      rearnsha  342:        {
                    343:                IFPGA_PCI_IO_VBASE,
                    344:                IFPGA_PCI_IO_BASE,
                    345:                IFPGA_PCI_IO_VSIZE,
                    346:                VM_PROT_READ|VM_PROT_WRITE,
                    347:                PTE_NOCACHE
                    348:        },
                    349:
                    350:        {
                    351:                IFPGA_PCI_CONF_VBASE,
                    352:                IFPGA_PCI_CONF_BASE,
                    353:                IFPGA_PCI_CONF_VSIZE,
                    354:                VM_PROT_READ|VM_PROT_WRITE,
1.42      thorpej   355:                PTE_NOCACHE
                    356:        },
1.1       rearnsha  357: #endif
                    358:
1.23      rearnsha  359:        {
                    360:                0,
                    361:                0,
                    362:                0,
                    363:                0,
                    364:                0
                    365:        }
1.1       rearnsha  366: };
                    367:
                    368: /*
1.23      rearnsha  369:  * u_int initarm(...)
1.1       rearnsha  370:  *
                    371:  * Initial entry point on startup. This gets called before main() is
                    372:  * entered.
                    373:  * It should be responsible for setting up everything that must be
                    374:  * in place when main is called.
                    375:  * This includes
                    376:  *   Taking a copy of the boot configuration structure.
                    377:  *   Initialising the physical console so characters can be printed.
                    378:  *   Setting up page tables for the kernel
                    379:  *   Relocating the kernel to the bottom of physical memory
                    380:  */
                    381:
                    382: u_int
1.23      rearnsha  383: initarm(void *arg)
1.1       rearnsha  384: {
                    385:        int loop;
                    386:        int loop1;
                    387:        u_int l1pagetable;
1.47    ! rearnsha  388:        extern char etext asm ("_etext");
        !           389:        extern char end asm ("_end");
1.1       rearnsha  390:        pv_addr_t kernel_l1pt;
1.23      rearnsha  391:        paddr_t memstart;
                    392:        psize_t memsize;
1.47    ! rearnsha  393:        vm_offset_t physical_freestart;
        !           394:        vm_offset_t physical_freeend;
1.1       rearnsha  395: #if NPLCOM > 0 && defined(PLCONSOLE)
                    396:        static struct bus_space plcom_bus_space;
                    397: #endif
                    398:
                    399:        /*
                    400:         * Heads up ... Setup the CPU / MMU / TLB functions
                    401:         */
                    402:        if (set_cpufuncs())
                    403:                panic("cpu not recognized!");
                    404:
                    405: #if NPLCOM > 0 && defined(PLCONSOLE)
                    406:        /*
                    407:         * Initialise the diagnostic serial console
                    408:         * This allows a means of generating output during initarm().
                    409:         * Once all the memory map changes are complete we can call consinit()
                    410:         * and not have to worry about things moving.
                    411:         */
                    412:
                    413:        if (PLCOMCNUNIT == 0) {
                    414:                ifpga_create_io_bs_tag(&plcom_bus_space, (void*)0xfd600000);
                    415:                plcomcnattach(&plcom_bus_space, 0, plcomcnspeed,
                    416:                    IFPGA_UART_CLK, plcomcnmode, PLCOMCNUNIT);
                    417:        } else if (PLCOMCNUNIT == 1) {
                    418:                ifpga_create_io_bs_tag(&plcom_bus_space, (void*)0xfd700000);
                    419:                plcomcnattach(&plcom_bus_space, 0, plcomcnspeed,
                    420:                    IFPGA_UART_CLK, plcomcnmode, PLCOMCNUNIT);
                    421:        }
                    422: #endif
                    423:
1.38      thorpej   424: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  425:        /* Talk to the user */
1.23      rearnsha  426:        printf("\nNetBSD/evbarm (Integrator) booting ...\n");
1.38      thorpej   427: #endif
1.1       rearnsha  428:
                    429:        /*
1.23      rearnsha  430:         * Fetch the SDRAM start/size from the CM configuration registers.
1.1       rearnsha  431:         */
1.23      rearnsha  432:        integrator_sdram_bounds(&memstart, &memsize);
1.1       rearnsha  433:
1.38      thorpej   434: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  435:        printf("initarm: Configuring system ...\n");
1.38      thorpej   436: #endif
1.1       rearnsha  437:
1.23      rearnsha  438:        /* Fake bootconfig structure for the benefit of pmap.c */
                    439:        /* XXX must make the memory description h/w independent */
                    440:        bootconfig.dramblocks = 1;
                    441:        bootconfig.dram[0].address = memstart;
1.31      thorpej   442:        bootconfig.dram[0].pages = memsize / PAGE_SIZE;
1.47    ! rearnsha  443:        bootconfig.dram[0].flags = BOOT_DRAM_CAN_DMA | BOOT_DRAM_PREFER;
1.23      rearnsha  444:
1.1       rearnsha  445:        /*
                    446:         * Set up the variables that define the availablilty of
1.23      rearnsha  447:         * physical memory.  For now, we're going to set
                    448:         * physical_freestart to 0x00200000 (where the kernel
                    449:         * was loaded), and allocate the memory we need downwards.
                    450:         * If we get too close to the L1 table that we set up, we
                    451:         * will panic.  We will update physical_freestart and
                    452:         * physical_freeend later to reflect what pmap_bootstrap()
                    453:         * wants to see.
                    454:         *
1.47    ! rearnsha  455:         * We assume that the kernel is loaded into bank[0].
        !           456:         *
1.23      rearnsha  457:         * XXX pmap_bootstrap() needs an enema.
1.1       rearnsha  458:         */
1.23      rearnsha  459:        physical_start = bootconfig.dram[0].address;
1.47    ! rearnsha  460:        physical_end = 0;
1.1       rearnsha  461:
1.47    ! rearnsha  462:        /* Update the address of the first free 16KB chunk of physical memory */
        !           463:        physical_freestart = ((uintptr_t) &end - KERNEL_BASE + PGOFSET)
        !           464:            & ~PGOFSET;
        !           465:        if (physical_freestart < bootconfig.dram[0].address)
        !           466:                physical_freestart = bootconfig.dram[0].address;
        !           467:        physical_freeend = bootconfig.dram[0].address +
        !           468:            bootconfig.dram[0].pages * PAGE_SIZE;
        !           469:
        !           470:        for (loop = 0, physmem = 0; loop < bootconfig.dramblocks; loop++) {
        !           471:                paddr_t memoryblock_end;
        !           472:
        !           473:                memoryblock_end = bootconfig.dram[loop].address +
        !           474:                    bootconfig.dram[loop].pages * PAGE_SIZE;
        !           475:                if (memoryblock_end > physical_end)
        !           476:                        physical_end = memoryblock_end;
        !           477:                if (bootconfig.dram[loop].address < physical_start)
        !           478:                        physical_start = bootconfig.dram[loop].address;
        !           479:
        !           480:                physmem += bootconfig.dram[loop].pages;
        !           481:        }
1.1       rearnsha  482:
1.38      thorpej   483: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  484:        /* Tell the user about the memory */
                    485:        printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
                    486:            physical_start, physical_end - 1);
1.38      thorpej   487: #endif
1.1       rearnsha  488:
                    489:        /*
1.23      rearnsha  490:         * Okay, the kernel starts 2MB in from the bottom of physical
                    491:         * memory.  We are going to allocate our bootstrap pages downwards
                    492:         * from there.
1.1       rearnsha  493:         *
1.23      rearnsha  494:         * We need to allocate some fixed page tables to get the kernel
                    495:         * going.  We allocate one page directory and a number of page
                    496:         * tables and store the physical addresses in the kernel_pt_table
                    497:         * array.
                    498:         *
                    499:         * The kernel page directory must be on a 16K boundary.  The page
                    500:         * tables must be on 4K bounaries.  What we do is allocate the
                    501:         * page directory on the first 16K boundary that we encounter, and
                    502:         * the page tables on 4K boundaries otherwise.  Since we allocate
                    503:         * at least 3 L2 page tables, we are guaranteed to encounter at
                    504:         * least one 16K aligned region.
1.1       rearnsha  505:         */
                    506:
                    507: #ifdef VERBOSE_INIT_ARM
                    508:        printf("Allocating page tables\n");
                    509: #endif
                    510:
                    511: #ifdef VERBOSE_INIT_ARM
1.47    ! rearnsha  512:        printf("freestart = 0x%08lx, free pages = %d (0x%08x)\n",
        !           513:               physical_freestart, physmem, physmem);
1.1       rearnsha  514: #endif
                    515:
                    516:        /* Define a macro to simplify memory allocation */
1.23      rearnsha  517: #define        valloc_pages(var, np)                           \
                    518:        alloc_pages((var).pv_pa, (np));                 \
1.47    ! rearnsha  519:        (var).pv_va = KERNEL_BASE + (var).pv_pa;
1.23      rearnsha  520:
                    521: #define alloc_pages(var, np)                           \
1.47    ! rearnsha  522:        (var) = physical_freestart;                     \
        !           523:        physical_freestart += ((np) * PAGE_SIZE);       \
1.23      rearnsha  524:        if (physical_freeend < physical_freestart)      \
                    525:                panic("initarm: out of memory");        \
1.31      thorpej   526:        memset((char *)(var), 0, ((np) * PAGE_SIZE));
1.1       rearnsha  527:
                    528:        loop1 = 0;
                    529:        kernel_l1pt.pv_pa = 0;
                    530:        for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
                    531:                /* Are we 16KB aligned for an L1 ? */
1.47    ! rearnsha  532:                if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0
1.1       rearnsha  533:                    && kernel_l1pt.pv_pa == 0) {
1.31      thorpej   534:                        valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
1.1       rearnsha  535:                } else {
1.33      thorpej   536:                        valloc_pages(kernel_pt_table[loop1],
                    537:                            L2_TABLE_SIZE / PAGE_SIZE);
1.23      rearnsha  538:                        ++loop1;
1.1       rearnsha  539:                }
                    540:        }
                    541:
                    542:        /* This should never be able to happen but better confirm that. */
1.21      thorpej   543:        if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0)
1.28      provos    544:                panic("initarm: Failed to align the kernel page directory");
1.1       rearnsha  545:
                    546:        /*
                    547:         * Allocate a page for the system page mapped to V0x00000000
                    548:         * This page will just contain the system vectors and can be
                    549:         * shared by all processes.
                    550:         */
                    551:        alloc_pages(systempage.pv_pa, 1);
                    552:
                    553:        /* Allocate stacks for all modes */
                    554:        valloc_pages(irqstack, IRQ_STACK_SIZE);
                    555:        valloc_pages(abtstack, ABT_STACK_SIZE);
                    556:        valloc_pages(undstack, UND_STACK_SIZE);
                    557:        valloc_pages(kernelstack, UPAGES);
                    558:
                    559: #ifdef VERBOSE_INIT_ARM
1.23      rearnsha  560:        printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa,
                    561:            irqstack.pv_va);
                    562:        printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa,
                    563:            abtstack.pv_va);
                    564:        printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa,
                    565:            undstack.pv_va);
                    566:        printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa,
                    567:            kernelstack.pv_va);
1.1       rearnsha  568: #endif
                    569:
1.31      thorpej   570:        alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE);
1.1       rearnsha  571:
                    572:        /*
                    573:         * Ok we have allocated physical pages for the primary kernel
                    574:         * page tables
                    575:         */
                    576:
                    577: #ifdef VERBOSE_INIT_ARM
1.23      rearnsha  578:        printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
1.1       rearnsha  579: #endif
                    580:
                    581:        /*
1.23      rearnsha  582:         * Now we start construction of the L1 page table
1.1       rearnsha  583:         * We start by mapping the L2 page tables into the L1.
                    584:         * This means that we can replace L1 mappings later on if necessary
                    585:         */
                    586:        l1pagetable = kernel_l1pt.pv_pa;
                    587:
                    588:        /* Map the L2 pages tables in the L1 page table */
1.11      thorpej   589:        pmap_link_l2pt(l1pagetable, 0x00000000,
1.14      thorpej   590:            &kernel_pt_table[KERNEL_PT_SYS]);
1.23      rearnsha  591:        for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
                    592:                pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000,
                    593:                    &kernel_pt_table[KERNEL_PT_KERNEL + loop]);
                    594:        for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
1.11      thorpej   595:                pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000,
1.14      thorpej   596:                    &kernel_pt_table[KERNEL_PT_VMDATA + loop]);
1.17      chris     597:
                    598:        /* update the top of the kernel VM */
1.19      thorpej   599:        pmap_curmaxkvaddr =
                    600:            KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
1.1       rearnsha  601:
                    602: #ifdef VERBOSE_INIT_ARM
                    603:        printf("Mapping kernel\n");
                    604: #endif
                    605:
                    606:        /* Now we fill in the L2 pagetable for the kernel static code/data */
                    607:        {
                    608:                size_t textsize = (uintptr_t) &etext - KERNEL_TEXT_BASE;
                    609:                size_t totalsize = (uintptr_t) &end - KERNEL_TEXT_BASE;
1.23      rearnsha  610:                u_int logical;
1.1       rearnsha  611:
1.23      rearnsha  612:                textsize = (textsize + PGOFSET) & ~PGOFSET;
1.1       rearnsha  613:                totalsize = (totalsize + PGOFSET) & ~PGOFSET;
1.23      rearnsha  614:
                    615:                logical = 0x00200000;   /* offset of kernel in RAM */
                    616:
                    617:                logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
1.47    ! rearnsha  618:                    logical, textsize, VM_PROT_READ | VM_PROT_WRITE,
        !           619:                    PTE_CACHE);
1.23      rearnsha  620:                logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
1.47    ! rearnsha  621:                    logical, totalsize - textsize,
        !           622:                    VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
1.1       rearnsha  623:        }
                    624:
                    625: #ifdef VERBOSE_INIT_ARM
                    626:        printf("Constructing L2 page tables\n");
                    627: #endif
                    628:
                    629:        /* Map the stack pages */
1.14      thorpej   630:        pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
1.31      thorpej   631:            IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.14      thorpej   632:        pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
1.31      thorpej   633:            ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.14      thorpej   634:        pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
1.31      thorpej   635:            UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.14      thorpej   636:        pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
1.31      thorpej   637:            UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.13      thorpej   638:
1.33      thorpej   639:        pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
                    640:            L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
1.1       rearnsha  641:
1.33      thorpej   642:        for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
                    643:                pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
1.44      rearnsha  644:                    kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
1.33      thorpej   645:                    VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
                    646:        }
1.1       rearnsha  647:
1.20      thorpej   648:        /* Map the vector page. */
1.1       rearnsha  649: #if 1
                    650:        /* MULTI-ICE requires that page 0 is NC/NB so that it can download
                    651:           the cache-clean code there.  */
1.20      thorpej   652:        pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa,
1.10      thorpej   653:            VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE);
1.1       rearnsha  654: #else
1.20      thorpej   655:        pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa,
                    656:            VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.1       rearnsha  657: #endif
                    658:
1.42      thorpej   659:        /* Map the statically mapped devices. */
                    660:        pmap_devmap_bootstrap(l1pagetable, integrator_devmap);
1.1       rearnsha  661:
                    662:        /*
                    663:         * Now we have the real page tables in place so we can switch to them.
1.23      rearnsha  664:         * Once this is done we will be running with the REAL kernel page
                    665:         * tables.
                    666:         */
                    667:
1.1       rearnsha  668:        /* Switch tables */
                    669: #ifdef VERBOSE_INIT_ARM
                    670:        printf("switching to new L1 page table  @%#lx...", kernel_l1pt.pv_pa);
                    671: #endif
1.33      thorpej   672:        cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
1.1       rearnsha  673:        setttb(kernel_l1pt.pv_pa);
1.23      rearnsha  674:        cpu_tlb_flushID();
1.33      thorpej   675:        cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
                    676:
                    677:        /*
                    678:         * Moved from cpu_startup() as data_abort_handler() references
                    679:         * this during uvm init
                    680:         */
                    681:        proc0paddr = (struct user *)kernelstack.pv_va;
                    682:        lwp0.l_addr = proc0paddr;
1.1       rearnsha  683:
                    684: #ifdef PLCONSOLE
                    685:        /*
                    686:         * The IFPGA registers have just moved.
                    687:         * Detach the diagnostic serial port and reattach at the new address.
                    688:         */
                    689:        plcomcndetach();
                    690: #endif
                    691:
                    692:        /*
                    693:         * XXX this should only be done in main() but it useful to
                    694:         * have output earlier ...
                    695:         */
                    696:        consinit();
                    697:
                    698: #ifdef VERBOSE_INIT_ARM
                    699:        printf("bootstrap done.\n");
                    700: #endif
                    701:
1.20      thorpej   702:        arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL);
1.1       rearnsha  703:
                    704:        /*
                    705:         * Pages were allocated during the secondary bootstrap for the
                    706:         * stacks for different CPU modes.
                    707:         * We must now set the r13 registers in the different CPU modes to
                    708:         * point to these stacks.
                    709:         * Since the ARM stacks use STMFD etc. we must set r13 to the top end
                    710:         * of the stack memory.
                    711:         */
1.38      thorpej   712: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  713:        printf("init subsystems: stacks ");
1.38      thorpej   714: #endif
1.1       rearnsha  715:
1.31      thorpej   716:        set_stackptr(PSR_IRQ32_MODE,
                    717:            irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
                    718:        set_stackptr(PSR_ABT32_MODE,
                    719:            abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
                    720:        set_stackptr(PSR_UND32_MODE,
                    721:            undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
1.1       rearnsha  722:
                    723:        /*
                    724:         * Well we should set a data abort handler.
1.23      rearnsha  725:         * Once things get going this will change as we will need a proper
                    726:         * handler.
1.1       rearnsha  727:         * Until then we will use a handler that just panics but tells us
                    728:         * why.
                    729:         * Initialisation of the vectors will just panic on a data abort.
                    730:         * This just fills in a slighly better one.
                    731:         */
1.38      thorpej   732: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  733:        printf("vectors ");
1.38      thorpej   734: #endif
1.1       rearnsha  735:        data_abort_handler_address = (u_int)data_abort_handler;
                    736:        prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
                    737:        undefined_handler_address = (u_int)undefinedinstruction_bounce;
                    738:
                    739:        /* Initialise the undefined instruction handlers */
1.38      thorpej   740: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  741:        printf("undefined ");
1.38      thorpej   742: #endif
1.1       rearnsha  743:        undefined_init();
                    744:
1.25      thorpej   745:        /* Load memory into UVM. */
1.38      thorpej   746: #ifdef VERBOSE_INIT_ARM
1.25      thorpej   747:        printf("page ");
1.38      thorpej   748: #endif
1.25      thorpej   749:        uvm_setpagesize();      /* initialize PAGE_SIZE-dependent variables */
1.47    ! rearnsha  750:
        !           751:        /* Round the start up and the end down to a page.  */
        !           752:        physical_freestart = (physical_freestart + PGOFSET) & ~PGOFSET;
        !           753:        physical_freeend &= ~PGOFSET;
        !           754:
        !           755:        for (loop = 0; loop < bootconfig.dramblocks; loop++) {
        !           756:                paddr_t block_start = (paddr_t) bootconfig.dram[loop].address;
        !           757:                paddr_t block_end = block_start +
        !           758:                    (bootconfig.dram[loop].pages * PAGE_SIZE);
        !           759:
        !           760:                if (loop == 0) {
        !           761:                        block_start = physical_freestart;
        !           762:                        block_end = physical_freeend;
        !           763:                }
        !           764:
        !           765:
        !           766:                uvm_page_physload(atop(block_start), atop(block_end),
        !           767:                    atop(block_start), atop(block_end),
        !           768:                    (bootconfig.dram[loop].flags & BOOT_DRAM_PREFER) ?
        !           769:                    VM_FREELIST_DEFAULT : VM_FREELIST_DEFAULT + 1);
        !           770:        }
1.25      thorpej   771:
1.1       rearnsha  772:        /* Boot strap pmap telling it where the kernel page table is */
1.38      thorpej   773: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  774:        printf("pmap ");
1.38      thorpej   775: #endif
1.35      thorpej   776:        pmap_bootstrap((pd_entry_t *)kernel_l1pt.pv_va, KERNEL_VM_BASE,
                    777:            KERNEL_VM_BASE + KERNEL_VM_SIZE);
1.1       rearnsha  778:
                    779:        /* Setup the IRQ system */
1.38      thorpej   780: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  781:        printf("irq ");
1.38      thorpej   782: #endif
1.1       rearnsha  783:        irq_init();
                    784:
1.38      thorpej   785: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  786:        printf("done.\n");
1.38      thorpej   787: #endif
1.1       rearnsha  788:
                    789: #ifdef IPKDB
                    790:        /* Initialise ipkdb */
                    791:        ipkdb_init();
                    792:        if (boothowto & RB_KDB)
                    793:                ipkdb_connect(0);
                    794: #endif
                    795:
1.32      ragge     796: #if NKSYMS || defined(DDB) || defined(LKM)
                    797:        /* Firmware doesn't load symbols. */
                    798:        ksyms_init(0, NULL, NULL);
                    799: #endif
                    800:
1.1       rearnsha  801: #ifdef DDB
                    802:        db_machine_init();
                    803:        if (boothowto & RB_KDB)
                    804:                Debugger();
                    805: #endif
                    806:
                    807:        /* We return the new stack pointer address */
                    808:        return(kernelstack.pv_va + USPACE_SVC_STACK_TOP);
                    809: }
                    810:
                    811: void
                    812: consinit(void)
                    813: {
                    814:        static int consinit_called = 0;
                    815: #if NPLCOM > 0 && defined(PLCONSOLE)
                    816:        static struct bus_space plcom_bus_space;
                    817: #endif
                    818: #if 0
                    819:        char *console = CONSDEVNAME;
                    820: #endif
                    821:
                    822:        if (consinit_called != 0)
                    823:                return;
                    824:
                    825:        consinit_called = 1;
                    826:
                    827: #if NPLCOM > 0 && defined(PLCONSOLE)
                    828:        if (PLCOMCNUNIT == 0) {
                    829:                ifpga_create_io_bs_tag(&plcom_bus_space,
                    830:                    (void*)UART0_BOOT_BASE);
                    831:                if (plcomcnattach(&plcom_bus_space, 0, plcomcnspeed,
                    832:                    IFPGA_UART_CLK, plcomcnmode, PLCOMCNUNIT))
                    833:                        panic("can't init serial console");
                    834:                return;
                    835:        } else if (PLCOMCNUNIT == 1) {
                    836:                ifpga_create_io_bs_tag(&plcom_bus_space,
                    837:                    (void*)UART0_BOOT_BASE);
                    838:                if (plcomcnattach(&plcom_bus_space, 0, plcomcnspeed,
                    839:                    IFPGA_UART_CLK, plcomcnmode, PLCOMCNUNIT))
                    840:                        panic("can't init serial console");
                    841:                return;
                    842:        }
                    843: #endif
                    844: #if (NCOM > 0)
                    845:        if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed,
1.41      thorpej   846:            COM_FREQ, COM_TYPE_NORMAL, comcnmode))
1.1       rearnsha  847:                panic("can't init serial console @%x", CONCOMADDR);
                    848:        return;
                    849: #endif
                    850:        panic("No serial console configured");
1.23      rearnsha  851: }
                    852:
                    853: static void
                    854: integrator_sdram_bounds(paddr_t *memstart, psize_t *memsize)
                    855: {
                    856:        volatile unsigned long *cm_sdram
                    857:            = (volatile unsigned long *)0x10000020;
1.46      rearnsha  858:        volatile unsigned long *cm_stat
                    859:            = (volatile unsigned long *)0x10000010;
1.23      rearnsha  860:
1.46      rearnsha  861:        *memstart = *cm_stat & 0x00ff0000;
1.23      rearnsha  862:
1.46      rearnsha  863:        /*
                    864:         * Although the SSRAM overlaps the SDRAM, we can use the wrap-around
                    865:         * to access the entire bank.
                    866:         */
1.23      rearnsha  867:        switch ((*cm_sdram >> 2) & 0x7)
                    868:        {
                    869:        case 0:
                    870:                *memsize = 16 * 1024 * 1024;
                    871:                break;
                    872:        case 1:
                    873:                *memsize = 32 * 1024 * 1024;
                    874:                break;
                    875:        case 2:
                    876:                *memsize = 64 * 1024 * 1024;
                    877:                break;
                    878:        case 3:
                    879:                *memsize = 128 * 1024 * 1024;
                    880:                break;
                    881:        case 4:
1.46      rearnsha  882:                /* With 256M of memory there is no wrap-around.  */
                    883:                *memsize = 256 * 1024 * 1024 - *memstart;
1.23      rearnsha  884:                break;
                    885:        default:
                    886:                printf("CM_SDRAM retuns unknown value, using 16M\n");
                    887:                *memsize = 16 * 1024 * 1024;
                    888:                break;
                    889:        }
1.1       rearnsha  890: }

CVSweb <webmaster@jp.NetBSD.org>