mp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "apic.h"
  15. /*
  16. * MultiProcessor Specification Version 1.[14].
  17. */
  18. typedef struct { /* MP Floating Pointer */
  19. uint8_t signature[4]; /* "_MP_" */
  20. uint8_t addr[4]; /* PCMP */
  21. uint8_t length; /* 1 */
  22. uint8_t revision; /* [14] */
  23. uint8_t checksum;
  24. uint8_t feature[5];
  25. } _MP_;
  26. typedef struct { /* MP Configuration Table */
  27. uint8_t signature[4]; /* "PCMP" */
  28. uint8_t length[2];
  29. uint8_t revision; /* [14] */
  30. uint8_t checksum;
  31. uint8_t string[20]; /* OEM + Product ID */
  32. uint8_t oaddr[4]; /* OEM table pointer */
  33. uint8_t olength[2]; /* OEM table length */
  34. uint8_t entry[2]; /* entry count */
  35. uint8_t apicpa[4]; /* local APIC address */
  36. uint8_t xlength[2]; /* extended table length */
  37. uint8_t xchecksum; /* extended table checksum */
  38. uint8_t reserved;
  39. uint8_t entries[];
  40. } PCMP;
  41. typedef struct {
  42. char type[6];
  43. int polarity; /* default for this bus */
  44. int trigger; /* default for this bus */
  45. } Mpbus;
  46. static Mpbus mpbusdef[] = {
  47. { "PCI ", IPlow, TMlevel, },
  48. { "ISA ", IPhigh, TMedge, },
  49. };
  50. static Mpbus* mpbus[Nbus];
  51. int mpisabusno = -1;
  52. static void
  53. mpintrprint(char* s, uint8_t* p)
  54. {
  55. char buf[128], *b, *e;
  56. char format[] = " type %d flags %#ux bus %d IRQ %d APIC %d INTIN %d\n";
  57. b = buf;
  58. e = b + sizeof(buf);
  59. b = seprint(b, e, "mpparse: intr:");
  60. if(s != nil)
  61. b = seprint(b, e, " %s:", s);
  62. seprint(b, e, format, p[1], l16get(p+2), p[4], p[5], p[6], p[7]);
  63. print(buf);
  64. }
  65. static uint32_t
  66. mpmkintr(uint8_t* p)
  67. {
  68. uint32_t v;
  69. Apic *apic;
  70. int n, polarity, trigger;
  71. /*
  72. * Check valid bus, interrupt input pin polarity
  73. * and trigger mode. If the APIC ID is 0xff it means
  74. * all APICs of this type so those checks for useable
  75. * APIC and valid INTIN must also be done later in
  76. * the appropriate init routine in that case. It's hard
  77. * to imagine routing a signal to all IOAPICs, the
  78. * usual case is routing NMI and ExtINT to all LAPICs.
  79. */
  80. if(mpbus[p[4]] == nil){
  81. mpintrprint("no source bus", p);
  82. return 0;
  83. }
  84. if(p[6] != 0xff){
  85. if(Napic < 256 && p[6] >= Napic){
  86. mpintrprint("APIC ID out of range", p);
  87. return 0;
  88. }
  89. switch(p[0]){
  90. default:
  91. mpintrprint("INTIN botch", p);
  92. return 0;
  93. case 3: /* IOINTR */
  94. apic = &xioapic[p[6]];
  95. if(!apic->useable){
  96. mpintrprint("unuseable ioapic", p);
  97. return 0;
  98. }
  99. if(p[7] >= apic->Ioapic.nrdt){
  100. mpintrprint("IO INTIN out of range", p);
  101. return 0;
  102. }
  103. break;
  104. case 4: /* LINTR */
  105. apic = &xlapic[p[6]];
  106. if(!apic->useable){
  107. mpintrprint("unuseable lapic", p);
  108. return 0;
  109. }
  110. if(p[7] >= nelem(apic->Lapic.lvt)){
  111. mpintrprint("LOCAL INTIN out of range", p);
  112. return 0;
  113. }
  114. break;
  115. }
  116. }
  117. n = l16get(p+2);
  118. if((polarity = (n & 0x03)) == 2 || (trigger = ((n>>2) & 0x03)) == 2){
  119. mpintrprint("invalid polarity/trigger", p);
  120. return 0;
  121. }
  122. /*
  123. * Create the low half of the vector table entry (LVT or RDT).
  124. * For the NMI, SMI and ExtINT cases, the polarity and trigger
  125. * are fixed (but are not always consistent over IA-32 generations).
  126. * For the INT case, either the polarity/trigger are given or
  127. * it defaults to that of the source bus;
  128. * whether INT is Fixed or Lowest Priority is left until later.
  129. */
  130. v = Im;
  131. switch(p[1]){
  132. default:
  133. mpintrprint("invalid type", p);
  134. return 0;
  135. case 0: /* INT */
  136. switch(polarity){
  137. case 0:
  138. v |= mpbus[p[4]]->polarity;
  139. break;
  140. case 1:
  141. v |= IPhigh;
  142. break;
  143. case 3:
  144. v |= IPlow;
  145. break;
  146. }
  147. switch(trigger){
  148. case 0:
  149. v |= mpbus[p[4]]->trigger;
  150. break;
  151. case 1:
  152. v |= TMedge;
  153. break;
  154. case 3:
  155. v |= TMlevel;
  156. break;
  157. }
  158. break;
  159. case 1: /* NMI */
  160. v |= TMedge|IPhigh|MTnmi;
  161. break;
  162. case 2: /* SMI */
  163. v |= TMedge|IPhigh|MTsmi;
  164. break;
  165. case 3: /* ExtINT */
  166. v |= TMedge|IPhigh|MTei;
  167. break;
  168. }
  169. return v;
  170. }
  171. static int
  172. mpparse(PCMP* pcmp, int maxcores)
  173. {
  174. uint32_t lo;
  175. uint8_t *e, *p;
  176. int devno, i, n;
  177. p = pcmp->entries;
  178. e = ((uint8_t*)pcmp)+l16get(pcmp->length);
  179. while(p < e) switch(*p){
  180. default:
  181. print("mpparse: unknown PCMP type %d (e-p %#ld)\n", *p, e-p);
  182. for(i = 0; p < e; i++){
  183. if(i && ((i & 0x0f) == 0))
  184. print("\n");
  185. print(" %#2.2ux", *p);
  186. p++;
  187. }
  188. print("\n");
  189. break;
  190. case 0: /* processor */
  191. /*
  192. * Initialise the APIC if it is enabled (p[3] & 0x01).
  193. * p[1] is the APIC ID, the memory mapped address comes
  194. * from the PCMP structure as the addess is local to the
  195. * CPU and identical for all. Indicate whether this is
  196. * the bootstrap processor (p[3] & 0x02).
  197. */
  198. DBG("mpparse: cpu %d pa %#ux bp %d\n",
  199. p[1], l32get(pcmp->apicpa), p[3] & 0x02);
  200. if((p[3] & 0x01) != 0 && maxcores-- > 0)
  201. apicinit(p[1], l32get(pcmp->apicpa), p[3] & 0x02);
  202. maxcores--;
  203. p += 20;
  204. break;
  205. case 1: /* bus */
  206. DBG("mpparse: bus: %d type %6.6s\n", p[1], (char*)p+2);
  207. if(mpbus[p[1]] != nil){
  208. print("mpparse: bus %d already allocated\n", p[1]);
  209. p += 8;
  210. break;
  211. }
  212. for(i = 0; i < nelem(mpbusdef); i++){
  213. if(memcmp(p+2, mpbusdef[i].type, 6) != 0)
  214. continue;
  215. if(memcmp(p+2, "ISA ", 6) == 0){
  216. if(mpisabusno != -1){
  217. print("mpparse: bus %d already have ISA bus %d\n",
  218. p[1], mpisabusno);
  219. continue;
  220. }
  221. mpisabusno = p[1];
  222. }
  223. mpbus[p[1]] = &mpbusdef[i];
  224. break;
  225. }
  226. if(mpbus[p[1]] == nil)
  227. print("mpparse: bus %d type %6.6s unknown\n",
  228. p[1], (char*)p+2);
  229. p += 8;
  230. break;
  231. case 2: /* IOAPIC */
  232. /*
  233. * Initialise the IOAPIC if it is enabled (p[3] & 0x01).
  234. * p[1] is the APIC ID, p[4-7] is the memory mapped address.
  235. */
  236. if(p[3] & 0x01)
  237. ioapicinit(p[1], -1, l32get(p+4));
  238. p += 8;
  239. break;
  240. case 3: /* IOINTR */
  241. /*
  242. * p[1] is the interrupt type;
  243. * p[2-3] contains the polarity and trigger mode;
  244. * p[4] is the source bus;
  245. * p[5] is the IRQ on the source bus;
  246. * p[6] is the destination APIC;
  247. * p[7] is the INITIN pin on the destination APIC.
  248. */
  249. if(p[6] == 0xff){
  250. mpintrprint("routed to all IOAPICs", p);
  251. p += 8;
  252. break;
  253. }
  254. if((lo = mpmkintr(p)) == 0){
  255. p += 8;
  256. break;
  257. }
  258. if(DBGFLG)
  259. mpintrprint(nil, p);
  260. /*
  261. * Always present the device number in the style
  262. * of a PCI Interrupt Assignment Entry. For the ISA
  263. * bus the IRQ is the device number but unencoded.
  264. * May need to handle other buses here in the future
  265. * (but unlikely).
  266. */
  267. devno = p[5];
  268. if(memcmp(mpbus[p[4]]->type, "PCI ", 6) != 0)
  269. devno <<= 2;
  270. ioapicintrinit(p[4], p[6], p[7], devno, lo);
  271. p += 8;
  272. break;
  273. case 4: /* LINTR */
  274. /*
  275. * Format is the same as IOINTR above.
  276. */
  277. if((lo = mpmkintr(p)) == 0){
  278. p += 8;
  279. break;
  280. }
  281. if(DBGFLG)
  282. mpintrprint(nil, p);
  283. /*
  284. * Everything was checked in mpmkintr above.
  285. */
  286. if(p[6] == 0xff){
  287. for(i = 0; i < Napic; i++){
  288. if(!xlapic[i].useable || xlapic[i].Ioapic.addr != nil)
  289. continue;
  290. xlapic[i].Lapic.lvt[p[7]] = lo;
  291. }
  292. }
  293. else
  294. xlapic[p[6]].Lapic.lvt[p[7]] = lo;
  295. p += 8;
  296. break;
  297. }
  298. /*
  299. * There's nothing of interest in the extended table,
  300. * but check it for consistency.
  301. */
  302. p = e;
  303. e = p + l16get(pcmp->xlength);
  304. while(p < e) switch(*p){
  305. default:
  306. n = p[1];
  307. print("mpparse: unknown extended entry %d length %d\n", *p, n);
  308. for(i = 0; i < n; i++){
  309. if(i && ((i & 0x0f) == 0))
  310. print("\n");
  311. print(" %#2.2ux", *p);
  312. p++;
  313. }
  314. print("\n");
  315. break;
  316. case 128:
  317. DBG("address space mapping\n");
  318. DBG(" bus %d type %d base %#llux length %#llux\n",
  319. p[2], p[3], l64get(p+4), l64get(p+12));
  320. p += p[1];
  321. break;
  322. case 129:
  323. DBG("bus hierarchy descriptor\n");
  324. DBG(" bus %d sd %d parent bus %d\n",
  325. p[2], p[3], p[4]);
  326. p += p[1];
  327. break;
  328. case 130:
  329. DBG("compatibility bus address space modifier\n");
  330. DBG(" bus %d pr %d range list %d\n",
  331. p[2], p[3], l32get(p+4));
  332. p += p[1];
  333. break;
  334. }
  335. return maxcores;
  336. }
  337. static int
  338. sigchecksum(void* address, int length)
  339. {
  340. uint8_t *p, sum;
  341. sum = 0;
  342. for(p = address; length-- > 0; p++)
  343. sum += *p;
  344. return sum;
  345. }
  346. void*
  347. sigscan(uint8_t* address, int length, char* signature)
  348. {
  349. uint8_t *e, *p;
  350. int siglength;
  351. e = address+length;
  352. siglength = strlen(signature);
  353. for(p = address; p+siglength < e; p += 16){
  354. if(memcmp(p, signature, siglength))
  355. continue;
  356. return p;
  357. }
  358. return nil;
  359. }
  360. static void*
  361. sigsearch(char* signature)
  362. {
  363. uintptr_t p;
  364. uint8_t *bda;
  365. void *r;
  366. /*
  367. * Search for the data structure:
  368. * 1) in the first KB of the EBDA;
  369. * 2) in the last KB of system base memory;
  370. * 3) in the BIOS ROM between 0xe0000 and 0xfffff.
  371. */
  372. bda = BIOSSEG(0x40);
  373. if(memcmp(KADDR(0xfffd9), "EISA", 4) == 0){
  374. if((p = (bda[0x0f]<<8)|bda[0x0e])){
  375. if((r = sigscan(BIOSSEG(p), 1024, signature)) != nil)
  376. return r;
  377. }
  378. }
  379. p = ((bda[0x14]<<8)|bda[0x13])*1024;
  380. if((r = sigscan(KADDR(p-1024), 1024, signature)) != nil)
  381. return r;
  382. return sigscan(BIOSSEG(0xe000), 0x20000, signature);
  383. }
  384. int
  385. mpsinit(int maxcores)
  386. {
  387. uint8_t *p;
  388. int i, n;
  389. _MP_ *mp;
  390. PCMP *pcmp;
  391. if((mp = sigsearch("_MP_")) == nil)
  392. return maxcores;
  393. if(DBGFLG){
  394. DBG("_MP_ @ %#p, addr %#ux length %ud rev %d",
  395. mp, l32get(mp->addr), mp->length, mp->revision);
  396. for(i = 0; i < sizeof(mp->feature); i++)
  397. DBG(" %2.2#ux", mp->feature[i]);
  398. DBG("\n");
  399. }
  400. if(mp->revision != 1 && mp->revision != 4)
  401. return maxcores;
  402. if(sigchecksum(mp, mp->length*16) != 0)
  403. return maxcores;
  404. if((pcmp = vmap(l32get(mp->addr), sizeof(PCMP))) == nil)
  405. return maxcores;
  406. if(pcmp->revision != 1 && pcmp->revision != 4){
  407. vunmap(pcmp, sizeof(PCMP));
  408. return maxcores;
  409. }
  410. n = l16get(pcmp->length) + l16get(pcmp->xlength);
  411. vunmap(pcmp, sizeof(PCMP));
  412. if((pcmp = vmap(l32get(mp->addr), n)) == nil)
  413. return maxcores;
  414. if(sigchecksum(pcmp, l16get(pcmp->length)) != 0){
  415. vunmap(pcmp, n);
  416. return maxcores;
  417. }
  418. if(DBGFLG){
  419. DBG("PCMP @ %#p length %#ux revision %d\n",
  420. pcmp, l16get(pcmp->length), pcmp->revision);
  421. DBG(" %20.20s oaddr %#ux olength %#ux\n",
  422. (char*)pcmp->string, l32get(pcmp->oaddr),
  423. l16get(pcmp->olength));
  424. DBG(" entry %d apicpa %#ux\n",
  425. l16get(pcmp->entry), l32get(pcmp->apicpa));
  426. DBG(" xlength %#ux xchecksum %#ux\n",
  427. l16get(pcmp->xlength), pcmp->xchecksum);
  428. }
  429. if(pcmp->xchecksum != 0){
  430. p = ((uint8_t*)pcmp) + l16get(pcmp->length);
  431. i = sigchecksum(p, l16get(pcmp->xlength));
  432. if(((i+pcmp->xchecksum) & 0xff) != 0){
  433. print("extended table checksums to %#ux\n", i);
  434. vunmap(pcmp, n);
  435. return maxcores;
  436. }
  437. }
  438. /*
  439. * Parse the PCMP table and set up the datastructures
  440. * for later interrupt enabling and application processor
  441. * startup.
  442. */
  443. maxcores = mpparse(pcmp, maxcores);
  444. apicdump();
  445. ioapicdump();
  446. return maxcores;
  447. }