]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/mips/mips/machdep.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / mips / mips / machdep.c
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$");
44
45 #include "opt_ddb.h"
46 #include "opt_md.h"
47 #include "opt_msgbuf.h"
48
49 #include <sys/param.h>
50 #include <sys/proc.h>
51 #include <sys/systm.h>
52 #include <sys/buf.h>
53 #include <sys/bus.h>
54 #include <sys/conf.h>
55 #include <sys/cpu.h>
56 #include <sys/kernel.h>
57 #include <sys/linker.h>
58 #include <sys/malloc.h>
59 #include <sys/mbuf.h>
60 #include <sys/msgbuf.h>
61 #include <sys/reboot.h>
62 #include <sys/sched.h>
63 #include <sys/sysctl.h>
64 #include <sys/sysproto.h>
65 #include <sys/vmmeter.h>
66
67 #include <vm/vm.h>
68 #include <vm/vm_kern.h>
69 #include <vm/vm_object.h>
70 #include <vm/vm_page.h>
71 #include <vm/pmap.h>
72 #include <vm/vm_map.h>
73 #include <vm/vm_pager.h>
74 #include <vm/vm_extern.h>
75 #include <sys/socket.h>
76
77 #include <sys/user.h>
78 #include <sys/cons.h>
79 #include <sys/syslog.h>
80 #include <machine/cache.h>
81 #include <machine/cpu.h>
82 #include <machine/pltfm.h>
83 #include <net/netisr.h>
84 #include <machine/md_var.h>
85 #include <machine/clock.h>
86 #include <machine/asm.h>
87 #include <machine/bootinfo.h>
88 #include <machine/hwfunc.h>
89 #ifdef DDB
90 #include <sys/kdb.h>
91 #include <ddb/ddb.h>
92 #endif
93
94 #include <sys/random.h>
95 #include <net/if.h>
96
97 #define BOOTINFO_DEBUG  0
98
99 char machine[] = "mips";
100 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class");
101
102 static char cpu_model[30];
103 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model");
104
105 int cold = 1;
106 long realmem = 0;
107 int cpu_clock = MIPS_DEFAULT_HZ;
108 SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 
109     &cpu_clock, 0, "CPU instruction clock rate");
110 int clocks_running = 0;
111
112 vm_offset_t kstack0;
113
114 #ifdef SMP
115 struct pcpu __pcpu[32];
116 char pcpu_boot_stack[KSTACK_PAGES * PAGE_SIZE * (MAXCPU-1)]; 
117 #else
118 struct pcpu pcpu;
119 struct pcpu *pcpup = &pcpu;
120 #endif
121
122 vm_offset_t phys_avail[10];
123 #ifdef UNIMPLEMENTED
124 struct platform platform;
125 #endif
126
127 vm_paddr_t      mips_wired_tlb_physmem_start;
128 vm_paddr_t      mips_wired_tlb_physmem_end;
129 u_int           need_wired_tlb_page_pool;
130
131 static void cpu_startup(void *);
132 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
133
134 struct kva_md_info kmi;
135
136 int cpucfg;                     /* Value of processor config register */
137 int num_tlbentries = 64;        /* Size of the CPU tlb */
138 int cputype;
139
140 extern char MipsException[], MipsExceptionEnd[];
141
142 /* TLB miss handler address and end */
143 extern char MipsTLBMiss[], MipsTLBMissEnd[];
144
145 /* Cache error handler */
146 extern char MipsCache[], MipsCacheEnd[];
147
148 extern char edata[], end[];
149
150 u_int32_t bootdev;
151 struct bootinfo bootinfo;
152
153
154 static void
155 cpu_startup(void *dummy)
156 {
157
158         if (boothowto & RB_VERBOSE)
159                 bootverbose++;
160
161         bootverbose++;
162         printf("real memory  = %lu (%luK bytes)\n", ptoa(realmem),
163             ptoa(realmem) / 1024);
164
165         /*
166          * Display any holes after the first chunk of extended memory.
167          */
168         if (bootverbose) {
169                 int indx;
170
171                 printf("Physical memory chunk(s):\n");
172                 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
173                         int size1 = phys_avail[indx + 1] - phys_avail[indx];
174
175                         printf("0x%08x - 0x%08x, %u bytes (%u pages)\n",
176                             phys_avail[indx], phys_avail[indx + 1] - 1, size1,
177                             size1 / PAGE_SIZE);
178                 }
179         }
180
181         vm_ksubmap_init(&kmi);
182
183         printf("avail memory = %lu (%luMB)\n", ptoa(cnt.v_free_count),
184             ptoa(cnt.v_free_count) / 1048576);
185
186         /*
187          * Set up buffers, so they can be used to read disk labels.
188          */
189         bufinit();
190         vm_pager_bufferinit();
191 }
192
193 /*
194  * Shutdown the CPU as much as possible
195  */
196 void
197 cpu_reset(void)
198 {
199
200         platform_reset();
201 }
202
203 /*
204  * Flush the D-cache for non-DMA I/O so that the I-cache can
205  * be made coherent later.
206  */
207 void
208 cpu_flush_dcache(void *ptr, size_t len)
209 {
210         /* TBD */
211 }
212
213 /* Get current clock frequency for the given cpu id. */
214 int
215 cpu_est_clockrate(int cpu_id, uint64_t *rate)
216 {
217
218         return (ENXIO);
219 }
220
221 /*
222  * Shutdown the CPU as much as possible
223  */
224 void
225 cpu_halt(void)
226 {
227         for (;;)
228                 ;
229 }
230
231 SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, CTLFLAG_RD, &bootinfo,
232     bootinfo, "Bootinfo struct: kernel filename, BIOS harddisk geometry, etc");
233
234 #ifdef PORT_TO_JMIPS
235 static int
236 sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
237 {
238 }
239
240 SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT | CTLFLAG_RW,
241     &adjkerntz, 0, sysctl_machdep_adjkerntz, "I",
242     "Local offset from GMT in seconds");
243 SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, CTLFLAG_RW,
244     &disable_rtc_set, 0, "Disable setting the real time clock to system time");
245 SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, CTLFLAG_RW,
246     &wall_cmos_clock, 0, "Wall CMOS clock assumed");
247 #endif  /* PORT_TO_JMIPS */
248
249 /*
250  * Initialize mips and configure to run kernel
251  */
252 void
253 mips_proc0_init(void)
254 {
255         proc_linkup(&proc0, &thread0);
256         thread0.td_kstack = kstack0;
257         thread0.td_kstack_pages = KSTACK_PAGES - 1;
258         if (thread0.td_kstack & (1 << PAGE_SHIFT))
259                 thread0.td_md.md_realstack = thread0.td_kstack + PAGE_SIZE;
260         else
261                 thread0.td_md.md_realstack = thread0.td_kstack;
262         /* Initialize pcpu info of cpu-zero */
263 #ifdef SMP
264         pcpu_init(&__pcpu[0], 0, sizeof(struct pcpu));
265 #else
266         pcpu_init(pcpup, 0, sizeof(struct pcpu));
267 #endif
268         /* 
269          * Do not use cpu_thread_alloc to initialize these fields 
270          * thread0 is the only thread that has kstack located in KSEG0 
271          * while cpu_thread_alloc handles kstack allocated in KSEG2.
272          */
273         thread0.td_pcb = (struct pcb *)(thread0.td_md.md_realstack +
274             (thread0.td_kstack_pages - 1) * PAGE_SIZE) - 1;
275         thread0.td_frame = &thread0.td_pcb->pcb_regs;
276
277         /*
278          * There is no need to initialize md_upte array for thread0 as it's
279          * located in .bss section and should be explicitly zeroed during 
280          * kernel initialization.
281          */
282
283         PCPU_SET(curthread, &thread0);
284         PCPU_SET(curpcb, thread0.td_pcb);
285 }
286
287 struct msgbuf *msgbufp=0;
288
289 /*
290  * Initialize the hardware exception vectors, and the jump table used to
291  * call locore cache and TLB management functions, based on the kind
292  * of CPU the kernel is running on.
293  */
294 void
295 mips_vector_init(void)
296 {
297         /*
298          * Copy down exception vector code.
299          */
300         if (MipsTLBMissEnd - MipsTLBMiss > 0x80)
301                 panic("startup: UTLB code too large");
302
303         if (MipsCacheEnd - MipsCache > 0x80)
304                 panic("startup: Cache error code too large");
305
306         bcopy(MipsTLBMiss, (void *)TLB_MISS_EXC_VEC,
307               MipsTLBMissEnd - MipsTLBMiss);
308
309 #ifdef TARGET_OCTEON
310 /* Fake, but sufficient, for the 32-bit with 64-bit hardware addresses  */
311         bcopy(MipsTLBMiss, (void *)XTLB_MISS_EXC_VEC,
312               MipsTLBMissEnd - MipsTLBMiss);
313 #endif
314
315         bcopy(MipsException, (void *)GEN_EXC_VEC,
316               MipsExceptionEnd - MipsException);
317
318         bcopy(MipsCache, (void *)CACHE_ERR_EXC_VEC,
319               MipsCacheEnd - MipsCache);
320
321         /*
322          * Clear out the I and D caches.
323          */
324         mips_icache_sync_all();
325         mips_dcache_wbinv_all();
326
327         /* 
328          * Mask all interrupts. Each interrupt will be enabled
329          * when handler is installed for it
330          */
331         set_intr_mask (ALL_INT_MASK);
332         /* Clear BEV in SR so we start handling our own exceptions */
333         mips_cp0_status_write(mips_cp0_status_read() & ~SR_BOOT_EXC_VEC);
334
335 }
336
337 /*
338  * Initialise a struct pcpu.
339  */
340 void
341 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
342 {
343 #ifdef SMP
344         if (cpuid != 0)
345                 pcpu->pc_boot_stack = (void *)(pcpu_boot_stack + cpuid *
346                     (KSTACK_PAGES * PAGE_SIZE));
347 #endif
348         pcpu->pc_next_asid = 1;
349         pcpu->pc_asid_generation = 1;
350 }
351
352 int
353 sysarch(struct thread *td, register struct sysarch_args *uap)
354 {
355         return (ENOSYS);
356 }
357
358 int
359 fill_dbregs(struct thread *td, struct dbreg *dbregs)
360 {
361
362         /* No debug registers on mips */
363         return (ENOSYS);
364 }
365
366 int
367 set_dbregs(struct thread *td, struct dbreg *dbregs)
368 {
369
370         /* No debug registers on mips */
371         return (ENOSYS);
372 }
373
374 void
375 spinlock_enter(void)
376 {
377         struct thread *td;
378
379         td = curthread;
380         if (td->td_md.md_spinlock_count == 0)
381                 td->td_md.md_saved_intr = disableintr();
382         td->td_md.md_spinlock_count++;
383         critical_enter();
384 }
385
386 void
387 spinlock_exit(void)
388 {
389         struct thread *td;
390
391         td = curthread;
392         critical_exit();
393         td->td_md.md_spinlock_count--;
394         if (td->td_md.md_spinlock_count == 0)
395                 restoreintr(td->td_md.md_saved_intr);
396 }
397
398 u_int32_t
399 get_cyclecount(void)
400 {
401         u_int32_t count;
402
403         mfc0_macro(count, 9);
404         return (count);
405 }
406
407 /*
408  * call platform specific code to halt (until next interrupt) for the idle loop
409  */
410 void
411 cpu_idle(int busy)
412 {
413         if (mips_cp0_status_read() & SR_INT_ENAB)
414                 __asm __volatile ("wait");
415         else
416                 panic("ints disabled in idleproc!");
417 }
418
419 void
420 dumpsys(struct dumperinfo *di __unused)
421 {
422
423         printf("Kernel dumps not implemented on this architecture\n");
424 }
425
426 int
427 cpu_idle_wakeup(int cpu)
428 {
429
430         return (0);
431 }