xref: /plan9-contrib/sys/src/9/pc/archmp.c (revision 00a4193c1e0554905f959f11961389c706f63ac9)
17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "io.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier #include "mp.h"
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier _MP_ *_mp_;
117dd7cddfSDavid du Colombier 
121206f3fcSDavid du Colombier static void
mpresetothers(void)131206f3fcSDavid du Colombier mpresetothers(void)
141206f3fcSDavid du Colombier {
151206f3fcSDavid du Colombier 	/*
161206f3fcSDavid du Colombier 	 * INIT all excluding self.
171206f3fcSDavid du Colombier 	 */
181206f3fcSDavid du Colombier 	lapicicrw(0, 0x000C0000|ApicINIT);
191206f3fcSDavid du Colombier }
201206f3fcSDavid du Colombier 
21e288d156SDavid du Colombier static int identify(void);
22e288d156SDavid du Colombier 
23e288d156SDavid du Colombier PCArch archmp = {
24e288d156SDavid du Colombier .id=		"_MP_",
25e288d156SDavid du Colombier .ident=		identify,
26e288d156SDavid du Colombier .reset=		mpshutdown,
27e288d156SDavid du Colombier .intrinit=	mpinit,
28e288d156SDavid du Colombier .intrenable=	mpintrenable,
294de34a7eSDavid du Colombier .intron=	lapicintron,
304de34a7eSDavid du Colombier .introff=	lapicintroff,
31e288d156SDavid du Colombier .fastclock=	i8253read,
32e288d156SDavid du Colombier .timerset=	lapictimerset,
331206f3fcSDavid du Colombier .resetothers=	mpresetothers,
34e288d156SDavid du Colombier };
35e288d156SDavid du Colombier 
367dd7cddfSDavid du Colombier static int
identify(void)377dd7cddfSDavid du Colombier identify(void)
387dd7cddfSDavid du Colombier {
39901484c1SDavid du Colombier 	char *cp;
407dd7cddfSDavid du Colombier 	PCMP *pcmp;
417dd7cddfSDavid du Colombier 	uchar *p, sum;
427dd7cddfSDavid du Colombier 	ulong length;
437dd7cddfSDavid du Colombier 
44901484c1SDavid du Colombier 	if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
457dd7cddfSDavid du Colombier 		return 1;
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier 	/*
487dd7cddfSDavid du Colombier 	 * Search for an MP configuration table. For now,
497dd7cddfSDavid du Colombier 	 * don't accept the default configurations (physaddr == 0).
507dd7cddfSDavid du Colombier 	 * Check for correct signature, calculate the checksum and,
517dd7cddfSDavid du Colombier 	 * if correct, check the version.
527dd7cddfSDavid du Colombier 	 * To do: check extended table checksum.
537dd7cddfSDavid du Colombier 	 */
54*00a4193cSDavid du Colombier 	if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0) {
55e360d427SDavid du Colombier 		/*
56e360d427SDavid du Colombier 		 * we can easily get processor info from acpi, but
57e360d427SDavid du Colombier 		 * interrupt routing, etc. would require interpreting aml.
58e360d427SDavid du Colombier 		 */
59e360d427SDavid du Colombier 		print("archmp: no mp table found, assuming uniprocessor\n");
607dd7cddfSDavid du Colombier 		return 1;
61e360d427SDavid du Colombier 	}
627dd7cddfSDavid du Colombier 
63*00a4193cSDavid du Colombier 	if (0)
64*00a4193cSDavid du Colombier 		iprint("mp physaddr %#lux\n", _mp_->physaddr);
657dd7cddfSDavid du Colombier 	pcmp = KADDR(_mp_->physaddr);
66e360d427SDavid du Colombier 	if(memcmp(pcmp, "PCMP", 4) != 0) {
67e360d427SDavid du Colombier 		print("archmp: mp table has bad magic");
687dd7cddfSDavid du Colombier 		return 1;
69e360d427SDavid du Colombier 	}
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier 	length = pcmp->length;
727dd7cddfSDavid du Colombier 	sum = 0;
737dd7cddfSDavid du Colombier 	for(p = (uchar*)pcmp; length; length--)
747dd7cddfSDavid du Colombier 		sum += *p++;
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	if(sum || (pcmp->version != 1 && pcmp->version != 4))
777dd7cddfSDavid du Colombier 		return 1;
787dd7cddfSDavid du Colombier 
79e288d156SDavid du Colombier 	if(cpuserver && m->havetsc)
80e288d156SDavid du Colombier 		archmp.fastclock = tscticks;
817dd7cddfSDavid du Colombier 	return 0;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier 
849a747e4fSDavid du Colombier Lock mpsynclock;
859a747e4fSDavid du Colombier 
869a747e4fSDavid du Colombier void
syncclock(void)879a747e4fSDavid du Colombier syncclock(void)
889a747e4fSDavid du Colombier {
899a747e4fSDavid du Colombier 	uvlong x;
909a747e4fSDavid du Colombier 
91dc5a79c1SDavid du Colombier 	if(arch->fastclock != tscticks)
92dc5a79c1SDavid du Colombier 		return;
93dc5a79c1SDavid du Colombier 
949a747e4fSDavid du Colombier 	if(m->machno == 0){
959a747e4fSDavid du Colombier 		wrmsr(0x10, 0);
969a747e4fSDavid du Colombier 		m->tscticks = 0;
979a747e4fSDavid du Colombier 	} else {
989a747e4fSDavid du Colombier 		x = MACHP(0)->tscticks;
999a747e4fSDavid du Colombier 		while(x == MACHP(0)->tscticks)
1009a747e4fSDavid du Colombier 			;
101e288d156SDavid du Colombier 		wrmsr(0x10, MACHP(0)->tscticks);
102da51d93aSDavid du Colombier 		cycles(&m->tscticks);
1039a747e4fSDavid du Colombier 	}
1049a747e4fSDavid du Colombier }
1059a747e4fSDavid du Colombier 
1069a747e4fSDavid du Colombier uvlong
tscticks(uvlong * hz)1079a747e4fSDavid du Colombier tscticks(uvlong *hz)
1089a747e4fSDavid du Colombier {
1099a747e4fSDavid du Colombier 	if(hz != nil)
1109a747e4fSDavid du Colombier 		*hz = m->cpuhz;
1119a747e4fSDavid du Colombier 
112e288d156SDavid du Colombier 	cycles(&m->tscticks);	/* Uses the rdtsc instruction */
113e288d156SDavid du Colombier 	return m->tscticks;
1149a747e4fSDavid du Colombier }
115