[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.60

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

CVSweb <webmaster@jp.NetBSD.org>