]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/archmp.c
perms
[plan9front.git] / sys / src / 9 / 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 }