[Skiboot] [PATCH v7 14/22] fadump: Add OPAL API to register for fadump
Vasant Hegde
hegdevasant at linux.vnet.ibm.com
Sat Apr 13 19:15:40 AEST 2019
This patch adds new API for fadump.
int64_t opal_fadump_manage(uint64_t cmd, void *data, uint64_t dsize)
cmd : 0x01 -> Register for fadump
0x02 -> Unregister fadump
0x03 -> Invalidate existing dump
data : For cmd = 0x01, data contains payload section reservation details
(uses fadump structure format to send data).
For other cmd values, data will be NULL.
dsize: Size of data
Return values:
OPAL_SUCCESS : Operation success
OPAL_PARAMETER : Payload passed invalid data
OPAL_RESOURCE : Ran out of MDST or MDDT table size
OPAL_PERMISSION: Already registered
OPAL_HARDWARE : Fadump not supported
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
core/opal-dump.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++
include/opal-api.h | 13 +++-
2 files changed, 206 insertions(+), 1 deletion(-)
diff --git a/core/opal-dump.c b/core/opal-dump.c
index 8e4014335..6400cbdb1 100644
--- a/core/opal-dump.c
+++ b/core/opal-dump.c
@@ -37,6 +37,197 @@ static struct spira_ntuple *ntuple_mdst;
static struct spira_ntuple *ntuple_mddt;
static struct spira_ntuple *ntuple_mdrt;
+/* Clear MDRT memory */
+static inline void opal_dump_invalidate(void)
+{
+ struct mdrt_table *mdrt = (void *)(MDRT_TABLE_BASE);
+
+ memset(mdrt, 0, MDRT_TABLE_SIZE);
+ /* Reset MDRT count */
+ ntuple_mdrt->act_cnt =
+ cpu_to_be16(MDRT_TABLE_SIZE / sizeof(struct mdrt_table));
+ ntuple_mdrt->alloc_cnt =
+ cpu_to_be16(MDRT_TABLE_SIZE / sizeof(struct mdrt_table));
+}
+
+static void opal_dump_unregister(void)
+{
+ int i, j;
+ struct mdst_table *mdst, *tmp_mdst;
+ struct mddt_table *mddt, *tmp_mddt;
+
+ mdst = (void *)(MDST_TABLE_BASE);
+ for (i = 0; i < ntuple_mdst->act_cnt; ) {
+ if (mdst->dump_type != DUMP_TYPE_FADUMP ||
+ mdst->data_region < FADUMP_REGION_HOST_START) {
+ mdst++;
+ i++;
+ continue;
+ }
+
+ tmp_mdst = mdst;
+ memset(tmp_mdst, 0, sizeof(struct mdst_table));
+ for (j = i; j < ntuple_mdst->act_cnt - 1; j++) {
+ memcpy((void *)tmp_mdst,
+ (void *)(tmp_mdst + 1), sizeof(struct mdst_table));
+ tmp_mdst++;
+ memset(tmp_mdst, 0, sizeof(struct mdst_table));
+ }
+ ntuple_mdst->act_cnt--;
+ }
+
+ mddt = (void *)(MDDT_TABLE_BASE);
+ for (i = 0; i < ntuple_mddt->act_cnt; ) {
+ if (mddt->data_region < FADUMP_REGION_HOST_START) {
+ mddt++;
+ i++;
+ continue;
+ }
+
+ tmp_mddt = mddt;
+ memset(tmp_mddt, 0, sizeof(struct mddt_table));
+ for (j = i; j < ntuple_mddt->act_cnt - 1; j++) {
+ memcpy((void *)tmp_mddt,
+ (void *)(tmp_mddt + 1), sizeof(struct mddt_table));
+ tmp_mddt++;
+ memset(tmp_mddt, 0, sizeof(struct mddt_table));
+ }
+ ntuple_mddt->act_cnt--;
+ }
+}
+
+static int opal_dump_register(void *data, uint64_t dsize)
+{
+ int i, sec_cnt, max_mdst_entry, max_mddt_entry;
+ struct fadump_section *section;
+ struct fadump *fadump = (void *)data;
+ struct mdst_table *mdst = (void *)(MDST_TABLE_BASE);
+ struct mddt_table *mddt = (void *)(MDDT_TABLE_BASE);
+
+ if (dsize < sizeof(struct fadump)) {
+ prlog(PR_DEBUG, "data size [0x%llx] < minimum size [0x%lx]\n",
+ dsize, sizeof(struct fadump));
+ return OPAL_PARAMETER;
+ }
+
+ sec_cnt = be16_to_cpu(fadump->section_count);
+ if (sec_cnt <= 0) {
+ prlog(PR_DEBUG, "Invalid section count = 0x%x\n", sec_cnt);
+ return OPAL_PARAMETER;
+ }
+
+ max_mdst_entry = MDST_TABLE_SIZE / sizeof(struct mdst_table);
+ if (ntuple_mdst->act_cnt >= (max_mdst_entry + sec_cnt)) {
+ prlog(PR_DEBUG, "MDST table is full\n");
+ return OPAL_RESOURCE;
+ }
+
+ max_mddt_entry = MDDT_TABLE_SIZE / sizeof(struct mddt_table);
+ if (ntuple_mddt->act_cnt >= (max_mddt_entry + sec_cnt)) {
+ prlog(PR_DEBUG, "MDDT table is full\n");
+ return OPAL_RESOURCE;
+ }
+
+ /* Already registered ? */
+ for (i = 0; i < ntuple_mdst->act_cnt; i++) {
+ if (mdst->dump_type == DUMP_TYPE_FADUMP &&
+ mdst->data_region >= FADUMP_REGION_HOST_START) {
+ prlog(PR_DEBUG, "Already registered\n");
+ return OPAL_PERMISSION;
+ }
+ mdst++;
+ }
+
+ mdst = (struct mdst_table *)(MDST_TABLE_BASE +
+ ntuple_mdst->act_cnt * sizeof(struct mdst_table));
+ mddt = (struct mddt_table *)(MDDT_TABLE_BASE +
+ ntuple_mddt->act_cnt * sizeof(struct mddt_table));
+ for (i = 0; i < sec_cnt; i++) {
+ section = &(fadump->section[i]);
+
+ if (section->source_type < FADUMP_REGION_HOST_START) {
+ prlog(PR_DEBUG, "Invalid source type [0x%x]\n",
+ section->source_type);
+ goto clr_entry;
+ }
+
+ if (!opal_addr_valid((void *)section->source_addr)) {
+ prlog(PR_DEBUG, "Invalid source address [0x%llx]\n",
+ section->source_addr);
+ goto clr_entry;
+ }
+
+ if (!opal_addr_valid((void *)section->dest_addr)) {
+ prlog(PR_DEBUG, "Invalid dest address [0x%llx]\n",
+ section->dest_addr);
+ goto clr_entry;
+ }
+
+ if (section->source_size <= 0) {
+ prlog(PR_DEBUG, "Invalid source size [0x%llx]\n",
+ section->source_size);
+ goto clr_entry;
+ }
+
+ if (section->dest_size <= 0) {
+ prlog(PR_DEBUG, "Invalid source size [0x%llx]\n",
+ section->dest_size);
+ goto clr_entry;
+ }
+
+ mdst->dump_type = DUMP_TYPE_FADUMP;
+ mdst->data_region = section->source_type;
+ mdst->addr = section->source_addr | HRMOR_BIT;
+ mdst->size = section->source_size;
+ mdst++;
+ ntuple_mdst->act_cnt++;
+
+ mddt->data_region = section->source_type;
+ mddt->addr = section->dest_addr | HRMOR_BIT;
+ mddt->size = section->dest_size;
+ mddt++;
+ ntuple_mddt->act_cnt++;
+
+ prlog(PR_NOTICE, "Registered new entry : src - 0x%llx, "
+ "dst - 0x%llx, size - 0x%llx\n", section->source_addr,
+ section->dest_addr, section->source_size);
+ }
+
+ return OPAL_SUCCESS;
+
+clr_entry:
+ opal_dump_unregister();
+ return OPAL_PARAMETER;
+}
+
+static int64_t opal_fadump_manage(uint64_t cmd, void *data, uint64_t dsize)
+{
+ int rc = OPAL_SUCCESS;
+
+ prlog(PR_TRACE, "opal_fadump_manage : cmd - 0x%llx\n", cmd);
+
+ switch (cmd) {
+ case OPAL_FADUMP_REGISTER:
+ rc = opal_dump_register(data, dsize);
+ if (rc == OPAL_SUCCESS)
+ prlog(PR_NOTICE, "Payload registered for fadump\n");
+ break;
+ case OPAL_FADUMP_UNREGISTER:
+ opal_dump_unregister();
+ prlog(PR_NOTICE, "Payload unregistered for fadump\n");
+ break;
+ case OPAL_FADUMP_INVALIDATE:
+ opal_dump_invalidate();
+ prlog(PR_NOTICE, "Payload invalidated fadump\n");
+ break;
+ default:
+ prlog(PR_ERR, "Unsupported command : 0x%llx\n", cmd);
+ rc = OPAL_PARAMETER;
+ break;
+ }
+
+ return rc;
+}
/* Reserve OPAL dump destination memory */
static void add_dump_reserve_node(struct dt_node *dump_node)
@@ -171,4 +362,7 @@ void opal_dump_init(void)
ntuple_mdrt = &(spirah.ntuples.mdump_res);
adjust_opal_dump_size(dump_node);
+
+ /* OPAL interface */
+ opal_register(OPAL_FADUMP_MANAGE, opal_fadump_manage, 3);
}
diff --git a/include/opal-api.h b/include/opal-api.h
index e783540e1..702e70841 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -229,7 +229,8 @@
#define OPAL_XIVE_GET_VP_STATE 170 /* Get NVT state */
#define OPAL_NPU_RESERVED1 171 /* LPC Allocate */
#define OPAL_NPU_RESERVED2 172 /* LPC Release */
-#define OPAL_LAST 172
+#define OPAL_FADUMP_MANAGE 173
+#define OPAL_LAST 173
#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
@@ -1350,6 +1351,16 @@ struct fadump {
struct fadump_section section[];
};
+/*
+ * Command option argument for fadump manage API (OPAL_FADUMP_MANAGE)
+ * - for registration payload should pass memory reservation details
+ * - Unregister option removes all entries from payload
+ * - Invalidate option invalidatates existing fadump
+ * */
+#define OPAL_FADUMP_REGISTER 0x01
+#define OPAL_FADUMP_UNREGISTER 0x02
+#define OPAL_FADUMP_INVALIDATE 0x03
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_API_H */
--
2.14.3
More information about the Skiboot
mailing list