xref: /plan9/sys/src/9/pc/archmp.c (revision 00a4193c1e0554905f959f11961389c706f63ac9)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 
8 #include "mp.h"
9 
10 _MP_ *_mp_;
11 
12 static void
mpresetothers(void)13 mpresetothers(void)
14 {
15 	/*
16 	 * INIT all excluding self.
17 	 */
18 	lapicicrw(0, 0x000C0000|ApicINIT);
19 }
20 
21 static int identify(void);
22 
23 PCArch archmp = {
24 .id=		"_MP_",
25 .ident=		identify,
26 .reset=		mpshutdown,
27 .intrinit=	mpinit,
28 .intrenable=	mpintrenable,
29 .intron=	lapicintron,
30 .introff=	lapicintroff,
31 .fastclock=	i8253read,
32 .timerset=	lapictimerset,
33 .resetothers=	mpresetothers,
34 };
35 
36 static int
identify(void)37 identify(void)
38 {
39 	char *cp;
40 	PCMP *pcmp;
41 	uchar *p, sum;
42 	ulong length;
43 
44 	if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
45 		return 1;
46 
47 	/*
48 	 * Search for an MP configuration table. For now,
49 	 * don't accept the default configurations (physaddr == 0).
50 	 * Check for correct signature, calculate the checksum and,
51 	 * if correct, check the version.
52 	 * To do: check extended table checksum.
53 	 */
54 	if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0) {
55 		/*
56 		 * we can easily get processor info from acpi, but
57 		 * interrupt routing, etc. would require interpreting aml.
58 		 */
59 		print("archmp: no mp table found, assuming uniprocessor\n");
60 		return 1;
61 	}
62 
63 	if (0)
64 		iprint("mp physaddr %#lux\n", _mp_->physaddr);
65 	pcmp = KADDR(_mp_->physaddr);
66 	if(memcmp(pcmp, "PCMP", 4) != 0) {
67 		print("archmp: mp table has bad magic");
68 		return 1;
69 	}
70 
71 	length = pcmp->length;
72 	sum = 0;
73 	for(p = (uchar*)pcmp; length; length--)
74 		sum += *p++;
75 
76 	if(sum || (pcmp->version != 1 && pcmp->version != 4))
77 		return 1;
78 
79 	if(cpuserver && m->havetsc)
80 		archmp.fastclock = tscticks;
81 	return 0;
82 }
83 
84 Lock mpsynclock;
85 
86 void
syncclock(void)87 syncclock(void)
88 {
89 	uvlong x;
90 
91 	if(arch->fastclock != tscticks)
92 		return;
93 
94 	if(m->machno == 0){
95 		wrmsr(0x10, 0);
96 		m->tscticks = 0;
97 	} else {
98 		x = MACHP(0)->tscticks;
99 		while(x == MACHP(0)->tscticks)
100 			;
101 		wrmsr(0x10, MACHP(0)->tscticks);
102 		cycles(&m->tscticks);
103 	}
104 }
105 
106 uvlong
tscticks(uvlong * hz)107 tscticks(uvlong *hz)
108 {
109 	if(hz != nil)
110 		*hz = m->cpuhz;
111 
112 	cycles(&m->tscticks);	/* Uses the rdtsc instruction */
113 	return m->tscticks;
114 }
115