diff options
-rw-r--r-- | core/hostservices.c | 62 | ||||
-rw-r--r-- | hw/fsp/fsp.c | 2 | ||||
-rw-r--r-- | hw/prd.c | 77 | ||||
-rw-r--r-- | include/fsp.h | 6 | ||||
-rw-r--r-- | include/hostservices.h | 2 | ||||
-rw-r--r-- | include/skiboot.h | 1 | ||||
-rw-r--r-- | platforms/ibm-fsp/zz.c | 1 |
7 files changed, 149 insertions, 2 deletions
diff --git a/core/hostservices.c b/core/hostservices.c index bf1b308..d515f13 100644 --- a/core/hostservices.c +++ b/core/hostservices.c @@ -879,3 +879,65 @@ out_tce_unmap: fsp_tce_unmap(PSI_DMA_HBRT_FSP_MSG, PSI_DMA_HBRT_FSP_MSG_SIZE); return rc; } + +void hservice_hbrt_msg_response(uint32_t rc) +{ + struct fsp_msg *resp; + + resp = fsp_mkmsg(FSP_RSP_FSP_TO_HBRT | (uint8_t)rc, 0); + if (!resp) { + prlog(PR_DEBUG, + "HBRT: Failed to allocate FSP - HBRT response message\n"); + return; + } + + if (fsp_queue_msg(resp, fsp_freemsg)) { + prlog(PR_DEBUG, + "HBRT: Failed to send FSP - HBRT response message\n"); + fsp_freemsg(resp); + return; + } +} + +/* FSP sends HBRT notification message. Pass this message to HBRT */ +static bool hservice_hbrt_msg_notify(uint32_t cmd_sub_mod, struct fsp_msg *msg) +{ + u32 tce_token, len; + void *buf; + + if (cmd_sub_mod != FSP_CMD_FSP_TO_HBRT) + return false; + + prlog(PR_TRACE, "HBRT: FSP - HBRT message generated\n"); + + tce_token = msg->data.words[1]; + len = msg->data.words[2]; + buf = fsp_inbound_buf_from_tce(tce_token); + if (!buf) { + prlog(PR_DEBUG, "HBRT: Invalid inbound data\n"); + hservice_hbrt_msg_response(FSP_STATUS_INVALID_DATA); + return true; + } + + if (prd_hbrt_fsp_msg_notify(buf, len)) + hservice_hbrt_msg_response(FSP_STATUS_GENERIC_FAILURE); + + return true; +} + +static struct fsp_client fsp_hbrt_msg_client = { + .message = hservice_hbrt_msg_notify, +}; + +/* Register for FSP 0xF2 class messages */ +void hservice_fsp_init(void) +{ + if (proc_gen < proc_gen_p9) + return; + + if (!fsp_present()) + return; + + /* Register for Class F2 */ + fsp_register_client(&fsp_hbrt_msg_client, FSP_MCLASS_HBRT); +} diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c index f7e6748..8fe2aed 100644 --- a/hw/fsp/fsp.c +++ b/hw/fsp/fsp.c @@ -178,6 +178,8 @@ static struct fsp_cmdclass fsp_cmdclass[FSP_MCLASS_LAST - FSP_MCLASS_FIRST + 1] DEF_CLASS(FSP_MCLASS_DIAG, 16), DEF_CLASS(FSP_MCLASS_PCIE_LINK_TOPO, 16), DEF_CLASS(FSP_MCLASS_OCC, 16), + DEF_CLASS(FSP_MCLASS_TRUSTED_BOOT, 2), + DEF_CLASS(FSP_MCLASS_HBRT, 2), }; static void fsp_trace_msg(struct fsp_msg *msg, u8 dir __unused) @@ -40,6 +40,7 @@ static uint8_t _prd_msg_buf[sizeof(struct opal_prd_msg) + sizeof(struct prd_fw_msg)]; static struct opal_prd_msg *prd_msg = (struct opal_prd_msg *)&_prd_msg_buf; static struct opal_prd_msg *prd_msg_fsp_req; +static struct opal_prd_msg *prd_msg_fsp_notify; static bool prd_msg_inuse, prd_active; static struct dt_node *prd_node; static bool prd_enabled = false; @@ -82,10 +83,11 @@ static uint64_t prd_ipoll_mask; static void send_next_pending_event(void); -static void prd_msg_consumed(void *data, int status __unused) +static void prd_msg_consumed(void *data, int status) { struct opal_prd_msg *msg = data; uint32_t proc; + int notify_status = OPAL_SUCCESS; uint8_t event = 0; lock(&events_lock); @@ -118,6 +120,18 @@ static void prd_msg_consumed(void *data, int status __unused) prd_msg_fsp_req = NULL; } break; + case OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY: + if (prd_msg_fsp_notify) { + free(prd_msg_fsp_notify); + prd_msg_fsp_notify = NULL; + } + if (status != 0) { + prlog(PR_DEBUG, + "PRD: Failed to send FSP -> HBRT message\n"); + notify_status = FSP_STATUS_GENERIC_FAILURE; + } + hservice_hbrt_msg_response(notify_status); + break; case OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH: proc = msg->sbe_passthrough.chip; event = EVENT_SBE_PASSTHROUGH; @@ -356,6 +370,67 @@ void prd_fw_resp_fsp_response(int status) unlock(&events_lock); } +int prd_hbrt_fsp_msg_notify(void *data, u32 dsize) +{ + int size; + int rc = FSP_STATUS_GENERIC_FAILURE; + enum opal_msg_type msg_type = OPAL_MSG_PRD2; + + if (!prd_enabled || !prd_active) { + prlog(PR_NOTICE, "PRD: PRD daemon is not ready\n"); + return rc; + } + + /* Calculate prd message size */ + size = sizeof(prd_msg->hdr) + sizeof(prd_msg->token) + + sizeof(prd_msg->fw_notify) + dsize; + + if (size > OPAL_PRD_MSG_SIZE_MAX) { + prlog(PR_DEBUG, "PRD: FSP - HBRT notify message size (0x%x)" + " is bigger than prd interface can handle\n", size); + return rc; + } + + lock(&events_lock); + + /* FSP - HBRT messages are serialized */ + if (prd_msg_fsp_notify) { + prlog(PR_DEBUG, "PRD: FSP - HBRT notify message is busy\n"); + goto unlock_events; + } + + /* Handle message allocation */ + prd_msg_fsp_notify = zalloc(size); + if (!prd_msg_fsp_notify) { + prlog(PR_DEBUG, + "PRD: %s: Failed to allocate memory.\n", __func__); + goto unlock_events; + } + + prd_msg_fsp_notify->hdr.type = OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY; + prd_msg_fsp_notify->hdr.size = cpu_to_be16(size); + prd_msg_fsp_notify->token = 0; + prd_msg_fsp_notify->fw_notify.len = cpu_to_be64(dsize); + memcpy(&(prd_msg_fsp_notify->fw_notify.data), data, dsize); + + /* + * If prd message size is <= OPAL_MSG_FIXED_PARAMS_SIZE then use + * OPAL_MSG_PRD to pass data to kernel. So that it works fine on + * older kernel (which does not support OPAL_MSG_PRD2). + */ + if (prd_msg_fsp_notify->hdr.size < OPAL_MSG_FIXED_PARAMS_SIZE) + msg_type = OPAL_MSG_PRD; + + rc = _opal_queue_msg(msg_type, prd_msg_fsp_notify, + prd_msg_consumed, size, prd_msg_fsp_notify); + if (!rc) + prd_msg_inuse = true; + +unlock_events: + unlock(&events_lock); + return rc; +} + /* incoming message handlers */ static int prd_msg_handle_attn_ack(struct opal_prd_msg *msg) { diff --git a/include/fsp.h b/include/fsp.h index 7518867..cfa51af 100644 --- a/include/fsp.h +++ b/include/fsp.h @@ -296,7 +296,9 @@ #define FSP_MCLASS_DIAG 0xee #define FSP_MCLASS_PCIE_LINK_TOPO 0xef #define FSP_MCLASS_OCC 0xf0 -#define FSP_MCLASS_LAST 0xf0 +#define FSP_MCLASS_TRUSTED_BOOT 0xf1 +#define FSP_MCLASS_HBRT 0xf2 +#define FSP_MCLASS_LAST 0xf2 /* * Commands are provided in rxxyyzz form where: @@ -584,6 +586,8 @@ * Class F2 */ #define FSP_CMD_HBRT_TO_FSP 0x1f20100 /* HV->FSP: HBRT message */ +#define FSP_CMD_FSP_TO_HBRT 0x0f20200 /* FSP->HV: HBRT message */ +#define FSP_RSP_FSP_TO_HBRT 0x0f28200 /* HV->FSP: HBRT message */ /* diff --git a/include/hostservices.h b/include/hostservices.h index 8c54935..bdff9da 100644 --- a/include/hostservices.h +++ b/include/hostservices.h @@ -43,5 +43,7 @@ int hservice_wakeup(uint32_t i_core, uint32_t i_mode); int fsp_occ_reset_status(u64 chipid, s64 status); int fsp_occ_load_start_status(u64 chipid, s64 status); int hservice_send_hbrt_msg(void *data, u64 dsize); +void hservice_hbrt_msg_response(uint32_t rc); +void hservice_fsp_init(void); #endif /* __HOSTSERVICES_H */ diff --git a/include/skiboot.h b/include/skiboot.h index 0a7c84a..d70d828 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -292,6 +292,7 @@ extern void prd_register_reserved_memory(void); extern void prd_fsp_occ_reset(uint32_t proc); extern void prd_fsp_occ_load_start(u32 proc); extern void prd_fw_resp_fsp_response(int status); +extern int prd_hbrt_fsp_msg_notify(void *data, u32 dsize); /* Flatten device-tree */ extern void *create_dtb(const struct dt_node *root, bool exclusive); diff --git a/platforms/ibm-fsp/zz.c b/platforms/ibm-fsp/zz.c index 29dd608..705906a 100644 --- a/platforms/ibm-fsp/zz.c +++ b/platforms/ibm-fsp/zz.c @@ -66,6 +66,7 @@ static uint32_t ibm_fsp_occ_timeout(void) static void zz_init(void) { ibm_fsp_init(); + hservice_fsp_init(); } DECLARE_PLATFORM(zz) = { |