-
Notifications
You must be signed in to change notification settings - Fork 134
/
opal-dump.c
144 lines (121 loc) · 3.83 KB
/
opal-dump.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* Copyright 2019 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define pr_fmt(fmt) "DUMP: " fmt
#include <device.h>
#include <mem-map.h>
#include <mem_region.h>
#include <mem_region-malloc.h>
#include <opal.h>
#include <opal-dump.h>
#include <opal-internal.h>
#include <skiboot.h>
#include <ccan/endian/endian.h>
#include "hdata/spira.h"
/* Actual address of MDST and MDDT table */
#define MDST_TABLE_BASE (SKIBOOT_BASE + MDST_TABLE_OFF)
#define MDDT_TABLE_BASE (SKIBOOT_BASE + MDDT_TABLE_OFF)
static struct spira_ntuple *ntuple_mdst;
static struct spira_ntuple *ntuple_mddt;
static struct spira_ntuple *ntuple_mdrt;
static int opal_mpipl_add_entry(u8 region, u64 src, u64 dest, u64 size)
{
int i, max_cnt;
struct mdst_table *mdst;
struct mddt_table *mddt;
max_cnt = MDST_TABLE_SIZE / sizeof(struct mdst_table);
if (ntuple_mdst->act_cnt >= max_cnt) {
prlog(PR_DEBUG, "MDST table is full\n");
return OPAL_RESOURCE;
}
max_cnt = MDDT_TABLE_SIZE / sizeof(struct mddt_table);
if (ntuple_mdst->act_cnt >= max_cnt) {
prlog(PR_DEBUG, "MDDT table is full\n");
return OPAL_RESOURCE;
}
/* Use relocated memory address */
mdst = (void *)(MDST_TABLE_BASE);
mddt = (void *)(MDDT_TABLE_BASE);
/* Check for duplicate entry */
for (i = 0; i < ntuple_mdst->act_cnt; i++) {
if (mdst->addr == (src | HRMOR_BIT)) {
prlog(PR_DEBUG,
"Duplicate source address : 0x%llx", src);
return OPAL_PARAMETER;
}
mdst++;
}
for (i = 0; i < ntuple_mddt->act_cnt; i++) {
if (mddt->addr == (dest | HRMOR_BIT)) {
prlog(PR_DEBUG,
"Duplicate destination address : 0x%llx", dest);
return OPAL_PARAMETER;
}
mddt++;
}
/* Add OPAL source address to MDST entry */
mdst->addr = src | HRMOR_BIT;
mdst->data_region = region;
mdst->size = size;
ntuple_mdst->act_cnt++;
/* Add OPAL destination address to MDDT entry */
mddt->addr = dest | HRMOR_BIT;
mddt->data_region = region;
mddt->size = size;
ntuple_mddt->act_cnt++;
prlog(PR_TRACE, "Added new entry. src : 0x%llx, dest : 0x%llx,"
" size : 0x%llx\n", src, dest, size);
return OPAL_SUCCESS;
}
/* Register for OPAL dump. */
static void opal_mpipl_register(void)
{
u64 opal_dest, opal_size;
/* Get OPAL runtime size */
if (!dt_find_property(opal_node, "opal-runtime-size")) {
prlog(PR_DEBUG, "Could not get OPAL runtime size\n");
return;
}
opal_size = dt_prop_get_u64(opal_node, "opal-runtime-size");
if (!opal_size) {
prlog(PR_DEBUG, "OPAL runtime size is zero\n");
return;
}
/* Calculate and reserve OPAL dump destination memory */
opal_dest = SKIBOOT_BASE + opal_size;
mem_reserve_fw("ibm,firmware-dump", opal_dest, opal_size);
/* Add OPAL reservation detail to MDST/MDDT table */
opal_mpipl_add_entry(DUMP_REGION_OPAL_MEMORY,
SKIBOOT_BASE, opal_dest, opal_size);
}
void opal_mpipl_init(void)
{
void *mdst_base = (void *)MDST_TABLE_BASE;
void *mddt_base = (void *)MDDT_TABLE_BASE;
struct dt_node *dump_node;
dump_node = dt_find_by_path(opal_node, "dump");
if (!dump_node)
return;
/* Get MDST and MDDT ntuple from SPIRAH */
ntuple_mdst = &(spirah.ntuples.mdump_src);
ntuple_mddt = &(spirah.ntuples.mdump_dst);
ntuple_mdrt = &(spirah.ntuples.mdump_res);
/* Clear MDST and MDDT table */
memset(mdst_base, 0, MDST_TABLE_SIZE);
ntuple_mdst->act_cnt = 0;
memset(mddt_base, 0, MDDT_TABLE_SIZE);
ntuple_mddt->act_cnt = 0;
opal_mpipl_register();
}