ofw_machdep.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. /*-
  2. * SPDX-License-Identifier: BSD-4-Clause
  3. *
  4. * Copyright (C) 1996 Wolfgang Solfrank.
  5. * Copyright (C) 1996 TooLs GmbH.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. All advertising materials mentioning features or use of this software
  17. * must display the following acknowledgement:
  18. * This product includes software developed by TooLs GmbH.
  19. * 4. The name of TooLs GmbH may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  28. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  30. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  31. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. * $NetBSD: ofw_machdep.c,v 1.5 2000/05/23 13:25:43 tsubai Exp $
  34. */
  35. #include <sys/cdefs.h>
  36. __FBSDID("$FreeBSD$");
  37. #include "opt_platform.h"
  38. #include <sys/param.h>
  39. #include <sys/bus.h>
  40. #include <sys/systm.h>
  41. #include <sys/conf.h>
  42. #include <sys/disk.h>
  43. #include <sys/fcntl.h>
  44. #include <sys/lock.h>
  45. #include <sys/malloc.h>
  46. #include <sys/smp.h>
  47. #include <sys/stat.h>
  48. #include <sys/endian.h>
  49. #include <net/ethernet.h>
  50. #include <dev/fdt/fdt_common.h>
  51. #include <dev/ofw/openfirm.h>
  52. #include <dev/ofw/ofw_pci.h>
  53. #include <dev/ofw/ofw_bus.h>
  54. #include <dev/ofw/ofw_subr.h>
  55. #include <vm/vm.h>
  56. #include <vm/vm_param.h>
  57. #include <vm/vm_page.h>
  58. #include <vm/vm_phys.h>
  59. #include <machine/bus.h>
  60. #include <machine/cpu.h>
  61. #include <machine/md_var.h>
  62. #include <machine/platform.h>
  63. #include <machine/ofw_machdep.h>
  64. #include <machine/trap.h>
  65. #include <contrib/libfdt/libfdt.h>
  66. #ifdef POWERNV
  67. #include <powerpc/powernv/opal.h>
  68. #endif
  69. static void *fdt;
  70. int ofw_real_mode;
  71. #ifdef AIM
  72. extern register_t ofmsr[5];
  73. extern void *openfirmware_entry;
  74. char save_trap_init[0x2f00]; /* EXC_LAST */
  75. char save_trap_of[0x2f00]; /* EXC_LAST */
  76. int ofwcall(void *);
  77. static int openfirmware(void *args);
  78. #pragma clang diagnostic push
  79. #pragma clang diagnostic ignored "-Wfortify-source"
  80. __inline void
  81. ofw_save_trap_vec(char *save_trap_vec)
  82. {
  83. if (!ofw_real_mode || !hw_direct_map)
  84. return;
  85. bcopy((void *)PHYS_TO_DMAP(EXC_RST), save_trap_vec, EXC_LAST - EXC_RST);
  86. }
  87. static __inline void
  88. ofw_restore_trap_vec(char *restore_trap_vec)
  89. {
  90. if (!ofw_real_mode || !hw_direct_map)
  91. return;
  92. bcopy(restore_trap_vec, (void *)PHYS_TO_DMAP(EXC_RST),
  93. EXC_LAST - EXC_RST);
  94. __syncicache((void *)PHYS_TO_DMAP(EXC_RSVD), EXC_LAST - EXC_RSVD);
  95. }
  96. #pragma clang diagnostic pop
  97. /*
  98. * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
  99. */
  100. register_t ofw_sprg0_save;
  101. static __inline void
  102. ofw_sprg_prepare(void)
  103. {
  104. if (ofw_real_mode)
  105. return;
  106. /*
  107. * Assume that interrupt are disabled at this point, or
  108. * SPRG1-3 could be trashed
  109. */
  110. #ifdef __powerpc64__
  111. __asm __volatile("mtsprg1 %0\n\t"
  112. "mtsprg2 %1\n\t"
  113. "mtsprg3 %2\n\t"
  114. :
  115. : "r"(ofmsr[2]),
  116. "r"(ofmsr[3]),
  117. "r"(ofmsr[4]));
  118. #else
  119. __asm __volatile("mfsprg0 %0\n\t"
  120. "mtsprg0 %1\n\t"
  121. "mtsprg1 %2\n\t"
  122. "mtsprg2 %3\n\t"
  123. "mtsprg3 %4\n\t"
  124. : "=&r"(ofw_sprg0_save)
  125. : "r"(ofmsr[1]),
  126. "r"(ofmsr[2]),
  127. "r"(ofmsr[3]),
  128. "r"(ofmsr[4]));
  129. #endif
  130. }
  131. static __inline void
  132. ofw_sprg_restore(void)
  133. {
  134. if (ofw_real_mode)
  135. return;
  136. /*
  137. * Note that SPRG1-3 contents are irrelevant. They are scratch
  138. * registers used in the early portion of trap handling when
  139. * interrupts are disabled.
  140. *
  141. * PCPU data cannot be used until this routine is called !
  142. */
  143. #ifndef __powerpc64__
  144. __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save));
  145. #endif
  146. }
  147. #endif
  148. static int
  149. parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
  150. {
  151. cell_t address_cells, size_cells;
  152. cell_t OFmem[4 * PHYS_AVAIL_SZ];
  153. int sz, i, j;
  154. phandle_t phandle;
  155. sz = 0;
  156. /*
  157. * Get #address-cells from root node, defaulting to 1 if it cannot
  158. * be found.
  159. */
  160. phandle = OF_finddevice("/");
  161. if (OF_getencprop(phandle, "#address-cells", &address_cells,
  162. sizeof(address_cells)) < (ssize_t)sizeof(address_cells))
  163. address_cells = 1;
  164. if (OF_getencprop(phandle, "#size-cells", &size_cells,
  165. sizeof(size_cells)) < (ssize_t)sizeof(size_cells))
  166. size_cells = 1;
  167. /*
  168. * Get memory.
  169. */
  170. if (node == -1 || (sz = OF_getencprop(node, prop,
  171. OFmem, sizeof(OFmem))) <= 0)
  172. panic("Physical memory map not found");
  173. i = 0;
  174. j = 0;
  175. while (i < sz/sizeof(cell_t)) {
  176. output[j].mr_start = OFmem[i++];
  177. if (address_cells == 2) {
  178. output[j].mr_start <<= 32;
  179. output[j].mr_start += OFmem[i++];
  180. }
  181. output[j].mr_size = OFmem[i++];
  182. if (size_cells == 2) {
  183. output[j].mr_size <<= 32;
  184. output[j].mr_size += OFmem[i++];
  185. }
  186. if (output[j].mr_start > BUS_SPACE_MAXADDR)
  187. continue;
  188. /*
  189. * Constrain memory to that which we can access.
  190. * 32-bit AIM can only reference 32 bits of address currently,
  191. * but Book-E can access 36 bits.
  192. */
  193. if (((uint64_t)output[j].mr_start +
  194. (uint64_t)output[j].mr_size - 1) >
  195. BUS_SPACE_MAXADDR) {
  196. output[j].mr_size = BUS_SPACE_MAXADDR -
  197. output[j].mr_start + 1;
  198. }
  199. j++;
  200. }
  201. return (j);
  202. }
  203. static int
  204. parse_numa_ofw_memory(phandle_t node, const char *prop,
  205. struct numa_mem_region *output)
  206. {
  207. cell_t address_cells, size_cells;
  208. cell_t OFmem[4 * PHYS_AVAIL_SZ];
  209. int sz, i, j;
  210. phandle_t phandle;
  211. sz = 0;
  212. /*
  213. * Get #address-cells from root node, defaulting to 1 if it cannot
  214. * be found.
  215. */
  216. phandle = OF_finddevice("/");
  217. if (OF_getencprop(phandle, "#address-cells", &address_cells,
  218. sizeof(address_cells)) < (ssize_t)sizeof(address_cells))
  219. address_cells = 1;
  220. if (OF_getencprop(phandle, "#size-cells", &size_cells,
  221. sizeof(size_cells)) < (ssize_t)sizeof(size_cells))
  222. size_cells = 1;
  223. /*
  224. * Get memory.
  225. */
  226. if (node == -1 || (sz = OF_getencprop(node, prop,
  227. OFmem, sizeof(OFmem))) <= 0)
  228. panic("Physical memory map not found");
  229. i = 0;
  230. j = 0;
  231. while (i < sz/sizeof(cell_t)) {
  232. output[j].mr_start = OFmem[i++];
  233. if (address_cells == 2) {
  234. output[j].mr_start <<= 32;
  235. output[j].mr_start += OFmem[i++];
  236. }
  237. output[j].mr_size = OFmem[i++];
  238. if (size_cells == 2) {
  239. output[j].mr_size <<= 32;
  240. output[j].mr_size += OFmem[i++];
  241. }
  242. j++;
  243. }
  244. return (j);
  245. }
  246. #ifdef FDT
  247. static int
  248. excise_reserved_regions(struct mem_region *avail, int asz,
  249. struct mem_region *exclude, int esz)
  250. {
  251. int i, j, k;
  252. for (i = 0; i < asz; i++) {
  253. for (j = 0; j < esz; j++) {
  254. /*
  255. * Case 1: Exclusion region encloses complete
  256. * available entry. Drop it and move on.
  257. */
  258. if (exclude[j].mr_start <= avail[i].mr_start &&
  259. exclude[j].mr_start + exclude[j].mr_size >=
  260. avail[i].mr_start + avail[i].mr_size) {
  261. for (k = i+1; k < asz; k++)
  262. avail[k-1] = avail[k];
  263. asz--;
  264. i--; /* Repeat some entries */
  265. continue;
  266. }
  267. /*
  268. * Case 2: Exclusion region starts in available entry.
  269. * Trim it to where the entry begins and append
  270. * a new available entry with the region after
  271. * the excluded region, if any.
  272. */
  273. if (exclude[j].mr_start >= avail[i].mr_start &&
  274. exclude[j].mr_start < avail[i].mr_start +
  275. avail[i].mr_size) {
  276. if (exclude[j].mr_start + exclude[j].mr_size <
  277. avail[i].mr_start + avail[i].mr_size) {
  278. avail[asz].mr_start =
  279. exclude[j].mr_start + exclude[j].mr_size;
  280. avail[asz].mr_size = avail[i].mr_start +
  281. avail[i].mr_size -
  282. avail[asz].mr_start;
  283. asz++;
  284. }
  285. avail[i].mr_size = exclude[j].mr_start -
  286. avail[i].mr_start;
  287. }
  288. /*
  289. * Case 3: Exclusion region ends in available entry.
  290. * Move start point to where the exclusion zone ends.
  291. * The case of a contained exclusion zone has already
  292. * been caught in case 2.
  293. */
  294. if (exclude[j].mr_start + exclude[j].mr_size >=
  295. avail[i].mr_start && exclude[j].mr_start +
  296. exclude[j].mr_size < avail[i].mr_start +
  297. avail[i].mr_size) {
  298. avail[i].mr_size += avail[i].mr_start;
  299. avail[i].mr_start =
  300. exclude[j].mr_start + exclude[j].mr_size;
  301. avail[i].mr_size -= avail[i].mr_start;
  302. }
  303. }
  304. }
  305. return (asz);
  306. }
  307. static int
  308. excise_initrd_region(struct mem_region *avail, int asz)
  309. {
  310. phandle_t chosen;
  311. uint64_t start, end;
  312. ssize_t size;
  313. struct mem_region initrdmap[1];
  314. pcell_t cell[2];
  315. chosen = OF_finddevice("/chosen");
  316. size = OF_getencprop(chosen, "linux,initrd-start", cell, sizeof(cell));
  317. if (size < 0)
  318. return (asz);
  319. else if (size == 4)
  320. start = cell[0];
  321. else if (size == 8)
  322. start = (uint64_t)cell[0] << 32 | cell[1];
  323. else {
  324. /* Invalid value length */
  325. printf("WARNING: linux,initrd-start must be either 4 or 8 bytes long\n");
  326. return (asz);
  327. }
  328. size = OF_getencprop(chosen, "linux,initrd-end", cell, sizeof(cell));
  329. if (size < 0)
  330. return (asz);
  331. else if (size == 4)
  332. end = cell[0];
  333. else if (size == 8)
  334. end = (uint64_t)cell[0] << 32 | cell[1];
  335. else {
  336. /* Invalid value length */
  337. printf("WARNING: linux,initrd-end must be either 4 or 8 bytes long\n");
  338. return (asz);
  339. }
  340. if (end <= start)
  341. return (asz);
  342. initrdmap[0].mr_start = start;
  343. initrdmap[0].mr_size = end - start;
  344. asz = excise_reserved_regions(avail, asz, initrdmap, 1);
  345. return (asz);
  346. }
  347. #ifdef POWERNV
  348. static int
  349. excise_msi_region(struct mem_region *avail, int asz)
  350. {
  351. uint64_t start, end;
  352. struct mem_region initrdmap[1];
  353. /*
  354. * This range of physical addresses is used to implement optimized
  355. * 32 bit MSI interrupts on POWER9. Exclude it to avoid accidentally
  356. * using it for DMA, as this will cause an immediate PHB fence.
  357. * While we could theoretically turn off this behavior in the ETU,
  358. * doing so would break 32-bit MSI, so just reserve the range in
  359. * the physical map instead.
  360. * See section 4.4.2.8 of the PHB4 specification.
  361. */
  362. start = 0x00000000ffff0000ul;
  363. end = 0x00000000fffffffful;
  364. initrdmap[0].mr_start = start;
  365. initrdmap[0].mr_size = end - start;
  366. asz = excise_reserved_regions(avail, asz, initrdmap, 1);
  367. return (asz);
  368. }
  369. #endif
  370. static int
  371. excise_fdt_reserved(struct mem_region *avail, int asz)
  372. {
  373. struct mem_region fdtmap[32];
  374. ssize_t fdtmapsize;
  375. phandle_t chosen;
  376. int j, fdtentries;
  377. chosen = OF_finddevice("/chosen");
  378. fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap));
  379. for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) {
  380. fdtmap[j].mr_start = be64toh(fdtmap[j].mr_start) & ~PAGE_MASK;
  381. fdtmap[j].mr_size = round_page(be64toh(fdtmap[j].mr_size));
  382. }
  383. KASSERT(j*sizeof(fdtmap[0]) < sizeof(fdtmap),
  384. ("Exceeded number of FDT reservations"));
  385. /* Add a virtual entry for the FDT itself */
  386. if (fdt != NULL) {
  387. fdtmap[j].mr_start = (vm_offset_t)fdt & ~PAGE_MASK;
  388. fdtmap[j].mr_size = round_page(fdt_totalsize(fdt));
  389. fdtmapsize += sizeof(fdtmap[0]);
  390. }
  391. fdtentries = fdtmapsize/sizeof(fdtmap[0]);
  392. asz = excise_reserved_regions(avail, asz, fdtmap, fdtentries);
  393. return (asz);
  394. }
  395. #endif
  396. /*
  397. * This is called during powerpc_init, before the system is really initialized.
  398. * It shall provide the total and the available regions of RAM.
  399. * The available regions need not take the kernel into account.
  400. */
  401. void
  402. ofw_numa_mem_regions(struct numa_mem_region *memp, int *memsz)
  403. {
  404. phandle_t phandle;
  405. int count, msz;
  406. char name[31];
  407. struct numa_mem_region *curmemp;
  408. msz = 0;
  409. /*
  410. * Get memory from all the /memory nodes.
  411. */
  412. for (phandle = OF_child(OF_peer(0)); phandle != 0;
  413. phandle = OF_peer(phandle)) {
  414. if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0)
  415. continue;
  416. if (strncmp(name, "memory@", strlen("memory@")) != 0)
  417. continue;
  418. count = parse_numa_ofw_memory(phandle, "reg", &memp[msz]);
  419. if (count == 0)
  420. continue;
  421. curmemp = &memp[msz];
  422. MPASS(count == 1);
  423. curmemp->mr_domain = platform_node_numa_domain(phandle);
  424. if (bootverbose)
  425. printf("%s %#jx-%#jx domain(%ju)\n",
  426. name, (uintmax_t)curmemp->mr_start,
  427. (uintmax_t)curmemp->mr_start + curmemp->mr_size,
  428. (uintmax_t)curmemp->mr_domain);
  429. msz += count;
  430. }
  431. *memsz = msz;
  432. }
  433. /*
  434. * This is called during powerpc_init, before the system is really initialized.
  435. * It shall provide the total and the available regions of RAM.
  436. * The available regions need not take the kernel into account.
  437. */
  438. void
  439. ofw_mem_regions(struct mem_region *memp, int *memsz,
  440. struct mem_region *availp, int *availsz)
  441. {
  442. phandle_t phandle;
  443. int asz, msz;
  444. int res;
  445. char name[31];
  446. asz = msz = 0;
  447. /*
  448. * Get memory from all the /memory nodes.
  449. */
  450. for (phandle = OF_child(OF_peer(0)); phandle != 0;
  451. phandle = OF_peer(phandle)) {
  452. if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0)
  453. continue;
  454. if (strncmp(name, "memory", sizeof(name)) != 0 &&
  455. strncmp(name, "memory@", strlen("memory@")) != 0)
  456. continue;
  457. res = parse_ofw_memory(phandle, "reg", &memp[msz]);
  458. msz += res;
  459. /*
  460. * On POWER9 Systems we might have both linux,usable-memory and
  461. * reg properties. 'reg' denotes all available memory, but we
  462. * must use 'linux,usable-memory', a subset, as some memory
  463. * regions are reserved for NVLink.
  464. */
  465. if (OF_getproplen(phandle, "linux,usable-memory") >= 0)
  466. res = parse_ofw_memory(phandle, "linux,usable-memory",
  467. &availp[asz]);
  468. else if (OF_getproplen(phandle, "available") >= 0)
  469. res = parse_ofw_memory(phandle, "available",
  470. &availp[asz]);
  471. else
  472. res = parse_ofw_memory(phandle, "reg", &availp[asz]);
  473. asz += res;
  474. }
  475. #ifdef FDT
  476. phandle = OF_finddevice("/chosen");
  477. if (OF_hasprop(phandle, "fdtmemreserv"))
  478. asz = excise_fdt_reserved(availp, asz);
  479. /* If the kernel is being loaded through kexec, initrd region is listed
  480. * in /chosen but the region is not marked as reserved, so, we might exclude
  481. * it here.
  482. */
  483. if (OF_hasprop(phandle, "linux,initrd-start"))
  484. asz = excise_initrd_region(availp, asz);
  485. #endif
  486. #ifdef POWERNV
  487. if (opal_check() == 0)
  488. asz = excise_msi_region(availp, asz);
  489. #endif
  490. *memsz = msz;
  491. *availsz = asz;
  492. }
  493. void
  494. OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
  495. {
  496. #ifdef AIM
  497. ofmsr[0] = mfmsr();
  498. #ifdef __powerpc64__
  499. ofmsr[0] &= ~PSL_SF;
  500. #ifdef __LITTLE_ENDIAN__
  501. /* Assume OFW is BE. */
  502. ofmsr[0] &= ~PSL_LE;
  503. #endif
  504. #else
  505. __asm __volatile("mfsprg0 %0" : "=&r"(ofmsr[1]));
  506. #endif
  507. __asm __volatile("mfsprg1 %0" : "=&r"(ofmsr[2]));
  508. __asm __volatile("mfsprg2 %0" : "=&r"(ofmsr[3]));
  509. __asm __volatile("mfsprg3 %0" : "=&r"(ofmsr[4]));
  510. openfirmware_entry = openfirm;
  511. if (ofmsr[0] & PSL_DR)
  512. ofw_real_mode = 0;
  513. else
  514. ofw_real_mode = 1;
  515. ofw_save_trap_vec(save_trap_init);
  516. #else
  517. ofw_real_mode = 1;
  518. #endif
  519. fdt = fdt_ptr;
  520. }
  521. boolean_t
  522. OF_bootstrap()
  523. {
  524. boolean_t status = FALSE;
  525. int err = 0;
  526. #ifdef AIM
  527. if (openfirmware_entry != NULL) {
  528. if (ofw_real_mode) {
  529. status = OF_install(OFW_STD_REAL, 0);
  530. } else {
  531. #ifdef __powerpc64__
  532. status = OF_install(OFW_STD_32BIT, 0);
  533. #else
  534. status = OF_install(OFW_STD_DIRECT, 0);
  535. #endif
  536. }
  537. if (status != TRUE)
  538. return status;
  539. err = OF_init(openfirmware);
  540. } else
  541. #endif
  542. if (fdt != NULL) {
  543. #ifdef FDT
  544. #ifdef AIM
  545. bus_space_tag_t fdt_bt;
  546. vm_offset_t tmp_fdt_ptr;
  547. vm_size_t fdt_size;
  548. uintptr_t fdt_va;
  549. #endif
  550. status = OF_install(OFW_FDT, 0);
  551. if (status != TRUE)
  552. return status;
  553. #ifdef AIM /* AIM-only for now -- Book-E does this remapping in early init */
  554. /* Get the FDT size for mapping if we can */
  555. tmp_fdt_ptr = pmap_early_io_map((vm_paddr_t)fdt, PAGE_SIZE);
  556. if (fdt_check_header((void *)tmp_fdt_ptr) != 0) {
  557. pmap_early_io_unmap(tmp_fdt_ptr, PAGE_SIZE);
  558. return FALSE;
  559. }
  560. fdt_size = fdt_totalsize((void *)tmp_fdt_ptr);
  561. pmap_early_io_unmap(tmp_fdt_ptr, PAGE_SIZE);
  562. /*
  563. * Map this for real. Use bus_space_map() to take advantage
  564. * of its auto-remapping function once the kernel is loaded.
  565. * This is a dirty hack, but what we have.
  566. */
  567. #ifdef __LITTLE_ENDIAN__
  568. fdt_bt = &bs_le_tag;
  569. #else
  570. fdt_bt = &bs_be_tag;
  571. #endif
  572. bus_space_map(fdt_bt, (vm_paddr_t)fdt, fdt_size, 0, &fdt_va);
  573. err = OF_init((void *)fdt_va);
  574. #else
  575. err = OF_init(fdt);
  576. #endif
  577. #endif
  578. }
  579. #ifdef FDT_DTB_STATIC
  580. /*
  581. * Check for a statically included blob already in the kernel and
  582. * needing no mapping.
  583. */
  584. else {
  585. status = OF_install(OFW_FDT, 0);
  586. if (status != TRUE)
  587. return status;
  588. err = OF_init(&fdt_static_dtb);
  589. }
  590. #endif
  591. if (err != 0) {
  592. OF_install(NULL, 0);
  593. status = FALSE;
  594. }
  595. return (status);
  596. }
  597. #ifdef AIM
  598. void
  599. ofw_quiesce(void)
  600. {
  601. struct {
  602. cell_t name;
  603. cell_t nargs;
  604. cell_t nreturns;
  605. } args;
  606. KASSERT(!pmap_bootstrapped, ("Cannot call ofw_quiesce after VM is up"));
  607. args.name = (cell_t)(uintptr_t)"quiesce";
  608. args.nargs = 0;
  609. args.nreturns = 0;
  610. openfirmware(&args);
  611. }
  612. static int
  613. openfirmware_core(void *args)
  614. {
  615. int result;
  616. register_t oldmsr;
  617. if (openfirmware_entry == NULL)
  618. return (-1);
  619. /*
  620. * Turn off exceptions - we really don't want to end up
  621. * anywhere unexpected with PCPU set to something strange
  622. * or the stack pointer wrong.
  623. */
  624. oldmsr = intr_disable();
  625. ofw_sprg_prepare();
  626. /* Save trap vectors */
  627. ofw_save_trap_vec(save_trap_of);
  628. /* Restore initially saved trap vectors */
  629. ofw_restore_trap_vec(save_trap_init);
  630. #ifndef __powerpc64__
  631. /*
  632. * Clear battable[] translations
  633. */
  634. if (!(cpu_features & PPC_FEATURE_64))
  635. __asm __volatile("mtdbatu 2, %0\n"
  636. "mtdbatu 3, %0" : : "r" (0));
  637. isync();
  638. #endif
  639. result = ofwcall(args);
  640. /* Restore trap vecotrs */
  641. ofw_restore_trap_vec(save_trap_of);
  642. ofw_sprg_restore();
  643. intr_restore(oldmsr);
  644. return (result);
  645. }
  646. #ifdef SMP
  647. struct ofw_rv_args {
  648. void *args;
  649. int retval;
  650. volatile int in_progress;
  651. };
  652. static void
  653. ofw_rendezvous_dispatch(void *xargs)
  654. {
  655. struct ofw_rv_args *rv_args = xargs;
  656. /* NOTE: Interrupts are disabled here */
  657. if (PCPU_GET(cpuid) == 0) {
  658. /*
  659. * Execute all OF calls on CPU 0
  660. */
  661. rv_args->retval = openfirmware_core(rv_args->args);
  662. rv_args->in_progress = 0;
  663. } else {
  664. /*
  665. * Spin with interrupts off on other CPUs while OF has
  666. * control of the machine.
  667. */
  668. while (rv_args->in_progress)
  669. cpu_spinwait();
  670. }
  671. }
  672. #endif
  673. static int
  674. openfirmware(void *args)
  675. {
  676. int result;
  677. #ifdef SMP
  678. struct ofw_rv_args rv_args;
  679. #endif
  680. if (openfirmware_entry == NULL)
  681. return (-1);
  682. #ifdef SMP
  683. if (cold) {
  684. result = openfirmware_core(args);
  685. } else {
  686. rv_args.args = args;
  687. rv_args.in_progress = 1;
  688. smp_rendezvous(smp_no_rendezvous_barrier,
  689. ofw_rendezvous_dispatch, smp_no_rendezvous_barrier,
  690. &rv_args);
  691. result = rv_args.retval;
  692. }
  693. #else
  694. result = openfirmware_core(args);
  695. #endif
  696. return (result);
  697. }
  698. void
  699. OF_reboot()
  700. {
  701. struct {
  702. cell_t name;
  703. cell_t nargs;
  704. cell_t nreturns;
  705. cell_t arg;
  706. } args;
  707. args.name = (cell_t)(uintptr_t)"interpret";
  708. args.nargs = 1;
  709. args.nreturns = 0;
  710. args.arg = (cell_t)(uintptr_t)"reset-all";
  711. openfirmware_core(&args); /* Don't do rendezvous! */
  712. for (;;); /* just in case */
  713. }
  714. #endif /* AIM */
  715. void
  716. OF_getetheraddr(device_t dev, u_char *addr)
  717. {
  718. phandle_t node;
  719. node = ofw_bus_get_node(dev);
  720. OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN);
  721. }
  722. /*
  723. * Return a bus handle and bus tag that corresponds to the register
  724. * numbered regno for the device referenced by the package handle
  725. * dev. This function is intended to be used by console drivers in
  726. * early boot only. It works by mapping the address of the device's
  727. * register in the address space of its parent and recursively walk
  728. * the device tree upward this way.
  729. */
  730. int
  731. OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
  732. bus_space_handle_t *handle, bus_size_t *sz)
  733. {
  734. bus_addr_t addr;
  735. bus_size_t size;
  736. pcell_t pci_hi;
  737. int flags, res;
  738. res = ofw_reg_to_paddr(dev, regno, &addr, &size, &pci_hi);
  739. if (res < 0)
  740. return (res);
  741. if (pci_hi == OFW_PADDR_NOT_PCI) {
  742. *tag = &bs_be_tag;
  743. flags = 0;
  744. } else {
  745. *tag = &bs_le_tag;
  746. flags = (pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) ?
  747. BUS_SPACE_MAP_PREFETCHABLE: 0;
  748. }
  749. if (sz != NULL)
  750. *sz = size;
  751. return (bus_space_map(*tag, addr, size, flags, handle));
  752. }