xref: /plan9/sys/src/9/pcboot/warp64.c (revision bf3a53f86959e0d59761d324f198ede9838801c7)
125210b06SDavid du Colombier #include	"u.h"
225210b06SDavid du Colombier #include	"../port/lib.h"
325210b06SDavid du Colombier #include	"mem.h"
425210b06SDavid du Colombier #include	"dat.h"
525210b06SDavid du Colombier #include	"fns.h"
625210b06SDavid du Colombier #include	"io.h"
725210b06SDavid du Colombier #include	"ureg.h"
825210b06SDavid du Colombier 
9*bf3a53f8SDavid du Colombier enum {
10*bf3a53f8SDavid du Colombier 	Ax,
11*bf3a53f8SDavid du Colombier 	Bx,
12*bf3a53f8SDavid du Colombier 	Cx,
13*bf3a53f8SDavid du Colombier 	Dx,
14*bf3a53f8SDavid du Colombier 
15*bf3a53f8SDavid du Colombier 	/*
16*bf3a53f8SDavid du Colombier 	 * common to intel & amd
17*bf3a53f8SDavid du Colombier 	 */
18*bf3a53f8SDavid du Colombier 	Extfunc	= 0x80000000,
19*bf3a53f8SDavid du Colombier 	Procsig,
20*bf3a53f8SDavid du Colombier 
21*bf3a53f8SDavid du Colombier 	/* Procsig bits */
22*bf3a53f8SDavid du Colombier 	Dxlongmode	= 1<<29,
23*bf3a53f8SDavid du Colombier };
24*bf3a53f8SDavid du Colombier 
2525210b06SDavid du Colombier typedef unsigned long long u64intptr;
2625210b06SDavid du Colombier 
27*bf3a53f8SDavid du Colombier static int
havelongmode(void)28*bf3a53f8SDavid du Colombier havelongmode(void)
29*bf3a53f8SDavid du Colombier {
30*bf3a53f8SDavid du Colombier 	ulong regs[4];
31*bf3a53f8SDavid du Colombier 
32*bf3a53f8SDavid du Colombier 	memset(regs, 0, sizeof regs);
33*bf3a53f8SDavid du Colombier 	cpuid(Extfunc, regs);
34*bf3a53f8SDavid du Colombier 	if(regs[Ax] < Extfunc)
35*bf3a53f8SDavid du Colombier 		return 0;
36*bf3a53f8SDavid du Colombier 
37*bf3a53f8SDavid du Colombier 	memset(regs, 0, sizeof regs);
38*bf3a53f8SDavid du Colombier 	cpuid(Procsig, regs);
39*bf3a53f8SDavid du Colombier 	return (regs[Dx] & Dxlongmode) != 0;
40*bf3a53f8SDavid du Colombier }
41*bf3a53f8SDavid du Colombier 
4225210b06SDavid du Colombier void
warp64(uvlong entry)4325210b06SDavid du Colombier warp64(uvlong entry)
4425210b06SDavid du Colombier {
4525210b06SDavid du Colombier 	u64intptr kzero64 = 0xfffffffff0000000ull;
4625210b06SDavid du Colombier 	extern void _warp64(ulong);
4725210b06SDavid du Colombier 
4825210b06SDavid du Colombier 	print("warp64(%#llux) %#llux %d\n", entry, entry & ~kzero64, nmmap);
49*bf3a53f8SDavid du Colombier 	if(!havelongmode()) {
50*bf3a53f8SDavid du Colombier 		print("can't run 64-bit kernel on 32-bit cpu\n");
51*bf3a53f8SDavid du Colombier 		delay(5000);
52*bf3a53f8SDavid du Colombier 		exit(0);
53*bf3a53f8SDavid du Colombier 	}
5425210b06SDavid du Colombier 	if(v_flag)
5525210b06SDavid du Colombier 		print("mkmultiboot\n");
5625210b06SDavid du Colombier 	mkmultiboot();
5725210b06SDavid du Colombier 	if(v_flag)
5825210b06SDavid du Colombier 		print("impulse\n");
5925210b06SDavid du Colombier 	/*
6025210b06SDavid du Colombier 	 * No output after impulse().
6125210b06SDavid du Colombier 	 */
6225210b06SDavid du Colombier 	if(v_flag)
6325210b06SDavid du Colombier 		print("_warp64\n");
6425210b06SDavid du Colombier 	impulse();
6525210b06SDavid du Colombier 	_warp64(entry & ~kzero64);
6625210b06SDavid du Colombier }
67