PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/sys/x86/x86/mptable.c

https://bitbucket.org/freebsd/freebsd-head/
C | 1226 lines | 954 code | 105 blank | 167 comment | 179 complexity | 302426293c0f92fc61ff348b41ee6ef2 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /*-
  2. * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
  3. * Copyright (c) 1996, by Steve Passe
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. The name of the developer may NOT be used to endorse or promote products
  12. * derived from this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. */
  26. #include <sys/cdefs.h>
  27. __FBSDID("$FreeBSD$");
  28. #include "opt_mptable_force_htt.h"
  29. #include <sys/param.h>
  30. #include <sys/systm.h>
  31. #include <sys/bus.h>
  32. #include <sys/kernel.h>
  33. #include <sys/limits.h>
  34. #include <sys/malloc.h>
  35. #ifdef NEW_PCIB
  36. #include <sys/rman.h>
  37. #endif
  38. #include <vm/vm.h>
  39. #include <vm/vm_param.h>
  40. #include <vm/pmap.h>
  41. #include <dev/pci/pcivar.h>
  42. #ifdef NEW_PCIB
  43. #include <dev/pci/pcib_private.h>
  44. #endif
  45. #include <x86/apicreg.h>
  46. #include <x86/mptable.h>
  47. #include <machine/frame.h>
  48. #include <machine/intr_machdep.h>
  49. #include <machine/apicvar.h>
  50. #include <machine/md_var.h>
  51. #ifdef NEW_PCIB
  52. #include <machine/resource.h>
  53. #endif
  54. #include <machine/specialreg.h>
  55. /* string defined by the Intel MP Spec as identifying the MP table */
  56. #define MP_SIG 0x5f504d5f /* _MP_ */
  57. #ifdef __amd64__
  58. #define MAX_LAPIC_ID 63 /* Max local APIC ID for HTT fixup */
  59. #else
  60. #define MAX_LAPIC_ID 31 /* Max local APIC ID for HTT fixup */
  61. #endif
  62. #ifdef PC98
  63. #define BIOS_BASE (0xe8000)
  64. #define BIOS_SIZE (0x18000)
  65. #else
  66. #define BIOS_BASE (0xf0000)
  67. #define BIOS_SIZE (0x10000)
  68. #endif
  69. #define BIOS_COUNT (BIOS_SIZE/4)
  70. typedef void mptable_entry_handler(u_char *entry, void *arg);
  71. typedef void mptable_extended_entry_handler(ext_entry_ptr entry, void *arg);
  72. static basetable_entry basetable_entry_types[] =
  73. {
  74. {0, 20, "Processor"},
  75. {1, 8, "Bus"},
  76. {2, 8, "I/O APIC"},
  77. {3, 8, "I/O INT"},
  78. {4, 8, "Local INT"}
  79. };
  80. typedef struct BUSDATA {
  81. u_char bus_id;
  82. enum busTypes bus_type;
  83. } bus_datum;
  84. typedef struct INTDATA {
  85. u_char int_type;
  86. u_short int_flags;
  87. u_char src_bus_id;
  88. u_char src_bus_irq;
  89. u_char dst_apic_id;
  90. u_char dst_apic_int;
  91. u_char int_vector;
  92. } io_int, local_int;
  93. typedef struct BUSTYPENAME {
  94. u_char type;
  95. char name[7];
  96. } bus_type_name;
  97. /* From MP spec v1.4, table 4-8. */
  98. static bus_type_name bus_type_table[] =
  99. {
  100. {UNKNOWN_BUSTYPE, "CBUS "},
  101. {UNKNOWN_BUSTYPE, "CBUSII"},
  102. {EISA, "EISA "},
  103. {UNKNOWN_BUSTYPE, "FUTURE"},
  104. {UNKNOWN_BUSTYPE, "INTERN"},
  105. {ISA, "ISA "},
  106. {UNKNOWN_BUSTYPE, "MBI "},
  107. {UNKNOWN_BUSTYPE, "MBII "},
  108. {MCA, "MCA "},
  109. {UNKNOWN_BUSTYPE, "MPI "},
  110. {UNKNOWN_BUSTYPE, "MPSA "},
  111. {UNKNOWN_BUSTYPE, "NUBUS "},
  112. {PCI, "PCI "},
  113. {UNKNOWN_BUSTYPE, "PCMCIA"},
  114. {UNKNOWN_BUSTYPE, "TC "},
  115. {UNKNOWN_BUSTYPE, "VL "},
  116. {UNKNOWN_BUSTYPE, "VME "},
  117. {UNKNOWN_BUSTYPE, "XPRESS"}
  118. };
  119. /* From MP spec v1.4, table 5-1. */
  120. static int default_data[7][5] =
  121. {
  122. /* nbus, id0, type0, id1, type1 */
  123. {1, 0, ISA, 255, NOBUS},
  124. {1, 0, EISA, 255, NOBUS},
  125. {1, 0, EISA, 255, NOBUS},
  126. {1, 0, MCA, 255, NOBUS},
  127. {2, 0, ISA, 1, PCI},
  128. {2, 0, EISA, 1, PCI},
  129. {2, 0, MCA, 1, PCI}
  130. };
  131. struct pci_probe_table_args {
  132. u_char bus;
  133. u_char found;
  134. };
  135. struct pci_route_interrupt_args {
  136. u_char bus; /* Source bus. */
  137. u_char irq; /* Source slot:pin. */
  138. int vector; /* Return value. */
  139. };
  140. static mpfps_t mpfps;
  141. static mpcth_t mpct;
  142. static ext_entry_ptr mpet;
  143. static void *ioapics[MAX_APIC_ID + 1];
  144. static bus_datum *busses;
  145. static int mptable_nioapics, mptable_nbusses, mptable_maxbusid;
  146. static int pci0 = -1;
  147. static MALLOC_DEFINE(M_MPTABLE, "mptable", "MP Table Items");
  148. static enum intr_polarity conforming_polarity(u_char src_bus,
  149. u_char src_bus_irq);
  150. static enum intr_trigger conforming_trigger(u_char src_bus, u_char src_bus_irq);
  151. static enum intr_polarity intentry_polarity(int_entry_ptr intr);
  152. static enum intr_trigger intentry_trigger(int_entry_ptr intr);
  153. static int lookup_bus_type(char *name);
  154. static void mptable_count_items(void);
  155. static void mptable_count_items_handler(u_char *entry, void *arg);
  156. #ifdef MPTABLE_FORCE_HTT
  157. static void mptable_hyperthread_fixup(u_int id_mask);
  158. #endif
  159. static void mptable_parse_apics_and_busses(void);
  160. static void mptable_parse_apics_and_busses_handler(u_char *entry,
  161. void *arg);
  162. static void mptable_parse_default_config_ints(void);
  163. static void mptable_parse_ints(void);
  164. static void mptable_parse_ints_handler(u_char *entry, void *arg);
  165. static void mptable_parse_io_int(int_entry_ptr intr);
  166. static void mptable_parse_local_int(int_entry_ptr intr);
  167. static void mptable_pci_probe_table_handler(u_char *entry, void *arg);
  168. static void mptable_pci_route_interrupt_handler(u_char *entry, void *arg);
  169. static void mptable_pci_setup(void);
  170. static int mptable_probe(void);
  171. static int mptable_probe_cpus(void);
  172. static void mptable_probe_cpus_handler(u_char *entry, void *arg __unused);
  173. static void mptable_register(void *dummy);
  174. static int mptable_setup_local(void);
  175. static int mptable_setup_io(void);
  176. #ifdef NEW_PCIB
  177. static void mptable_walk_extended_table(
  178. mptable_extended_entry_handler *handler, void *arg);
  179. #endif
  180. static void mptable_walk_table(mptable_entry_handler *handler, void *arg);
  181. static int search_for_sig(u_int32_t target, int count);
  182. static struct apic_enumerator mptable_enumerator = {
  183. "MPTable",
  184. mptable_probe,
  185. mptable_probe_cpus,
  186. mptable_setup_local,
  187. mptable_setup_io
  188. };
  189. /*
  190. * look for the MP spec signature
  191. */
  192. static int
  193. search_for_sig(u_int32_t target, int count)
  194. {
  195. int x;
  196. u_int32_t *addr = (u_int32_t *) (KERNBASE + target);
  197. for (x = 0; x < count; x += 4)
  198. if (addr[x] == MP_SIG)
  199. /* make array index a byte index */
  200. return (target + (x * sizeof(u_int32_t)));
  201. return (-1);
  202. }
  203. static int
  204. lookup_bus_type(char *name)
  205. {
  206. int x;
  207. for (x = 0; x < MAX_BUSTYPE; ++x)
  208. if (strncmp(bus_type_table[x].name, name, 6) == 0)
  209. return (bus_type_table[x].type);
  210. return (UNKNOWN_BUSTYPE);
  211. }
  212. /*
  213. * Look for an Intel MP spec table (ie, SMP capable hardware).
  214. */
  215. static int
  216. mptable_probe(void)
  217. {
  218. int x;
  219. u_long segment;
  220. u_int32_t target;
  221. /* see if EBDA exists */
  222. if ((segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) != 0) {
  223. /* search first 1K of EBDA */
  224. target = (u_int32_t) (segment << 4);
  225. if ((x = search_for_sig(target, 1024 / 4)) >= 0)
  226. goto found;
  227. } else {
  228. /* last 1K of base memory, effective 'top of base' passed in */
  229. target = (u_int32_t) ((basemem * 1024) - 0x400);
  230. if ((x = search_for_sig(target, 1024 / 4)) >= 0)
  231. goto found;
  232. }
  233. /* search the BIOS */
  234. target = (u_int32_t) BIOS_BASE;
  235. if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
  236. goto found;
  237. /* nothing found */
  238. return (ENXIO);
  239. found:
  240. mpfps = (mpfps_t)(KERNBASE + x);
  241. /* Map in the configuration table if it exists. */
  242. if (mpfps->config_type != 0) {
  243. if (bootverbose)
  244. printf(
  245. "MP Table version 1.%d found using Default Configuration %d\n",
  246. mpfps->spec_rev, mpfps->config_type);
  247. if (mpfps->config_type != 5 && mpfps->config_type != 6) {
  248. printf(
  249. "MP Table Default Configuration %d is unsupported\n",
  250. mpfps->config_type);
  251. return (ENXIO);
  252. }
  253. mpct = NULL;
  254. } else {
  255. if ((uintptr_t)mpfps->pap >= 1024 * 1024) {
  256. printf("%s: Unable to map MP Configuration Table\n",
  257. __func__);
  258. return (ENXIO);
  259. }
  260. mpct = (mpcth_t)(KERNBASE + (uintptr_t)mpfps->pap);
  261. if (mpct->base_table_length + (uintptr_t)mpfps->pap >=
  262. 1024 * 1024) {
  263. printf("%s: Unable to map end of MP Config Table\n",
  264. __func__);
  265. return (ENXIO);
  266. }
  267. if (mpct->extended_table_length != 0 &&
  268. mpct->extended_table_length + mpct->base_table_length +
  269. (uintptr_t)mpfps->pap < 1024 * 1024)
  270. mpet = (ext_entry_ptr)((char *)mpct +
  271. mpct->base_table_length);
  272. if (mpct->signature[0] != 'P' || mpct->signature[1] != 'C' ||
  273. mpct->signature[2] != 'M' || mpct->signature[3] != 'P') {
  274. printf("%s: MP Config Table has bad signature: %c%c%c%c\n",
  275. __func__, mpct->signature[0], mpct->signature[1],
  276. mpct->signature[2], mpct->signature[3]);
  277. return (ENXIO);
  278. }
  279. if (bootverbose)
  280. printf(
  281. "MP Configuration Table version 1.%d found at %p\n",
  282. mpct->spec_rev, mpct);
  283. }
  284. return (-100);
  285. }
  286. /*
  287. * Run through the MP table enumerating CPUs.
  288. */
  289. static int
  290. mptable_probe_cpus(void)
  291. {
  292. u_int cpu_mask;
  293. /* Is this a pre-defined config? */
  294. if (mpfps->config_type != 0) {
  295. lapic_create(0, 1);
  296. lapic_create(1, 0);
  297. } else {
  298. cpu_mask = 0;
  299. mptable_walk_table(mptable_probe_cpus_handler, &cpu_mask);
  300. #ifdef MPTABLE_FORCE_HTT
  301. mptable_hyperthread_fixup(cpu_mask);
  302. #endif
  303. }
  304. return (0);
  305. }
  306. /*
  307. * Initialize the local APIC on the BSP.
  308. */
  309. static int
  310. mptable_setup_local(void)
  311. {
  312. vm_paddr_t addr;
  313. /* Is this a pre-defined config? */
  314. printf("MPTable: <");
  315. if (mpfps->config_type != 0) {
  316. addr = DEFAULT_APIC_BASE;
  317. printf("Default Configuration %d", mpfps->config_type);
  318. } else {
  319. addr = mpct->apic_address;
  320. printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id,
  321. (int)sizeof(mpct->product_id), mpct->product_id);
  322. }
  323. printf(">\n");
  324. lapic_init(addr);
  325. return (0);
  326. }
  327. /*
  328. * Run through the MP table enumerating I/O APICs.
  329. */
  330. static int
  331. mptable_setup_io(void)
  332. {
  333. int i;
  334. u_char byte;
  335. /* First, we count individual items and allocate arrays. */
  336. mptable_count_items();
  337. busses = malloc((mptable_maxbusid + 1) * sizeof(bus_datum), M_MPTABLE,
  338. M_WAITOK);
  339. for (i = 0; i <= mptable_maxbusid; i++)
  340. busses[i].bus_type = NOBUS;
  341. /* Second, we run through adding I/O APIC's and busses. */
  342. mptable_parse_apics_and_busses();
  343. /* Third, we run through the table tweaking interrupt sources. */
  344. mptable_parse_ints();
  345. /* Fourth, we register all the I/O APIC's. */
  346. for (i = 0; i <= MAX_APIC_ID; i++)
  347. if (ioapics[i] != NULL)
  348. ioapic_register(ioapics[i]);
  349. /* Fifth, we setup data structures to handle PCI interrupt routing. */
  350. mptable_pci_setup();
  351. /* Finally, we throw the switch to enable the I/O APIC's. */
  352. if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) {
  353. outb(0x22, 0x70); /* select IMCR */
  354. byte = inb(0x23); /* current contents */
  355. byte |= 0x01; /* mask external INTR */
  356. outb(0x23, byte); /* disconnect 8259s/NMI */
  357. }
  358. return (0);
  359. }
  360. static void
  361. mptable_register(void *dummy __unused)
  362. {
  363. apic_register_enumerator(&mptable_enumerator);
  364. }
  365. SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, mptable_register,
  366. NULL);
  367. /*
  368. * Call the handler routine for each entry in the MP config base table.
  369. */
  370. static void
  371. mptable_walk_table(mptable_entry_handler *handler, void *arg)
  372. {
  373. u_int i;
  374. u_char *entry;
  375. entry = (u_char *)(mpct + 1);
  376. for (i = 0; i < mpct->entry_count; i++) {
  377. switch (*entry) {
  378. case MPCT_ENTRY_PROCESSOR:
  379. case MPCT_ENTRY_IOAPIC:
  380. case MPCT_ENTRY_BUS:
  381. case MPCT_ENTRY_INT:
  382. case MPCT_ENTRY_LOCAL_INT:
  383. break;
  384. default:
  385. panic("%s: Unknown MP Config Entry %d\n", __func__,
  386. (int)*entry);
  387. }
  388. handler(entry, arg);
  389. entry += basetable_entry_types[*entry].length;
  390. }
  391. }
  392. #ifdef NEW_PCIB
  393. /*
  394. * Call the handler routine for each entry in the MP config extended
  395. * table.
  396. */
  397. static void
  398. mptable_walk_extended_table(mptable_extended_entry_handler *handler, void *arg)
  399. {
  400. ext_entry_ptr end, entry;
  401. if (mpet == NULL)
  402. return;
  403. entry = mpet;
  404. end = (ext_entry_ptr)((char *)mpet + mpct->extended_table_length);
  405. while (entry < end) {
  406. handler(entry, arg);
  407. entry = (ext_entry_ptr)((char *)entry + entry->length);
  408. }
  409. }
  410. #endif
  411. static void
  412. mptable_probe_cpus_handler(u_char *entry, void *arg)
  413. {
  414. proc_entry_ptr proc;
  415. u_int *cpu_mask;
  416. switch (*entry) {
  417. case MPCT_ENTRY_PROCESSOR:
  418. proc = (proc_entry_ptr)entry;
  419. if (proc->cpu_flags & PROCENTRY_FLAG_EN) {
  420. lapic_create(proc->apic_id, proc->cpu_flags &
  421. PROCENTRY_FLAG_BP);
  422. if (proc->apic_id < MAX_LAPIC_ID) {
  423. cpu_mask = (u_int *)arg;
  424. *cpu_mask |= (1ul << proc->apic_id);
  425. }
  426. }
  427. break;
  428. }
  429. }
  430. static void
  431. mptable_count_items_handler(u_char *entry, void *arg __unused)
  432. {
  433. io_apic_entry_ptr apic;
  434. bus_entry_ptr bus;
  435. switch (*entry) {
  436. case MPCT_ENTRY_BUS:
  437. bus = (bus_entry_ptr)entry;
  438. mptable_nbusses++;
  439. if (bus->bus_id > mptable_maxbusid)
  440. mptable_maxbusid = bus->bus_id;
  441. break;
  442. case MPCT_ENTRY_IOAPIC:
  443. apic = (io_apic_entry_ptr)entry;
  444. if (apic->apic_flags & IOAPICENTRY_FLAG_EN)
  445. mptable_nioapics++;
  446. break;
  447. }
  448. }
  449. /*
  450. * Count items in the table.
  451. */
  452. static void
  453. mptable_count_items(void)
  454. {
  455. /* Is this a pre-defined config? */
  456. if (mpfps->config_type != 0) {
  457. mptable_nioapics = 1;
  458. switch (mpfps->config_type) {
  459. case 1:
  460. case 2:
  461. case 3:
  462. case 4:
  463. mptable_nbusses = 1;
  464. break;
  465. case 5:
  466. case 6:
  467. case 7:
  468. mptable_nbusses = 2;
  469. break;
  470. default:
  471. panic("Unknown pre-defined MP Table config type %d",
  472. mpfps->config_type);
  473. }
  474. mptable_maxbusid = mptable_nbusses - 1;
  475. } else
  476. mptable_walk_table(mptable_count_items_handler, NULL);
  477. }
  478. /*
  479. * Add a bus or I/O APIC from an entry in the table.
  480. */
  481. static void
  482. mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused)
  483. {
  484. io_apic_entry_ptr apic;
  485. bus_entry_ptr bus;
  486. enum busTypes bus_type;
  487. int i;
  488. switch (*entry) {
  489. case MPCT_ENTRY_BUS:
  490. bus = (bus_entry_ptr)entry;
  491. bus_type = lookup_bus_type(bus->bus_type);
  492. if (bus_type == UNKNOWN_BUSTYPE) {
  493. printf("MPTable: Unknown bus %d type \"", bus->bus_id);
  494. for (i = 0; i < 6; i++)
  495. printf("%c", bus->bus_type[i]);
  496. printf("\"\n");
  497. }
  498. busses[bus->bus_id].bus_id = bus->bus_id;
  499. busses[bus->bus_id].bus_type = bus_type;
  500. break;
  501. case MPCT_ENTRY_IOAPIC:
  502. apic = (io_apic_entry_ptr)entry;
  503. if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN))
  504. break;
  505. if (apic->apic_id > MAX_APIC_ID)
  506. panic("%s: I/O APIC ID %d too high", __func__,
  507. apic->apic_id);
  508. if (ioapics[apic->apic_id] != NULL)
  509. panic("%s: Double APIC ID %d", __func__,
  510. apic->apic_id);
  511. ioapics[apic->apic_id] = ioapic_create(apic->apic_address,
  512. apic->apic_id, -1);
  513. break;
  514. default:
  515. break;
  516. }
  517. }
  518. /*
  519. * Enumerate I/O APIC's and busses.
  520. */
  521. static void
  522. mptable_parse_apics_and_busses(void)
  523. {
  524. /* Is this a pre-defined config? */
  525. if (mpfps->config_type != 0) {
  526. ioapics[2] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0);
  527. busses[0].bus_id = 0;
  528. busses[0].bus_type = default_data[mpfps->config_type - 1][2];
  529. if (mptable_nbusses > 1) {
  530. busses[1].bus_id = 1;
  531. busses[1].bus_type =
  532. default_data[mpfps->config_type - 1][4];
  533. }
  534. } else
  535. mptable_walk_table(mptable_parse_apics_and_busses_handler,
  536. NULL);
  537. }
  538. /*
  539. * Determine conforming polarity for a given bus type.
  540. */
  541. static enum intr_polarity
  542. conforming_polarity(u_char src_bus, u_char src_bus_irq)
  543. {
  544. KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
  545. switch (busses[src_bus].bus_type) {
  546. case ISA:
  547. case EISA:
  548. return (INTR_POLARITY_HIGH);
  549. case PCI:
  550. return (INTR_POLARITY_LOW);
  551. default:
  552. panic("%s: unknown bus type %d", __func__,
  553. busses[src_bus].bus_type);
  554. }
  555. }
  556. /*
  557. * Determine conforming trigger for a given bus type.
  558. */
  559. static enum intr_trigger
  560. conforming_trigger(u_char src_bus, u_char src_bus_irq)
  561. {
  562. KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
  563. switch (busses[src_bus].bus_type) {
  564. case ISA:
  565. #ifndef PC98
  566. if (elcr_found)
  567. return (elcr_read_trigger(src_bus_irq));
  568. else
  569. #endif
  570. return (INTR_TRIGGER_EDGE);
  571. case PCI:
  572. return (INTR_TRIGGER_LEVEL);
  573. #ifndef PC98
  574. case EISA:
  575. KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq));
  576. KASSERT(elcr_found, ("Missing ELCR"));
  577. return (elcr_read_trigger(src_bus_irq));
  578. #endif
  579. default:
  580. panic("%s: unknown bus type %d", __func__,
  581. busses[src_bus].bus_type);
  582. }
  583. }
  584. static enum intr_polarity
  585. intentry_polarity(int_entry_ptr intr)
  586. {
  587. switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) {
  588. case INTENTRY_FLAGS_POLARITY_CONFORM:
  589. return (conforming_polarity(intr->src_bus_id,
  590. intr->src_bus_irq));
  591. case INTENTRY_FLAGS_POLARITY_ACTIVEHI:
  592. return (INTR_POLARITY_HIGH);
  593. case INTENTRY_FLAGS_POLARITY_ACTIVELO:
  594. return (INTR_POLARITY_LOW);
  595. default:
  596. panic("Bogus interrupt flags");
  597. }
  598. }
  599. static enum intr_trigger
  600. intentry_trigger(int_entry_ptr intr)
  601. {
  602. switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) {
  603. case INTENTRY_FLAGS_TRIGGER_CONFORM:
  604. return (conforming_trigger(intr->src_bus_id,
  605. intr->src_bus_irq));
  606. case INTENTRY_FLAGS_TRIGGER_EDGE:
  607. return (INTR_TRIGGER_EDGE);
  608. case INTENTRY_FLAGS_TRIGGER_LEVEL:
  609. return (INTR_TRIGGER_LEVEL);
  610. default:
  611. panic("Bogus interrupt flags");
  612. }
  613. }
  614. /*
  615. * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC.
  616. */
  617. static void
  618. mptable_parse_io_int(int_entry_ptr intr)
  619. {
  620. void *ioapic;
  621. u_int pin, apic_id;
  622. apic_id = intr->dst_apic_id;
  623. if (intr->dst_apic_id == 0xff) {
  624. /*
  625. * An APIC ID of 0xff means that the interrupt is connected
  626. * to the specified pin on all I/O APICs in the system. If
  627. * there is only one I/O APIC, then use that APIC to route
  628. * the interrupts. If there is more than one I/O APIC, then
  629. * punt.
  630. */
  631. if (mptable_nioapics == 1) {
  632. apic_id = 0;
  633. while (ioapics[apic_id] == NULL)
  634. apic_id++;
  635. } else {
  636. printf(
  637. "MPTable: Ignoring global interrupt entry for pin %d\n",
  638. intr->dst_apic_int);
  639. return;
  640. }
  641. }
  642. if (apic_id > MAX_APIC_ID) {
  643. printf("MPTable: Ignoring interrupt entry for ioapic%d\n",
  644. intr->dst_apic_id);
  645. return;
  646. }
  647. ioapic = ioapics[apic_id];
  648. if (ioapic == NULL) {
  649. printf(
  650. "MPTable: Ignoring interrupt entry for missing ioapic%d\n",
  651. apic_id);
  652. return;
  653. }
  654. pin = intr->dst_apic_int;
  655. switch (intr->int_type) {
  656. case INTENTRY_TYPE_INT:
  657. switch (busses[intr->src_bus_id].bus_type) {
  658. case NOBUS:
  659. panic("interrupt from missing bus");
  660. case ISA:
  661. case EISA:
  662. if (busses[intr->src_bus_id].bus_type == ISA)
  663. ioapic_set_bus(ioapic, pin, APIC_BUS_ISA);
  664. else
  665. ioapic_set_bus(ioapic, pin, APIC_BUS_EISA);
  666. if (intr->src_bus_irq == pin)
  667. break;
  668. ioapic_remap_vector(ioapic, pin, intr->src_bus_irq);
  669. if (ioapic_get_vector(ioapic, intr->src_bus_irq) ==
  670. intr->src_bus_irq)
  671. ioapic_disable_pin(ioapic, intr->src_bus_irq);
  672. break;
  673. case PCI:
  674. ioapic_set_bus(ioapic, pin, APIC_BUS_PCI);
  675. break;
  676. default:
  677. ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN);
  678. break;
  679. }
  680. break;
  681. case INTENTRY_TYPE_NMI:
  682. ioapic_set_nmi(ioapic, pin);
  683. break;
  684. case INTENTRY_TYPE_SMI:
  685. ioapic_set_smi(ioapic, pin);
  686. break;
  687. case INTENTRY_TYPE_EXTINT:
  688. ioapic_set_extint(ioapic, pin);
  689. break;
  690. default:
  691. panic("%s: invalid interrupt entry type %d\n", __func__,
  692. intr->int_type);
  693. }
  694. if (intr->int_type == INTENTRY_TYPE_INT ||
  695. (intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
  696. INTENTRY_FLAGS_TRIGGER_CONFORM)
  697. ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr));
  698. if (intr->int_type == INTENTRY_TYPE_INT ||
  699. (intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
  700. INTENTRY_FLAGS_POLARITY_CONFORM)
  701. ioapic_set_polarity(ioapic, pin, intentry_polarity(intr));
  702. }
  703. /*
  704. * Parse an interrupt entry for a local APIC LVT pin.
  705. */
  706. static void
  707. mptable_parse_local_int(int_entry_ptr intr)
  708. {
  709. u_int apic_id, pin;
  710. if (intr->dst_apic_id == 0xff)
  711. apic_id = APIC_ID_ALL;
  712. else
  713. apic_id = intr->dst_apic_id;
  714. if (intr->dst_apic_int == 0)
  715. pin = LVT_LINT0;
  716. else
  717. pin = LVT_LINT1;
  718. switch (intr->int_type) {
  719. case INTENTRY_TYPE_INT:
  720. #if 1
  721. printf(
  722. "MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n",
  723. intr->dst_apic_int, intr->src_bus_irq);
  724. return;
  725. #else
  726. lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED);
  727. break;
  728. #endif
  729. case INTENTRY_TYPE_NMI:
  730. lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
  731. break;
  732. case INTENTRY_TYPE_SMI:
  733. lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI);
  734. break;
  735. case INTENTRY_TYPE_EXTINT:
  736. lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT);
  737. break;
  738. default:
  739. panic("%s: invalid interrupt entry type %d\n", __func__,
  740. intr->int_type);
  741. }
  742. if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
  743. INTENTRY_FLAGS_TRIGGER_CONFORM)
  744. lapic_set_lvt_triggermode(apic_id, pin,
  745. intentry_trigger(intr));
  746. if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
  747. INTENTRY_FLAGS_POLARITY_CONFORM)
  748. lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr));
  749. }
  750. /*
  751. * Parse interrupt entries.
  752. */
  753. static void
  754. mptable_parse_ints_handler(u_char *entry, void *arg __unused)
  755. {
  756. int_entry_ptr intr;
  757. intr = (int_entry_ptr)entry;
  758. switch (*entry) {
  759. case MPCT_ENTRY_INT:
  760. mptable_parse_io_int(intr);
  761. break;
  762. case MPCT_ENTRY_LOCAL_INT:
  763. mptable_parse_local_int(intr);
  764. break;
  765. }
  766. }
  767. /*
  768. * Configure interrupt pins for a default configuration. For details see
  769. * Table 5-2 in Section 5 of the MP Table specification.
  770. */
  771. static void
  772. mptable_parse_default_config_ints(void)
  773. {
  774. struct INTENTRY entry;
  775. int pin;
  776. /*
  777. * All default configs route IRQs from bus 0 to the first 16 pins
  778. * of the first I/O APIC with an APIC ID of 2.
  779. */
  780. entry.type = MPCT_ENTRY_INT;
  781. entry.int_flags = INTENTRY_FLAGS_POLARITY_CONFORM |
  782. INTENTRY_FLAGS_TRIGGER_CONFORM;
  783. entry.src_bus_id = 0;
  784. entry.dst_apic_id = 2;
  785. /* Run through all 16 pins. */
  786. for (pin = 0; pin < 16; pin++) {
  787. entry.dst_apic_int = pin;
  788. switch (pin) {
  789. case 0:
  790. /* Pin 0 is an ExtINT pin. */
  791. entry.int_type = INTENTRY_TYPE_EXTINT;
  792. break;
  793. case 2:
  794. /* IRQ 0 is routed to pin 2. */
  795. entry.int_type = INTENTRY_TYPE_INT;
  796. entry.src_bus_irq = 0;
  797. break;
  798. default:
  799. /* All other pins are identity mapped. */
  800. entry.int_type = INTENTRY_TYPE_INT;
  801. entry.src_bus_irq = pin;
  802. break;
  803. }
  804. mptable_parse_io_int(&entry);
  805. }
  806. /* Certain configs disable certain pins. */
  807. if (mpfps->config_type == 7)
  808. ioapic_disable_pin(ioapics[2], 0);
  809. if (mpfps->config_type == 2) {
  810. ioapic_disable_pin(ioapics[2], 2);
  811. ioapic_disable_pin(ioapics[2], 13);
  812. }
  813. }
  814. /*
  815. * Configure the interrupt pins
  816. */
  817. static void
  818. mptable_parse_ints(void)
  819. {
  820. /* Is this a pre-defined config? */
  821. if (mpfps->config_type != 0) {
  822. /* Configure LINT pins. */
  823. lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT0, APIC_LVT_DM_EXTINT);
  824. lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI);
  825. /* Configure I/O APIC pins. */
  826. mptable_parse_default_config_ints();
  827. } else
  828. mptable_walk_table(mptable_parse_ints_handler, NULL);
  829. }
  830. #ifdef MPTABLE_FORCE_HTT
  831. /*
  832. * Perform a hyperthreading "fix-up" to enumerate any logical CPU's
  833. * that aren't already listed in the table.
  834. *
  835. * XXX: We assume that all of the physical CPUs in the
  836. * system have the same number of logical CPUs.
  837. *
  838. * XXX: We assume that APIC ID's are allocated such that
  839. * the APIC ID's for a physical processor are aligned
  840. * with the number of logical CPU's in the processor.
  841. */
  842. static void
  843. mptable_hyperthread_fixup(u_int id_mask)
  844. {
  845. u_int i, id, logical_cpus;
  846. /* Nothing to do if there is no HTT support. */
  847. if ((cpu_feature & CPUID_HTT) == 0)
  848. return;
  849. logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
  850. if (logical_cpus <= 1)
  851. return;
  852. /*
  853. * For each APIC ID of a CPU that is set in the mask,
  854. * scan the other candidate APIC ID's for this
  855. * physical processor. If any of those ID's are
  856. * already in the table, then kill the fixup.
  857. */
  858. for (id = 0; id <= MAX_LAPIC_ID; id++) {
  859. if ((id_mask & 1 << id) == 0)
  860. continue;
  861. /* First, make sure we are on a logical_cpus boundary. */
  862. if (id % logical_cpus != 0)
  863. return;
  864. for (i = id + 1; i < id + logical_cpus; i++)
  865. if ((id_mask & 1 << i) != 0)
  866. return;
  867. }
  868. /*
  869. * Ok, the ID's checked out, so perform the fixup by
  870. * adding the logical CPUs.
  871. */
  872. while ((id = ffs(id_mask)) != 0) {
  873. id--;
  874. for (i = id + 1; i < id + logical_cpus; i++) {
  875. if (bootverbose)
  876. printf(
  877. "MPTable: Adding logical CPU %d from main CPU %d\n",
  878. i, id);
  879. lapic_create(i, 0);
  880. }
  881. id_mask &= ~(1 << id);
  882. }
  883. }
  884. #endif /* MPTABLE_FORCE_HTT */
  885. /*
  886. * Support code for routing PCI interrupts using the MP Table.
  887. */
  888. static void
  889. mptable_pci_setup(void)
  890. {
  891. int i;
  892. /*
  893. * Find the first pci bus and call it 0. Panic if pci0 is not
  894. * bus zero and there are multiple PCI busses.
  895. */
  896. for (i = 0; i <= mptable_maxbusid; i++)
  897. if (busses[i].bus_type == PCI) {
  898. if (pci0 == -1)
  899. pci0 = i;
  900. else if (pci0 != 0)
  901. panic(
  902. "MPTable contains multiple PCI busses but no PCI bus 0");
  903. }
  904. }
  905. static void
  906. mptable_pci_probe_table_handler(u_char *entry, void *arg)
  907. {
  908. struct pci_probe_table_args *args;
  909. int_entry_ptr intr;
  910. if (*entry != MPCT_ENTRY_INT)
  911. return;
  912. intr = (int_entry_ptr)entry;
  913. args = (struct pci_probe_table_args *)arg;
  914. KASSERT(args->bus <= mptable_maxbusid,
  915. ("bus %d is too big", args->bus));
  916. KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus"));
  917. if (intr->src_bus_id == args->bus)
  918. args->found = 1;
  919. }
  920. int
  921. mptable_pci_probe_table(int bus)
  922. {
  923. struct pci_probe_table_args args;
  924. if (bus < 0)
  925. return (EINVAL);
  926. if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid)
  927. return (ENXIO);
  928. if (busses[pci0 + bus].bus_type != PCI)
  929. return (ENXIO);
  930. args.bus = pci0 + bus;
  931. args.found = 0;
  932. mptable_walk_table(mptable_pci_probe_table_handler, &args);
  933. if (args.found == 0)
  934. return (ENXIO);
  935. return (0);
  936. }
  937. static void
  938. mptable_pci_route_interrupt_handler(u_char *entry, void *arg)
  939. {
  940. struct pci_route_interrupt_args *args;
  941. int_entry_ptr intr;
  942. int vector;
  943. if (*entry != MPCT_ENTRY_INT)
  944. return;
  945. intr = (int_entry_ptr)entry;
  946. args = (struct pci_route_interrupt_args *)arg;
  947. if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq)
  948. return;
  949. /* Make sure the APIC maps to a known APIC. */
  950. KASSERT(ioapics[intr->dst_apic_id] != NULL,
  951. ("No I/O APIC %d to route interrupt to", intr->dst_apic_id));
  952. /*
  953. * Look up the vector for this APIC / pin combination. If we
  954. * have previously matched an entry for this PCI IRQ but it
  955. * has the same vector as this entry, just return. Otherwise,
  956. * we use the vector for this APIC / pin combination.
  957. */
  958. vector = ioapic_get_vector(ioapics[intr->dst_apic_id],
  959. intr->dst_apic_int);
  960. if (args->vector == vector)
  961. return;
  962. KASSERT(args->vector == -1,
  963. ("Multiple IRQs for PCI interrupt %d.%d.INT%c: %d and %d\n",
  964. args->bus, args->irq >> 2, 'A' + (args->irq & 0x3), args->vector,
  965. vector));
  966. args->vector = vector;
  967. }
  968. int
  969. mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin)
  970. {
  971. struct pci_route_interrupt_args args;
  972. int slot;
  973. /* Like ACPI, pin numbers are 0-3, not 1-4. */
  974. pin--;
  975. KASSERT(pci0 != -1, ("do not know how to route PCI interrupts"));
  976. args.bus = pci_get_bus(dev) + pci0;
  977. slot = pci_get_slot(dev);
  978. /*
  979. * PCI interrupt entries in the MP Table encode both the slot and
  980. * pin into the IRQ with the pin being the two least significant
  981. * bits, the slot being the next five bits, and the most significant
  982. * bit being reserved.
  983. */
  984. args.irq = slot << 2 | pin;
  985. args.vector = -1;
  986. mptable_walk_table(mptable_pci_route_interrupt_handler, &args);
  987. if (args.vector < 0) {
  988. device_printf(pcib, "unable to route slot %d INT%c\n", slot,
  989. 'A' + pin);
  990. return (PCI_INVALID_IRQ);
  991. }
  992. if (bootverbose)
  993. device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot,
  994. 'A' + pin, args.vector);
  995. return (args.vector);
  996. }
  997. #ifdef NEW_PCIB
  998. struct host_res_args {
  999. struct mptable_hostb_softc *sc;
  1000. device_t dev;
  1001. u_char bus;
  1002. };
  1003. /*
  1004. * Initialize a Host-PCI bridge so it can restrict resource allocation
  1005. * requests to the resources it actually decodes according to MP
  1006. * config table extended entries.
  1007. */
  1008. static void
  1009. mptable_host_res_handler(ext_entry_ptr entry, void *arg)
  1010. {
  1011. struct host_res_args *args;
  1012. cbasm_entry_ptr cbasm;
  1013. sas_entry_ptr sas;
  1014. const char *name;
  1015. uint64_t start, end;
  1016. int error, *flagp, flags, type;
  1017. args = arg;
  1018. switch (entry->type) {
  1019. case MPCT_EXTENTRY_SAS:
  1020. sas = (sas_entry_ptr)entry;
  1021. if (sas->bus_id != args->bus)
  1022. break;
  1023. switch (sas->address_type) {
  1024. case SASENTRY_TYPE_IO:
  1025. type = SYS_RES_IOPORT;
  1026. flags = 0;
  1027. break;
  1028. case SASENTRY_TYPE_MEMORY:
  1029. type = SYS_RES_MEMORY;
  1030. flags = 0;
  1031. break;
  1032. case SASENTRY_TYPE_PREFETCH:
  1033. type = SYS_RES_MEMORY;
  1034. flags = RF_PREFETCHABLE;
  1035. break;
  1036. default:
  1037. printf(
  1038. "MPTable: Unknown systems address space type for bus %u: %d\n",
  1039. sas->bus_id, sas->address_type);
  1040. return;
  1041. }
  1042. start = sas->address_base;
  1043. end = sas->address_base + sas->address_length - 1;
  1044. #ifdef __i386__
  1045. if (start > ULONG_MAX) {
  1046. device_printf(args->dev,
  1047. "Ignoring %d range above 4GB (%#jx-%#jx)\n",
  1048. type, (uintmax_t)start, (uintmax_t)end);
  1049. break;
  1050. }
  1051. if (end > ULONG_MAX) {
  1052. device_printf(args->dev,
  1053. "Truncating end of %d range above 4GB (%#jx-%#jx)\n",
  1054. type, (uintmax_t)start, (uintmax_t)end);
  1055. end = ULONG_MAX;
  1056. }
  1057. #endif
  1058. error = pcib_host_res_decodes(&args->sc->sc_host_res, type,
  1059. start, end, flags);
  1060. if (error)
  1061. panic("Failed to manage %d range (%#jx-%#jx): %d",
  1062. type, (uintmax_t)start, (uintmax_t)end, error);
  1063. break;
  1064. case MPCT_EXTENTRY_CBASM:
  1065. cbasm = (cbasm_entry_ptr)entry;
  1066. if (cbasm->bus_id != args->bus)
  1067. break;
  1068. switch (cbasm->predefined_range) {
  1069. case CBASMENTRY_RANGE_ISA_IO:
  1070. flagp = &args->sc->sc_decodes_isa_io;
  1071. name = "ISA I/O";
  1072. break;
  1073. case CBASMENTRY_RANGE_VGA_IO:
  1074. flagp = &args->sc->sc_decodes_vga_io;
  1075. name = "VGA I/O";
  1076. break;
  1077. default:
  1078. printf(
  1079. "MPTable: Unknown compatiblity address space range for bus %u: %d\n",
  1080. cbasm->bus_id, cbasm->predefined_range);
  1081. return;
  1082. }
  1083. if (*flagp != 0)
  1084. printf(
  1085. "MPTable: Duplicate compatibility %s range for bus %u\n",
  1086. name, cbasm->bus_id);
  1087. switch (cbasm->address_mod) {
  1088. case CBASMENTRY_ADDRESS_MOD_ADD:
  1089. *flagp = 1;
  1090. if (bootverbose)
  1091. device_printf(args->dev, "decoding %s ports\n",
  1092. name);
  1093. break;
  1094. case CBASMENTRY_ADDRESS_MOD_SUBTRACT:
  1095. *flagp = -1;
  1096. if (bootverbose)
  1097. device_printf(args->dev,
  1098. "not decoding %s ports\n", name);
  1099. break;
  1100. default:
  1101. printf(
  1102. "MPTable: Unknown compatibility address space modifier: %u\n",
  1103. cbasm->address_mod);
  1104. break;
  1105. }
  1106. break;
  1107. }
  1108. }
  1109. void
  1110. mptable_pci_host_res_init(device_t pcib)
  1111. {
  1112. struct host_res_args args;
  1113. KASSERT(pci0 != -1, ("do not know how to map PCI bus IDs"));
  1114. args.bus = pci_get_bus(pcib) + pci0;
  1115. args.dev = pcib;
  1116. args.sc = device_get_softc(pcib);
  1117. if (pcib_host_res_init(pcib, &args.sc->sc_host_res) != 0)
  1118. panic("failed to init hostb resources");
  1119. mptable_walk_extended_table(mptable_host_res_handler, &args);
  1120. }
  1121. #endif