1234920Srwatson/*-
2234920Srwatson * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
3234920Srwatson * All rights reserved.
4234920Srwatson *
5234920Srwatson * Redistribution and use in source and binary forms, with or without
6234920Srwatson * modification, are permitted provided that the following conditions
7234920Srwatson * are met:
8234920Srwatson * 1. Redistributions of source code must retain the above copyright
9234920Srwatson *    notice, this list of conditions and the following disclaimer.
10234920Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11234920Srwatson *    notice, this list of conditions and the following disclaimer in the
12234920Srwatson *    documentation and/or other materials provided with the distribution.
13234920Srwatson *
14234920Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15234920Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16234920Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17234920Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18234920Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19234920Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20234920Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21234920Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22234920Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23234920Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24234920Srwatson * SUCH DAMAGE.
25234920Srwatson */
26234920Srwatson#include <sys/cdefs.h>
27234920Srwatson__FBSDID("$FreeBSD: releng/10.3/sys/mips/gxemul/gxemul_machdep.c 247297 2013-02-26 01:00:11Z attilio $");
28234920Srwatson
29234920Srwatson#include "opt_ddb.h"
30234920Srwatson
31234920Srwatson#include <sys/param.h>
32234920Srwatson#include <sys/conf.h>
33234920Srwatson#include <sys/kernel.h>
34234920Srwatson#include <sys/systm.h>
35234920Srwatson#include <sys/imgact.h>
36234920Srwatson#include <sys/bio.h>
37234920Srwatson#include <sys/buf.h>
38234920Srwatson#include <sys/bus.h>
39234920Srwatson#include <sys/cpu.h>
40234920Srwatson#include <sys/cons.h>
41234920Srwatson#include <sys/exec.h>
42234920Srwatson#include <sys/ucontext.h>
43234920Srwatson#include <sys/proc.h>
44234920Srwatson#include <sys/kdb.h>
45234920Srwatson#include <sys/ptrace.h>
46234920Srwatson#include <sys/reboot.h>
47234920Srwatson#include <sys/signalvar.h>
48234920Srwatson#include <sys/sysent.h>
49234920Srwatson#include <sys/sysproto.h>
50234920Srwatson#include <sys/user.h>
51234920Srwatson
52234920Srwatson#include <vm/vm.h>
53234920Srwatson#include <vm/vm_object.h>
54234920Srwatson#include <vm/vm_page.h>
55234920Srwatson
56234920Srwatson#include <machine/clock.h>
57234920Srwatson#include <machine/cpu.h>
58234920Srwatson#include <machine/cpuregs.h>
59234920Srwatson#include <machine/hwfunc.h>
60234920Srwatson#include <machine/md_var.h>
61234920Srwatson#include <machine/pmap.h>
62234920Srwatson#include <machine/trap.h>
63234920Srwatson
64235118Sjmallett#ifdef SMP
65235118Sjmallett#include <sys/smp.h>
66235118Sjmallett#include <machine/smp.h>
67235118Sjmallett#endif
68235118Sjmallett
69235070Sjmallett#include <mips/gxemul/mpreg.h>
70235070Sjmallett
71234920Srwatsonextern int	*edata;
72234920Srwatsonextern int	*end;
73234920Srwatson
74234920Srwatsonvoid
75234920Srwatsonplatform_cpu_init()
76234920Srwatson{
77234920Srwatson	/* Nothing special */
78234920Srwatson}
79234920Srwatson
80234920Srwatsonstatic void
81234920Srwatsonmips_init(void)
82234920Srwatson{
83234920Srwatson	int i;
84234920Srwatson
85234920Srwatson	for (i = 0; i < 10; i++) {
86234920Srwatson		phys_avail[i] = 0;
87234920Srwatson	}
88234920Srwatson
89234920Srwatson	/* phys_avail regions are in bytes */
90234920Srwatson	phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
91234920Srwatson	phys_avail[1] = ctob(realmem);
92234920Srwatson
93234920Srwatson	dump_avail[0] = phys_avail[0];
94234920Srwatson	dump_avail[1] = phys_avail[1];
95234920Srwatson
96234920Srwatson	physmem = realmem;
97234920Srwatson
98234920Srwatson	init_param1();
99234920Srwatson	init_param2(physmem);
100234920Srwatson	mips_cpu_init();
101234920Srwatson	pmap_bootstrap();
102234920Srwatson	mips_proc0_init();
103234920Srwatson	mutex_init();
104234920Srwatson	kdb_init();
105234920Srwatson#ifdef KDB
106234920Srwatson	if (boothowto & RB_KDB)
107234920Srwatson		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
108234920Srwatson#endif
109234920Srwatson}
110234920Srwatson
111234920Srwatson/*
112234920Srwatson * Perform a board-level soft-reset.
113234920Srwatson *
114234920Srwatson * XXXRW: Does gxemul have a moral equivalent to board-level reset?
115234920Srwatson */
116234920Srwatsonvoid
117234920Srwatsonplatform_reset(void)
118234920Srwatson{
119234920Srwatson
120234920Srwatson	panic("%s: not yet", __func__);
121234920Srwatson}
122234920Srwatson
123234920Srwatsonvoid
124234920Srwatsonplatform_start(__register_t a0, __register_t a1,  __register_t a2,
125234920Srwatson    __register_t a3)
126234920Srwatson{
127234920Srwatson	vm_offset_t kernend;
128234920Srwatson	uint64_t platform_counter_freq;
129234920Srwatson	int argc = a0;
130234920Srwatson	char **argv = (char **)a1;
131234920Srwatson	char **envp = (char **)a2;
132234920Srwatson	int i;
133234920Srwatson
134234920Srwatson	/* clear the BSS and SBSS segments */
135234920Srwatson	kernend = (vm_offset_t)&end;
136234920Srwatson	memset(&edata, 0, kernend - (vm_offset_t)(&edata));
137234920Srwatson
138234920Srwatson	mips_postboot_fixup();
139234920Srwatson
140234920Srwatson	mips_pcpu0_init();
141234920Srwatson
142234920Srwatson	/*
143234920Srwatson	 * XXXRW: Support for the gxemul real-time clock required in order to
144234920Srwatson	 * usefully determine our emulated timer frequency.  Go with something
145234920Srwatson	 * classic as the default in the mean time.
146234920Srwatson	 */
147234920Srwatson	platform_counter_freq = MIPS_DEFAULT_HZ;
148234920Srwatson	mips_timer_early_init(platform_counter_freq);
149234920Srwatson
150234920Srwatson	cninit();
151234920Srwatson	printf("entry: platform_start()\n");
152234920Srwatson
153234920Srwatson	bootverbose = 1;
154234920Srwatson	if (bootverbose) {
155234920Srwatson		printf("cmd line: ");
156234920Srwatson		for (i = 0; i < argc; i++)
157234920Srwatson			printf("%s ", argv[i]);
158234920Srwatson		printf("\n");
159234920Srwatson
160235070Sjmallett		if (envp != NULL) {
161235070Sjmallett			printf("envp:\n");
162235070Sjmallett			for (i = 0; envp[i]; i += 2)
163235070Sjmallett				printf("\t%s = %s\n", envp[i], envp[i+1]);
164235070Sjmallett		} else {
165235070Sjmallett			printf("no envp.\n");
166235070Sjmallett		}
167234920Srwatson	}
168234920Srwatson
169235070Sjmallett	realmem = btoc(GXEMUL_MP_DEV_READ(GXEMUL_MP_DEV_MEMORY));
170234920Srwatson	mips_init();
171234920Srwatson
172234920Srwatson	mips_timer_init_params(platform_counter_freq, 0);
173234920Srwatson}
174235118Sjmallett
175235118Sjmallett#ifdef SMP
176235118Sjmallettvoid
177235118Sjmallettplatform_ipi_send(int cpuid)
178235118Sjmallett{
179235118Sjmallett	GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_IPI_ONE, (1 << 16) | cpuid);
180235118Sjmallett}
181235118Sjmallett
182235118Sjmallettvoid
183235118Sjmallettplatform_ipi_clear(void)
184235118Sjmallett{
185235118Sjmallett	GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_IPI_READ, 0);
186235118Sjmallett}
187235118Sjmallett
188235118Sjmallettint
189235118Sjmallettplatform_ipi_intrnum(void)
190235118Sjmallett{
191235118Sjmallett	return (GXEMUL_MP_DEV_IPI_INTERRUPT - 2);
192235118Sjmallett}
193235118Sjmallett
194235118Sjmallettstruct cpu_group *
195235118Sjmallettplatform_smp_topo(void)
196235118Sjmallett{
197235118Sjmallett	return (smp_topo_none());
198235118Sjmallett}
199235118Sjmallett
200235118Sjmallettvoid
201235118Sjmallettplatform_init_ap(int cpuid)
202235118Sjmallett{
203235118Sjmallett	int ipi_int_mask, clock_int_mask;
204235118Sjmallett
205235118Sjmallett	/*
206235118Sjmallett	 * Unmask the clock and ipi interrupts.
207235118Sjmallett	 */
208235118Sjmallett	clock_int_mask = hard_int_mask(5);
209235118Sjmallett	ipi_int_mask = hard_int_mask(platform_ipi_intrnum());
210235118Sjmallett	set_intr_mask(ipi_int_mask | clock_int_mask);
211235118Sjmallett}
212235118Sjmallett
213235118Sjmallettvoid
214235118Sjmallettplatform_cpu_mask(cpuset_t *mask)
215235118Sjmallett{
216235118Sjmallett	unsigned i, n;
217235118Sjmallett
218235118Sjmallett	n = GXEMUL_MP_DEV_READ(GXEMUL_MP_DEV_NCPUS);
219235118Sjmallett	CPU_ZERO(mask);
220235118Sjmallett	for (i = 0; i < n; i++)
221235118Sjmallett		CPU_SET(i, mask);
222235118Sjmallett}
223235118Sjmallett
224235118Sjmallettint
225235118Sjmallettplatform_processor_id(void)
226235118Sjmallett{
227235118Sjmallett	return (GXEMUL_MP_DEV_READ(GXEMUL_MP_DEV_WHOAMI));
228235118Sjmallett}
229235118Sjmallett
230235118Sjmallettint
231235118Sjmallettplatform_start_ap(int cpuid)
232235118Sjmallett{
233235118Sjmallett	GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_STARTADDR, (intptr_t)mpentry);
234235118Sjmallett	GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_START, cpuid);
235235118Sjmallett	return (0);
236235118Sjmallett}
237235118Sjmallett#endif	/* SMP */
238