1 /* Copyright 2013-2014 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20
21 #include <lock.h>
22 #include <device.h>
23 #include <compiler.h>
24 #include <hostservices.h>
25 #include <mem_region.h>
26 #include <xscom.h>
27 #include <fsp.h>
28 #include <chip.h>
29 #include <console.h>
30 #include <mem-map.h>
31 #include <timebase.h>
32
33 #define HOSTBOOT_RUNTIME_INTERFACE_VERSION 1
34
35 struct host_interfaces {
36 /** Interface version. */
37 uint64_t interface_version;
38
39 /** Put a string to the console. */
40 void (*puts)(const char*);
41 /** Critical failure in runtime execution. */
42 void (*assert)(void);
43
44 /** OPTIONAL. Hint to environment that the page may be executed. */
45 int (*set_page_execute)(void*);
46
47 /** malloc */
48 void *(*malloc)(size_t);
49 /** free */
50 void (*free)(void*);
51 /** realloc */
52 void *(*realloc)(void*, size_t);
53
54 /** sendErrorLog
55 * @param[in] plid Platform Log identifier
56 * @param[in] data size in bytes
57 * @param[in] pointer to data
58 * @return 0 on success else error code
59 */
60 int (*send_error_log)(uint32_t,uint32_t,void *);
61
62 /** Scan communication read
63 * @param[in] chip_id (based on devtree defn)
64 * @param[in] address
65 * @param[in] pointer to 8-byte data buffer
66 * @return 0 on success else return code
67 */
68 int (*scom_read)(uint64_t, uint64_t, void*);
69
70 /** Scan communication write
71 * @param[in] chip_id (based on devtree defn)
72 * @param[in] address
73 * @param[in] pointer to 8-byte data buffer
74 * @return 0 on success else return code
75 */
76 int (*scom_write)(uint64_t, uint64_t, const void *);
77
78 /** lid_load
79 * Load a LID from PNOR, FSP, etc.
80 *
81 * @param[in] LID number.
82 * @param[out] Allocated buffer for LID.
83 * @param[out] Size of LID (in bytes).
84 *
85 * @return 0 on success, else RC.
86 */
87 int (*lid_load)(uint32_t lid, void **buf, size_t *len);
88
89 /** lid_unload
90 * Release memory from previously loaded LID.
91 *
92 * @param[in] Allocated buffer for LID to release.
93 *
94 * @return 0 on success, else RC.
95 */
96 int (*lid_unload)(void *buf);
97
98 /** Get the address of a reserved memory region by its devtree name.
99 *
100 * @param[in] Devtree name (ex. "ibm,hbrt-vpd-image")
101 * @return physical address of region (or NULL).
102 **/
103 uint64_t (*get_reserved_mem)(const char*);
104
105 /**
106 * @brief Force a core to be awake, or clear the force
107 * @param[in] i_core Core to wake up (pid)
108 * @param[in] i_mode 0=force awake
109 * 1=clear force
110 * 2=clear all previous forces
111 * @return rc non-zero on error
112 */
113 int (*wakeup)( uint32_t i_core, uint32_t i_mode );
114
115 /**
116 * @brief Delay/sleep for at least the time given
117 * @param[in] seconds
118 * @param[in] nano seconds
119 */
120 void (*nanosleep)(uint64_t i_seconds, uint64_t i_nano_seconds);
121
122 // Reserve some space for future growth.
123 void (*reserved[32])(void);
124 };
125
126 struct runtime_interfaces {
127 /** Interface version. */
128 uint64_t interface_version;
129
130 /** Execute CxxTests that may be contained in the image.
131 *
132 * @param[in] - Pointer to CxxTestStats structure for results reporting.
133 */
134 void (*cxxtestExecute)(void *);
135 /** Get a list of lids numbers of the lids known to HostBoot
136 *
137 * @param[out] o_num - the number of lids in the list
138 * @return a pointer to the list
139 */
140 const uint32_t * (*get_lid_list)(size_t * o_num);
141
142 /** Load OCC Image and common data into mainstore, also setup OCC BARSs
143 *
144 * @param[in] i_homer_addr_phys - The physical mainstore address of the
145 * start of the HOMER image
146 * @param[in] i_homer_addr_va - Virtual memory address of the HOMER image
147 * @param[in] i_common_addr_phys - The physical mainstore address of the
148 * OCC common area.
149 * @param[in] i_common_addr_va - Virtual memory address of the common area
150 * @param[in] i_chip - The HW chip id (XSCOM chip ID)
151 * @return 0 on success else return code
152 */
153 int(*loadOCC)(uint64_t i_homer_addr_phys,
154 uint64_t i_homer_addr_va,
155 uint64_t i_common_addr_phys,
156 uint64_t i_common_addr_va,
157 uint64_t i_chip);
158
159 /** Start OCC on all chips, by module
160 *
161 * @param[in] i_chip - Array of functional HW chip ids
162 * @Note The caller must include a complete modules worth of chips
163 * @param[in] i_num_chips - Number of chips in the array
164 * @return 0 on success else return code
165 */
166 int (*startOCCs)(uint64_t* i_chip,
167 size_t i_num_chips);
168
169 /** Stop OCC hold OCCs in reset
170 *
171 * @param[in] i_chip - Array of functional HW chip ids
172 * @Note The caller must include a complete modules worth of chips
173 * @param[in] i_num_chips - Number of chips in the array
174 * @return 0 on success else return code
175 */
176 int (*stopOCCs)(uint64_t* i_chip,
177 size_t i_num_chips);
178
179 /* Reserve some space for future growth. */
180 void (*reserved[32])(void);
181 };
182
183 static struct runtime_interfaces *hservice_runtime;
184
185 static char *hbrt_con_buf = (char *)HBRT_CON_START;
186 static size_t hbrt_con_pos;
187 static bool hbrt_con_wrapped;
188
189 #define HBRT_CON_IN_LEN 0
190 #define HBRT_CON_OUT_LEN (HBRT_CON_LEN - HBRT_CON_IN_LEN)
191
192 static struct memcons hbrt_memcons __section(".data.memcons") = {
193 .magic = MEMCONS_MAGIC,
194 .obuf_phys = HBRT_CON_START,
195 .ibuf_phys = HBRT_CON_START + HBRT_CON_OUT_LEN,
196 .obuf_size = HBRT_CON_OUT_LEN,
197 .ibuf_size = HBRT_CON_IN_LEN,
198 };
199
hservice_putc(char c)200 static void hservice_putc(char c)
201 {
202 uint32_t opos;
203
204 hbrt_con_buf[hbrt_con_pos++] = c;
205 if (hbrt_con_pos >= HBRT_CON_OUT_LEN) {
206 hbrt_con_pos = 0;
207 hbrt_con_wrapped = true;
208 }
209
210 /*
211 * We must always re-generate memcons.out_pos because
212 * under some circumstances, the console script will
213 * use a broken putmemproc that does RMW on the full
214 * 8 bytes containing out_pos and in_prod, thus corrupting
215 * out_pos
216 */
217 opos = hbrt_con_pos;
218 if (hbrt_con_wrapped)
219 opos |= MEMCONS_OUT_POS_WRAP;
220 lwsync();
221 hbrt_memcons.out_pos = opos;
222 }
223
hservice_puts(const char * str)224 static void hservice_puts(const char *str)
225 {
226 char c;
227
228 while((c = *(str++)) != 0)
229 hservice_putc(c);
230 hservice_putc(10);
231 }
232
hservice_mark(void)233 static void hservice_mark(void)
234 {
235 hservice_puts("--------------------------------------------------"
236 "--------------------------------------------------\n");
237 }
238
hservice_assert(void)239 static void hservice_assert(void)
240 {
241 /**
242 * @fwts-label HBRTassert
243 * @fwts-advice HBRT triggered assert: you need to debug HBRT
244 */
245 prlog(PR_EMERG, "HBRT: Assertion from hostservices\n");
246 abort();
247 }
248
hservice_malloc(size_t size)249 static void *hservice_malloc(size_t size)
250 {
251 return malloc(size);
252 }
253
hservice_free(void * ptr)254 static void hservice_free(void *ptr)
255 {
256 free(ptr);
257 }
258
259
hservice_realloc(void * ptr,size_t size)260 static void *hservice_realloc(void *ptr, size_t size)
261 {
262 return realloc(ptr, size);
263 }
264
265 struct hbrt_elog_ent {
266 void *buf;
267 unsigned int size;
268 unsigned int plid;
269 struct list_node link;
270 };
271 static LIST_HEAD(hbrt_elogs);
272 static struct lock hbrt_elog_lock = LOCK_UNLOCKED;
273 static bool hbrt_elog_sending;
274 static void hservice_start_elog_send(void);
275
hservice_elog_write_complete(struct fsp_msg * msg)276 static void hservice_elog_write_complete(struct fsp_msg *msg)
277 {
278 struct hbrt_elog_ent *ent = msg->user_data;
279
280 lock(&hbrt_elog_lock);
281 prlog(PR_DEBUG, "HBRT: Completed send of PLID 0x%08x\n", ent->plid);
282 hbrt_elog_sending = false;
283 fsp_tce_unmap(PSI_DMA_HBRT_LOG_WRITE_BUF,
284 PSI_DMA_HBRT_LOG_WRITE_BUF_SZ);
285 free(ent->buf);
286 free(ent);
287 fsp_freemsg(msg);
288 hservice_start_elog_send();
289 unlock(&hbrt_elog_lock);
290 }
291
hservice_start_elog_send(void)292 static void hservice_start_elog_send(void)
293 {
294 struct fsp_msg *msg;
295 struct hbrt_elog_ent *ent;
296
297 again:
298 if (list_empty(&hbrt_elogs))
299 return;
300 ent = list_pop(&hbrt_elogs, struct hbrt_elog_ent, link);
301
302 hbrt_elog_sending = true;
303
304 prlog(PR_DEBUG, "HBRT: Starting send of PLID 0x%08x\n", ent->plid);
305
306 fsp_tce_map(PSI_DMA_HBRT_LOG_WRITE_BUF, ent->buf,
307 PSI_DMA_HBRT_LOG_WRITE_BUF_SZ);
308
309 msg = fsp_mkmsg(FSP_CMD_WRITE_SP_DATA, 6, FSP_DATASET_HBRT_BLOB,
310 0, 0, 0, PSI_DMA_HBRT_LOG_WRITE_BUF,
311 ent->size);
312
313 if (!msg) {
314 prerror("HBRT: Failed to create error msg log to FSP\n");
315 goto error;
316 }
317 msg->user_data = ent;
318 if (!fsp_queue_msg(msg, hservice_elog_write_complete))
319 return;
320 prerror("FSP: Error queueing elog update\n");
321 error:
322 if (msg)
323 fsp_freemsg(msg);
324 fsp_tce_unmap(PSI_DMA_HBRT_LOG_WRITE_BUF,
325 PSI_DMA_HBRT_LOG_WRITE_BUF_SZ);
326 free(ent->buf);
327 free(ent);
328 hbrt_elog_sending = false;
329 goto again;
330 }
331
hservice_send_error_log(uint32_t plid,uint32_t dsize,void * data)332 static int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data)
333 {
334 struct hbrt_elog_ent *ent;
335 void *abuf;
336
337 prlog(PR_ERR, "HBRT: Error log generated with plid 0x%08x\n", plid);
338
339 /* We only know how to send error logs to FSP */
340 if (!fsp_present()) {
341 prerror("HBRT: Warning, error log from HBRT discarded !\n");
342 return OPAL_UNSUPPORTED;
343 }
344 if (dsize > PSI_DMA_HBRT_LOG_WRITE_BUF_SZ) {
345 prerror("HBRT: Warning, error log from HBRT too big (%d) !\n",
346 dsize);
347 dsize = PSI_DMA_HBRT_LOG_WRITE_BUF_SZ;
348 }
349
350 lock(&hbrt_elog_lock);
351
352 /* Create and populate a tracking structure */
353 ent = zalloc(sizeof(struct hbrt_elog_ent));
354 if (!ent) {
355 unlock(&hbrt_elog_lock);
356 return OPAL_NO_MEM;
357 }
358
359 /* Grab a 4k aligned page */
360 abuf = memalign(0x1000, PSI_DMA_HBRT_LOG_WRITE_BUF_SZ);
361 if (!abuf) {
362 free(ent);
363 unlock(&hbrt_elog_lock);
364 return OPAL_NO_MEM;
365 }
366 memset(abuf, 0, PSI_DMA_HBRT_LOG_WRITE_BUF_SZ);
367 memcpy(abuf, data, dsize);
368 ent->buf = abuf;
369 ent->size = dsize;
370 ent->plid = plid;
371 list_add_tail(&hbrt_elogs, &ent->link);
372 if (!hbrt_elog_sending)
373 hservice_start_elog_send();
374 unlock(&hbrt_elog_lock);
375
376 return 0;
377 }
378
hservice_scom_read(uint64_t chip_id,uint64_t addr,void * buf)379 static int hservice_scom_read(uint64_t chip_id, uint64_t addr, void *buf)
380 {
381 return xscom_read(chip_id, addr, buf);
382 }
383
hservice_scom_write(uint64_t chip_id,uint64_t addr,const void * buf)384 static int hservice_scom_write(uint64_t chip_id, uint64_t addr,
385 const void *buf)
386 {
387 uint64_t val;
388
389 memcpy(&val, buf, sizeof(val));
390 return xscom_write(chip_id, addr, val);
391 }
392
393 struct hbrt_lid {
394 void *load_addr;
395 size_t len;
396 uint32_t id;
397 struct list_node link;
398 };
399 static LIST_HEAD(hbrt_lid_list);
400
401 static bool hbrt_lid_preload_complete = false;
402
hservices_lid_preload_complete(void)403 bool hservices_lid_preload_complete(void)
404 {
405 return hbrt_lid_preload_complete;
406 }
407
408 /* TODO: Few of the following routines can be generalized */
__hservice_lid_load(uint32_t lid,void ** buf,size_t * len)409 static int __hservice_lid_load(uint32_t lid, void **buf, size_t *len)
410 {
411 int rc;
412
413 /* Adjust LID side first or we get a cache mismatch */
414 lid = fsp_adjust_lid_side(lid);
415
416 /*
417 * Allocate a new buffer and load the LID into it
418 * XXX: We currently use the same size for each HBRT lid.
419 */
420 *buf = malloc(HBRT_LOAD_LID_SIZE);
421 *len = HBRT_LOAD_LID_SIZE;
422 rc = fsp_preload_lid(lid, *buf, len);
423 rc = fsp_wait_lid_loaded(lid);
424 if (rc != 0)
425 /* Take advantage of realloc corner case here. */
426 *len = 0;
427 *buf = realloc(*buf, *len);
428
429 prlog(PR_DEBUG, "HBRT: LID 0x%08x successfully loaded, len=0x%lx\n",
430 lid, (unsigned long)len);
431
432 return rc;
433 }
434
__hservice_lid_preload(const uint32_t lid)435 static int __hservice_lid_preload(const uint32_t lid)
436 {
437 struct hbrt_lid *hlid;
438 void *buf;
439 size_t len;
440 int rc;
441
442 hlid = zalloc(sizeof(struct hbrt_lid));
443 if (!hlid) {
444 prerror("HBRT: Could not allocate struct hbrt_lid\n");
445 return OPAL_NO_MEM;
446 }
447
448 rc = __hservice_lid_load(lid, &buf, &len);
449 if (rc) {
450 free(hlid);
451 return rc;
452 }
453
454 hlid->load_addr = buf;
455 hlid->len = len;
456 hlid->id = lid;
457 list_add_tail(&hbrt_lid_list, &hlid->link);
458
459 return 0;
460 }
461
462 /* Find and preload all lids needed by hostservices */
hservices_lid_preload(void)463 void hservices_lid_preload(void)
464 {
465 const uint32_t *lid_list = NULL;
466 size_t num_lids;
467 int i;
468
469 if (!hservice_runtime)
470 return;
471
472 lid_list = (const uint32_t *)hservice_runtime->get_lid_list(&num_lids);
473 if (!lid_list) {
474 prerror("HBRT: get_lid_list() returned NULL\n");
475 return;
476 }
477
478 prlog(PR_INFO, "HBRT: %d lids to load\n", (int)num_lids);
479
480 /* Currently HBRT needs only one (OCC) lid */
481 for (i = 0; i < num_lids; i++)
482 __hservice_lid_preload(lid_list[i]);
483
484 hbrt_lid_preload_complete = true;
485 occ_poke_load_queue();
486 }
487
hservice_lid_load(uint32_t lid,void ** buf,size_t * len)488 static int hservice_lid_load(uint32_t lid, void **buf, size_t *len)
489 {
490 struct hbrt_lid *hlid;
491
492 prlog(PR_INFO, "HBRT: Lid load request for 0x%08x\n", lid);
493
494 if (list_empty(&hbrt_lid_list)) { /* Should not happen */
495 /**
496 * @fwts-label HBRTlidLoadFail
497 * @fwts-advice Firmware should have aborted boot
498 */
499 prlog(PR_CRIT, "HBRT: LID Load failed\n");
500 abort();
501 }
502
503 list_for_each(&hbrt_lid_list, hlid, link) {
504 if (hlid->id == lid) {
505 *buf = hlid->load_addr;
506 *len = hlid->len;
507 prlog(PR_DEBUG, "HBRT: LID Serviced from cache,"
508 " %x, len=0x%lx\n", hlid->id, hlid->len);
509 return 0;
510 }
511 }
512 return -ENOENT;
513 }
514
hservice_lid_unload(void * buf __unused)515 static int hservice_lid_unload(void *buf __unused)
516 {
517 /* We do nothing as the LID is held in cache */
518 return 0;
519 }
520
hservice_get_reserved_mem(const char * name)521 static uint64_t hservice_get_reserved_mem(const char *name)
522 {
523 struct mem_region *region;
524 uint64_t ret;
525
526 /* We assume it doesn't change after we've unlocked it, but
527 * lock ensures list is safe to walk. */
528 lock(&mem_region_lock);
529 region = find_mem_region(name);
530 ret = region ? region->start : 0;
531 unlock(&mem_region_lock);
532
533 if (!ret)
534 prlog(PR_WARNING, "HBRT: Mem region '%s' not found !\n", name);
535
536 return ret;
537 }
538
hservice_nanosleep(uint64_t i_seconds,uint64_t i_nano_seconds)539 static void hservice_nanosleep(uint64_t i_seconds, uint64_t i_nano_seconds)
540 {
541 struct timespec ts;
542
543 ts.tv_sec = i_seconds;
544 ts.tv_nsec = i_nano_seconds;
545 nanosleep_nopoll(&ts, NULL);
546 }
547
hservice_set_special_wakeup(struct cpu_thread * cpu)548 static int hservice_set_special_wakeup(struct cpu_thread *cpu)
549 {
550 uint64_t val, core_id, poll_target, stamp;
551 int rc;
552
553 /*
554 * Note: HWP checks for checkstops, but I assume we don't need to
555 * as we wouldn't be running if one was present
556 */
557
558 /* Grab core ID once */
559 core_id = pir_to_core_id(cpu->pir);
560
561 /*
562 * The original HWp reads the XSCOM first but ignores the result
563 * and error, let's do the same until I know for sure that is
564 * not necessary
565 */
566 xscom_read(cpu->chip_id,
567 XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP),
568 &val);
569
570 /* Then we write special wakeup */
571 rc = xscom_write(cpu->chip_id,
572 XSCOM_ADDR_P8_EX_SLAVE(core_id,
573 EX_PM_SPECIAL_WAKEUP_PHYP),
574 PPC_BIT(0));
575 if (rc) {
576 prerror("HBRT: XSCOM error %d asserting special"
577 " wakeup on 0x%x\n", rc, cpu->pir);
578 return rc;
579 }
580
581 /*
582 * HWP uses the history for Perf register here, dunno why it uses
583 * that one instead of the pHyp one, maybe to avoid clobbering it...
584 *
585 * In any case, it does that to check for run/nap vs.sleep/winkle/other
586 * to decide whether to poll on checkstop or not. Since we don't deal
587 * with checkstop conditions here, we ignore that part.
588 */
589
590 /*
591 * Now poll for completion of special wakeup. The HWP is nasty here,
592 * it will poll at 5ms intervals for up to 200ms. This is not quite
593 * acceptable for us at runtime, at least not until we have the
594 * ability to "context switch" HBRT. In practice, because we don't
595 * winkle, it will never take that long, so we increase the polling
596 * frequency to 1us per poll. However we do have to keep the same
597 * timeout.
598 *
599 * We don't use time_wait_ms() either for now as we don't want to
600 * poll the FSP here.
601 */
602 stamp = mftb();
603 poll_target = stamp + msecs_to_tb(200);
604 val = 0;
605 while (!(val & EX_PM_GP0_SPECIAL_WAKEUP_DONE)) {
606 /* Wait 1 us */
607 hservice_nanosleep(0, 1000);
608
609 /* Read PM state */
610 rc = xscom_read(cpu->chip_id,
611 XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_GP0),
612 &val);
613 if (rc) {
614 prerror("HBRT: XSCOM error %d reading PM state on"
615 " 0x%x\n", rc, cpu->pir);
616 return rc;
617 }
618 /* Check timeout */
619 if (mftb() > poll_target)
620 break;
621 }
622
623 /* Success ? */
624 if (val & EX_PM_GP0_SPECIAL_WAKEUP_DONE) {
625 uint64_t now = mftb();
626 prlog(PR_TRACE, "HBRT: Special wakeup complete after %ld us\n",
627 tb_to_usecs(now - stamp));
628 return 0;
629 }
630
631 /*
632 * We timed out ...
633 *
634 * HWP has a complex workaround for HW255321 which affects
635 * Murano DD1 and Venice DD1. Ignore that for now
636 *
637 * Instead we just dump some XSCOMs for error logging
638 */
639 prerror("HBRT: Timeout on special wakeup of 0x%0x\n", cpu->pir);
640 prerror("HBRT: PM0 = 0x%016llx\n", val);
641 val = -1;
642 xscom_read(cpu->chip_id,
643 XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP),
644 &val);
645 prerror("HBRT: SPC_WKUP = 0x%016llx\n", val);
646 val = -1;
647 xscom_read(cpu->chip_id,
648 XSCOM_ADDR_P8_EX_SLAVE(core_id,
649 EX_PM_IDLE_STATE_HISTORY_PHYP),
650 &val);
651 prerror("HBRT: HISTORY = 0x%016llx\n", val);
652
653 return OPAL_HARDWARE;
654 }
655
hservice_clr_special_wakeup(struct cpu_thread * cpu)656 static int hservice_clr_special_wakeup(struct cpu_thread *cpu)
657 {
658 uint64_t val, core_id;
659 int rc;
660
661 /*
662 * Note: HWP checks for checkstops, but I assume we don't need to
663 * as we wouldn't be running if one was present
664 */
665
666 /* Grab core ID once */
667 core_id = pir_to_core_id(cpu->pir);
668
669 /*
670 * The original HWp reads the XSCOM first but ignores the result
671 * and error, let's do the same until I know for sure that is
672 * not necessary
673 */
674 xscom_read(cpu->chip_id,
675 XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP),
676 &val);
677
678 /* Then we write special wakeup */
679 rc = xscom_write(cpu->chip_id,
680 XSCOM_ADDR_P8_EX_SLAVE(core_id,
681 EX_PM_SPECIAL_WAKEUP_PHYP), 0);
682 if (rc) {
683 prerror("HBRT: XSCOM error %d deasserting"
684 " special wakeup on 0x%x\n", rc, cpu->pir);
685 return rc;
686 }
687
688 /*
689 * The original HWp reads the XSCOM again with the comment
690 * "This puts an inherent delay in the propagation of the reset
691 * transition"
692 */
693 xscom_read(cpu->chip_id,
694 XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP),
695 &val);
696
697 return 0;
698 }
699
hservice_wakeup(uint32_t i_core,uint32_t i_mode)700 static int hservice_wakeup(uint32_t i_core, uint32_t i_mode)
701 {
702 struct cpu_thread *cpu;
703 int rc = OPAL_SUCCESS;
704
705 /*
706 * Mask out the top nibble of i_core since it may contain
707 * 0x4 (which we use for XSCOM targeting)
708 */
709 i_core &= 0x0fffffff;
710
711 /* What do we need to do ? */
712 switch(i_mode) {
713 case 0: /* Assert special wakeup */
714 /* XXX Assume P8 */
715 cpu = find_cpu_by_pir(i_core << 3);
716 if (!cpu)
717 return OPAL_PARAMETER;
718 prlog(PR_DEBUG, "HBRT: Special wakeup assert for core 0x%x,"
719 " count=%d\n", i_core, cpu->hbrt_spec_wakeup);
720 if (cpu->hbrt_spec_wakeup == 0)
721 rc = hservice_set_special_wakeup(cpu);
722 if (rc == 0)
723 cpu->hbrt_spec_wakeup++;
724 return rc;
725 case 1: /* Deassert special wakeup */
726 /* XXX Assume P8 */
727 cpu = find_cpu_by_pir(i_core << 3);
728 if (!cpu)
729 return OPAL_PARAMETER;
730 prlog(PR_DEBUG, "HBRT: Special wakeup release for core"
731 " 0x%x, count=%d\n", i_core, cpu->hbrt_spec_wakeup);
732 if (cpu->hbrt_spec_wakeup == 0) {
733 prerror("HBRT: Special wakeup clear"
734 " on core 0x%x with count=0\n",
735 i_core);
736 return OPAL_WRONG_STATE;
737 }
738 /* What to do with count on errors ? */
739 cpu->hbrt_spec_wakeup--;
740 if (cpu->hbrt_spec_wakeup == 0)
741 rc = hservice_clr_special_wakeup(cpu);
742 return rc;
743 case 2: /* Clear all special wakeups */
744 prlog(PR_DEBUG, "HBRT: Special wakeup release for all cores\n");
745 for_each_cpu(cpu) {
746 if (cpu->hbrt_spec_wakeup) {
747 cpu->hbrt_spec_wakeup = 0;
748 /* What to do on errors ? */
749 hservice_clr_special_wakeup(cpu);
750 }
751 }
752 return OPAL_SUCCESS;
753 default:
754 return OPAL_PARAMETER;
755 }
756 }
757
758 static struct host_interfaces hinterface = {
759 .interface_version = HOSTBOOT_RUNTIME_INTERFACE_VERSION,
760 .puts = hservice_puts,
761 .assert = hservice_assert,
762 .malloc = hservice_malloc,
763 .free = hservice_free,
764 .realloc = hservice_realloc,
765 .send_error_log = hservice_send_error_log,
766 .scom_read = hservice_scom_read,
767 .scom_write = hservice_scom_write,
768 .lid_load = hservice_lid_load,
769 .lid_unload = hservice_lid_unload,
770 .get_reserved_mem = hservice_get_reserved_mem,
771 .wakeup = hservice_wakeup,
772 .nanosleep = hservice_nanosleep,
773 };
774
host_services_occ_load(void)775 int host_services_occ_load(void)
776 {
777 struct proc_chip *chip;
778 int rc = 0;
779
780 prlog(PR_DEBUG, "HBRT: OCC Load requested\n");
781
782 if (!(hservice_runtime && hservice_runtime->loadOCC)) {
783 prerror("HBRT: No hservice_runtime->loadOCC\n");
784 return -ENOENT;
785 }
786
787 for_each_chip(chip) {
788
789 prlog(PR_DEBUG, "HBRT: Calling loadOCC() homer"
790 " %016llx, occ_common_area %016llx, chip %04x\n",
791 chip->homer_base,
792 chip->occ_common_base,
793 chip->id);
794
795 rc = hservice_runtime->loadOCC(chip->homer_base,
796 chip->homer_base,
797 chip->occ_common_base,
798 chip->occ_common_base,
799 chip->id);
800
801 hservice_mark();
802 prlog(PR_DEBUG, "HBRT: -> rc = %d\n", rc);
803 }
804 return rc;
805 }
806
host_services_occ_start(void)807 int host_services_occ_start(void)
808 {
809 struct proc_chip *chip;
810 int i, rc = 0, nr_chips=0;
811 uint64_t chipids[MAX_CHIPS];
812
813 prlog(PR_INFO, "HBRT: OCC Start requested\n");
814
815 if (!(hservice_runtime && hservice_runtime->startOCCs)) {
816 prerror("HBRT: No hservice_runtime->startOCCs\n");
817 return -ENOENT;
818 }
819
820 for_each_chip(chip) {
821 chipids[nr_chips++] = chip->id;
822 }
823
824 for (i = 0; i < nr_chips; i++)
825 prlog(PR_TRACE, "HBRT: Calling startOCC() for %04llx\n",
826 chipids[i]);
827
828 /* Lets start all OCC */
829 rc = hservice_runtime->startOCCs(chipids, nr_chips);
830 hservice_mark();
831 prlog(PR_DEBUG, "HBRT: startOCCs() rc = %d\n", rc);
832 return rc;
833 }
834
host_services_occ_stop(void)835 int host_services_occ_stop(void)
836 {
837 int i, rc = 0, nr_slaves = 0, nr_masters = 0;
838 uint64_t *master_chipids = NULL, *slave_chipids = NULL;
839
840 prlog(PR_INFO, "HBRT: OCC Stop requested\n");
841
842 if (!(hservice_runtime && hservice_runtime->stopOCCs)) {
843 prerror("HBRT: No hservice_runtime->stopOCCs\n");
844 return -ENOENT;
845 }
846
847 rc = find_master_and_slave_occ(&master_chipids, &slave_chipids,
848 &nr_masters, &nr_slaves);
849 if (rc)
850 goto out;
851
852 for (i = 0; i < nr_slaves; i++)
853 prlog(PR_TRACE, "HBRT: Calling stopOCC() for %04llx ",
854 slave_chipids[i]);
855
856 if (!nr_slaves)
857 goto master;
858
859 /* Lets STOP all the slave OCC */
860 rc = hservice_runtime->stopOCCs(slave_chipids, nr_slaves);
861 prlog(PR_DEBUG, "HBRT: stopOCCs() slave rc = %d\n", rc);
862
863 master:
864 for (i = 0; i < nr_masters; i++)
865 prlog(PR_TRACE, "HBRT: Calling stopOCC() for %04llx ",
866 master_chipids[i]);
867
868 /* Lets STOP all the master OCC */
869 rc = hservice_runtime->stopOCCs(master_chipids, nr_masters);
870
871 hservice_mark();
872 prlog(PR_DEBUG, "HBRT: stopOCCs() master rc = %d\n", rc);
873
874 out:
875 free(master_chipids);
876 free(slave_chipids);
877 return rc;
878 }
879
host_services_occ_base_setup(void)880 void host_services_occ_base_setup(void)
881 {
882 struct proc_chip *chip;
883 uint64_t occ_common;
884
885 chip = next_chip(NULL); /* Frist chip */
886 occ_common = (uint64_t) local_alloc(chip->id, OCC_COMMON_SIZE, OCC_COMMON_SIZE);
887
888 for_each_chip(chip) {
889 chip->occ_common_base = occ_common;
890 chip->occ_common_size = OCC_COMMON_SIZE;
891
892 chip->homer_base = (uint64_t) local_alloc(chip->id, HOMER_IMAGE_SIZE,
893 HOMER_IMAGE_SIZE);
894 chip->homer_size = HOMER_IMAGE_SIZE;
895 memset((void *)chip->homer_base, 0, chip->homer_size);
896
897 prlog(PR_DEBUG, "HBRT: Chip %d HOMER base %016llx : %08llx\n",
898 chip->id, chip->homer_base, chip->homer_size);
899 prlog(PR_DEBUG, "HBRT: OCC common base %016llx : %08llx\n",
900 chip->occ_common_base, chip->occ_common_size);
901 }
902 }
903
hservices_init(void)904 bool hservices_init(void)
905 {
906 void *code = NULL;
907 struct runtime_interfaces *(*hbrt_init)(struct host_interfaces *);
908
909 struct function_descriptor {
910 void *addr;
911 void *toc;
912 } fdesc;
913
914 code = (void *)hservice_get_reserved_mem("ibm,hbrt-code-image");
915 if (!code) {
916 prerror("HBRT: No ibm,hbrt-code-image found.\n");
917 return false;
918 }
919
920 if (memcmp(code, "HBRTVERS", 8) != 0) {
921 prerror("HBRT: Bad eyecatcher for ibm,hbrt-code-image!\n");
922 return false;
923 }
924
925 prlog(PR_INFO, "HBRT: Found HostBoot Runtime version %llu\n",
926 ((u64 *)code)[1]);
927
928 /* We enter at 0x100 into the image. */
929 fdesc.addr = code + 0x100;
930 /* It doesn't care about TOC */
931 fdesc.toc = NULL;
932
933 hbrt_init = (void *)&fdesc;
934
935 hservice_runtime = hbrt_init(&hinterface);
936 hservice_mark();
937 if (!hservice_runtime) {
938 prerror("HBRT: Host services init failed\n");
939 return false;
940 }
941
942 prlog(PR_INFO, "HBRT: Interface version %llu\n",
943 hservice_runtime->interface_version);
944
945 return true;
946 }
947