machdep.c revision 202046
1178172Simp    /*	$OpenBSD: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp $	*/
2178172Simp/* tracked to 1.38 */
3178172Simp/*
4178172Simp * Copyright (c) 1988 University of Utah.
5178172Simp * Copyright (c) 1992, 1993
6178172Simp *	The Regents of the University of California.  All rights reserved.
7178172Simp *
8178172Simp * This code is derived from software contributed to Berkeley by
9178172Simp * the Systems Programming Group of the University of Utah Computer
10178172Simp * Science Department, The Mach Operating System project at
11178172Simp * Carnegie-Mellon University and Ralph Campbell.
12178172Simp *
13178172Simp * Redistribution and use in source and binary forms, with or without
14178172Simp * modification, are permitted provided that the following conditions
15178172Simp * are met:
16178172Simp * 1. Redistributions of source code must retain the above copyright
17178172Simp *    notice, this list of conditions and the following disclaimer.
18178172Simp * 2. Redistributions in binary form must reproduce the above copyright
19178172Simp *    notice, this list of conditions and the following disclaimer in the
20178172Simp *    documentation and/or other materials provided with the distribution.
21178172Simp * 4. Neither the name of the University nor the names of its contributors
22178172Simp *    may be used to endorse or promote products derived from this software
23178172Simp *    without specific prior written permission.
24178172Simp *
25178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28178172Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35178172Simp * SUCH DAMAGE.
36178172Simp *
37178172Simp *	from: @(#)machdep.c	8.3 (Berkeley) 1/12/94
38178172Simp *	Id: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp
39187305Simp *	JNPR: machdep.c,v 1.11.2.3 2007/08/29 12:24:49
40178172Simp */
41178172Simp
42178172Simp#include <sys/cdefs.h>
43178172Simp__FBSDID("$FreeBSD: head/sys/mips/mips/machdep.c 202046 2010-01-10 20:29:20Z imp $");
44178172Simp
45202046Simp#include "opt_cputype.h"
46183771Simp#include "opt_ddb.h"
47178172Simp#include "opt_md.h"
48183771Simp#include "opt_msgbuf.h"
49178172Simp
50178172Simp#include <sys/param.h>
51178172Simp#include <sys/proc.h>
52178172Simp#include <sys/systm.h>
53178172Simp#include <sys/buf.h>
54178172Simp#include <sys/bus.h>
55178172Simp#include <sys/conf.h>
56178172Simp#include <sys/cpu.h>
57178172Simp#include <sys/kernel.h>
58178172Simp#include <sys/linker.h>
59178172Simp#include <sys/malloc.h>
60178172Simp#include <sys/mbuf.h>
61178172Simp#include <sys/msgbuf.h>
62178172Simp#include <sys/reboot.h>
63178172Simp#include <sys/sched.h>
64178172Simp#include <sys/sysctl.h>
65178172Simp#include <sys/sysproto.h>
66178172Simp#include <sys/vmmeter.h>
67178172Simp
68178172Simp#include <vm/vm.h>
69178172Simp#include <vm/vm_kern.h>
70178172Simp#include <vm/vm_object.h>
71178172Simp#include <vm/vm_page.h>
72178172Simp#include <vm/pmap.h>
73178172Simp#include <vm/vm_map.h>
74178172Simp#include <vm/vm_pager.h>
75178172Simp#include <vm/vm_extern.h>
76178172Simp#include <sys/socket.h>
77178172Simp
78178172Simp#include <sys/user.h>
79202046Simp#include <sys/interrupt.h>
80178172Simp#include <sys/cons.h>
81178172Simp#include <sys/syslog.h>
82202046Simp#include <machine/asm.h>
83202046Simp#include <machine/bootinfo.h>
84178172Simp#include <machine/cache.h>
85202046Simp#include <machine/clock.h>
86178172Simp#include <machine/cpu.h>
87202046Simp#include <machine/hwfunc.h>
88202046Simp#include <machine/intr_machdep.h>
89178172Simp#include <machine/md_var.h>
90178172Simp#ifdef DDB
91178172Simp#include <sys/kdb.h>
92178172Simp#include <ddb/ddb.h>
93178172Simp#endif
94178172Simp
95178172Simp#include <sys/random.h>
96178172Simp#include <net/if.h>
97178172Simp
98178172Simp#define	BOOTINFO_DEBUG	0
99178172Simp
100178172Simpchar machine[] = "mips";
101178172SimpSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class");
102178172Simp
103178172Simpstatic char cpu_model[30];
104178172SimpSYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model");
105178172Simp
106178172Simpint cold = 1;
107178172Simplong realmem = 0;
108202046Simplong Maxmem = 0;
109178172Simpint cpu_clock = MIPS_DEFAULT_HZ;
110178172SimpSYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD,
111178172Simp    &cpu_clock, 0, "CPU instruction clock rate");
112178172Simpint clocks_running = 0;
113178172Simp
114178172Simpvm_offset_t kstack0;
115178172Simp
116178172Simp#ifdef SMP
117202046Simpstruct pcpu __pcpu[MAXCPU];
118202046Simpchar pcpu_boot_stack[KSTACK_PAGES * PAGE_SIZE * MAXCPU];
119178172Simp#else
120178172Simpstruct pcpu pcpu;
121178172Simpstruct pcpu *pcpup = &pcpu;
122178172Simp#endif
123178172Simp
124202046Simpvm_offset_t phys_avail[PHYS_AVAIL_ENTRIES + 2];
125202046Simpvm_offset_t physmem_desc[PHYS_AVAIL_ENTRIES + 2];
126202046Simp
127178172Simp#ifdef UNIMPLEMENTED
128178172Simpstruct platform platform;
129178172Simp#endif
130178172Simp
131178172Simpvm_paddr_t	mips_wired_tlb_physmem_start;
132178172Simpvm_paddr_t	mips_wired_tlb_physmem_end;
133178172Simpu_int		need_wired_tlb_page_pool;
134178172Simp
135178172Simpstatic void cpu_startup(void *);
136178172SimpSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
137178172Simp
138178172Simpstruct kva_md_info kmi;
139178172Simp
140178172Simpint cpucfg;			/* Value of processor config register */
141178172Simpint num_tlbentries = 64;	/* Size of the CPU tlb */
142178172Simpint cputype;
143178172Simp
144178172Simpextern char MipsException[], MipsExceptionEnd[];
145178172Simp
146178172Simp/* TLB miss handler address and end */
147178172Simpextern char MipsTLBMiss[], MipsTLBMissEnd[];
148178172Simp
149178172Simp/* Cache error handler */
150178172Simpextern char MipsCache[], MipsCacheEnd[];
151178172Simp
152178172Simpextern char edata[], end[];
153178172Simp
154178172Simpu_int32_t bootdev;
155178172Simpstruct bootinfo bootinfo;
156178172Simp
157178172Simpstatic void
158178172Simpcpu_startup(void *dummy)
159178172Simp{
160178172Simp
161178172Simp	if (boothowto & RB_VERBOSE)
162178172Simp		bootverbose++;
163178172Simp
164187305Simp	bootverbose++;
165187305Simp	printf("real memory  = %lu (%luK bytes)\n", ptoa(realmem),
166187305Simp	    ptoa(realmem) / 1024);
167187305Simp
168178172Simp	/*
169178172Simp	 * Display any holes after the first chunk of extended memory.
170178172Simp	 */
171178172Simp	if (bootverbose) {
172178172Simp		int indx;
173178172Simp
174178172Simp		printf("Physical memory chunk(s):\n");
175178172Simp		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
176202046Simp			uintptr_t size1 = phys_avail[indx + 1] - phys_avail[indx];
177178172Simp
178202046Simp			printf("0x%08llx - 0x%08llx, %llu bytes (%llu pages)\n",
179202046Simp			    (unsigned long long)phys_avail[indx],
180202046Simp			    (unsigned long long)phys_avail[indx + 1] - 1,
181202046Simp			    (unsigned long long)size1,
182202046Simp			    (unsigned long long)size1 / PAGE_SIZE);
183178172Simp		}
184178172Simp	}
185178172Simp
186178172Simp	vm_ksubmap_init(&kmi);
187178172Simp
188178172Simp	printf("avail memory = %lu (%luMB)\n", ptoa(cnt.v_free_count),
189178172Simp	    ptoa(cnt.v_free_count) / 1048576);
190202046Simp	cpu_init_interrupts();
191178172Simp
192178172Simp	/*
193178172Simp	 * Set up buffers, so they can be used to read disk labels.
194178172Simp	 */
195178172Simp	bufinit();
196178172Simp	vm_pager_bufferinit();
197178172Simp}
198178172Simp
199178172Simp/*
200178172Simp * Shutdown the CPU as much as possible
201178172Simp */
202178172Simpvoid
203178172Simpcpu_reset(void)
204178172Simp{
205187294Simp
206187294Simp	platform_reset();
207178172Simp}
208178172Simp
209192323Smarcel/*
210192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can
211192323Smarcel * be made coherent later.
212192323Smarcel */
213192323Smarcelvoid
214192323Smarcelcpu_flush_dcache(void *ptr, size_t len)
215192323Smarcel{
216192323Smarcel	/* TBD */
217192323Smarcel}
218192323Smarcel
219178172Simp/* Get current clock frequency for the given cpu id. */
220178172Simpint
221178172Simpcpu_est_clockrate(int cpu_id, uint64_t *rate)
222178172Simp{
223178172Simp
224187294Simp	return (ENXIO);
225178172Simp}
226178172Simp
227178172Simp/*
228178172Simp * Shutdown the CPU as much as possible
229178172Simp */
230178172Simpvoid
231178172Simpcpu_halt(void)
232178172Simp{
233178172Simp	for (;;)
234178172Simp		;
235178172Simp}
236178172Simp
237187326SimpSYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, CTLFLAG_RD, &bootinfo,
238187326Simp    bootinfo, "Bootinfo struct: kernel filename, BIOS harddisk geometry, etc");
239187326Simp
240178172Simp#ifdef PORT_TO_JMIPS
241178172Simpstatic int
242178172Simpsysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
243178172Simp{
244178172Simp}
245178172Simp
246178172SimpSYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT | CTLFLAG_RW,
247181236Strhodes    &adjkerntz, 0, sysctl_machdep_adjkerntz, "I",
248181236Strhodes    "Local offset from GMT in seconds");
249178172SimpSYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, CTLFLAG_RW,
250181236Strhodes    &disable_rtc_set, 0, "Disable setting the real time clock to system time");
251178172SimpSYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, CTLFLAG_RW,
252181236Strhodes    &wall_cmos_clock, 0, "Wall CMOS clock assumed");
253178172Simp#endif	/* PORT_TO_JMIPS */
254178172Simp
255178172Simp/*
256202046Simp * Initialize per cpu data structures, include curthread.
257178172Simp */
258178172Simpvoid
259202046Simpmips_pcpu0_init()
260178172Simp{
261178172Simp	/* Initialize pcpu info of cpu-zero */
262178172Simp#ifdef SMP
263178172Simp	pcpu_init(&__pcpu[0], 0, sizeof(struct pcpu));
264178172Simp#else
265178172Simp	pcpu_init(pcpup, 0, sizeof(struct pcpu));
266178172Simp#endif
267202046Simp	PCPU_SET(curthread, &thread0);
268202046Simp}
269202046Simp
270202046Simp/*
271202046Simp * Initialize mips and configure to run kernel
272202046Simp */
273202046Simpvoid
274202046Simpmips_proc0_init(void)
275202046Simp{
276202046Simp	proc_linkup0(&proc0, &thread0);
277202046Simp
278202046Simp	KASSERT((kstack0 & PAGE_MASK) == 0,
279202046Simp		("kstack0 is not aligned on a page boundary: 0x%0lx",
280202046Simp		(long)kstack0));
281202046Simp	thread0.td_kstack = kstack0;
282202046Simp	thread0.td_kstack_pages = KSTACK_PAGES;
283202046Simp	thread0.td_md.md_realstack = roundup2(thread0.td_kstack, PAGE_SIZE * 2);
284178172Simp	/*
285178172Simp	 * Do not use cpu_thread_alloc to initialize these fields
286178172Simp	 * thread0 is the only thread that has kstack located in KSEG0
287178172Simp	 * while cpu_thread_alloc handles kstack allocated in KSEG2.
288178172Simp	 */
289178172Simp	thread0.td_pcb = (struct pcb *)(thread0.td_md.md_realstack +
290178172Simp	    (thread0.td_kstack_pages - 1) * PAGE_SIZE) - 1;
291178172Simp	thread0.td_frame = &thread0.td_pcb->pcb_regs;
292187326Simp
293199114Sgonzo	/* Steal memory for the dynamic per-cpu area. */
294199114Sgonzo	dpcpu_init((void *)pmap_steal_memory(DPCPU_SIZE), 0);
295199114Sgonzo
296202046Simp	PCPU_SET(curpcb, thread0.td_pcb);
297178172Simp	/*
298178172Simp	 * There is no need to initialize md_upte array for thread0 as it's
299178172Simp	 * located in .bss section and should be explicitly zeroed during
300178172Simp	 * kernel initialization.
301178172Simp	 */
302202046Simp}
303178172Simp
304202046Simpvoid
305202046Simpcpu_initclocks(void)
306202046Simp{
307202046Simp	platform_initclocks();
308178172Simp}
309178172Simp
310178172Simpstruct msgbuf *msgbufp=0;
311178172Simp
312178172Simp/*
313178172Simp * Initialize the hardware exception vectors, and the jump table used to
314178172Simp * call locore cache and TLB management functions, based on the kind
315178172Simp * of CPU the kernel is running on.
316178172Simp */
317178172Simpvoid
318178172Simpmips_vector_init(void)
319178172Simp{
320178172Simp	/*
321178172Simp	 * Copy down exception vector code.
322178172Simp	 */
323178172Simp	if (MipsTLBMissEnd - MipsTLBMiss > 0x80)
324178172Simp		panic("startup: UTLB code too large");
325178172Simp
326178172Simp	if (MipsCacheEnd - MipsCache > 0x80)
327178172Simp		panic("startup: Cache error code too large");
328178172Simp
329178172Simp	bcopy(MipsTLBMiss, (void *)TLB_MISS_EXC_VEC,
330178172Simp	      MipsTLBMissEnd - MipsTLBMiss);
331178172Simp
332178172Simp#ifdef TARGET_OCTEON
333178172Simp/* Fake, but sufficient, for the 32-bit with 64-bit hardware addresses  */
334178172Simp	bcopy(MipsTLBMiss, (void *)XTLB_MISS_EXC_VEC,
335178172Simp	      MipsTLBMissEnd - MipsTLBMiss);
336178172Simp#endif
337178172Simp
338178172Simp	bcopy(MipsException, (void *)GEN_EXC_VEC,
339178172Simp	      MipsExceptionEnd - MipsException);
340178172Simp
341178172Simp	bcopy(MipsCache, (void *)CACHE_ERR_EXC_VEC,
342178172Simp	      MipsCacheEnd - MipsCache);
343178172Simp
344178172Simp	/*
345178172Simp	 * Clear out the I and D caches.
346178172Simp	 */
347178172Simp	mips_icache_sync_all();
348178172Simp	mips_dcache_wbinv_all();
349178172Simp
350178172Simp	/*
351178172Simp	 * Mask all interrupts. Each interrupt will be enabled
352178172Simp	 * when handler is installed for it
353178172Simp	 */
354178172Simp	set_intr_mask (ALL_INT_MASK);
355178172Simp	/* Clear BEV in SR so we start handling our own exceptions */
356178172Simp	mips_cp0_status_write(mips_cp0_status_read() & ~SR_BOOT_EXC_VEC);
357178172Simp
358178172Simp}
359178172Simp
360178172Simp/*
361178172Simp * Initialise a struct pcpu.
362178172Simp */
363178172Simpvoid
364178172Simpcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
365178172Simp{
366178172Simp#ifdef SMP
367178172Simp	if (cpuid != 0)
368178172Simp		pcpu->pc_boot_stack = (void *)(pcpu_boot_stack + cpuid *
369178172Simp		    (KSTACK_PAGES * PAGE_SIZE));
370178172Simp#endif
371178172Simp	pcpu->pc_next_asid = 1;
372178172Simp	pcpu->pc_asid_generation = 1;
373178172Simp}
374178172Simp
375178172Simpint
376178172Simpfill_dbregs(struct thread *td, struct dbreg *dbregs)
377178172Simp{
378178172Simp
379178172Simp	/* No debug registers on mips */
380178172Simp	return (ENOSYS);
381178172Simp}
382178172Simp
383178172Simpint
384178172Simpset_dbregs(struct thread *td, struct dbreg *dbregs)
385178172Simp{
386178172Simp
387178172Simp	/* No debug registers on mips */
388178172Simp	return (ENOSYS);
389178172Simp}
390178172Simp
391178172Simpvoid
392178172Simpspinlock_enter(void)
393178172Simp{
394178172Simp	struct thread *td;
395178172Simp
396178172Simp	td = curthread;
397178172Simp	if (td->td_md.md_spinlock_count == 0)
398178172Simp		td->td_md.md_saved_intr = disableintr();
399178172Simp	td->td_md.md_spinlock_count++;
400178172Simp	critical_enter();
401178172Simp}
402178172Simp
403178172Simpvoid
404178172Simpspinlock_exit(void)
405178172Simp{
406178172Simp	struct thread *td;
407178172Simp
408178172Simp	td = curthread;
409178172Simp	critical_exit();
410178172Simp	td->td_md.md_spinlock_count--;
411178172Simp	if (td->td_md.md_spinlock_count == 0)
412178172Simp		restoreintr(td->td_md.md_saved_intr);
413178172Simp}
414178172Simp
415178172Simpu_int32_t
416178172Simpget_cyclecount(void)
417178172Simp{
418178172Simp	u_int32_t count;
419178172Simp
420178172Simp	mfc0_macro(count, 9);
421178172Simp	return (count);
422178172Simp}
423178172Simp
424178172Simp/*
425178172Simp * call platform specific code to halt (until next interrupt) for the idle loop
426178172Simp */
427178172Simpvoid
428178471Sjeffcpu_idle(int busy)
429178172Simp{
430178172Simp	if (mips_cp0_status_read() & SR_INT_ENAB)
431178172Simp		__asm __volatile ("wait");
432178172Simp	else
433178172Simp		panic("ints disabled in idleproc!");
434178172Simp}
435178172Simp
436187293Simpvoid
437187293Simpdumpsys(struct dumperinfo *di __unused)
438178471Sjeff{
439178471Sjeff
440187293Simp	printf("Kernel dumps not implemented on this architecture\n");
441178471Sjeff}
442178471Sjeff
443187293Simpint
444187293Simpcpu_idle_wakeup(int cpu)
445178172Simp{
446178172Simp
447187293Simp	return (0);
448178172Simp}
449202046Simp
450202046Simpint
451202046Simpis_physical_memory(vm_offset_t addr)
452202046Simp{
453202046Simp	int i;
454202046Simp
455202046Simp	for (i = 0; physmem_desc[i + 1] != 0; i += 2) {
456202046Simp		if (addr >= physmem_desc[i] && addr < physmem_desc[i + 1])
457202046Simp			return (1);
458202046Simp	}
459202046Simp
460202046Simp	return (0);
461202046Simp}
462