FreeBSD/Linux Kernel Cross Reference
sys/pc/archmp.c
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 _MP_*
13 mpscan(uchar *addr, int len)
14 {
15 uchar *e, *p, sum;
16 int i;
17
18 e = addr+len;
19 for(p = addr; p < e; p += sizeof(_MP_)){
20 if(memcmp(p, "_MP_", 4))
21 continue;
22 sum = 0;
23 for(i = 0; i < sizeof(_MP_); i++)
24 sum += p[i];
25 if(sum == 0)
26 return (_MP_*)p;
27 }
28 return 0;
29 }
30
31 static _MP_*
32 mpsearch(void)
33 {
34 uchar *bda;
35 ulong p;
36 _MP_ *mp;
37
38 /*
39 * Search for the MP Floating Pointer Structure:
40 * 1) in the first KB of the EBDA;
41 * 2) in the last KB of system base memory;
42 * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
43 */
44 bda = KADDR(0x400);
45 if((p = (bda[0x0F]<<8)|bda[0x0E])){
46 if(mp = mpscan(KADDR(p<<4), 1024))
47 return mp;
48 }
49 else{
50 p = ((bda[0x14]<<8)|bda[0x13])*1024;
51 if(mp = mpscan(KADDR(p-1024), 1024))
52 return mp;
53 }
54 return mpscan(KADDR(0xF0000), 0x10000);
55 }
56
57 static int identify(void);
58
59 PCArch archmp = {
60 .id= "_MP_",
61 .ident= identify,
62 .reset= mpshutdown,
63 .intrinit= mpinit,
64 .intrenable= mpintrenable,
65 .intron= lapicintron,
66 .introff= lapicintroff,
67 .fastclock= i8253read,
68 .timerset= lapictimerset,
69 };
70
71 static int
72 identify(void)
73 {
74 char *cp;
75 PCMP *pcmp;
76 uchar *p, sum;
77 ulong length;
78
79 if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
80 return 1;
81
82 /*
83 * Search for an MP configuration table. For now,
84 * don't accept the default configurations (physaddr == 0).
85 * Check for correct signature, calculate the checksum and,
86 * if correct, check the version.
87 * To do: check extended table checksum.
88 */
89 if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
90 return 1;
91
92 pcmp = KADDR(_mp_->physaddr);
93 if(memcmp(pcmp, "PCMP", 4))
94 return 1;
95
96 length = pcmp->length;
97 sum = 0;
98 for(p = (uchar*)pcmp; length; length--)
99 sum += *p++;
100
101 if(sum || (pcmp->version != 1 && pcmp->version != 4))
102 return 1;
103
104 if(cpuserver && m->havetsc)
105 archmp.fastclock = tscticks;
106 return 0;
107 }
108
109 Lock mpsynclock;
110
111 void
112 syncclock(void)
113 {
114 uvlong x;
115
116 if(arch->fastclock != tscticks)
117 return;
118
119 if(m->machno == 0){
120 wrmsr(0x10, 0);
121 m->tscticks = 0;
122 } else {
123 x = MACHP(0)->tscticks;
124 while(x == MACHP(0)->tscticks)
125 ;
126 wrmsr(0x10, MACHP(0)->tscticks);
127 cycles(&m->tscticks);
128 }
129 }
130
131 uvlong
132 tscticks(uvlong *hz)
133 {
134 if(hz != nil)
135 *hz = m->cpuhz;
136
137 cycles(&m->tscticks); /* Uses the rdtsc instruction */
138 return m->tscticks;
139 }
Cache object: 4d2fa4f6b34fd972fe017bb625477835
|