mp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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->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->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 void
  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. p += 20;
  203. break;
  204. case 1: /* bus */
  205. DBG("mpparse: bus: %d type %6.6s\n", p[1], (char*)p+2);
  206. if(mpbus[p[1]] != nil){
  207. print("mpparse: bus %d already allocated\n", p[1]);
  208. p += 8;
  209. break;
  210. }
  211. for(i = 0; i < nelem(mpbusdef); i++){
  212. if(memcmp(p+2, mpbusdef[i].type, 6) != 0)
  213. continue;
  214. if(memcmp(p+2, "ISA ", 6) == 0){
  215. if(mpisabusno != -1){
  216. print("mpparse: bus %d already have ISA bus %d\n",
  217. p[1], mpisabusno);
  218. continue;
  219. }
  220. mpisabusno = p[1];
  221. }
  222. mpbus[p[1]] = &mpbusdef[i];
  223. break;
  224. }
  225. if(mpbus[p[1]] == nil)
  226. print("mpparse: bus %d type %6.6s unknown\n",
  227. p[1], (char*)p+2);
  228. p += 8;
  229. break;
  230. case 2: /* IOAPIC */
  231. /*
  232. * Initialise the IOAPIC if it is enabled (p[3] & 0x01).
  233. * p[1] is the APIC ID, p[4-7] is the memory mapped address.
  234. */
  235. if(p[3] & 0x01)
  236. ioapicinit(p[1], l32get(p+4));
  237. p += 8;
  238. break;
  239. case 3: /* IOINTR */
  240. /*
  241. * p[1] is the interrupt type;
  242. * p[2-3] contains the polarity and trigger mode;
  243. * p[4] is the source bus;
  244. * p[5] is the IRQ on the source bus;
  245. * p[6] is the destination APIC;
  246. * p[7] is the INITIN pin on the destination APIC.
  247. */
  248. if(p[6] == 0xff){
  249. mpintrprint("routed to all IOAPICs", p);
  250. p += 8;
  251. break;
  252. }
  253. if((lo = mpmkintr(p)) == 0){
  254. p += 8;
  255. break;
  256. }
  257. if(DBGFLG)
  258. mpintrprint(nil, p);
  259. /*
  260. * Always present the device number in the style
  261. * of a PCI Interrupt Assignment Entry. For the ISA
  262. * bus the IRQ is the device number but unencoded.
  263. * May need to handle other buses here in the future
  264. * (but unlikely).
  265. */
  266. devno = p[5];
  267. if(memcmp(mpbus[p[4]]->type, "PCI ", 6) != 0)
  268. devno <<= 2;
  269. ioapicintrinit(p[4], p[6], p[7], devno, lo);
  270. p += 8;
  271. break;
  272. case 4: /* LINTR */
  273. /*
  274. * Format is the same as IOINTR above.
  275. */
  276. if((lo = mpmkintr(p)) == 0){
  277. p += 8;
  278. break;
  279. }
  280. if(DBGFLG)
  281. mpintrprint(nil, p);
  282. /*
  283. * Everything was checked in mpmkintr above.
  284. */
  285. if(p[6] == 0xff){
  286. for(i = 0; i < Napic; i++){
  287. if(!xlapic[i].useable || xlapic[i].addr != nil)
  288. continue;
  289. xlapic[i].lvt[p[7]] = lo;
  290. }
  291. }
  292. else
  293. xlapic[p[6]].lvt[p[7]] = lo;
  294. p += 8;
  295. break;
  296. }
  297. /*
  298. * There's nothing of interest in the extended table,
  299. * but check it for consistency.
  300. */
  301. p = e;
  302. e = p + l16get(pcmp->xlength);
  303. while(p < e) switch(*p){
  304. default:
  305. n = p[1];
  306. print("mpparse: unknown extended entry %d length %d\n", *p, n);
  307. for(i = 0; i < n; i++){
  308. if(i && ((i & 0x0f) == 0))
  309. print("\n");
  310. print(" %#2.2ux", *p);
  311. p++;
  312. }
  313. print("\n");
  314. break;
  315. case 128:
  316. DBG("address space mapping\n");
  317. DBG(" bus %d type %d base %#llux length %#llux\n",
  318. p[2], p[3], l64get(p+4), l64get(p+12));
  319. p += p[1];
  320. break;
  321. case 129:
  322. DBG("bus hierarchy descriptor\n");
  323. DBG(" bus %d sd %d parent bus %d\n",
  324. p[2], p[3], p[4]);
  325. p += p[1];
  326. break;
  327. case 130:
  328. DBG("compatibility bus address space modifier\n");
  329. DBG(" bus %d pr %d range list %d\n",
  330. p[2], p[3], l32get(p+4));
  331. p += p[1];
  332. break;
  333. }
  334. }
  335. static int
  336. sigchecksum(void* address, int length)
  337. {
  338. uint8_t *p, sum;
  339. sum = 0;
  340. for(p = address; length-- > 0; p++)
  341. sum += *p;
  342. return sum;
  343. }
  344. static void*
  345. sigscan(uint8_t* address, int length, char* signature)
  346. {
  347. uint8_t *e, *p;
  348. int siglength;
  349. e = address+length;
  350. siglength = strlen(signature);
  351. for(p = address; p+siglength < e; p += 16){
  352. if(memcmp(p, signature, siglength))
  353. continue;
  354. return p;
  355. }
  356. return nil;
  357. }
  358. static void*
  359. sigsearch(char* signature)
  360. {
  361. uintptr_t p;
  362. uint8_t *bda;
  363. void *r;
  364. /*
  365. * Search for the data structure:
  366. * 1) in the first KB of the EBDA;
  367. * 2) in the last KB of system base memory;
  368. * 3) in the BIOS ROM between 0xe0000 and 0xfffff.
  369. */
  370. bda = BIOSSEG(0x40);
  371. if(memcmp(KADDR(0xfffd9), "EISA", 4) == 0){
  372. if((p = (bda[0x0f]<<8)|bda[0x0e])){
  373. if((r = sigscan(BIOSSEG(p), 1024, signature)) != nil)
  374. return r;
  375. }
  376. }
  377. p = ((bda[0x14]<<8)|bda[0x13])*1024;
  378. if((r = sigscan(KADDR(p-1024), 1024, signature)) != nil)
  379. return r;
  380. return sigscan(BIOSSEG(0xe000), 0x20000, signature);
  381. }
  382. void
  383. mpsinit(int maxcores)
  384. {
  385. uint8_t *p;
  386. int i, n;
  387. _MP_ *mp;
  388. PCMP *pcmp;
  389. if((mp = sigsearch("_MP_")) == nil)
  390. return;
  391. if(DBGFLG){
  392. DBG("_MP_ @ %#p, addr %#ux length %ud rev %d",
  393. mp, l32get(mp->addr), mp->length, mp->revision);
  394. for(i = 0; i < sizeof(mp->feature); i++)
  395. DBG(" %2.2#ux", mp->feature[i]);
  396. DBG("\n");
  397. }
  398. if(mp->revision != 1 && mp->revision != 4)
  399. return;
  400. if(sigchecksum(mp, mp->length*16) != 0)
  401. return;
  402. if((pcmp = vmap(l32get(mp->addr), sizeof(PCMP))) == nil)
  403. return;
  404. if(pcmp->revision != 1 && pcmp->revision != 4){
  405. vunmap(pcmp, sizeof(PCMP));
  406. return;
  407. }
  408. n = l16get(pcmp->length) + l16get(pcmp->xlength);
  409. vunmap(pcmp, sizeof(PCMP));
  410. if((pcmp = vmap(l32get(mp->addr), n)) == nil)
  411. return;
  412. if(sigchecksum(pcmp, l16get(pcmp->length)) != 0){
  413. vunmap(pcmp, n);
  414. return;
  415. }
  416. if(DBGFLG){
  417. DBG("PCMP @ %#p length %#ux revision %d\n",
  418. pcmp, l16get(pcmp->length), pcmp->revision);
  419. DBG(" %20.20s oaddr %#ux olength %#ux\n",
  420. (char*)pcmp->string, l32get(pcmp->oaddr),
  421. l16get(pcmp->olength));
  422. DBG(" entry %d apicpa %#ux\n",
  423. l16get(pcmp->entry), l32get(pcmp->apicpa));
  424. DBG(" xlength %#ux xchecksum %#ux\n",
  425. l16get(pcmp->xlength), pcmp->xchecksum);
  426. }
  427. if(pcmp->xchecksum != 0){
  428. p = ((uint8_t*)pcmp) + l16get(pcmp->length);
  429. i = sigchecksum(p, l16get(pcmp->xlength));
  430. if(((i+pcmp->xchecksum) & 0xff) != 0){
  431. print("extended table checksums to %#ux\n", i);
  432. vunmap(pcmp, n);
  433. return;
  434. }
  435. }
  436. /*
  437. * Parse the PCMP table and set up the datastructures
  438. * for later interrupt enabling and application processor
  439. * startup.
  440. */
  441. mpparse(pcmp, maxcores);
  442. apicdump();
  443. ioapicdump();
  444. }