xref: /openbsd/sys/arch/loongson/loongson/machdep.c (revision bb00e811)
1*bb00e811Sclaudio /*	$OpenBSD: machdep.c,v 1.101 2023/10/24 13:20:10 claudio Exp $ */
22bf3c060Smiod 
32bf3c060Smiod /*
46f377552Smiod  * Copyright (c) 2009, 2010, 2014 Miodrag Vallat.
52bf3c060Smiod  *
62bf3c060Smiod  * Permission to use, copy, modify, and distribute this software for any
72bf3c060Smiod  * purpose with or without fee is hereby granted, provided that the above
82bf3c060Smiod  * copyright notice and this permission notice appear in all copies.
92bf3c060Smiod  *
102bf3c060Smiod  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
112bf3c060Smiod  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
122bf3c060Smiod  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
132bf3c060Smiod  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
142bf3c060Smiod  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
152bf3c060Smiod  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
162bf3c060Smiod  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
172bf3c060Smiod  */
182bf3c060Smiod /*
192bf3c060Smiod  * Copyright (c) 2003-2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
202bf3c060Smiod  *
212bf3c060Smiod  * Redistribution and use in source and binary forms, with or without
222bf3c060Smiod  * modification, are permitted provided that the following conditions
232bf3c060Smiod  * are met:
242bf3c060Smiod  * 1. Redistributions of source code must retain the above copyright
252bf3c060Smiod  *    notice, this list of conditions and the following disclaimer.
262bf3c060Smiod  * 2. Redistributions in binary form must reproduce the above copyright
272bf3c060Smiod  *    notice, this list of conditions and the following disclaimer in the
282bf3c060Smiod  *    documentation and/or other materials provided with the distribution.
292bf3c060Smiod  *
302bf3c060Smiod  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
312bf3c060Smiod  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
322bf3c060Smiod  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
332bf3c060Smiod  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
342bf3c060Smiod  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
352bf3c060Smiod  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
362bf3c060Smiod  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
372bf3c060Smiod  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
382bf3c060Smiod  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
392bf3c060Smiod  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
402bf3c060Smiod  * SUCH DAMAGE.
412bf3c060Smiod  *
422bf3c060Smiod  */
432bf3c060Smiod #include <sys/param.h>
442bf3c060Smiod #include <sys/systm.h>
452bf3c060Smiod #include <sys/kernel.h>
462bf3c060Smiod #include <sys/proc.h>
472bf3c060Smiod #include <sys/buf.h>
482bf3c060Smiod #include <sys/reboot.h>
492bf3c060Smiod #include <sys/conf.h>
502bf3c060Smiod #include <sys/msgbuf.h>
512bf3c060Smiod #include <sys/tty.h>
522bf3c060Smiod #include <sys/user.h>
532bf3c060Smiod #include <sys/exec.h>
542bf3c060Smiod #include <sys/sysctl.h>
552bf3c060Smiod #include <sys/mount.h>
562bf3c060Smiod #include <sys/syscallargs.h>
572bf3c060Smiod #include <sys/exec_elf.h>
582bf3c060Smiod #ifdef SYSVSHM
592bf3c060Smiod #include <sys/shm.h>
602bf3c060Smiod #endif
612bf3c060Smiod #ifdef SYSVSEM
622bf3c060Smiod #include <sys/sem.h>
632bf3c060Smiod #endif
642bf3c060Smiod 
657d9ca166Sderaadt #include <net/if.h>
66a43a5a68Smpi 
67a43a5a68Smpi #include <uvm/uvm_extern.h>
682bf3c060Smiod 
692bf3c060Smiod #include <machine/db_machdep.h>
702bf3c060Smiod #include <ddb/db_interface.h>
712bf3c060Smiod 
722bf3c060Smiod #include <machine/autoconf.h>
73737df64eSmiod #include <mips64/cache.h>
742bf3c060Smiod #include <machine/cpu.h>
757b6ae6a5Smiod #include <mips64/mips_cpu.h>
762bf3c060Smiod #include <machine/memconf.h>
772bf3c060Smiod #include <machine/pmon.h>
782bf3c060Smiod 
793fc8f127Spirofti #ifdef HIBERNATE
803fc8f127Spirofti #include <machine/hibernate_var.h>
813fc8f127Spirofti #endif /* HIBERNATE */
823fc8f127Spirofti 
832bf3c060Smiod #include <dev/cons.h>
842bf3c060Smiod 
85f75298a7Smiod #include <dev/pci/pcireg.h>
86f75298a7Smiod #include <dev/pci/pcivar.h>
87f75298a7Smiod #include <dev/pci/pcidevs.h>
88f75298a7Smiod 
892bf3c060Smiod /* The following is used externally (sysctl_hw) */
902bf3c060Smiod char	machine[] = MACHINE;		/* Machine "architecture" */
912bf3c060Smiod char	cpu_model[30];
92b9984aa0Sotto char	pmon_bootp[80];
932bf3c060Smiod 
942bf3c060Smiod /*
956f377552Smiod  * Even though the system is 64bit, 2E- and 2F-based hardware is constrained
9636fd90dcSjsg  * to up to 2G of contiguous physical memory (direct 2GB DMA area). 2Gq- and
976f377552Smiod  * 3A-based hardware only supports 32-bit DMA addresses, even though
986f377552Smiod  * physical memory may exist beyond 4GB.
99b426ab7bSthib  */
100b426ab7bSthib struct uvm_constraint_range  dma_constraint = { 0x0, 0xffffffffUL };
101b426ab7bSthib struct uvm_constraint_range *uvm_md_constraints[] = { NULL };
102b426ab7bSthib 
1032bf3c060Smiod vm_map_t exec_map;
1042bf3c060Smiod vm_map_t phys_map;
1052bf3c060Smiod 
106c72644a3Sderaadt /*
107c72644a3Sderaadt  * safepri is a safe priority for sleep to set for a spin-wait
108c72644a3Sderaadt  * during autoconfiguration or after a panic.
109c72644a3Sderaadt  */
110c72644a3Sderaadt int   safepri = 0;
111c72644a3Sderaadt 
1122bf3c060Smiod caddr_t	msgbufbase;
1132bf3c060Smiod 
1142bf3c060Smiod int	physmem;		/* Max supported memory, changes to actual. */
1152bf3c060Smiod int	ncpu = 1;		/* At least one CPU in the system. */
1167d353fccSvisa int	nnodes = 1;		/* Number of NUMA nodes, only on 3A. */
1172bf3c060Smiod struct	user *proc0paddr;
1182d357aedSnatano int	lid_action = 1;
119e9721e48Stedu int	pwr_action = 1;
1202bf3c060Smiod 
12139de0dfdSvisa #ifdef MULTIPROCESSOR
12239de0dfdSvisa uint64_t cpu_spinup_a0;
12339de0dfdSvisa uint64_t cpu_spinup_sp;
12439de0dfdSvisa uint32_t ipi_mask;
12539de0dfdSvisa #endif
12639de0dfdSvisa 
12751b07be5Smiod const struct platform *sys_platform;
128c301e791Smiod struct cpu_hwinfo bootcpu_hwinfo;
12977e35563Svisa void *loongson_videobios;
1303485d230Svisa uint loongson_cpumask = 1;
131d57a735dSmiod uint loongson_ver;
1322bf3c060Smiod 
1332bf3c060Smiod /* Pointers to the start and end of the symbol table. */
1342bf3c060Smiod caddr_t	ssym;
1352bf3c060Smiod caddr_t	esym;
1362bf3c060Smiod caddr_t	ekern;
1372bf3c060Smiod 
1382bf3c060Smiod struct phys_mem_desc mem_layout[MAXMEMSEGS];
1395acbfd54Svisa paddr_t	loongson_memlo_alias;
1402bf3c060Smiod 
14103052511Smiod pcitag_t (*pci_make_tag_early)(int, int, int);
14203052511Smiod pcireg_t (*pci_conf_read_early)(pcitag_t, int);
14303052511Smiod bus_space_tag_t early_mem_t;
14403052511Smiod bus_space_tag_t early_io_t;
14503052511Smiod 
1462bf3c060Smiod static u_long atoi(const char *, uint);
1472bf3c060Smiod static void dobootopts(int);
1482bf3c060Smiod 
1492bf3c060Smiod void	dumpsys(void);
1502bf3c060Smiod void	dumpconf(void);
151b9984aa0Sotto extern	void parsepmonbp(void);
1526f377552Smiod const struct platform *loongson_identify(const char *, int);
1536f377552Smiod vaddr_t	mips_init(uint64_t, uint64_t, uint64_t, uint64_t, char *);
1542bf3c060Smiod 
1557d353fccSvisa extern	void htb_early_setup(void);
1567d353fccSvisa 
1572bf3c060Smiod extern	void loongson2e_setup(u_long, u_long);
1582bf3c060Smiod extern	void loongson2f_setup(u_long, u_long);
1596f377552Smiod extern	void loongson3a_setup(u_long, u_long);
1602bf3c060Smiod 
1612bf3c060Smiod cons_decl(pmon);
1622bf3c060Smiod 
1632bf3c060Smiod struct consdev pmoncons = {
1642bf3c060Smiod 	NULL,
1652bf3c060Smiod 	NULL,
1662bf3c060Smiod 	pmoncngetc,
1672bf3c060Smiod 	pmoncnputc,
1682bf3c060Smiod 	nullcnpollc,
1692bf3c060Smiod 	NULL,
1702bf3c060Smiod 	makedev(0, 0),
1712bf3c060Smiod 	CN_DEAD
1722bf3c060Smiod };
1732bf3c060Smiod 
1742bf3c060Smiod /*
175e1844cd9Smiod  * List of supported system types, from the ``Version'' environment
176e1844cd9Smiod  * variable.
177e1844cd9Smiod  */
178e1844cd9Smiod 
179e1844cd9Smiod struct bonito_flavour {
180e1844cd9Smiod 	const char *prefix;
18151b07be5Smiod 	const struct platform *platform;
182e1844cd9Smiod };
183e1844cd9Smiod 
184f75298a7Smiod extern const struct platform ebenton_platform;
18551b07be5Smiod extern const struct platform fuloong_platform;
18651b07be5Smiod extern const struct platform gdium_platform;
187d57a735dSmiod extern const struct platform generic2e_platform;
188c2d35888Smiod extern const struct platform lynloong_platform;
1897d353fccSvisa extern const struct platform rs780e_platform;
19051b07be5Smiod extern const struct platform yeeloong_platform;
19151b07be5Smiod 
192e1844cd9Smiod const struct bonito_flavour bonito_flavours[] = {
1936f377552Smiod #ifdef CPU_LOONGSON2
194f75298a7Smiod 	/* eBenton EBT700 netbook */
195f75298a7Smiod 	{ "EBT700",	&ebenton_platform },	/* prefix added by user */
19651b07be5Smiod 	/* Lemote Fuloong 2F mini-PC */
197f75298a7Smiod 	{ "LM6002",	&fuloong_platform },	/* dual Ethernet,
198f75298a7Smiod 						   prefix added by user */
199cd66aef1Smiod 	{ "LM6003",	&fuloong_platform },
20051b07be5Smiod 	{ "LM6004",	&fuloong_platform },
201e1844cd9Smiod 	/* EMTEC Gdium Liberty 1000 */
20251b07be5Smiod 	{ "Gdium",	&gdium_platform },
20351b07be5Smiod 	/* Lemote Yeeloong 8.9" netbook */
20451b07be5Smiod 	{ "LM8089",	&yeeloong_platform },
20551b07be5Smiod 	/* supposedly Lemote Yeeloong 10.1" netbook, but those found so far
20651b07be5Smiod 	   report themselves as LM8089 */
20751b07be5Smiod 	{ "LM8101",	&yeeloong_platform },
208c2d35888Smiod 	/* Lemote Lynloong all-in-one computer */
209c2d35888Smiod 	{ "LM9001",	&lynloong_platform },
210b07de51bSvisa 	{ "LM9002",	&lynloong_platform },
211b07de51bSvisa 	{ "LM9003",	&lynloong_platform },
212b07de51bSvisa 	/* Lemote Lynloong all-in-one computer, Xueloong edition */
213b07de51bSvisa 	{ "LM9013",	&lynloong_platform },
2146f377552Smiod #endif
2156f377552Smiod #ifdef CPU_LOONGSON3
2166f377552Smiod 	/* Laptops */
2177d353fccSvisa 	{ "A1004",	&rs780e_platform },	/* 3A */
2187d353fccSvisa 	{ "A1201",	&rs780e_platform },	/* 2Gq */
2196f377552Smiod 	/* Lemote Xinghuo 6100 (mini-ITX PC) */
2207d353fccSvisa 	{ "A1101",	&rs780e_platform },	/* 3A */
2216f377552Smiod 	/* All-in-one PC */
2227d353fccSvisa 	{ "A1205",	&rs780e_platform },	/* 2Gq */
2236f377552Smiod #endif
224e1844cd9Smiod 	{ NULL }
225e1844cd9Smiod };
226e1844cd9Smiod 
227e1844cd9Smiod /*
228f75298a7Smiod  * Try to figure out what particular machine we run on, depending on the
229f75298a7Smiod  * scarce PMON version information and whatever else we can figure.
230f75298a7Smiod  */
231f75298a7Smiod const struct platform *
loongson_identify(const char * version,int envtype)2326f377552Smiod loongson_identify(const char *version, int envtype)
233f75298a7Smiod {
234f75298a7Smiod 	const struct bonito_flavour *f;
235f75298a7Smiod 
2366f377552Smiod 	switch (envtype) {
2375acbfd54Svisa #ifdef CPU_LOONGSON3
2386f377552Smiod 	case PMON_ENVTYPE_EFI:
2397d353fccSvisa 		if (loongson_ver == 0x3a || loongson_ver == 0x3b) {
2407d353fccSvisa 			pcitag_t tag;
2417d353fccSvisa 			pcireg_t id;
2427d353fccSvisa 
2437d353fccSvisa 			htb_early_setup();
2447d353fccSvisa 
2457d353fccSvisa 			/* Determine platform by host bridge. */
2467d353fccSvisa 			tag = pci_make_tag_early(0, 0, 0);
2477d353fccSvisa 			id = pci_conf_read_early(tag, PCI_ID_REG);
2487d353fccSvisa 			switch (id) {
2497d353fccSvisa 			case PCI_ID_CODE(PCI_VENDOR_AMD,
2507d353fccSvisa 			    PCI_PRODUCT_AMD_RS780_HB):
2517d353fccSvisa 				return &rs780e_platform;
2527d353fccSvisa 			}
2537d353fccSvisa 		}
2547d353fccSvisa 		pmon_printf("Unable to figure out model!\n");
2557d353fccSvisa 		return NULL;
2565acbfd54Svisa #endif
2576f377552Smiod 
2586f377552Smiod 	default:
2596f377552Smiod 	case PMON_ENVTYPE_ENVP:
260f75298a7Smiod 		if (version == NULL) {
2615acbfd54Svisa #ifdef CPU_LOONGSON2
262f75298a7Smiod 			/*
2636f377552Smiod 		 	 * If there is no `Version' variable, we expect to be
2646f377552Smiod 			 * running on a 2E system, use the generic code and
2656f377552Smiod 			 * hope for the best.
266f75298a7Smiod 		 	 */
2675acbfd54Svisa 			if (loongson_ver == 0x2e)
268f75298a7Smiod 				return &generic2e_platform;
2695acbfd54Svisa #endif
270f75298a7Smiod 			pmon_printf("Unable to figure out model!\n");
271f75298a7Smiod 			return NULL;
272f75298a7Smiod 		}
273f75298a7Smiod 
274f75298a7Smiod 		for (f = bonito_flavours; f->prefix != NULL; f++)
275f75298a7Smiod 			if (strncmp(version, f->prefix, strlen(f->prefix)) == 0)
276f75298a7Smiod 				return f->platform;
277f75298a7Smiod 
2785acbfd54Svisa #ifdef CPU_LOONGSON2
279f75298a7Smiod 		/*
280f75298a7Smiod 	 	 * Early Lemote designs shipped without a model prefix.
281f75298a7Smiod 	 	 *
2826f377552Smiod 	 	 * We can reasonably expect these to be close enough to either
2836f377552Smiod 		 * the first generation Fuloong 2F design (LM6002), or the 7
2846f377552Smiod 		 * inch first netbook model; we can tell them apart by looking
2856f377552Smiod 		 * at which video chip they embed.
286f75298a7Smiod 	 	 *
287f75298a7Smiod 	 	 * Note that this is only worth doing if the version string is
2886f377552Smiod 	 	 * 1.2.something (1.3 onwards are expected to have a model
2896f377552Smiod 		 * prefix, and there are currently no reports of 1.1 and
290f75298a7Smiod 	 	 * below being 2F systems).
291f75298a7Smiod 	 	 *
292f75298a7Smiod 	 	 * LM6002 users are encouraged to add the system model prefix to
293f75298a7Smiod 	 	 * the `Version' variable.
294f75298a7Smiod 	 	 */
295f75298a7Smiod 		if (strncmp(version, "1.2.", 4) == 0) {
296f75298a7Smiod 			const struct platform *p = NULL;
297f75298a7Smiod 			pcitag_t tag;
298f75298a7Smiod 			pcireg_t id, class;
299f75298a7Smiod 			int dev;
300f75298a7Smiod 
3016f377552Smiod 			pmon_printf("No model prefix "
3026f377552Smiod 			    "in version string \"%s\".\n", version);
303f75298a7Smiod 
3046f377552Smiod 			if (loongson_ver == 0x2f)
305f75298a7Smiod 				for (dev = 0; dev < 32; dev++) {
306f75298a7Smiod 					tag = pci_make_tag_early(0, dev, 0);
3076f377552Smiod 					id = pci_conf_read_early(tag,
3086f377552Smiod 					    PCI_ID_REG);
3096f377552Smiod 					if (id == 0 || PCI_VENDOR(id) ==
3106f377552Smiod 					    PCI_VENDOR_INVALID)
311f75298a7Smiod 						continue;
312f75298a7Smiod 
3136f377552Smiod 					/*
3146f377552Smiod 					 * No need to check for
3156f377552Smiod 					 * DEVICE_IS_VGA_PCI here, since we
3166f377552Smiod 					 * expect a linear framebuffer.
3176f377552Smiod 					 */
3186f377552Smiod 					class = pci_conf_read_early(tag,
3196f377552Smiod 					    PCI_CLASS_REG);
3206f377552Smiod 					if (PCI_CLASS(class) !=
3216f377552Smiod 					    PCI_CLASS_DISPLAY ||
3226f377552Smiod 					    (PCI_SUBCLASS(class) !=
3236f377552Smiod 					     PCI_SUBCLASS_DISPLAY_VGA &&
3246f377552Smiod 					     PCI_SUBCLASS(class) !=
3256f377552Smiod 					     PCI_SUBCLASS_DISPLAY_MISC))
326f75298a7Smiod 						continue;
327f75298a7Smiod 
328f75298a7Smiod 					switch (id) {
329f75298a7Smiod 					case PCI_ID_CODE(PCI_VENDOR_SIS,
330f75298a7Smiod 				    	    PCI_PRODUCT_SIS_315PRO_VGA):
331f75298a7Smiod 						p = &fuloong_platform;
332f75298a7Smiod 						break;
333f75298a7Smiod 					case PCI_ID_CODE(PCI_VENDOR_SMI,
334f75298a7Smiod 			    		    PCI_PRODUCT_SMI_SM712):
335f75298a7Smiod 						p = &ebenton_platform;
336f75298a7Smiod 						break;
337f75298a7Smiod 					}
3386f377552Smiod 				}
339f75298a7Smiod 
340f75298a7Smiod 			if (p != NULL) {
3416f377552Smiod 				pmon_printf("Attempting to match as "
3426f377552Smiod 				    "%s %s\n", p->vendor, p->product);
343f75298a7Smiod 				return p;
344f75298a7Smiod 			}
345f75298a7Smiod 		}
3465acbfd54Svisa #endif
347f75298a7Smiod 	}
348f75298a7Smiod 
349f75298a7Smiod 	pmon_printf("This kernel doesn't support model \"%s\"." "\n", version);
350f75298a7Smiod 	return NULL;
351f75298a7Smiod }
352f75298a7Smiod 
3535acbfd54Svisa /*
3545acbfd54Svisa  * Figure out machine parameters using the 'EFI-like' interface.
3555acbfd54Svisa  */
3565acbfd54Svisa int
loongson_efi_setup(void)3575acbfd54Svisa loongson_efi_setup(void)
3585acbfd54Svisa {
359afa841fbSvisa 	struct pmon_env_mem_entry entry;
3603485d230Svisa 	const struct pmon_env_cpu *cpuenv;
3615acbfd54Svisa 	const struct pmon_env_mem *mem;
3625acbfd54Svisa 	paddr_t fp, lp;
3633485d230Svisa 	uint32_t i, ncpus, seg = 0;
3645acbfd54Svisa 
3653485d230Svisa 	cpuenv = pmon_get_env_cpu();
3663485d230Svisa 	bootcpu_hwinfo.clock = cpuenv->speed;
3673485d230Svisa 
3683485d230Svisa 	/*
3693485d230Svisa 	 * Get available CPUs.
3703485d230Svisa 	 */
3713485d230Svisa 
3723485d230Svisa 	ncpus = cpuenv->ncpus;
3733485d230Svisa 	if (ncpus > LOONGSON_MAXCPUS)
3743485d230Svisa 		ncpus = LOONGSON_MAXCPUS;
3753485d230Svisa 
3763485d230Svisa 	loongson_cpumask = (1u << ncpus) - 1;
3773485d230Svisa 	loongson_cpumask &= ~(uint)cpuenv->reserved_cores;
3783485d230Svisa 
3793485d230Svisa 	ncpusfound = 0;
3803485d230Svisa 	for (i = 0; i < ncpus; i++) {
3813485d230Svisa 		if (ISSET(loongson_cpumask, 1u << i))
3823485d230Svisa 			ncpusfound++;
3833485d230Svisa 	}
3843485d230Svisa 
3853485d230Svisa 	/*
3863485d230Svisa 	 * Get free memory segments.
3873485d230Svisa 	 */
3885acbfd54Svisa 
3895acbfd54Svisa 	mem = pmon_get_env_mem();
3905acbfd54Svisa 	physmem = 0;
3915acbfd54Svisa 	for (i = 0; i < mem->nentries && seg < MAXMEMSEGS; i++) {
392afa841fbSvisa 		memcpy(&entry, &mem->mem_map[i], sizeof(entry));
393afa841fbSvisa 		if (entry.node != 0 ||
394afa841fbSvisa 		    (entry.type != PMON_MEM_SYSTEM_LOW &&
395afa841fbSvisa 		     entry.type != PMON_MEM_SYSTEM_HIGH))
3965acbfd54Svisa 			continue;
397afa841fbSvisa 		fp = atop(entry.address);
39832192ce3Svisa 		lp = atop(entry.address + ((uint64_t)entry.size << 20));
3995acbfd54Svisa 		if (lp > atop(pfn_to_pad(PG_FRAME)) + 1)
4005acbfd54Svisa 			lp = atop(pfn_to_pad(PG_FRAME)) + 1;
4015acbfd54Svisa 		if (fp >= lp)
4025acbfd54Svisa 			continue;
4035acbfd54Svisa 		physmem += lp - fp;
4045acbfd54Svisa 		mem_layout[seg].mem_first_page = fp;
4055acbfd54Svisa 		mem_layout[seg].mem_last_page = lp;
4065acbfd54Svisa 		seg++;
4075acbfd54Svisa 	}
4085acbfd54Svisa 
4095acbfd54Svisa 	return 0;
4105acbfd54Svisa }
4115acbfd54Svisa 
4125acbfd54Svisa /*
4135acbfd54Svisa  * Figure out machine parameters using the PMON interface.
4145acbfd54Svisa  */
4155acbfd54Svisa int
loongson_envp_setup(void)4165acbfd54Svisa loongson_envp_setup(void)
4175acbfd54Svisa {
4185acbfd54Svisa 	const char *envvar;
4195acbfd54Svisa 	u_long cpuspeed, memlo, memhi;
4205acbfd54Svisa 
4215acbfd54Svisa 	/*
4225acbfd54Svisa 	 * Figure out processor clock speed.
4235acbfd54Svisa 	 * Hopefully the processor speed, in Hertz, will not overflow
4245acbfd54Svisa 	 * uint32_t...
4255acbfd54Svisa 	 */
4265acbfd54Svisa 
4275acbfd54Svisa 	cpuspeed = 0;
4285acbfd54Svisa 	envvar = pmon_getenv("cpuclock");
4295acbfd54Svisa 	if (envvar != NULL)
4305acbfd54Svisa 		cpuspeed = atoi(envvar, 10);	/* speed in Hz */
4315acbfd54Svisa 	if (cpuspeed < 100 * 1000000)
4325acbfd54Svisa 		cpuspeed = 797000000;  /* Reasonable default */
4335acbfd54Svisa 	bootcpu_hwinfo.clock = cpuspeed;
4345acbfd54Svisa 
4355acbfd54Svisa 	/*
4363485d230Svisa 	 * Guess the available CPUs.
4373485d230Svisa 	 */
4383485d230Svisa 
4393485d230Svisa 	switch (loongson_ver) {
4403485d230Svisa #ifdef CPU_LOONGSON3
4413485d230Svisa 	case 0x3a:
4423485d230Svisa 		loongson_cpumask = 0x0f;
4433485d230Svisa 		ncpusfound = 4;
4443485d230Svisa 		break;
4453485d230Svisa 	case 0x3b:
4463485d230Svisa 		loongson_cpumask = 0xff;
4473485d230Svisa 		ncpusfound = 8;
4483485d230Svisa 		break;
4493485d230Svisa #endif
4503485d230Svisa 	}
4513485d230Svisa 
4523485d230Svisa 	/*
4535acbfd54Svisa 	 * Figure out memory information.
4545acbfd54Svisa 	 * PMON reports it in two chunks, the memory under the 256MB
4555acbfd54Svisa 	 * CKSEG limit, and memory above that limit.  We need to do the
4565acbfd54Svisa 	 * math ourselves.
4575acbfd54Svisa 	 */
4585acbfd54Svisa 
4595acbfd54Svisa 	envvar = pmon_getenv("memsize");
4605acbfd54Svisa 	if (envvar == NULL) {
4615acbfd54Svisa 		pmon_printf("Could not get memory information"
4625acbfd54Svisa 		    " from the firmware\n");
4635acbfd54Svisa 		return -1;
4645acbfd54Svisa 	}
4655acbfd54Svisa 	memlo = atoi(envvar, 10);	/* size in MB */
4665acbfd54Svisa 	if (memlo < 0 || memlo > 256) {
4675acbfd54Svisa 		pmon_printf("Incorrect low memory size `%s'\n", envvar);
4685acbfd54Svisa 		return -1;
4695acbfd54Svisa 	}
4705acbfd54Svisa 
4715acbfd54Svisa 	/* 3A PMON only reports up to 240MB as low memory */
4725acbfd54Svisa 	if (memlo >= 240) {
4735acbfd54Svisa 		envvar = pmon_getenv("highmemsize");
4745acbfd54Svisa 		if (envvar == NULL)
4755acbfd54Svisa 			memhi = 0;
4765acbfd54Svisa 		else
4775acbfd54Svisa 			memhi = atoi(envvar, 10);	/* size in MB */
4785acbfd54Svisa 		if (memhi < 0 || memhi > (64 * 1024) - 256) {
4795acbfd54Svisa 			pmon_printf("Incorrect high memory size `%s'\n",
4805acbfd54Svisa 			    envvar);
4815acbfd54Svisa 			/* better expose the problem than limit to 256MB */
4825acbfd54Svisa 			return -1;
4835acbfd54Svisa 		}
4845acbfd54Svisa 	} else
4855acbfd54Svisa 		memhi = 0;
4865acbfd54Svisa 
4875acbfd54Svisa 	switch (loongson_ver) {
4885acbfd54Svisa 	default:
4895acbfd54Svisa #ifdef CPU_LOONGSON2
4905acbfd54Svisa 	case 0x2e:
4915acbfd54Svisa 		loongson2e_setup(memlo, memhi);
4925acbfd54Svisa 		break;
4935acbfd54Svisa 	case 0x2f:
4945acbfd54Svisa 		loongson2f_setup(memlo, memhi);
4955acbfd54Svisa 		break;
4965acbfd54Svisa #endif
4975acbfd54Svisa #ifdef CPU_LOONGSON3
4985acbfd54Svisa 	case 0x3a:
4995acbfd54Svisa 		loongson3a_setup(memlo, memhi);
5005acbfd54Svisa 		break;
5015acbfd54Svisa #endif
5025acbfd54Svisa 	}
5035acbfd54Svisa 
5045acbfd54Svisa 	return 0;
5055acbfd54Svisa }
506f75298a7Smiod 
507f75298a7Smiod /*
5082bf3c060Smiod  * Do all the stuff that locore normally does before calling main().
5092bf3c060Smiod  * Reset mapping and set up mapping to hardware and init "wired" reg.
5102bf3c060Smiod  */
5112bf3c060Smiod 
5122bf3c060Smiod vaddr_t
mips_init(uint64_t argc,uint64_t argv,uint64_t envp,uint64_t cv,char * boot_esym)5136f377552Smiod mips_init(uint64_t argc, uint64_t argv, uint64_t envp, uint64_t cv,
514e923757cSmiod     char *boot_esym)
5152bf3c060Smiod {
5166f377552Smiod 	uint32_t prid;
5172bf3c060Smiod 	vaddr_t xtlb_handler;
5182bf3c060Smiod 	const char *envvar;
5192bf3c060Smiod 	int i;
5202bf3c060Smiod 
5212bf3c060Smiod 	extern char start[], edata[], end[];
5222bf3c060Smiod 	extern char exception[], e_exception[];
5232bf3c060Smiod 	extern void xtlb_miss;
5242bf3c060Smiod 
52539de0dfdSvisa #ifdef MULTIPROCESSOR
52639de0dfdSvisa 	/*
52739de0dfdSvisa 	 * Set curcpu address on primary processor.
52839de0dfdSvisa 	 */
52939de0dfdSvisa 	setcurcpu(&cpu_info_primary);
53039de0dfdSvisa #endif
53139de0dfdSvisa 
5322bf3c060Smiod 	/*
5336cfc9e23Smiod 	 * Make sure we can access the extended address space.
5346cfc9e23Smiod 	 * This is not necessary on real hardware, but some emulators
5356cfc9e23Smiod 	 * are not aware of this.
5366cfc9e23Smiod 	 */
5376cfc9e23Smiod 	setsr(getsr() | SR_KX | SR_UX);
5386cfc9e23Smiod 
5396cfc9e23Smiod 	/*
5402bf3c060Smiod 	 * Clear the compiled BSS segment in OpenBSD code.
5412bf3c060Smiod 	 * PMON is supposed to have done this, though.
5422bf3c060Smiod 	 */
5432bf3c060Smiod 
5442bf3c060Smiod 	bzero(edata, end - edata);
5452bf3c060Smiod 
5462bf3c060Smiod 	/*
5472bf3c060Smiod 	 * Set up early console output.
5482bf3c060Smiod 	 */
5492bf3c060Smiod 
5506f377552Smiod 	prid = cp0_get_prid();
5516f377552Smiod 	pmon_init((int32_t)argc, (int32_t)argv, (int32_t)envp, (int32_t)cv,
5526f377552Smiod 	    prid);
5532bf3c060Smiod 	cn_tab = &pmoncons;
5542bf3c060Smiod 
5552bf3c060Smiod 	/*
556e923757cSmiod 	 * Reserve space for the symbol table, if it exists.
5572bf3c060Smiod 	 */
5582bf3c060Smiod 
559e923757cSmiod 	/* Attempt to locate ELF header and symbol table after kernel. */
560e923757cSmiod 	if (end[0] == ELFMAG0 && end[1] == ELFMAG1 &&
561e923757cSmiod 	    end[2] == ELFMAG2 && end[3] == ELFMAG3) {
562e923757cSmiod 		/* ELF header exists directly after kernel. */
563e923757cSmiod 		ssym = end;
564e923757cSmiod 		esym = boot_esym;
565e923757cSmiod 		ekern = esym;
566e923757cSmiod 	} else {
5672bf3c060Smiod 		ssym = (char *)(vaddr_t)*(int32_t *)end;
5682bf3c060Smiod 		if (((long)ssym - (long)end) >= 0 &&
5692bf3c060Smiod 		    ((long)ssym - (long)end) <= 0x1000 &&
5702bf3c060Smiod 		    ssym[0] == ELFMAG0 && ssym[1] == ELFMAG1 &&
5712bf3c060Smiod 		    ssym[2] == ELFMAG2 && ssym[3] == ELFMAG3) {
5722bf3c060Smiod 			/* Pointers exist directly after kernel. */
5732bf3c060Smiod 			esym = (char *)(vaddr_t)*((int32_t *)end + 1);
5742bf3c060Smiod 			ekern = esym;
5752bf3c060Smiod 		} else {
5762bf3c060Smiod 			/* Pointers aren't setup either... */
577e923757cSmiod 			ssym = NULL;
578e923757cSmiod 			esym = NULL;
5792bf3c060Smiod 			ekern = end;
5802bf3c060Smiod 		}
581e923757cSmiod 	}
5822bf3c060Smiod 
5832bf3c060Smiod 	/*
5846f377552Smiod 	 * While the kernel supports other processor types than Loongson,
5856f377552Smiod 	 * we are currently not expecting to run on a system with a
5866f377552Smiod 	 * different processor.  Just to be on the safe side, refuse to
5875acbfd54Svisa 	 * run on non-Loongson processors for now.
5886f377552Smiod 	 */
5896f377552Smiod 
5906f377552Smiod 	switch ((prid >> 8) & 0xff) {
5916f377552Smiod 	case MIPS_LOONGSON2:
5926f377552Smiod 		switch (prid & 0xff) {
5936f377552Smiod #ifdef CPU_LOONGSON2
5946f377552Smiod #ifdef CPU_LOONGSON2C
5956f377552Smiod 		case 0x00:
5966f377552Smiod 			loongson_ver = 0x2c;
5976f377552Smiod 			break;
5986f377552Smiod #endif
5996f377552Smiod 		case 0x02:
6006f377552Smiod 			loongson_ver = 0x2e;
6016f377552Smiod 			break;
6026f377552Smiod 		case 0x03:
6036f377552Smiod 			loongson_ver = 0x2f;
6046f377552Smiod 			break;
6056f377552Smiod #endif
6066f377552Smiod #ifdef CPU_LOONGSON3
6076f377552Smiod 		case 0x05:
60800cbda18Svisa 		case 0x08:
6096f377552Smiod 			loongson_ver = 0x3a;
6106f377552Smiod 			break;
6116f377552Smiod #endif
6126f377552Smiod 		default:
6136f377552Smiod 			break;
6146f377552Smiod 		}
6156f377552Smiod 	}
6166f377552Smiod 	if (loongson_ver == 0) {
6176f377552Smiod 		pmon_printf("This kernel doesn't support processor type 0x%x"
6186f377552Smiod 		    ", version %d.%d.\n",
6196f377552Smiod 		    (prid >> 8) & 0xff, (prid >> 4) & 0x0f, prid & 0x0f);
6206f377552Smiod 		goto unsupported;
6216f377552Smiod 	}
6226f377552Smiod 
6236f377552Smiod 	/*
6242bf3c060Smiod 	 * Try and figure out what kind of hardware we are.
6252bf3c060Smiod 	 */
6262bf3c060Smiod 
6276f377552Smiod 	switch (pmon_getenvtype()) {
6286f377552Smiod 	default:
6296f377552Smiod 		pmon_printf("Unable to figure out "
6306f377552Smiod 		    "firmware environment information!\n");
6316f377552Smiod 		goto unsupported;
6326f377552Smiod 
6336f377552Smiod 	case PMON_ENVTYPE_EFI:
6346f377552Smiod 		break;
6356f377552Smiod 
6366f377552Smiod 	case PMON_ENVTYPE_ENVP:
6372bf3c060Smiod 		envvar = pmon_getenv("systype");
6382bf3c060Smiod 		if (envvar == NULL) {
6392bf3c060Smiod 			pmon_printf("Unable to figure out system type!\n");
6402bf3c060Smiod 			goto unsupported;
6412bf3c060Smiod 		}
6422bf3c060Smiod 		if (strcmp(envvar, "Bonito") != 0) {
6432bf3c060Smiod 			pmon_printf("This kernel doesn't support system type \"%s\".\n",
6442bf3c060Smiod 		    	envvar);
6452bf3c060Smiod 			goto unsupported;
6462bf3c060Smiod 		}
6472bf3c060Smiod 	}
6482bf3c060Smiod 
6492bf3c060Smiod 	/*
6502bf3c060Smiod 	 * Try to figure out what particular machine we run on, depending
6512bf3c060Smiod 	 * on the PMON version information.
6522bf3c060Smiod 	 */
6532bf3c060Smiod 
6546f377552Smiod 	if ((sys_platform = loongson_identify(pmon_getenv("Version"),
6556f377552Smiod 	    pmon_getenvtype())) == NULL)
6562bf3c060Smiod 		goto unsupported;
6572bf3c060Smiod 
65851b07be5Smiod 	hw_vendor = sys_platform->vendor;
65951b07be5Smiod 	hw_prod = sys_platform->product;
6602bf3c060Smiod 	pmon_printf("Found %s %s, setting up.\n", hw_vendor, hw_prod);
6612bf3c060Smiod 
6622bf3c060Smiod 	snprintf(cpu_model, sizeof cpu_model, "Loongson %X", loongson_ver);
6632bf3c060Smiod 
6642bf3c060Smiod 	/*
6652bf3c060Smiod 	 * Look at arguments passed to us and compute boothowto.
6662bf3c060Smiod 	 */
6672bf3c060Smiod 
6682bf3c060Smiod 	boothowto = RB_AUTOBOOT;
6692bf3c060Smiod 	dobootopts(argc);
6702bf3c060Smiod 
6715acbfd54Svisa 	switch (pmon_getenvtype()) {
6725acbfd54Svisa 	case PMON_ENVTYPE_EFI:
6735acbfd54Svisa 		if (loongson_efi_setup() != 0)
6742bf3c060Smiod 			goto unsupported;
6755acbfd54Svisa 		break;
6762bf3c060Smiod 
6775acbfd54Svisa 	case PMON_ENVTYPE_ENVP:
6785acbfd54Svisa 		if (loongson_envp_setup() != 0)
6792bf3c060Smiod 			goto unsupported;
6802bf3c060Smiod 		break;
6812bf3c060Smiod 	}
6822bf3c060Smiod 
6838a850467Smiod 	if (sys_platform->setup != NULL)
6848a850467Smiod 		(*(sys_platform->setup))();
6858a850467Smiod 
6862bf3c060Smiod 	/*
6878a850467Smiod 	 * PMON functions should no longer be used from now on.
6882bf3c060Smiod 	 */
6892bf3c060Smiod 
6902bf3c060Smiod 	/*
6912bf3c060Smiod 	 * Set pagesize to enable use of page macros and functions.
6922bf3c060Smiod 	 * Commit available memory to UVM system.
6932bf3c060Smiod 	 */
6942bf3c060Smiod 
6952bf3c060Smiod 	uvmexp.pagesize = PAGE_SIZE;
6962bf3c060Smiod 	uvm_setpagesize();
6972bf3c060Smiod 
6982bf3c060Smiod 	for (i = 0; i < MAXMEMSEGS && mem_layout[i].mem_last_page != 0; i++) {
6992bf3c060Smiod 		uint64_t fp, lp;
7002bf3c060Smiod 		uint64_t firstkernpage, lastkernpage;
7012bf3c060Smiod 		paddr_t firstkernpa, lastkernpa;
7022bf3c060Smiod 
7032bf3c060Smiod 		/* kernel is linked in CKSEG0 */
7049b065564Smiod 		firstkernpa = CKSEG0_TO_PHYS((vaddr_t)start);
7059b065564Smiod 		lastkernpa = CKSEG0_TO_PHYS((vaddr_t)ekern);
7062bf3c060Smiod 
7075acbfd54Svisa 		firstkernpage = atop(trunc_page(firstkernpa));
7083fc8f127Spirofti #ifdef HIBERNATE
7093fc8f127Spirofti 		firstkernpage -= HIBERNATE_RESERVED_PAGES;
7103fc8f127Spirofti #endif
7115acbfd54Svisa 		lastkernpage = atop(round_page(lastkernpa));
7125acbfd54Svisa 
7135acbfd54Svisa 		if (loongson_memlo_alias != 0) {
7145acbfd54Svisa 			firstkernpage += atop(loongson_memlo_alias);
7155acbfd54Svisa 			lastkernpage += atop(loongson_memlo_alias);
7165acbfd54Svisa 		}
7172bf3c060Smiod 
7182bf3c060Smiod 		fp = mem_layout[i].mem_first_page;
7192bf3c060Smiod 		lp = mem_layout[i].mem_last_page;
7202bf3c060Smiod 
7212bf3c060Smiod 		/* Account for kernel and kernel symbol table. */
7222bf3c060Smiod 		if (fp >= firstkernpage && lp < lastkernpage)
7232bf3c060Smiod 			continue;	/* In kernel. */
7242bf3c060Smiod 
7252bf3c060Smiod 		if (lp < firstkernpage || fp > lastkernpage) {
7262ce3b4a8Soga 			uvm_page_physload(fp, lp, fp, lp, 0);
7272bf3c060Smiod 			continue;	/* Outside kernel. */
7282bf3c060Smiod 		}
7292bf3c060Smiod 
7302bf3c060Smiod 		if (fp >= firstkernpage)
7312bf3c060Smiod 			fp = lastkernpage;
7322bf3c060Smiod 		else if (lp < lastkernpage)
7332bf3c060Smiod 			lp = firstkernpage;
7342bf3c060Smiod 		else { /* Need to split! */
7352bf3c060Smiod 			uint64_t xp = firstkernpage;
7362ce3b4a8Soga 			uvm_page_physload(fp, xp, fp, xp, 0);
7372bf3c060Smiod 			fp = lastkernpage;
7382bf3c060Smiod 		}
7392bf3c060Smiod 		if (lp > fp) {
7402ce3b4a8Soga 			uvm_page_physload(fp, lp, fp, lp, 0);
7412bf3c060Smiod 		}
7422bf3c060Smiod 	}
7432bf3c060Smiod 
744c301e791Smiod 	bootcpu_hwinfo.c0prid = prid;
745c301e791Smiod 	bootcpu_hwinfo.type = (prid >> 8) & 0xff;
7462bf3c060Smiod 	/* FPU reports itself as type 5, version 0.1... */
747c301e791Smiod 	bootcpu_hwinfo.c1prid = bootcpu_hwinfo.c0prid;
7482bf3c060Smiod 
7492bf3c060Smiod 	/*
7506f377552Smiod 	 * Configure cache and tlb.
7512bf3c060Smiod 	 */
7522bf3c060Smiod 
7536f377552Smiod 	switch (loongson_ver) {
7546f377552Smiod 	default:
7556f377552Smiod #ifdef CPU_LOONGSON2
7566f377552Smiod #ifdef CPU_LOONGSON2C
7576f377552Smiod 	case 0x2c:
7586f377552Smiod #endif
7596f377552Smiod 	case 0x2e:
7606f377552Smiod 	case 0x2f:
7616f377552Smiod 		bootcpu_hwinfo.tlbsize = 64;
762c1805af1Smiod 		Loongson2_ConfigCache(curcpu());
763f894e8c8Smiod 		Loongson2_SyncCache(curcpu());
7646f377552Smiod 		break;
7656f377552Smiod #endif
7666f377552Smiod #ifdef CPU_LOONGSON3
7676f377552Smiod 	case 0x3a:
7686f377552Smiod 		bootcpu_hwinfo.tlbsize =
76954efcfedSvisa 		    1 + ((cp0_get_config_1() & CONFIG1_MMUSize1) >>
77054efcfedSvisa 		    CONFIG1_MMUSize1_SHIFT);
7716f377552Smiod 		Loongson3_ConfigCache(curcpu());
7726f377552Smiod 		Loongson3_SyncCache(curcpu());
7736f377552Smiod 		break;
7746f377552Smiod #endif
7756f377552Smiod 	}
7762bf3c060Smiod 
777caeb30e1Smiod 	tlb_init(bootcpu_hwinfo.tlbsize);
7782bf3c060Smiod 
7792bf3c060Smiod 	/*
7802bf3c060Smiod 	 * Get a console, very early but after initial mapping setup.
7812bf3c060Smiod 	 */
7822bf3c060Smiod 
7832bf3c060Smiod 	consinit();
7842bf3c060Smiod 	printf("Initial setup done, switching console.\n");
7852bf3c060Smiod 
7862bf3c060Smiod 	/*
78713142ff7Smiod 	 * Init message buffer. This is similar to pmap_steal_memory(), but
78813142ff7Smiod 	 * without zeroing the area, to keep the message buffer from the
78913142ff7Smiod 	 * previous kernel run intact, if any.
7902bf3c060Smiod 	 */
79113142ff7Smiod 	for (i = 0; i < vm_nphysseg; i++) {
79213142ff7Smiod 		struct vm_physseg *vps = &vm_physmem[i];
79313142ff7Smiod 		uint npg = atop(round_page(MSGBUFSIZE));
79413142ff7Smiod 		int j;
7952bf3c060Smiod 
79613142ff7Smiod 		if (vps->avail_start != vps->start ||
79713142ff7Smiod 		    vps->avail_start >= vps->avail_end) {
79813142ff7Smiod 			continue;
79913142ff7Smiod 		}
80013142ff7Smiod 
80113142ff7Smiod 		if ((vps->avail_end - vps->avail_start) < npg)
80213142ff7Smiod 			continue;
80313142ff7Smiod 
80413142ff7Smiod 		msgbufbase = (caddr_t)PHYS_TO_XKPHYS(ptoa(vps->avail_start),
80513142ff7Smiod 		    CCA_CACHED);
80613142ff7Smiod 		vps->avail_start += npg;
80713142ff7Smiod 		vps->start += npg;
80813142ff7Smiod 
80913142ff7Smiod 		if (vps->avail_start == vps->end) {
81013142ff7Smiod 			/* don't bother panicing if nphysseg becomes zero, */
81113142ff7Smiod 			/* the next pmap_steal_memory() call will. */
81213142ff7Smiod 			vm_nphysseg--;
81313142ff7Smiod 			for (j = i; j < vm_nphysseg; j++)
81413142ff7Smiod 				vm_physmem[j] = vm_physmem[j + 1];
81513142ff7Smiod 		}
81613142ff7Smiod 
81713142ff7Smiod 		break;
81813142ff7Smiod 	}
81913142ff7Smiod 	if (msgbufbase == NULL)
82013142ff7Smiod 		panic("not enough contiguous memory for message buffer");
8212bf3c060Smiod 	initmsgbuf(msgbufbase, MSGBUFSIZE);
8222bf3c060Smiod 
8232bf3c060Smiod 	/*
8242bf3c060Smiod 	 * Allocate U page(s) for proc[0], pm_tlbpid 1.
8252bf3c060Smiod 	 */
8262bf3c060Smiod 
8272bf3c060Smiod 	proc0.p_addr = proc0paddr = curcpu()->ci_curprocpaddr =
8282bf3c060Smiod 	    (struct user *)pmap_steal_memory(USPACE, NULL, NULL);
829b43ebd13Smpi 	proc0.p_md.md_regs = (struct trapframe *)&proc0paddr->u_pcb.pcb_regs;
830caeb30e1Smiod 	tlb_set_pid(MIN_USER_ASID);
8312bf3c060Smiod 
8322bf3c060Smiod 	/*
8332bf3c060Smiod 	 * Bootstrap VM system.
8342bf3c060Smiod 	 */
8352bf3c060Smiod 
8362bf3c060Smiod 	pmap_bootstrap();
8372bf3c060Smiod 
8382bf3c060Smiod 	/*
8392bf3c060Smiod 	 * Copy down exception vector code.
8402bf3c060Smiod 	 */
8412bf3c060Smiod 
8422bf3c060Smiod 	bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception);
8432bf3c060Smiod 	bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception);
8442bf3c060Smiod 
8452bf3c060Smiod 	/*
8462bf3c060Smiod 	 * Build proper TLB refill handler trampolines.
847c5cb0eb4Svisa 	 *
848c5cb0eb4Svisa 	 * On Loongson 2F, the XTLB refill exception actually uses
849c5cb0eb4Svisa 	 * the TLB refill vector.
8502bf3c060Smiod 	 */
8512bf3c060Smiod 
8522bf3c060Smiod 	xtlb_handler = (vaddr_t)&xtlb_miss;
8532bf3c060Smiod 	build_trampoline(TLB_MISS_EXC_VEC, xtlb_handler);
854c5cb0eb4Svisa 	build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler);
8552bf3c060Smiod 
8562bf3c060Smiod 	/*
8572bf3c060Smiod 	 * Turn off bootstrap exception vectors.
8582bf3c060Smiod 	 * (this is done by PMON already, but it doesn't hurt to be safe)
8592bf3c060Smiod 	 */
8602bf3c060Smiod 
8612bf3c060Smiod 	setsr(getsr() & ~SR_BOOT_EXC_VEC);
8622bf3c060Smiod 	proc0.p_md.md_regs->sr = getsr();
8632bf3c060Smiod 
8642bf3c060Smiod #ifdef DDB
8652bf3c060Smiod 	db_machine_init();
8662bf3c060Smiod 	if (boothowto & RB_KDB)
867e97088d6Smpi 		db_enter();
8682bf3c060Smiod #endif
8692bf3c060Smiod 
8702bf3c060Smiod 	/*
8712bf3c060Smiod 	 * Return the new kernel stack pointer.
8722bf3c060Smiod 	 */
8732bf3c060Smiod 
8742bf3c060Smiod 	return ((vaddr_t)proc0paddr + USPACE - 64);
8752bf3c060Smiod 
8762bf3c060Smiod unsupported:
8772bf3c060Smiod 	pmon_printf("Halting system.\nPress enter to return to PMON\n");
8782bf3c060Smiod 	cngetc();
8792bf3c060Smiod 	return 0;	/* causes us to return to pmon */
8802bf3c060Smiod }
8812bf3c060Smiod 
8822bf3c060Smiod /*
8832bf3c060Smiod  * Decode boot options.
8842bf3c060Smiod  */
8852bf3c060Smiod static void
dobootopts(int argc)8862bf3c060Smiod dobootopts(int argc)
8872bf3c060Smiod {
8882bf3c060Smiod 	const char *arg;
8892bf3c060Smiod 	const char *cp;
8902bf3c060Smiod 	int ignore = 1;
8912bf3c060Smiod 	int i;
8922bf3c060Smiod 
8932bf3c060Smiod 	/*
8942bf3c060Smiod 	 * Parse the boot command line.
8952bf3c060Smiod 	 *
8962bf3c060Smiod 	 * It should be of the form `boot [flags] filename [args]', so we
8972bf3c060Smiod 	 * need to ignore flags to the boot command.
8982bf3c060Smiod 	 * To achieve this, we ignore argc[0], which is the `boot' command
8992bf3c060Smiod 	 * itself, and ignore arguments starting with dashes until the
9002bf3c060Smiod 	 * boot file has been found.
9012bf3c060Smiod 	 */
9022bf3c060Smiod 
903ac91c5e9Smiod 	if (argc != 0) {
904ac91c5e9Smiod 		arg = pmon_getarg(0);
905ac91c5e9Smiod 		if (arg == NULL)
906ac91c5e9Smiod 			return;
907ac91c5e9Smiod 		/* if `go', not `boot', then no path and command options */
908ac91c5e9Smiod 		if (*arg == 'g')
909ac91c5e9Smiod 			ignore = 0;
910ac91c5e9Smiod 	}
9112bf3c060Smiod 	for (i = 1; i < argc; i++) {
9122bf3c060Smiod 		arg = pmon_getarg(i);
9132bf3c060Smiod 		if (arg == NULL)
9142bf3c060Smiod 			continue;
9152bf3c060Smiod 
916ac91c5e9Smiod 		/* device path */
917af751efbSvisa 		if (*arg == '/' || strncmp(arg, "bootduid=", 9) == 0 ||
918af751efbSvisa 		    strncmp(arg, "tftp://", 7) == 0) {
919b9984aa0Sotto 			if (*pmon_bootp == '\0') {
920b9984aa0Sotto 				strlcpy(pmon_bootp, arg, sizeof pmon_bootp);
921b9984aa0Sotto 				parsepmonbp();
922b9984aa0Sotto 			}
923ac91c5e9Smiod 			ignore = 0;	/* further options are for the kernel */
9242bf3c060Smiod 			continue;
9252bf3c060Smiod 		}
9262bf3c060Smiod 
927ac91c5e9Smiod 		/* not an option, or not a kernel option */
928ac91c5e9Smiod 		if (*arg != '-' || ignore)
9292bf3c060Smiod 			continue;
9302bf3c060Smiod 
9312bf3c060Smiod 		for (cp = arg + 1; *cp != '\0'; cp++)
9322bf3c060Smiod 			switch (*cp) {
9332bf3c060Smiod 			case '-':
9342bf3c060Smiod 				break;
9352bf3c060Smiod 			case 'a':
9362bf3c060Smiod 				boothowto |= RB_ASKNAME;
9372bf3c060Smiod 				break;
9382bf3c060Smiod 			case 'c':
9392bf3c060Smiod 				boothowto |= RB_CONFIG;
9402bf3c060Smiod 				break;
9412bf3c060Smiod 			case 'd':
9422bf3c060Smiod 				boothowto |= RB_KDB;
9432bf3c060Smiod 				break;
9442bf3c060Smiod 			case 's':
9452bf3c060Smiod 				boothowto |= RB_SINGLE;
9462bf3c060Smiod 				break;
9474b422019Smiod 			case 'g':
9484b422019Smiod 				boothowto |= RB_GOODRANDOM;
9494b422019Smiod 				break;
9502bf3c060Smiod 			default:
9512bf3c060Smiod 				pmon_printf("unrecognized option `%c'", *cp);
9522bf3c060Smiod 				break;
9532bf3c060Smiod 			}
9542bf3c060Smiod 	}
9552bf3c060Smiod 
9562bf3c060Smiod 	/*
9572bf3c060Smiod 	 * Consider parsing the `karg' environment variable here too?
9582bf3c060Smiod 	 */
9592bf3c060Smiod }
9602bf3c060Smiod 
9612bf3c060Smiod 
9622bf3c060Smiod /*
9632bf3c060Smiod  * Console initialization: called early on from main, before vm init or startup.
9642bf3c060Smiod  * Do enough configuration to choose and initialize a console.
9652bf3c060Smiod  */
9662bf3c060Smiod void
consinit()9672bf3c060Smiod consinit()
9682bf3c060Smiod {
9692bf3c060Smiod 	static int console_ok = 0;
9702bf3c060Smiod 
9712bf3c060Smiod 	if (console_ok == 0) {
9726f377552Smiod 		cn_tab = NULL;
9732bf3c060Smiod 		cninit();
9742bf3c060Smiod 		console_ok = 1;
9752bf3c060Smiod 	}
9762bf3c060Smiod }
9772bf3c060Smiod 
9782bf3c060Smiod /*
9792bf3c060Smiod  * cpu_startup: allocate memory for variable-sized tables, initialize CPU, and
9802bf3c060Smiod  * do auto-configuration.
9812bf3c060Smiod  */
9822bf3c060Smiod void
cpu_startup()9832bf3c060Smiod cpu_startup()
9842bf3c060Smiod {
9852bf3c060Smiod 	vaddr_t minaddr, maxaddr;
9862bf3c060Smiod 
9872bf3c060Smiod 	/*
9882bf3c060Smiod 	 * Good {morning,afternoon,evening,night}.
9892bf3c060Smiod 	 */
990c268af84Svisa 	printf("%s", version);
991b7eb4a84Sjsing 	printf("real mem = %lu (%luMB)\n", ptoa((psize_t)physmem),
992901254b4Sjasper 	    ptoa((psize_t)physmem)/1024/1024);
9932bf3c060Smiod 
9942bf3c060Smiod 	/*
9952bf3c060Smiod 	 * Allocate a submap for exec arguments. This map effectively
9962bf3c060Smiod 	 * limits the number of processes exec'ing at any time.
9972bf3c060Smiod 	 */
9982bf3c060Smiod 	minaddr = vm_map_min(kernel_map);
9992bf3c060Smiod 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
10002bf3c060Smiod 	    16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
10012bf3c060Smiod 	/* Allocate a submap for physio. */
10022bf3c060Smiod 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
10032bf3c060Smiod 	    VM_PHYS_SIZE, 0, FALSE, NULL);
10042bf3c060Smiod 
1005b7eb4a84Sjsing 	printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
10062bf3c060Smiod 	    ptoa(uvmexp.free)/1024/1024);
10072bf3c060Smiod 
10082bf3c060Smiod 	/*
10092bf3c060Smiod 	 * Set up buffers, so they can be used to read disk labels.
10102bf3c060Smiod 	 */
10112bf3c060Smiod 	bufinit();
10122bf3c060Smiod 
10132bf3c060Smiod 	/*
10142bf3c060Smiod 	 * Configure the system.
10152bf3c060Smiod 	 */
10162bf3c060Smiod 	if (boothowto & RB_CONFIG) {
10172bf3c060Smiod #ifdef BOOT_CONFIG
10182bf3c060Smiod 		user_config();
10192bf3c060Smiod #else
10202bf3c060Smiod 		printf("kernel does not support -c; continuing..\n");
10212bf3c060Smiod #endif
10222bf3c060Smiod 	}
10232bf3c060Smiod }
10242bf3c060Smiod 
1025e5680b7fSgnezdo const struct sysctl_bounded_args cpuctl_vars[] = {
1026e5680b7fSgnezdo 	{ CPU_LIDACTION, &lid_action, 0, 2 },
1027e5680b7fSgnezdo };
1028e5680b7fSgnezdo 
10292bf3c060Smiod /*
10302bf3c060Smiod  * Machine dependent system variables.
10312bf3c060Smiod  */
10322bf3c060Smiod int
cpu_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)1033e262726eSfcambus cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
1034e262726eSfcambus     size_t newlen, struct proc *p)
10352bf3c060Smiod {
1036e5680b7fSgnezdo 	return (sysctl_bounded_arr(cpuctl_vars, nitems(cpuctl_vars),
1037e5680b7fSgnezdo 	    name, namelen, oldp, oldlenp, newp, newlen));
10382bf3c060Smiod }
10392bf3c060Smiod 
10402bf3c060Smiod int	waittime = -1;
10412bf3c060Smiod 
1042ff261808Suebayasi __dead void
boot(int howto)10432bf3c060Smiod boot(int howto)
10442bf3c060Smiod {
104536ffd15aStedu 	void (*__reset)(void) = (void (*)(void))RESET_EXC_VEC;
104636ffd15aStedu 
10473c291078Stedu 	if ((howto & RB_RESET) != 0)
10483c291078Stedu 		goto doreset;
10493c291078Stedu 
10502bf3c060Smiod 	if (curproc)
10512bf3c060Smiod 		savectx(curproc->p_addr, 0);
10522bf3c060Smiod 
10532bf3c060Smiod 	if (cold) {
10542bf3c060Smiod 		if ((howto & RB_USERREQ) == 0)
10552bf3c060Smiod 			howto |= RB_HALT;
10562bf3c060Smiod 		goto haltsys;
10572bf3c060Smiod 	}
10582bf3c060Smiod 
10592bf3c060Smiod 	boothowto = howto;
10602bf3c060Smiod 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
10612bf3c060Smiod 		waittime = 0;
10627efda1a1Sderaadt 		vfs_shutdown(curproc);
10632bf3c060Smiod 
10642bf3c060Smiod 		if ((howto & RB_TIMEBAD) == 0) {
10652bf3c060Smiod 			resettodr();
10662bf3c060Smiod 		} else {
10672bf3c060Smiod 			printf("WARNING: not updating battery clock\n");
10682bf3c060Smiod 		}
10692bf3c060Smiod 	}
10707d9ca166Sderaadt 	if_downall();
10712bf3c060Smiod 
10722bf3c060Smiod 	uvm_shutdown();
10739f43f03fSuebayasi 	splhigh();
107480ce5a38Smpi 	cold = 1;
10752bf3c060Smiod 
1076b33b2f20Suebayasi 	if ((howto & RB_DUMP) != 0)
10772bf3c060Smiod 		dumpsys();
10782bf3c060Smiod 
10792bf3c060Smiod haltsys:
1080c16e7cd6Spirofti 	pci_dopm = 0;
108196f419e1Skettenis 	config_suspend_all(DVACT_POWERDOWN);
10822bf3c060Smiod 
1083b33b2f20Suebayasi 	if ((howto & RB_HALT) != 0) {
1084b33b2f20Suebayasi 		if ((howto & RB_POWERDOWN) != 0) {
108551b07be5Smiod 			if (sys_platform->powerdown != NULL) {
10862bf3c060Smiod 				printf("System Power Down.\n");
108751b07be5Smiod 				(*(sys_platform->powerdown))();
108851b07be5Smiod 			} else {
108951b07be5Smiod 				printf("System Power Down not supported,"
109051b07be5Smiod 				    " halting system.\n");
1091e1844cd9Smiod 			}
10922bf3c060Smiod 		} else
10932bf3c060Smiod 			printf("System Halt.\n");
10942bf3c060Smiod 	} else {
10953c291078Stedu doreset:
10962bf3c060Smiod 		printf("System restart.\n");
10978a850467Smiod 		if (sys_platform->reset != NULL)
10988a850467Smiod 			(*(sys_platform->reset))();
10998a850467Smiod 		(void)disableintr();
11008a850467Smiod 		tlb_set_wired(0);
11018a850467Smiod 		tlb_flush(bootcpu_hwinfo.tlbsize);
11022bf3c060Smiod 		__reset();
11032bf3c060Smiod 	}
11042bf3c060Smiod 
1105de5ed823Stom 	for (;;)
1106de5ed823Stom 		continue;
11072bf3c060Smiod 	/* NOTREACHED */
11082bf3c060Smiod }
11092bf3c060Smiod 
11102bf3c060Smiod u_long	dumpmag = 0x8fca0101;	/* Magic number for savecore. */
11112bf3c060Smiod int	dumpsize = 0;			/* Also for savecore. */
11122bf3c060Smiod long	dumplo = 0;
11132bf3c060Smiod 
11142bf3c060Smiod void
dumpconf(void)11152bf3c060Smiod dumpconf(void)
11162bf3c060Smiod {
11172bf3c060Smiod 	int nblks;
11182bf3c060Smiod 
11192bf3c060Smiod 	if (dumpdev == NODEV ||
11202bf3c060Smiod 	    (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
11212bf3c060Smiod 		return;
11222bf3c060Smiod 	if (nblks <= ctod(1))
11232bf3c060Smiod 		return;
11242bf3c060Smiod 
11252bf3c060Smiod 	dumpsize = ptoa(physmem);
11262bf3c060Smiod 	if (dumpsize > atop(round_page(dbtob(nblks - dumplo))))
11272bf3c060Smiod 		dumpsize = atop(round_page(dbtob(nblks - dumplo)));
11282bf3c060Smiod 	else if (dumplo == 0)
11292bf3c060Smiod 		dumplo = nblks - btodb(ptoa(physmem));
11302bf3c060Smiod 
11312bf3c060Smiod 	/*
11322bf3c060Smiod 	 * Don't dump on the first page in case the dump device includes a
11332bf3c060Smiod 	 * disk label.
11342bf3c060Smiod 	 */
11352bf3c060Smiod 	if (dumplo < btodb(PAGE_SIZE))
11362bf3c060Smiod 		dumplo = btodb(PAGE_SIZE);
11372bf3c060Smiod }
11382bf3c060Smiod 
11392bf3c060Smiod void
dumpsys()11402bf3c060Smiod dumpsys()
11412bf3c060Smiod {
11422bf3c060Smiod 	/* XXX TBD */
11432bf3c060Smiod }
11442bf3c060Smiod 
11452bf3c060Smiod /*
11462bf3c060Smiod  * Convert an ASCII string into an integer.
11472bf3c060Smiod  */
11482bf3c060Smiod static u_long
atoi(const char * s,uint b)11492bf3c060Smiod atoi(const char *s, uint b)
11502bf3c060Smiod {
11512bf3c060Smiod 	int c;
11522bf3c060Smiod 	uint base = b, d;
11532bf3c060Smiod 	int neg = 0;
11542bf3c060Smiod 	u_long val = 0;
11552bf3c060Smiod 
11562bf3c060Smiod 	if (s == NULL || *s == '\0')
11572bf3c060Smiod 		return 0;
11582bf3c060Smiod 
11592bf3c060Smiod 	/* Skip spaces if any. */
11602bf3c060Smiod 	do {
11612bf3c060Smiod 		c = *s++;
11622bf3c060Smiod 	} while (c == ' ' || c == '\t');
11632bf3c060Smiod 
11642bf3c060Smiod 	/* Parse sign, allow more than one (compat). */
11652bf3c060Smiod 	while (c == '-') {
11662bf3c060Smiod 		neg = !neg;
11672bf3c060Smiod 		c = *s++;
11682bf3c060Smiod 	}
11692bf3c060Smiod 
11702bf3c060Smiod 	/* Parse base specification, if any. */
11712bf3c060Smiod 	if (base == 0 && c == '0') {
11722bf3c060Smiod 		c = *s++;
11732bf3c060Smiod 		switch (c) {
11742bf3c060Smiod 		case 'X':
11752bf3c060Smiod 		case 'x':
11762bf3c060Smiod 			base = 16;
11772bf3c060Smiod 			c = *s++;
11782bf3c060Smiod 			break;
11792bf3c060Smiod 		case 'B':
11802bf3c060Smiod 		case 'b':
11812bf3c060Smiod 			base = 2;
11822bf3c060Smiod 			c = *s++;
11832bf3c060Smiod 			break;
11842bf3c060Smiod 		default:
11852bf3c060Smiod 			base = 8;
11862bf3c060Smiod 			break;
11872bf3c060Smiod 		}
11882bf3c060Smiod 	}
11892bf3c060Smiod 
11902bf3c060Smiod 	/* Parse number proper. */
11912bf3c060Smiod 	for (;;) {
11922bf3c060Smiod 		if (c >= '0' && c <= '9')
11932bf3c060Smiod 			d = c - '0';
11942bf3c060Smiod 		else if (c >= 'a' && c <= 'z')
11952bf3c060Smiod 			d = c - 'a' + 10;
11962bf3c060Smiod 		else if (c >= 'A' && c <= 'Z')
11972bf3c060Smiod 			d = c - 'A' + 10;
11982bf3c060Smiod 		else
11992bf3c060Smiod 			break;
12002bf3c060Smiod 		if (d >= base)
12012bf3c060Smiod 			break;
12022bf3c060Smiod 		val *= base;
12032bf3c060Smiod 		val += d;
12042bf3c060Smiod 		c = *s++;
12052bf3c060Smiod 	}
12062bf3c060Smiod 
12072bf3c060Smiod 	return neg ? -val : val;
12082bf3c060Smiod }
12092bf3c060Smiod 
12102bf3c060Smiod /*
12112bf3c060Smiod  * Early console through pmon routines.
12122bf3c060Smiod  */
12132bf3c060Smiod 
12142bf3c060Smiod int
pmoncngetc(dev_t dev)12152bf3c060Smiod pmoncngetc(dev_t dev)
12162bf3c060Smiod {
12172bf3c060Smiod 	/*
12182bf3c060Smiod 	 * PMON does not give us a getc routine.  So try to get a whole line
12192bf3c060Smiod 	 * and return it char by char, trying not to lose the \n.  Kind
12202bf3c060Smiod 	 * of ugly but should work.
1221e1844cd9Smiod 	 *
1222e1844cd9Smiod 	 * Note that one could theoretically use pmon_read(STDIN, &c, 1)
1223e1844cd9Smiod 	 * but the value of STDIN within PMON is not a constant and there
1224e1844cd9Smiod 	 * does not seem to be a way of letting us know which value to use.
12252bf3c060Smiod 	 */
12262bf3c060Smiod 	static char buf[1 + PMON_MAXLN];
12272bf3c060Smiod 	static char *bufpos = buf;
12282bf3c060Smiod 	int c;
12292bf3c060Smiod 
12302bf3c060Smiod 	if (*bufpos == '\0') {
12312bf3c060Smiod 		bufpos = buf;
12322bf3c060Smiod 		if (pmon_gets(buf) == NULL) {
12332bf3c060Smiod 			/* either an empty line or EOF. assume the former */
12342bf3c060Smiod 			return (int)'\n';
12352bf3c060Smiod 		} else {
12362bf3c060Smiod 			/* put back the \n sign */
12372bf3c060Smiod 			buf[strlen(buf)] = '\n';
12382bf3c060Smiod 		}
12392bf3c060Smiod 	}
12402bf3c060Smiod 
12412bf3c060Smiod 	c = (int)*bufpos++;
12422bf3c060Smiod 	if (bufpos - buf > PMON_MAXLN) {
12432bf3c060Smiod 		bufpos = buf;
12442bf3c060Smiod 		*bufpos = '\0';
12452bf3c060Smiod 	}
12462bf3c060Smiod 
12472bf3c060Smiod 	return c;
12482bf3c060Smiod }
12492bf3c060Smiod 
12502bf3c060Smiod void
pmoncnputc(dev_t dev,int c)12512bf3c060Smiod pmoncnputc(dev_t dev, int c)
12522bf3c060Smiod {
12532bf3c060Smiod 	if (c == '\n')
12542bf3c060Smiod 		pmon_printf("\n");
12552bf3c060Smiod 	else
12562bf3c060Smiod 		pmon_printf("%c", c);
12572bf3c060Smiod }
125839de0dfdSvisa 
1259cae6d111Svisa void
intr_barrier(void * cookie)1260cae6d111Svisa intr_barrier(void *cookie)
1261cae6d111Svisa {
1262cae6d111Svisa 	sched_barrier(NULL);
1263cae6d111Svisa }
1264cae6d111Svisa 
126539de0dfdSvisa #ifdef MULTIPROCESSOR
126639de0dfdSvisa 
126739de0dfdSvisa void
hw_cpu_hatch(struct cpu_info * ci)126839de0dfdSvisa hw_cpu_hatch(struct cpu_info *ci)
126939de0dfdSvisa {
127039de0dfdSvisa 	/*
127139de0dfdSvisa 	 * Set curcpu address on this processor.
127239de0dfdSvisa 	 */
127339de0dfdSvisa 	setcurcpu(ci);
127439de0dfdSvisa 
127539de0dfdSvisa 	/*
127639de0dfdSvisa 	 * Make sure we can access the extended address space.
127739de0dfdSvisa 	 */
127839de0dfdSvisa 	setsr(getsr() | SR_KX | SR_UX);
127939de0dfdSvisa 
1280f4728271Svisa 	tlb_init(ci->ci_hw.tlbsize);
1281f4728271Svisa 	tlb_set_pid(0);
1282f4728271Svisa 
128339de0dfdSvisa 	/*
128439de0dfdSvisa 	 * Turn off bootstrap exception vectors.
128539de0dfdSvisa 	 */
128639de0dfdSvisa 	setsr(getsr() & ~SR_BOOT_EXC_VEC);
128739de0dfdSvisa 
128839de0dfdSvisa 	/*
128939de0dfdSvisa 	 * Clear out the I and D caches.
129039de0dfdSvisa 	 */
129139de0dfdSvisa 	switch (loongson_ver) {
129239de0dfdSvisa #ifdef CPU_LOONGSON3
129339de0dfdSvisa 	case 0x3a:
129439de0dfdSvisa 	case 0x3b:
129539de0dfdSvisa 		Loongson3_ConfigCache(ci);
129639de0dfdSvisa 		Loongson3_SyncCache(ci);
129739de0dfdSvisa 		break;
129839de0dfdSvisa #endif
129939de0dfdSvisa 	default:
13004123b6a7Sderaadt 		panic("%s: unhandled Loongson version %x", __func__,
130139de0dfdSvisa 		    loongson_ver);
130239de0dfdSvisa 	}
130339de0dfdSvisa 
130439de0dfdSvisa 	(*md_startclock)(ci);
130539de0dfdSvisa 
130639de0dfdSvisa 	mips64_ipi_init();
130739de0dfdSvisa 
13085c29d161Svisa 	ci->ci_flags |= CPUF_RUNNING;
13095c29d161Svisa 	membar_sync();
13105c29d161Svisa 
131139de0dfdSvisa 	ncpus++;
131239de0dfdSvisa 
131339de0dfdSvisa 	spl0();
131439de0dfdSvisa 	(void)updateimask(0);
131539de0dfdSvisa 
1316*bb00e811Sclaudio 	sched_toidle();
131739de0dfdSvisa }
131839de0dfdSvisa 
131939de0dfdSvisa void
hw_cpu_boot_secondary(struct cpu_info * ci)132039de0dfdSvisa hw_cpu_boot_secondary(struct cpu_info *ci)
132139de0dfdSvisa {
132239de0dfdSvisa 	sys_platform->boot_secondary_cpu(ci);
132339de0dfdSvisa }
132439de0dfdSvisa 
132539de0dfdSvisa int
hw_ipi_intr_establish(int (* func)(void *),u_long cpuid)132639de0dfdSvisa hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
132739de0dfdSvisa {
132839de0dfdSvisa 	if (sys_platform->ipi_establish != NULL)
132939de0dfdSvisa 		return sys_platform->ipi_establish(func, cpuid);
133039de0dfdSvisa 	else
133139de0dfdSvisa 		return 0;
133239de0dfdSvisa }
133339de0dfdSvisa 
133439de0dfdSvisa void
hw_ipi_intr_set(u_long cpuid)133539de0dfdSvisa hw_ipi_intr_set(u_long cpuid)
133639de0dfdSvisa {
133739de0dfdSvisa 	sys_platform->ipi_set(cpuid);
133839de0dfdSvisa }
133939de0dfdSvisa 
134039de0dfdSvisa void
hw_ipi_intr_clear(u_long cpuid)134139de0dfdSvisa hw_ipi_intr_clear(u_long cpuid)
134239de0dfdSvisa {
134339de0dfdSvisa 	if (sys_platform->ipi_clear != NULL)
134439de0dfdSvisa 		sys_platform->ipi_clear(cpuid);
134539de0dfdSvisa }
134639de0dfdSvisa 
134739de0dfdSvisa #endif /* MULTIPROCESSOR */
1348