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/mips/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     /*  $OpenBSD: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp $       */
    2 /* tracked to 1.38 */
    3 /*
    4  * Copyright (c) 1988 University of Utah.
    5  * Copyright (c) 1992, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * the Systems Programming Group of the University of Utah Computer
   10  * Science Department, The Mach Operating System project at
   11  * Carnegie-Mellon University and Ralph Campbell.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 4. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      from: @(#)machdep.c     8.3 (Berkeley) 1/12/94
   38  *      Id: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp
   39  *      JNPR: machdep.c,v 1.11.2.3 2007/08/29 12:24:49
   40  */
   41 
   42 #include <sys/cdefs.h>
   43 __FBSDID("$FreeBSD: releng/8.2/sys/mips/mips/machdep.c 215938 2010-11-27 12:26:40Z jchandra $");
   44 
   45 #include "opt_cputype.h"
   46 #include "opt_ddb.h"
   47 #include "opt_md.h"
   48 #include "opt_msgbuf.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/proc.h>
   52 #include <sys/systm.h>
   53 #include <sys/buf.h>
   54 #include <sys/bus.h>
   55 #include <sys/conf.h>
   56 #include <sys/cpu.h>
   57 #include <sys/kernel.h>
   58 #include <sys/linker.h>
   59 #include <sys/malloc.h>
   60 #include <sys/mbuf.h>
   61 #include <sys/msgbuf.h>
   62 #include <sys/reboot.h>
   63 #include <sys/sched.h>
   64 #include <sys/sysctl.h>
   65 #include <sys/sysproto.h>
   66 #include <sys/vmmeter.h>
   67 
   68 #include <vm/vm.h>
   69 #include <vm/vm_kern.h>
   70 #include <vm/vm_object.h>
   71 #include <vm/vm_page.h>
   72 #include <vm/pmap.h>
   73 #include <vm/vm_map.h>
   74 #include <vm/vm_pager.h>
   75 #include <vm/vm_extern.h>
   76 #include <sys/socket.h>
   77 
   78 #include <sys/user.h>
   79 #include <sys/interrupt.h>
   80 #include <sys/cons.h>
   81 #include <sys/syslog.h>
   82 #include <machine/asm.h>
   83 #include <machine/bootinfo.h>
   84 #include <machine/cache.h>
   85 #include <machine/clock.h>
   86 #include <machine/cpu.h>
   87 #include <machine/cpuregs.h>
   88 #include <machine/elf.h>
   89 #include <machine/hwfunc.h>
   90 #include <machine/intr_machdep.h>
   91 #include <machine/md_var.h>
   92 #include <machine/tlb.h>
   93 #ifdef DDB
   94 #include <sys/kdb.h>
   95 #include <ddb/ddb.h>
   96 #endif
   97 
   98 #include <sys/random.h>
   99 #include <net/if.h>
  100 
  101 #define BOOTINFO_DEBUG  0
  102 
  103 char machine[] = "mips";
  104 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class");
  105 
  106 static char cpu_model[30];
  107 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model");
  108 
  109 int cold = 1;
  110 long realmem = 0;
  111 long Maxmem = 0;
  112 int cpu_clock = MIPS_DEFAULT_HZ;
  113 SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 
  114     &cpu_clock, 0, "CPU instruction clock rate");
  115 int clocks_running = 0;
  116 
  117 vm_offset_t kstack0;
  118 
  119 /*
  120  * Each entry in the pcpu_space[] array is laid out in the following manner:
  121  * struct pcpu for cpu 'n'      pcpu_space[n]
  122  * boot stack for cpu 'n'       pcpu_space[n] + PAGE_SIZE * 2 - CALLFRAME_SIZ
  123  *
  124  * Note that the boot stack grows downwards and we assume that we never
  125  * use enough stack space to trample over the 'struct pcpu' that is at
  126  * the beginning of the array.
  127  *
  128  * The array is aligned on a (PAGE_SIZE * 2) boundary so that the 'struct pcpu'
  129  * is always in the even page frame of the wired TLB entry on SMP kernels.
  130  *
  131  * The array is in the .data section so that the stack does not get zeroed out
  132  * when the .bss section is zeroed.
  133  */
  134 char pcpu_space[MAXCPU][PAGE_SIZE * 2] \
  135         __aligned(PAGE_SIZE * 2) __section(".data");
  136 
  137 struct pcpu *pcpup = (struct pcpu *)pcpu_space;
  138 
  139 vm_offset_t phys_avail[PHYS_AVAIL_ENTRIES + 2];
  140 vm_offset_t physmem_desc[PHYS_AVAIL_ENTRIES + 2];
  141 vm_paddr_t dump_avail[PHYS_AVAIL_ENTRIES + 2];
  142 
  143 #ifdef UNIMPLEMENTED
  144 struct platform platform;
  145 #endif
  146 
  147 static void cpu_startup(void *);
  148 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
  149 
  150 struct kva_md_info kmi;
  151 
  152 int cpucfg;                     /* Value of processor config register */
  153 int num_tlbentries = 64;        /* Size of the CPU tlb */
  154 int cputype;
  155 
  156 extern char MipsException[], MipsExceptionEnd[];
  157 
  158 /* TLB miss handler address and end */
  159 extern char MipsTLBMiss[], MipsTLBMissEnd[];
  160 
  161 /* Cache error handler */
  162 extern char MipsCache[], MipsCacheEnd[];
  163 
  164 extern char edata[], end[];
  165 #ifdef DDB
  166 extern vm_offset_t ksym_start, ksym_end;
  167 #endif
  168 
  169 u_int32_t bootdev;
  170 struct bootinfo bootinfo;
  171 /*
  172  * First kseg0 address available for use. By default it's equal to &end.
  173  * But in some cases there might be additional data placed right after 
  174  * _end by loader or ELF trampoline.
  175  */
  176 vm_offset_t kernel_kseg0_end = (vm_offset_t)&end;
  177 
  178 static void
  179 cpu_startup(void *dummy)
  180 {
  181 
  182         if (boothowto & RB_VERBOSE)
  183                 bootverbose++;
  184 
  185         printf("real memory  = %lu (%luK bytes)\n", ptoa(realmem),
  186             ptoa(realmem) / 1024);
  187 
  188         /*
  189          * Display any holes after the first chunk of extended memory.
  190          */
  191         if (bootverbose) {
  192                 int indx;
  193 
  194                 printf("Physical memory chunk(s):\n");
  195                 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
  196                         uintptr_t size1 = phys_avail[indx + 1] - phys_avail[indx];
  197 
  198                         printf("0x%08llx - 0x%08llx, %llu bytes (%llu pages)\n",
  199                             (unsigned long long)phys_avail[indx],
  200                             (unsigned long long)phys_avail[indx + 1] - 1,
  201                             (unsigned long long)size1,
  202                             (unsigned long long)size1 / PAGE_SIZE);
  203                 }
  204         }
  205 
  206         vm_ksubmap_init(&kmi);
  207 
  208         printf("avail memory = %lu (%luMB)\n", ptoa(cnt.v_free_count),
  209             ptoa(cnt.v_free_count) / 1048576);
  210         cpu_init_interrupts();
  211 
  212         /*
  213          * Set up buffers, so they can be used to read disk labels.
  214          */
  215         bufinit();
  216         vm_pager_bufferinit();
  217 }
  218 
  219 /*
  220  * Shutdown the CPU as much as possible
  221  */
  222 void
  223 cpu_reset(void)
  224 {
  225 
  226         platform_reset();
  227 }
  228 
  229 /*
  230  * Flush the D-cache for non-DMA I/O so that the I-cache can
  231  * be made coherent later.
  232  */
  233 void
  234 cpu_flush_dcache(void *ptr, size_t len)
  235 {
  236         /* TBD */
  237 }
  238 
  239 /* Get current clock frequency for the given cpu id. */
  240 int
  241 cpu_est_clockrate(int cpu_id, uint64_t *rate)
  242 {
  243 
  244         return (ENXIO);
  245 }
  246 
  247 /*
  248  * Shutdown the CPU as much as possible
  249  */
  250 void
  251 cpu_halt(void)
  252 {
  253         for (;;)
  254                 ;
  255 }
  256 
  257 SYSCTL_STRUCT(_machdep, OID_AUTO, bootinfo, CTLFLAG_RD, &bootinfo,
  258     bootinfo, "Bootinfo struct: kernel filename, BIOS harddisk geometry, etc");
  259 
  260 /*
  261  * Initialize per cpu data structures, include curthread.
  262  */
  263 void
  264 mips_pcpu0_init()
  265 {
  266         /* Initialize pcpu info of cpu-zero */
  267         pcpu_init(PCPU_ADDR(0), 0, sizeof(struct pcpu));
  268         PCPU_SET(curthread, &thread0);
  269 }
  270 
  271 /*
  272  * Initialize mips and configure to run kernel
  273  */
  274 void
  275 mips_proc0_init(void)
  276 {
  277 #ifdef SMP
  278         if (platform_processor_id() != 0)
  279                 panic("BSP must be processor number 0");
  280 #endif
  281         proc_linkup0(&proc0, &thread0);
  282 
  283         KASSERT((kstack0 & PAGE_MASK) == 0,
  284                 ("kstack0 is not aligned on a page boundary: 0x%0lx",
  285                 (long)kstack0));
  286         thread0.td_kstack = kstack0;
  287         thread0.td_kstack_pages = KSTACK_PAGES;
  288         /* 
  289          * Do not use cpu_thread_alloc to initialize these fields 
  290          * thread0 is the only thread that has kstack located in KSEG0 
  291          * while cpu_thread_alloc handles kstack allocated in KSEG2.
  292          */
  293         thread0.td_pcb = (struct pcb *)(thread0.td_kstack +
  294             thread0.td_kstack_pages * PAGE_SIZE) - 1;
  295         thread0.td_frame = &thread0.td_pcb->pcb_regs;
  296 
  297         /* Steal memory for the dynamic per-cpu area. */
  298         dpcpu_init((void *)pmap_steal_memory(DPCPU_SIZE), 0);
  299 
  300         PCPU_SET(curpcb, thread0.td_pcb);
  301         /*
  302          * There is no need to initialize md_upte array for thread0 as it's
  303          * located in .bss section and should be explicitly zeroed during 
  304          * kernel initialization.
  305          */
  306 }
  307 
  308 void
  309 cpu_initclocks(void)
  310 {
  311         platform_initclocks();
  312 }
  313 
  314 struct msgbuf *msgbufp=0;
  315 
  316 /*
  317  * Initialize the hardware exception vectors, and the jump table used to
  318  * call locore cache and TLB management functions, based on the kind
  319  * of CPU the kernel is running on.
  320  */
  321 void
  322 mips_vector_init(void)
  323 {
  324         /*
  325          * Copy down exception vector code.
  326          */
  327         if (MipsTLBMissEnd - MipsTLBMiss > 0x80)
  328                 panic("startup: UTLB code too large");
  329 
  330         if (MipsCacheEnd - MipsCache > 0x80)
  331                 panic("startup: Cache error code too large");
  332 
  333         bcopy(MipsTLBMiss, (void *)MIPS_UTLB_MISS_EXC_VEC,
  334               MipsTLBMissEnd - MipsTLBMiss);
  335 
  336 #if defined(CPU_CNMIPS) || defined(CPU_RMI)
  337 /* Fake, but sufficient, for the 32-bit with 64-bit hardware addresses  */
  338         bcopy(MipsTLBMiss, (void *)MIPS3_XTLB_MISS_EXC_VEC,
  339               MipsTLBMissEnd - MipsTLBMiss);
  340 #endif
  341 
  342         bcopy(MipsException, (void *)MIPS3_GEN_EXC_VEC,
  343               MipsExceptionEnd - MipsException);
  344 
  345         bcopy(MipsCache, (void *)MIPS3_CACHE_ERR_EXC_VEC,
  346               MipsCacheEnd - MipsCache);
  347 
  348         /*
  349          * Clear out the I and D caches.
  350          */
  351         mips_icache_sync_all();
  352         mips_dcache_wbinv_all();
  353 
  354         /* 
  355          * Mask all interrupts. Each interrupt will be enabled
  356          * when handler is installed for it
  357          */
  358         set_intr_mask(0);
  359 
  360         /* Clear BEV in SR so we start handling our own exceptions */
  361         mips_wr_status(mips_rd_status() & ~MIPS_SR_BEV);
  362 }
  363 
  364 /*
  365  * Fix kernel_kseg0_end address in case trampoline placed debug sympols 
  366  * data there
  367  */
  368 void
  369 mips_postboot_fixup(void)
  370 {
  371 #ifdef DDB
  372         Elf_Size *trampoline_data = (Elf_Size*)kernel_kseg0_end;
  373         Elf_Size symtabsize = 0;
  374 
  375         if (trampoline_data[0] == SYMTAB_MAGIC) {
  376                 symtabsize = trampoline_data[1];
  377                 kernel_kseg0_end += 2 * sizeof(Elf_Size);
  378                 /* start of .symtab */
  379                 ksym_start = kernel_kseg0_end;
  380                 kernel_kseg0_end += symtabsize;
  381                 /* end of .strtab */
  382                 ksym_end = kernel_kseg0_end;
  383         }
  384 #endif
  385 }
  386 
  387 /*
  388  * Many SoCs have a means to reset the core itself.  Others do not, or
  389  * the method is unknown to us.  For those cases, we jump to the mips
  390  * reset vector and hope for the best.  This works well in practice.
  391  */
  392 void
  393 mips_generic_reset()
  394 {
  395         ((void(*)(void))(intptr_t)MIPS_VEC_RESET)();
  396 }
  397 
  398 #ifdef SMP
  399 void
  400 mips_pcpu_tlb_init(struct pcpu *pcpu)
  401 {
  402         vm_paddr_t pa;
  403         pt_entry_t pte;
  404 
  405         /*
  406          * Map the pcpu structure at the virtual address 'pcpup'.
  407          * We use a wired tlb index to do this one-time mapping.
  408          */
  409         pa = vtophys(pcpu);
  410         pte = PTE_D | PTE_V | PTE_G | PTE_C_CACHE;
  411         tlb_insert_wired(PCPU_TLB_ENTRY, (vm_offset_t)pcpup,
  412                          TLBLO_PA_TO_PFN(pa) | pte,
  413                          TLBLO_PA_TO_PFN(pa + PAGE_SIZE) | pte);
  414 }
  415 #endif
  416 
  417 /*
  418  * Initialise a struct pcpu.
  419  */
  420 void
  421 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
  422 {
  423 
  424         pcpu->pc_next_asid = 1;
  425         pcpu->pc_asid_generation = 1;
  426 #ifdef SMP
  427         if ((vm_offset_t)pcpup >= VM_MIN_KERNEL_ADDRESS)
  428                 mips_pcpu_tlb_init(pcpu);
  429 #endif
  430 }
  431 
  432 int
  433 fill_dbregs(struct thread *td, struct dbreg *dbregs)
  434 {
  435 
  436         /* No debug registers on mips */
  437         return (ENOSYS);
  438 }
  439 
  440 int
  441 set_dbregs(struct thread *td, struct dbreg *dbregs)
  442 {
  443 
  444         /* No debug registers on mips */
  445         return (ENOSYS);
  446 }
  447 
  448 void
  449 spinlock_enter(void)
  450 {
  451         struct thread *td;
  452 
  453         td = curthread;
  454         if (td->td_md.md_spinlock_count == 0)
  455                 td->td_md.md_saved_intr = intr_disable();
  456         td->td_md.md_spinlock_count++;
  457         critical_enter();
  458 }
  459 
  460 void
  461 spinlock_exit(void)
  462 {
  463         struct thread *td;
  464 
  465         td = curthread;
  466         critical_exit();
  467         td->td_md.md_spinlock_count--;
  468         if (td->td_md.md_spinlock_count == 0)
  469                 intr_restore(td->td_md.md_saved_intr);
  470 }
  471 
  472 /*
  473  * call platform specific code to halt (until next interrupt) for the idle loop
  474  */
  475 void
  476 cpu_idle(int busy)
  477 {
  478         if (mips_rd_status() & MIPS_SR_INT_IE)
  479                 __asm __volatile ("wait");
  480         else
  481                 panic("ints disabled in idleproc!");
  482 }
  483 
  484 int
  485 cpu_idle_wakeup(int cpu)
  486 {
  487 
  488         return (0);
  489 }
  490 
  491 int
  492 is_cacheable_mem(vm_offset_t addr)
  493 {
  494         int i;
  495 
  496         for (i = 0; physmem_desc[i + 1] != 0; i += 2) {
  497                 if (addr >= physmem_desc[i] && addr < physmem_desc[i + 1])
  498                         return (1);
  499         }
  500 
  501         return (0);
  502 }

Cache object: 56a391b7d8248037cdbacf96399066a8


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