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