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$");
   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 
   59 #include <machine/cache.h>
   60 #include <machine/clock.h>
   61 #include <machine/cpu.h>
   62 #include <machine/cpuinfo.h>
   63 #include <machine/cpufunc.h>
   64 #include <machine/cpuregs.h>
   65 #include <machine/hwfunc.h>
   66 #include <machine/intr_machdep.h>
   67 #include <machine/locore.h>
   68 #include <machine/md_var.h>
   69 #include <machine/pte.h>
   70 #include <machine/sigframe.h>
   71 #include <machine/trap.h>
   72 #include <machine/vmparam.h>
   73 
   74 #ifdef SMP
   75 #include <sys/smp.h>
   76 #include <machine/smp.h>
   77 #endif
   78 
   79 #ifdef CFE
   80 #include <dev/cfe/cfe_api.h>
   81 #endif
   82 
   83 #include "sb_scd.h"
   84 
   85 #ifdef DDB
   86 #ifndef KDB
   87 #error KDB must be enabled in order for DDB to work!
   88 #endif
   89 #endif
   90 
   91 #ifdef CFE_ENV
   92 extern void cfe_env_init(void);
   93 #endif
   94 
   95 extern int *edata;
   96 extern int *end;
   97 
   98 extern char MipsTLBMiss[], MipsTLBMissEnd[];
   99 
  100 void
  101 platform_cpu_init()
  102 {
  103         /* Nothing special */
  104 }
  105 
  106 static void
  107 sb_intr_init(int cpuid)
  108 {
  109         int intrnum, intsrc;
  110 
  111         /*
  112          * Disable all sources to the interrupt mapper and setup the mapping
  113          * between an interrupt source and the mips hard interrupt number.
  114          */
  115         for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) {
  116                 intrnum = sb_route_intsrc(intsrc);
  117                 sb_disable_intsrc(cpuid, intsrc);
  118                 sb_write_intmap(cpuid, intsrc, intrnum);
  119 #ifdef SMP
  120                 /*
  121                  * Set up the mailbox interrupt mapping.
  122                  *
  123                  * The mailbox interrupt is "special" in that it is not shared
  124                  * with any other interrupt source.
  125                  */
  126                 if (intsrc == INTSRC_MAILBOX3) {
  127                         intrnum = platform_ipi_intrnum();
  128                         sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum);
  129                         sb_enable_intsrc(cpuid, INTSRC_MAILBOX3);
  130                 }
  131 #endif
  132         }
  133 }
  134 
  135 static void
  136 mips_init(void)
  137 {
  138         int i, j, cfe_mem_idx, tmp;
  139         uint64_t maxmem;
  140 
  141 #ifdef CFE_ENV
  142         cfe_env_init();
  143 #endif
  144 
  145         TUNABLE_INT_FETCH("boothowto", &boothowto);
  146 
  147         if (boothowto & RB_VERBOSE)
  148                 bootverbose++;
  149 
  150 #ifdef MAXMEM
  151         tmp = MAXMEM;
  152 #else
  153         tmp = 0;
  154 #endif
  155         TUNABLE_INT_FETCH("hw.physmem", &tmp);
  156         maxmem = (uint64_t)tmp * 1024;
  157 
  158         /*
  159          * XXX
  160          * If we used vm_paddr_t consistently in pmap, etc., we could
  161          * use 64-bit page numbers on !n64 systems, too, like i386
  162          * does with PAE.
  163          */
  164 #if !defined(__mips_n64)
  165         if (maxmem == 0 || maxmem > 0xffffffff)
  166                 maxmem = 0xffffffff;
  167 #endif
  168 
  169 #ifdef CFE
  170         /*
  171          * Query DRAM memory map from CFE.
  172          */
  173         physmem = 0;
  174         cfe_mem_idx = 0;
  175         for (i = 0; i < 10; i += 2) {
  176                 int result;
  177                 uint64_t addr, len, type;
  178 
  179                 result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type);
  180                 if (result < 0) {
  181                         phys_avail[i] = phys_avail[i + 1] = 0;
  182                         break;
  183                 }
  184 
  185                 KASSERT(type == CFE_MI_AVAILABLE,
  186                         ("CFE DRAM region is not available?"));
  187 
  188                 if (bootverbose)
  189                         printf("cfe_enummem: 0x%016jx/%ju.\n", addr, len);
  190 
  191                 if (maxmem != 0) {
  192                         if (addr >= maxmem) {
  193                                 printf("Ignoring %ju bytes of memory at 0x%jx "
  194                                        "that is above maxmem %dMB\n",
  195                                        len, addr,
  196                                        (int)(maxmem / (1024 * 1024)));
  197                                 continue;
  198                         }
  199 
  200                         if (addr + len > maxmem) {
  201                                 printf("Ignoring %ju bytes of memory "
  202                                        "that is above maxmem %dMB\n",
  203                                        (addr + len) - maxmem,
  204                                        (int)(maxmem / (1024 * 1024)));
  205                                 len = maxmem - addr;
  206                         }
  207                 }
  208 
  209                 phys_avail[i] = addr;
  210                 if (i == 0 && addr == 0) {
  211                         /*
  212                          * If this is the first physical memory segment probed
  213                          * from CFE, omit the region at the start of physical
  214                          * memory where the kernel has been loaded.
  215                          */
  216                         phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
  217                 }
  218                 phys_avail[i + 1] = addr + len;
  219                 physmem += len;
  220         }
  221 
  222         realmem = btoc(physmem);
  223 #endif
  224 
  225         for (j = 0; j < i; j++)
  226                 dump_avail[j] = phys_avail[j];
  227 
  228         physmem = realmem;
  229 
  230         init_param1();
  231         init_param2(physmem);
  232         mips_cpu_init();
  233 
  234         /*
  235          * Sibyte has a L1 data cache coherent with DMA. This includes
  236          * on-chip network interfaces as well as PCI/HyperTransport bus
  237          * masters.
  238          */
  239         cpuinfo.cache_coherent_dma = TRUE;
  240 
  241         /*
  242          * XXX
  243          * The kernel is running in 32-bit mode but the CFE is running in
  244          * 64-bit mode. So the SR_KX bit in the status register is turned
  245          * on by the CFE every time we call into it - for e.g. CFE_CONSOLE.
  246          *
  247          * This means that if get a TLB miss for any address above 0xc0000000
  248          * and the SR_KX bit is set then we will end up in the XTLB exception
  249          * vector.
  250          *
  251          * For now work around this by copying the TLB exception handling
  252          * code to the XTLB exception vector.
  253          */
  254         {
  255                 bcopy(MipsTLBMiss, (void *)MIPS_XTLB_MISS_EXC_VEC,
  256                       MipsTLBMissEnd - MipsTLBMiss);
  257 
  258                 mips_icache_sync_all();
  259                 mips_dcache_wbinv_all();
  260         }
  261 
  262         pmap_bootstrap();
  263         mips_proc0_init();
  264         mutex_init();
  265 
  266         kdb_init();
  267 #ifdef KDB
  268         if (boothowto & RB_KDB)
  269                 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
  270 #endif
  271 }
  272 
  273 void
  274 platform_reset(void)
  275 {
  276         
  277         /*
  278          * XXX SMP
  279          * XXX flush data caches
  280          */
  281         sb_system_reset();
  282 }
  283 
  284 static void
  285 kseg0_map_coherent(void)
  286 {
  287         uint32_t config;
  288         const int CFG_K0_COHERENT = 5;
  289 
  290         config = mips_rd_config();
  291         config &= ~MIPS_CONFIG_K0_MASK;
  292         config |= CFG_K0_COHERENT;
  293         mips_wr_config(config);
  294 }
  295 
  296 #ifdef SMP
  297 void
  298 platform_ipi_send(int cpuid)
  299 {
  300         KASSERT(cpuid == 0 || cpuid == 1,
  301                 ("platform_ipi_send: invalid cpuid %d", cpuid));
  302 
  303         sb_set_mailbox(cpuid, 1ULL);
  304 }
  305 
  306 void
  307 platform_ipi_clear(void)
  308 {
  309         int cpuid;
  310 
  311         cpuid = PCPU_GET(cpuid);
  312         sb_clear_mailbox(cpuid, 1ULL);
  313 }
  314 
  315 int
  316 platform_ipi_intrnum(void)
  317 {
  318 
  319         return (4);
  320 }
  321 
  322 struct cpu_group *
  323 platform_smp_topo(void)
  324 {
  325 
  326         return (smp_topo_none());
  327 }
  328 
  329 void
  330 platform_init_ap(int cpuid)
  331 {
  332         int ipi_int_mask, clock_int_mask;
  333 
  334         KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid));
  335 
  336         /*
  337          * Make sure that kseg0 is mapped cacheable-coherent
  338          */
  339         kseg0_map_coherent();
  340 
  341         sb_intr_init(cpuid);
  342 
  343         /*
  344          * Unmask the clock and ipi interrupts.
  345          */
  346         clock_int_mask = hard_int_mask(5);
  347         ipi_int_mask = hard_int_mask(platform_ipi_intrnum());
  348         set_intr_mask(ipi_int_mask | clock_int_mask);
  349 }
  350 
  351 int
  352 platform_start_ap(int cpuid)
  353 {
  354 #ifdef CFE
  355         int error;
  356 
  357         if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) {
  358                 printf("cfe_cpu_start error: %d\n", error);
  359                 return (-1);
  360         } else {
  361                 return (0);
  362         }
  363 #else
  364         return (-1);
  365 #endif  /* CFE */
  366 }
  367 #endif  /* SMP */
  368 
  369 static u_int
  370 sb_get_timecount(struct timecounter *tc)
  371 {
  372 
  373         return ((u_int)sb_zbbus_cycle_count());
  374 }
  375 
  376 static void
  377 sb_timecounter_init(void)
  378 {
  379         static struct timecounter sb_timecounter = {
  380                 sb_get_timecount,
  381                 NULL,
  382                 ~0u,
  383                 0,
  384                 "sibyte_zbbus_counter",
  385                 2000
  386         };
  387 
  388         /*
  389          * The ZBbus cycle counter runs at half the cpu frequency.
  390          */
  391         sb_timecounter.tc_frequency = sb_cpu_speed() / 2;
  392         platform_timecounter = &sb_timecounter;
  393 }
  394 
  395 void
  396 platform_start(__register_t a0, __register_t a1, __register_t a2,
  397                __register_t a3)
  398 {
  399         /*
  400          * Make sure that kseg0 is mapped cacheable-coherent
  401          */
  402         kseg0_map_coherent();
  403 
  404         /* clear the BSS and SBSS segments */
  405         memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata);
  406         mips_postboot_fixup();
  407 
  408         sb_intr_init(0);
  409         sb_timecounter_init();
  410 
  411         /* Initialize pcpu stuff */
  412         mips_pcpu0_init();
  413 
  414 #ifdef CFE
  415         /*
  416          * Initialize CFE firmware trampolines before
  417          * we initialize the low-level console.
  418          *
  419          * CFE passes the following values in registers:
  420          * a0: firmware handle
  421          * a2: firmware entry point
  422          * a3: entry point seal
  423          */
  424         if (a3 == CFE_EPTSEAL)
  425                 cfe_init(a0, a2);
  426 #endif
  427         cninit();
  428 
  429         mips_init();
  430 
  431         mips_timer_init_params(sb_cpu_speed(), 0);
  432 }

Cache object: 4563105bb0d6f105b1245df65dd49351


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