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 <sys/param.h>
   31 
   32 #include "opt_ddb.h"
   33 #include "opt_kdb.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/conf.h>
   37 #include <sys/kernel.h>
   38 #include <sys/systm.h>
   39 #include <sys/imgact.h>
   40 #include <sys/bio.h>
   41 #include <sys/buf.h>
   42 #include <sys/bus.h>
   43 #include <sys/cpu.h>
   44 #include <sys/cons.h>
   45 #include <sys/exec.h>
   46 #include <sys/ucontext.h>
   47 #include <sys/proc.h>
   48 #include <sys/kdb.h>
   49 #include <sys/ptrace.h>
   50 #include <sys/reboot.h>
   51 #include <sys/signalvar.h>
   52 #include <sys/sysent.h>
   53 #include <sys/sysproto.h>
   54 #include <sys/user.h>
   55 #include <sys/timetc.h>
   56 
   57 #include <vm/vm.h>
   58 #include <vm/vm_object.h>
   59 #include <vm/vm_page.h>
   60 #include <vm/vm_pager.h>
   61 
   62 #include <machine/cache.h>
   63 #include <machine/clock.h>
   64 #include <machine/cpu.h>
   65 #include <machine/cpuinfo.h>
   66 #include <machine/cpufunc.h>
   67 #include <machine/cpuregs.h>
   68 #include <machine/hwfunc.h>
   69 #include <machine/intr_machdep.h>
   70 #include <machine/locore.h>
   71 #include <machine/md_var.h>
   72 #include <machine/pte.h>
   73 #include <machine/sigframe.h>
   74 #include <machine/trap.h>
   75 #include <machine/vmparam.h>
   76 
   77 #ifdef SMP
   78 #include <sys/smp.h>
   79 #include <machine/smp.h>
   80 #endif
   81 
   82 #ifdef CFE
   83 #include <dev/cfe/cfe_api.h>
   84 #endif
   85 
   86 #include "sb_scd.h"
   87 
   88 #ifdef DDB
   89 #ifndef KDB
   90 #error KDB must be enabled in order for DDB to work!
   91 #endif
   92 #endif
   93 
   94 #ifdef CFE_ENV
   95 extern void cfe_env_init(void);
   96 #endif
   97 
   98 extern int *edata;
   99 extern int *end;
  100 
  101 extern char MipsTLBMiss[], MipsTLBMissEnd[];
  102 
  103 void
  104 platform_cpu_init()
  105 {
  106         /* Nothing special */
  107 }
  108 
  109 static void
  110 sb_intr_init(int cpuid)
  111 {
  112         int intrnum, intsrc;
  113 
  114         /*
  115          * Disable all sources to the interrupt mapper and setup the mapping
  116          * between an interrupt source and the mips hard interrupt number.
  117          */
  118         for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) {
  119                 intrnum = sb_route_intsrc(intsrc);
  120                 sb_disable_intsrc(cpuid, intsrc);
  121                 sb_write_intmap(cpuid, intsrc, intrnum);
  122 #ifdef SMP
  123                 /*
  124                  * Set up the mailbox interrupt mapping.
  125                  *
  126                  * The mailbox interrupt is "special" in that it is not shared
  127                  * with any other interrupt source.
  128                  */
  129                 if (intsrc == INTSRC_MAILBOX3) {
  130                         intrnum = platform_ipi_intrnum();
  131                         sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum);
  132                         sb_enable_intsrc(cpuid, INTSRC_MAILBOX3);
  133                 }
  134 #endif
  135         }
  136 }
  137 
  138 static void
  139 mips_init(void)
  140 {
  141         int i, cfe_mem_idx, tmp;
  142         uint64_t maxmem;
  143 
  144 #ifdef CFE_ENV
  145         cfe_env_init();
  146 #endif
  147 
  148         TUNABLE_INT_FETCH("boothowto", &boothowto);
  149 
  150         if (boothowto & RB_VERBOSE)
  151                 bootverbose++;
  152 
  153 #ifdef MAXMEM
  154         tmp = MAXMEM;
  155 #else
  156         tmp = 0;
  157 #endif
  158         TUNABLE_INT_FETCH("hw.physmem", &tmp);
  159         maxmem = (uint64_t)tmp * 1024;
  160 
  161         /*
  162          * XXX
  163          * If we used vm_paddr_t consistently in pmap, etc., we could
  164          * use 64-bit page numbers on !n64 systems, too, like i386
  165          * does with PAE.
  166          */
  167 #if !defined(__mips_n64)
  168         if (maxmem == 0 || maxmem > 0xffffffff)
  169                 maxmem = 0xffffffff;
  170 #endif
  171 
  172 #ifdef CFE
  173         /*
  174          * Query DRAM memory map from CFE.
  175          */
  176         physmem = 0;
  177         cfe_mem_idx = 0;
  178         for (i = 0; i < 10; i += 2) {
  179                 int result;
  180                 uint64_t addr, len, type;
  181 
  182                 result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type);
  183                 if (result < 0) {
  184                         phys_avail[i] = phys_avail[i + 1] = 0;
  185                         break;
  186                 }
  187 
  188                 KASSERT(type == CFE_MI_AVAILABLE,
  189                         ("CFE DRAM region is not available?"));
  190 
  191                 if (bootverbose)
  192                         printf("cfe_enummem: 0x%016jx/%ju.\n", addr, len);
  193 
  194                 if (maxmem != 0) {
  195                         if (addr >= maxmem) {
  196                                 printf("Ignoring %ju bytes of memory at 0x%jx "
  197                                        "that is above maxmem %dMB\n",
  198                                        len, addr,
  199                                        (int)(maxmem / (1024 * 1024)));
  200                                 continue;
  201                         }
  202 
  203                         if (addr + len > maxmem) {
  204                                 printf("Ignoring %ju bytes of memory "
  205                                        "that is above maxmem %dMB\n",
  206                                        (addr + len) - maxmem,
  207                                        (int)(maxmem / (1024 * 1024)));
  208                                 len = maxmem - addr;
  209                         }
  210                 }
  211 
  212                 phys_avail[i] = addr;
  213                 if (i == 0 && addr == 0) {
  214                         /*
  215                          * If this is the first physical memory segment probed
  216                          * from CFE, omit the region at the start of physical
  217                          * memory where the kernel has been loaded.
  218                          */
  219                         phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
  220                 }
  221                 phys_avail[i + 1] = addr + len;
  222                 physmem += len;
  223         }
  224 
  225         realmem = btoc(physmem);
  226 #endif
  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 *)MIPS3_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_halt(void)
  275 {
  276 
  277 }
  278 
  279 
  280 void
  281 platform_identify(void)
  282 {
  283 
  284 }
  285 
  286 void
  287 platform_reset(void)
  288 {
  289         
  290         /*
  291          * XXX SMP
  292          * XXX flush data caches
  293          */
  294         sb_system_reset();
  295 }
  296 
  297 void
  298 platform_trap_enter(void)
  299 {
  300 
  301 }
  302 
  303 void
  304 platform_trap_exit(void)
  305 {
  306 
  307 }
  308 
  309 static void
  310 kseg0_map_coherent(void)
  311 {
  312         uint32_t config;
  313         const int CFG_K0_COHERENT = 5;
  314 
  315         config = mips_rd_config();
  316         config &= ~MIPS3_CONFIG_K0_MASK;
  317         config |= CFG_K0_COHERENT;
  318         mips_wr_config(config);
  319 }
  320 
  321 #ifdef SMP
  322 void
  323 platform_ipi_send(int cpuid)
  324 {
  325         KASSERT(cpuid == 0 || cpuid == 1,
  326                 ("platform_ipi_send: invalid cpuid %d", cpuid));
  327 
  328         sb_set_mailbox(cpuid, 1ULL);
  329 }
  330 
  331 void
  332 platform_ipi_clear(void)
  333 {
  334         int cpuid;
  335 
  336         cpuid = PCPU_GET(cpuid);
  337         sb_clear_mailbox(cpuid, 1ULL);
  338 }
  339 
  340 int
  341 platform_ipi_intrnum(void)
  342 {
  343 
  344         return (4);
  345 }
  346 
  347 struct cpu_group *
  348 platform_smp_topo(void)
  349 {
  350 
  351         return (smp_topo_none());
  352 }
  353 
  354 void
  355 platform_init_ap(int cpuid)
  356 {
  357         int ipi_int_mask, clock_int_mask;
  358 
  359         KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid));
  360 
  361         /*
  362          * Make sure that kseg0 is mapped cacheable-coherent
  363          */
  364         kseg0_map_coherent();
  365 
  366         sb_intr_init(cpuid);
  367 
  368         /*
  369          * Unmask the clock and ipi interrupts.
  370          */
  371         clock_int_mask = hard_int_mask(5);
  372         ipi_int_mask = hard_int_mask(platform_ipi_intrnum());
  373         set_intr_mask(ipi_int_mask | clock_int_mask);
  374 }
  375 
  376 int
  377 platform_start_ap(int cpuid)
  378 {
  379 #ifdef CFE
  380         int error;
  381 
  382         if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) {
  383                 printf("cfe_cpu_start error: %d\n", error);
  384                 return (-1);
  385         } else {
  386                 return (0);
  387         }
  388 #else
  389         return (-1);
  390 #endif  /* CFE */
  391 }
  392 #endif  /* SMP */
  393 
  394 static u_int
  395 sb_get_timecount(struct timecounter *tc)
  396 {
  397 
  398         return ((u_int)sb_zbbus_cycle_count());
  399 }
  400 
  401 static void
  402 sb_timecounter_init(void)
  403 {
  404         static struct timecounter sb_timecounter = {
  405                 sb_get_timecount,
  406                 NULL,
  407                 ~0u,
  408                 0,
  409                 "sibyte_zbbus_counter",
  410                 2000
  411         };
  412 
  413         /*
  414          * The ZBbus cycle counter runs at half the cpu frequency.
  415          */
  416         sb_timecounter.tc_frequency = sb_cpu_speed() / 2;
  417         platform_timecounter = &sb_timecounter;
  418 }
  419 
  420 void
  421 platform_start(__register_t a0, __register_t a1, __register_t a2,
  422                __register_t a3)
  423 {
  424         /*
  425          * Make sure that kseg0 is mapped cacheable-coherent
  426          */
  427         kseg0_map_coherent();
  428 
  429         /* clear the BSS and SBSS segments */
  430         memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata);
  431         mips_postboot_fixup();
  432 
  433         sb_intr_init(0);
  434         sb_timecounter_init();
  435 
  436         /* Initialize pcpu stuff */
  437         mips_pcpu0_init();
  438 
  439 #ifdef CFE
  440         /*
  441          * Initialize CFE firmware trampolines before
  442          * we initialize the low-level console.
  443          *
  444          * CFE passes the following values in registers:
  445          * a0: firmware handle
  446          * a2: firmware entry point
  447          * a3: entry point seal
  448          */
  449         if (a3 == CFE_EPTSEAL)
  450                 cfe_init(a0, a2);
  451 #endif
  452         cninit();
  453 
  454         mips_init();
  455 
  456         mips_timer_init_params(sb_cpu_speed(), 0);
  457 
  458         set_cputicker(sb_zbbus_cycle_count, sb_cpu_speed() / 2, 1);
  459 }

Cache object: 058584dfa3aae622da2c30c7cf3647a7


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