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 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 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 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 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