The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/sibyte/sb_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2007 Bruce M. Simpson.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/9.0/sys/mips/sibyte/sb_machdep.c 223562 2011-06-26 10:07:48Z kevlo $");
   29 
   30 #include "opt_ddb.h"
   31 #include "opt_kdb.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/conf.h>
   35 #include <sys/kernel.h>
   36 #include <sys/systm.h>
   37 #include <sys/imgact.h>
   38 #include <sys/bio.h>
   39 #include <sys/buf.h>
   40 #include <sys/bus.h>
   41 #include <sys/cpu.h>
   42 #include <sys/cons.h>
   43 #include <sys/exec.h>
   44 #include <sys/ucontext.h>
   45 #include <sys/proc.h>
   46 #include <sys/kdb.h>
   47 #include <sys/ptrace.h>
   48 #include <sys/reboot.h>
   49 #include <sys/signalvar.h>
   50 #include <sys/sysent.h>
   51 #include <sys/sysproto.h>
   52 #include <sys/user.h>
   53 #include <sys/timetc.h>
   54 
   55 #include <vm/vm.h>
   56 #include <vm/vm_object.h>
   57 #include <vm/vm_page.h>
   58 #include <vm/vm_pager.h>
   59 
   60 #include <machine/cache.h>
   61 #include <machine/clock.h>
   62 #include <machine/cpu.h>
   63 #include <machine/cpuinfo.h>
   64 #include <machine/cpufunc.h>
   65 #include <machine/cpuregs.h>
   66 #include <machine/hwfunc.h>
   67 #include <machine/intr_machdep.h>
   68 #include <machine/locore.h>
   69 #include <machine/md_var.h>
   70 #include <machine/pte.h>
   71 #include <machine/sigframe.h>
   72 #include <machine/trap.h>
   73 #include <machine/vmparam.h>
   74 
   75 #ifdef SMP
   76 #include <sys/smp.h>
   77 #include <machine/smp.h>
   78 #endif
   79 
   80 #ifdef CFE
   81 #include <dev/cfe/cfe_api.h>
   82 #endif
   83 
   84 #include "sb_scd.h"
   85 
   86 #ifdef DDB
   87 #ifndef KDB
   88 #error KDB must be enabled in order for DDB to work!
   89 #endif
   90 #endif
   91 
   92 #ifdef CFE_ENV
   93 extern void cfe_env_init(void);
   94 #endif
   95 
   96 extern int *edata;
   97 extern int *end;
   98 
   99 extern char MipsTLBMiss[], MipsTLBMissEnd[];
  100 
  101 void
  102 platform_cpu_init()
  103 {
  104         /* Nothing special */
  105 }
  106 
  107 static void
  108 sb_intr_init(int cpuid)
  109 {
  110         int intrnum, intsrc;
  111 
  112         /*
  113          * Disable all sources to the interrupt mapper and setup the mapping
  114          * between an interrupt source and the mips hard interrupt number.
  115          */
  116         for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) {
  117                 intrnum = sb_route_intsrc(intsrc);
  118                 sb_disable_intsrc(cpuid, intsrc);
  119                 sb_write_intmap(cpuid, intsrc, intrnum);
  120 #ifdef SMP
  121                 /*
  122                  * Set up the mailbox interrupt mapping.
  123                  *
  124                  * The mailbox interrupt is "special" in that it is not shared
  125                  * with any other interrupt source.
  126                  */
  127                 if (intsrc == INTSRC_MAILBOX3) {
  128                         intrnum = platform_ipi_intrnum();
  129                         sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum);
  130                         sb_enable_intsrc(cpuid, INTSRC_MAILBOX3);
  131                 }
  132 #endif
  133         }
  134 }
  135 
  136 static void
  137 mips_init(void)
  138 {
  139         int i, j, cfe_mem_idx, tmp;
  140         uint64_t maxmem;
  141 
  142 #ifdef CFE_ENV
  143         cfe_env_init();
  144 #endif
  145 
  146         TUNABLE_INT_FETCH("boothowto", &boothowto);
  147 
  148         if (boothowto & RB_VERBOSE)
  149                 bootverbose++;
  150 
  151 #ifdef MAXMEM
  152         tmp = MAXMEM;
  153 #else
  154         tmp = 0;
  155 #endif
  156         TUNABLE_INT_FETCH("hw.physmem", &tmp);
  157         maxmem = (uint64_t)tmp * 1024;
  158 
  159         /*
  160          * XXX
  161          * If we used vm_paddr_t consistently in pmap, etc., we could
  162          * use 64-bit page numbers on !n64 systems, too, like i386
  163          * does with PAE.
  164          */
  165 #if !defined(__mips_n64)
  166         if (maxmem == 0 || maxmem > 0xffffffff)
  167                 maxmem = 0xffffffff;
  168 #endif
  169 
  170 #ifdef CFE
  171         /*
  172          * Query DRAM memory map from CFE.
  173          */
  174         physmem = 0;
  175         cfe_mem_idx = 0;
  176         for (i = 0; i < 10; i += 2) {
  177                 int result;
  178                 uint64_t addr, len, type;
  179 
  180                 result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type);
  181                 if (result < 0) {
  182                         phys_avail[i] = phys_avail[i + 1] = 0;
  183                         break;
  184                 }
  185 
  186                 KASSERT(type == CFE_MI_AVAILABLE,
  187                         ("CFE DRAM region is not available?"));
  188 
  189                 if (bootverbose)
  190                         printf("cfe_enummem: 0x%016jx/%ju.\n", addr, len);
  191 
  192                 if (maxmem != 0) {
  193                         if (addr >= maxmem) {
  194                                 printf("Ignoring %ju bytes of memory at 0x%jx "
  195                                        "that is above maxmem %dMB\n",
  196                                        len, addr,
  197                                        (int)(maxmem / (1024 * 1024)));
  198                                 continue;
  199                         }
  200 
  201                         if (addr + len > maxmem) {
  202                                 printf("Ignoring %ju bytes of memory "
  203                                        "that is above maxmem %dMB\n",
  204                                        (addr + len) - maxmem,
  205                                        (int)(maxmem / (1024 * 1024)));
  206                                 len = maxmem - addr;
  207                         }
  208                 }
  209 
  210                 phys_avail[i] = addr;
  211                 if (i == 0 && addr == 0) {
  212                         /*
  213                          * If this is the first physical memory segment probed
  214                          * from CFE, omit the region at the start of physical
  215                          * memory where the kernel has been loaded.
  216                          */
  217                         phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
  218                 }
  219                 phys_avail[i + 1] = addr + len;
  220                 physmem += len;
  221         }
  222 
  223         realmem = btoc(physmem);
  224 #endif
  225 
  226         for (j = 0; j < i; j++)
  227                 dump_avail[j] = phys_avail[j];
  228 
  229         physmem = realmem;
  230 
  231         init_param1();
  232         init_param2(physmem);
  233         mips_cpu_init();
  234 
  235         /*
  236          * Sibyte has a L1 data cache coherent with DMA. This includes
  237          * on-chip network interfaces as well as PCI/HyperTransport bus
  238          * masters.
  239          */
  240         cpuinfo.cache_coherent_dma = TRUE;
  241 
  242         /*
  243          * XXX
  244          * The kernel is running in 32-bit mode but the CFE is running in
  245          * 64-bit mode. So the SR_KX bit in the status register is turned
  246          * on by the CFE every time we call into it - for e.g. CFE_CONSOLE.
  247          *
  248          * This means that if get a TLB miss for any address above 0xc0000000
  249          * and the SR_KX bit is set then we will end up in the XTLB exception
  250          * vector.
  251          *
  252          * For now work around this by copying the TLB exception handling
  253          * code to the XTLB exception vector.
  254          */
  255         {
  256                 bcopy(MipsTLBMiss, (void *)MIPS3_XTLB_MISS_EXC_VEC,
  257                       MipsTLBMissEnd - MipsTLBMiss);
  258 
  259                 mips_icache_sync_all();
  260                 mips_dcache_wbinv_all();
  261         }
  262 
  263         pmap_bootstrap();
  264         mips_proc0_init();
  265         mutex_init();
  266 
  267         kdb_init();
  268 #ifdef KDB
  269         if (boothowto & RB_KDB)
  270                 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
  271 #endif
  272 }
  273 
  274 void
  275 platform_halt(void)
  276 {
  277 
  278 }
  279 
  280 
  281 void
  282 platform_identify(void)
  283 {
  284 
  285 }
  286 
  287 void
  288 platform_reset(void)
  289 {
  290         
  291         /*
  292          * XXX SMP
  293          * XXX flush data caches
  294          */
  295         sb_system_reset();
  296 }
  297 
  298 void
  299 platform_trap_enter(void)
  300 {
  301 
  302 }
  303 
  304 void
  305 platform_trap_exit(void)
  306 {
  307 
  308 }
  309 
  310 static void
  311 kseg0_map_coherent(void)
  312 {
  313         uint32_t config;
  314         const int CFG_K0_COHERENT = 5;
  315 
  316         config = mips_rd_config();
  317         config &= ~MIPS3_CONFIG_K0_MASK;
  318         config |= CFG_K0_COHERENT;
  319         mips_wr_config(config);
  320 }
  321 
  322 #ifdef SMP
  323 void
  324 platform_ipi_send(int cpuid)
  325 {
  326         KASSERT(cpuid == 0 || cpuid == 1,
  327                 ("platform_ipi_send: invalid cpuid %d", cpuid));
  328 
  329         sb_set_mailbox(cpuid, 1ULL);
  330 }
  331 
  332 void
  333 platform_ipi_clear(void)
  334 {
  335         int cpuid;
  336 
  337         cpuid = PCPU_GET(cpuid);
  338         sb_clear_mailbox(cpuid, 1ULL);
  339 }
  340 
  341 int
  342 platform_ipi_intrnum(void)
  343 {
  344 
  345         return (4);
  346 }
  347 
  348 struct cpu_group *
  349 platform_smp_topo(void)
  350 {
  351 
  352         return (smp_topo_none());
  353 }
  354 
  355 void
  356 platform_init_ap(int cpuid)
  357 {
  358         int ipi_int_mask, clock_int_mask;
  359 
  360         KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid));
  361 
  362         /*
  363          * Make sure that kseg0 is mapped cacheable-coherent
  364          */
  365         kseg0_map_coherent();
  366 
  367         sb_intr_init(cpuid);
  368 
  369         /*
  370          * Unmask the clock and ipi interrupts.
  371          */
  372         clock_int_mask = hard_int_mask(5);
  373         ipi_int_mask = hard_int_mask(platform_ipi_intrnum());
  374         set_intr_mask(ipi_int_mask | clock_int_mask);
  375 }
  376 
  377 int
  378 platform_start_ap(int cpuid)
  379 {
  380 #ifdef CFE
  381         int error;
  382 
  383         if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) {
  384                 printf("cfe_cpu_start error: %d\n", error);
  385                 return (-1);
  386         } else {
  387                 return (0);
  388         }
  389 #else
  390         return (-1);
  391 #endif  /* CFE */
  392 }
  393 #endif  /* SMP */
  394 
  395 static u_int
  396 sb_get_timecount(struct timecounter *tc)
  397 {
  398 
  399         return ((u_int)sb_zbbus_cycle_count());
  400 }
  401 
  402 static void
  403 sb_timecounter_init(void)
  404 {
  405         static struct timecounter sb_timecounter = {
  406                 sb_get_timecount,
  407                 NULL,
  408                 ~0u,
  409                 0,
  410                 "sibyte_zbbus_counter",
  411                 2000
  412         };
  413 
  414         /*
  415          * The ZBbus cycle counter runs at half the cpu frequency.
  416          */
  417         sb_timecounter.tc_frequency = sb_cpu_speed() / 2;
  418         platform_timecounter = &sb_timecounter;
  419 }
  420 
  421 void
  422 platform_start(__register_t a0, __register_t a1, __register_t a2,
  423                __register_t a3)
  424 {
  425         /*
  426          * Make sure that kseg0 is mapped cacheable-coherent
  427          */
  428         kseg0_map_coherent();
  429 
  430         /* clear the BSS and SBSS segments */
  431         memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata);
  432         mips_postboot_fixup();
  433 
  434         sb_intr_init(0);
  435         sb_timecounter_init();
  436 
  437         /* Initialize pcpu stuff */
  438         mips_pcpu0_init();
  439 
  440 #ifdef CFE
  441         /*
  442          * Initialize CFE firmware trampolines before
  443          * we initialize the low-level console.
  444          *
  445          * CFE passes the following values in registers:
  446          * a0: firmware handle
  447          * a2: firmware entry point
  448          * a3: entry point seal
  449          */
  450         if (a3 == CFE_EPTSEAL)
  451                 cfe_init(a0, a2);
  452 #endif
  453         cninit();
  454 
  455         mips_init();
  456 
  457         mips_timer_init_params(sb_cpu_speed(), 0);
  458 }

Cache object: 3c25abb859f72a8e87bdd88b7f2dd48b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.