Skip to content

Commit

Permalink
MPIPL: Add OPAL API to register for dump region
Browse files Browse the repository at this point in the history
This patch add new API to register for dump region.
  u64 opal_mpipl_update(u8 ops, u64 src, u64 dest, u64 size)

  ops :
    OPAL_MPIPL_ADD_RANGE
      Add new entry to MPIPL table. Kernel will send src, dest and size.
      During MPIPL content from source address is moved to destination address.
        src  = Source start address
        dest = Destination start address
        size = size

    OPAL_MPIPL_REMOVE_RANGE
      Remove kernel requested entry from MPIPL table.
        src  = Source start address
        dest = Destination start address
        size = ignore

    OPAL_MPIPL_REMOVE_ALL
      Remove all kernel passed entry from MPIPL table.
        src  = ignore
        dest = ignore
        size = ignore

    OPAL_MPIPL_FREE_PRESERVED_MEMORY
      Post MPIPL, kernel will indicate OPAL that it has processed dump and
      it can clear/release metadata area.
        src  = ignore
        dest = ignore
        size = ignore

Return values:
  OPAL_SUCCESS   : Operation success
  OPAL_PARAMETER : Payload passed invalid data
  OPAL_RESOURCE  : Ran out of MDST or MDDT table size
  OPAL_HARDWARE  : MPIPL not supported

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
[oliver: rebased]
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
  • Loading branch information
Vasant Hegde authored and oohal committed Aug 15, 2019
1 parent 4f94bda commit ef6da5f
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 1 deletion.
181 changes: 181 additions & 0 deletions core/opal-dump.c
Expand Up @@ -96,6 +96,102 @@ static int opal_mpipl_add_entry(u8 region, u64 src, u64 dest, u64 size)
return OPAL_SUCCESS;
}

/* Remove entry from source (MDST) table */
static int opal_mpipl_remove_entry_mdst(bool remove_all, u8 region, u64 src)
{
bool found = false;
int i, j;
struct mdst_table *tmp_mdst;
struct mdst_table *mdst = (void *)(MDST_TABLE_BASE);

for (i = 0; i < ntuple_mdst->act_cnt;) {
if (mdst->data_region != region) {
mdst++;
i++;
continue;
}

if (remove_all != true && mdst->addr != (src | HRMOR_BIT)) {
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--;

if (remove_all == false) {
found = true;
break;
}
} /* end - for loop */

if (remove_all == false && found == false) {
prlog(PR_DEBUG,
"Source address [0x%llx] not found in MDST table\n", src);
return OPAL_PARAMETER;
}

return OPAL_SUCCESS;
}

/* Remove entry from destination (MDDT) table */
static int opal_mpipl_remove_entry_mddt(bool remove_all, u8 region, u64 dest)
{
bool found = false;
int i, j;
struct mddt_table *tmp_mddt;
struct mddt_table *mddt = (void *)(MDDT_TABLE_BASE);

for (i = 0; i < ntuple_mddt->act_cnt;) {
if (mddt->data_region != region) {
mddt++;
i++;
continue;
}

if (remove_all != true && mddt->addr != (dest | HRMOR_BIT)) {
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--;

if (remove_all == false) {
found = true;
break;
}
} /* end - for loop */

if (remove_all == false && found == false) {
prlog(PR_DEBUG,
"Dest address [0x%llx] not found in MDDT table\n", dest);
return OPAL_PARAMETER;
}

return OPAL_SUCCESS;
}

/* Register for OPAL dump. */
static void opal_mpipl_register(void)
{
Expand All @@ -121,6 +217,88 @@ static void opal_mpipl_register(void)
SKIBOOT_BASE, opal_dest, opal_size);
}

static int payload_mpipl_register(u64 src, u64 dest, u64 size)
{
if (!opal_addr_valid((void *)src)) {
prlog(PR_DEBUG, "Invalid source address [0x%llx]\n", src);
return OPAL_PARAMETER;
}

if (!opal_addr_valid((void *)dest)) {
prlog(PR_DEBUG, "Invalid dest address [0x%llx]\n", dest);
return OPAL_PARAMETER;
}

if (size <= 0) {
prlog(PR_DEBUG, "Invalid size [0x%llx]\n", size);
return OPAL_PARAMETER;
}

return opal_mpipl_add_entry(DUMP_REGION_KERNEL, src, dest, size);
}

static int payload_mpipl_unregister(u64 src, u64 dest)
{
int rc;

/* Remove src from MDST table */
rc = opal_mpipl_remove_entry_mdst(false, DUMP_REGION_KERNEL, src);
if (rc)
return rc;

/* Remove dest from MDDT table */
rc = opal_mpipl_remove_entry_mddt(false, DUMP_REGION_KERNEL, dest);
return rc;
}

static int payload_mpipl_unregister_all(void)
{
opal_mpipl_remove_entry_mdst(true, DUMP_REGION_KERNEL, 0);
opal_mpipl_remove_entry_mddt(true, DUMP_REGION_KERNEL, 0);

return OPAL_SUCCESS;
}

static int64_t opal_mpipl_update(enum opal_mpipl_ops ops,
u64 src, u64 dest, u64 size)
{
int rc;

switch (ops) {
case OPAL_MPIPL_ADD_RANGE:
rc = payload_mpipl_register(src, dest, size);
if (!rc)
prlog(PR_NOTICE, "Payload registered for MPIPL\n");
break;
case OPAL_MPIPL_REMOVE_RANGE:
rc = payload_mpipl_unregister(src, dest);
if (!rc) {
prlog(PR_NOTICE, "Payload removed entry from MPIPL."
"[src : 0x%llx, dest : 0x%llx]\n", src, dest);
}
break;
case OPAL_MPIPL_REMOVE_ALL:
rc = payload_mpipl_unregister_all();
if (!rc)
prlog(PR_NOTICE, "Payload unregistered for MPIPL\n");
break;
case OPAL_MPIPL_FREE_PRESERVED_MEMORY:
/* Clear MDRT table */
memset((void *)MDRT_TABLE_BASE, 0, MDRT_TABLE_SIZE);
/* Set MDRT count to max allocated count */
ntuple_mdrt->act_cnt = MDRT_TABLE_SIZE / sizeof(struct mdrt_table);
rc = OPAL_SUCCESS;
prlog(PR_NOTICE, "Payload Invalidated MPIPL\n");
break;
default:
prlog(PR_DEBUG, "Unsupported MPIPL update operation : 0x%x\n", ops);
rc = OPAL_PARAMETER;
break;
}

return rc;
}

void opal_mpipl_init(void)
{
void *mdst_base = (void *)MDST_TABLE_BASE;
Expand Down Expand Up @@ -154,4 +332,7 @@ void opal_mpipl_init(void)
ntuple_mddt->act_cnt = 0;

opal_mpipl_register();

/* OPAL API for MPIPL update */
opal_register(OPAL_MPIPL_UPDATE, opal_mpipl_update, 4);
}
11 changes: 10 additions & 1 deletion include/opal-api.h
Expand Up @@ -219,7 +219,8 @@
#define OPAL_XIVE_GET_VP_STATE 170 /* Get NVT state */
#define OPAL_NPU_MEM_ALLOC 171
#define OPAL_NPU_MEM_RELEASE 172
#define OPAL_LAST 172
#define OPAL_MPIPL_UPDATE 173
#define OPAL_LAST 173

#define QUIESCE_HOLD 1 /* Spin all calls at entry */
#define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
Expand Down Expand Up @@ -1202,6 +1203,14 @@ enum {
OPAL_PCI_P2P_TARGET = 1,
};

/* MPIPL update operations */
enum opal_mpipl_ops {
OPAL_MPIPL_ADD_RANGE = 0,
OPAL_MPIPL_REMOVE_RANGE = 1,
OPAL_MPIPL_REMOVE_ALL = 2,
OPAL_MPIPL_FREE_PRESERVED_MEMORY= 3,
};

#endif /* __ASSEMBLY__ */

#endif /* __OPAL_API_H */
1 change: 1 addition & 0 deletions include/opal-dump.h
Expand Up @@ -20,6 +20,7 @@
#define DUMP_REGION_CONSOLE 0x01
#define DUMP_REGION_HBRT_LOG 0x02
#define DUMP_REGION_OPAL_MEMORY 0x03
#define DUMP_REGION_KERNEL 0x80

/* Mainstore memory to be captured by FSP SYSDUMP */
#define DUMP_TYPE_SYSDUMP 0xF5
Expand Down

0 comments on commit ef6da5f

Please sign in to comment.