Skip to content

Commit 5ac3d3b

Browse files
SergiiDmytrukkrystian-hebel
authored andcommitted
fetch_and_insert_vpd_rings() (#81)
* soc/power9/vpd.c: fix some comments Change-Id: If68733b6d0535589f6d997df1a209f200eff689a Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> * soc/power9/vpd.c: export vpd_find_kwd() Change-Id: If418564d2498a06b3fd6fb426016d1b82809ee0e Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> * soc/power9/rom_media.c: MVPD partition Change-Id: I1312410e76376367cc61b5f04306e77df369dc26 Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> * soc/power9/mvpd.c: implement mvpd_extract_ring() Change-Id: I29e9b193af5f001d5a1f87f538e421d74700c735 Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> * soc/power9/tor.c: implement basic tor functions Change-Id: Ic3b6a40d0d998c925d5bddf034c9314e4bc13e1f Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> * soc/power9/homer.c: proto-getPpeScanRings() Change-Id: Ibcbf19b5621554c144962c1246c3fe518ddb4afb Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> * soc/power9/tor.c: tor_fetch_and_insert_vpd_rings() This changes previous version to tor_fetch_and_insert_vpd_ring() and provides function that adds all the necessary rings (ignoring EX which are unused according to analysis) Change-Id: I2005c4f0a24615f67a4041c35ef529a6bb60a645 Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
1 parent 881547d commit 5ac3d3b

File tree

11 files changed

+2398
-26
lines changed

11 files changed

+2398
-26
lines changed

src/include/cpu/power/mvpd.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef CPU_PPC64_MVPD_H
4+
#define CPU_PPC64_MVPD_H
5+
6+
#include <stdbool.h>
7+
#include <stdint.h>
8+
9+
struct region_device;
10+
11+
void mvpd_pnor_main(void);
12+
13+
void mvpd_device_init(void);
14+
15+
void mvpd_device_unmount(void);
16+
17+
const struct region_device *mvpd_device_ro(void);
18+
19+
bool mvpd_extract_ring(const char *record_name, const char *kwd_name,
20+
uint8_t chiplet_id, uint16_t ring_id, uint8_t *buf,
21+
uint32_t buf_size);
22+
23+
#endif /* CPU_PPC64_MVPD_H */

src/include/cpu/power/vpd.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
#ifndef CPU_PPC64_VPD_H
44
#define CPU_PPC64_VPD_H
55

6+
#include <stddef.h>
7+
#include <stdint.h>
8+
9+
#define VPD_RECORD_NAME_LEN 4
10+
611
void vpd_pnor_main(void);
712

13+
/* Finds a keyword by its name. Retrieves its size too. Returns NULL on
14+
* failure. */
15+
const uint8_t *vpd_find_kwd(const uint8_t *record, const char *record_name,
16+
const char *kwd_name, size_t *size);
17+
818
#endif /* CPU_PPC64_VPD_H */

src/soc/ibm/power9/Makefile.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,9 @@ ramstage-y += rom_media.c
3030
ramstage-y += timer.c
3131
ramstage-y += istep_18_11.c
3232
ramstage-y += istep_18_12.c
33+
ramstage-y += mvpd.c
34+
ramstage-y += vpd.c
35+
ramstage-y += tor.c
36+
ramstage-y += rs4.c
3337

3438
endif

src/soc/ibm/power9/homer.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
#include <cbfs.h>
55
#include <commonlib/region.h>
66
#include <console/console.h>
7+
#include <cpu/power/mvpd.h>
78
#include <cpu/power/scom.h>
89
#include <cpu/power/spr.h>
910
#include <string.h> // memset, memcpy
1011
#include <timer.h>
1112

1213
#include "chip.h"
1314
#include "homer.h"
15+
#include "tor.h"
1416
#include "xip.h"
1517

1618
#include <lib.h>
@@ -885,6 +887,38 @@ static void istep_16_1(int this_core)
885887
// p9_stop_save_scom() and others
886888
}
887889

890+
static void getPpeScanRings(struct xip_hw_header *hw, uint8_t dd)
891+
{
892+
static uint8_t ppe[16 * KiB];
893+
894+
static uint8_t buf1[MAX_RING_BUF_SIZE];
895+
static uint8_t buf2[MAX_RING_BUF_SIZE];
896+
static uint8_t buf3[MAX_RING_BUF_SIZE];
897+
898+
uint32_t ppe_size = sizeof(ppe);
899+
900+
struct tor_hdr *rings;
901+
struct tor_hdr *overlays;
902+
903+
if (dd < 20)
904+
die("DD must be at least 20!");
905+
if (!hw->overlays.dd_support)
906+
die("Overlays must support DD!");
907+
908+
copy_section(&rings, &hw->rings, hw, dd, FIND);
909+
copy_section(&overlays, &hw->overlays, hw, dd, FIND);
910+
911+
tor_access_ring(rings, EC_TIME, PT_CME, 0, ppe, &ppe_size, GET_PPE_LEVEL_RINGS);
912+
913+
printk(BIOS_EMERG, "original ppe_size = 0x%08x\n", ppe_size);
914+
915+
tor_fetch_and_insert_vpd_rings((struct tor_hdr *)ppe, &ppe_size,
916+
sizeof(ppe), overlays,
917+
PT_CME, 32, buf1, buf2, buf3);
918+
919+
printk(BIOS_EMERG, "new ppe_size = 0x%08x\n", ppe_size);
920+
}
921+
888922
/*
889923
* This logic is for SMF disabled only!
890924
*/
@@ -947,6 +981,9 @@ void build_homer_image(void *homer_bar)
947981
build_pgpe(homer, (struct xip_pgpe_header *)(homer_bar + hw->pgpe.offset),
948982
dd);
949983

984+
// "test" of tor_fetch_and_insert_vpd_rings()
985+
getPpeScanRings(hw, dd);
986+
950987
// TBD
951988
// getPpeScanRings() for CME
952989
// layoutRingsForCME()

src/soc/ibm/power9/mvpd.c

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#include <cpu/power/mvpd.h>
4+
5+
#include <commonlib/region.h>
6+
#include <console/console.h>
7+
#include <cpu/power/vpd.h>
8+
#include <endian.h>
9+
#include <stdint.h>
10+
#include <string.h>
11+
12+
#include "tor.h"
13+
#include "rs4.h"
14+
15+
#define MVPD_TOC_ENTRIES 32
16+
#define MVPD_TOC_SIZE (MVPD_TOC_ENTRIES*sizeof(struct mvpd_toc_entry))
17+
18+
/* Each entry points to a VPD record */
19+
struct mvpd_toc_entry {
20+
char name[4]; // Name without trailing NUL byte
21+
uint16_t offset; // Offset from the beginning of partition in LE
22+
uint8_t reserved[2]; // Unused
23+
} __attribute__((packed));
24+
25+
static struct mvpd_toc_entry *find_record(struct mvpd_toc_entry *toc,
26+
const char *name)
27+
{
28+
int i = 0;
29+
for (i = 0; i < MVPD_TOC_ENTRIES; ++i) {
30+
if (memcmp(toc[i].name, name, VPD_RECORD_NAME_LEN) == 0)
31+
return &toc[i];
32+
}
33+
return NULL;
34+
}
35+
36+
/* Checks if rings ends here. End is marked by an "END" string. */
37+
static bool is_end_of_rings(const uint8_t *buf_left, uint32_t len_left)
38+
{
39+
return (len_left < 3 || memcmp(buf_left, "END", 3) == 0);
40+
}
41+
42+
/* Finds specific ring by combination of chiplet and ring ids */
43+
static struct ring_hdr *find_ring_step(uint8_t chiplet_id, uint16_t ring_id,
44+
const uint8_t **buf_left,
45+
uint32_t *len_left)
46+
{
47+
uint32_t even_odd_mask = 0;
48+
struct ring_hdr *hdr = (struct ring_hdr *)*buf_left;
49+
50+
if (*len_left < sizeof(struct ring_hdr) ||
51+
be16toh(hdr->magic) != RS4_MAGIC)
52+
return NULL;
53+
54+
*buf_left += be16toh(hdr->size);
55+
*len_left -= be16toh(hdr->size);
56+
57+
switch (even_odd_mask) {
58+
case EX_L3_REPR: even_odd_mask = 0x00001000; break;
59+
case EX_L2_REPR: even_odd_mask = 0x00000400; break;
60+
case EX_L3_REFR_TIME:
61+
case EX_L3_REFR_REPR: even_odd_mask = 0x00000040; break;
62+
63+
default: even_odd_mask = 0; break;
64+
}
65+
66+
if (be16toh(hdr->ring_id) != ring_id)
67+
return NULL;
68+
if (((be32toh(hdr->scan_addr) >> 24) & 0xFF) != chiplet_id)
69+
return NULL;
70+
if (even_odd_mask != 0 && !(be32toh(hdr->scan_addr) & even_odd_mask))
71+
return NULL;
72+
73+
return hdr;
74+
}
75+
76+
/* Searches for a specific ring in a keyword */
77+
static struct ring_hdr *find_ring(uint8_t chiplet_id, uint16_t ring_id,
78+
const uint8_t *buf, uint32_t buf_len)
79+
{
80+
/* Skip version number */
81+
--buf_len;
82+
++buf;
83+
84+
while (!is_end_of_rings(buf, buf_len)) {
85+
struct ring_hdr *ring = find_ring_step(chiplet_id, ring_id,
86+
&buf, &buf_len);
87+
if (ring != NULL)
88+
return ring;
89+
}
90+
91+
return NULL;
92+
}
93+
94+
/* Finds a specific ring in MVPD partition and extracts it */
95+
bool mvpd_extract_ring(const char *record_name, const char *kwd_name,
96+
uint8_t chiplet_id, uint16_t ring_id, uint8_t *buf,
97+
uint32_t buf_size)
98+
{
99+
const struct region_device *mvpd_device;
100+
101+
uint8_t mvpd_buf[MVPD_TOC_SIZE];
102+
struct mvpd_toc_entry *mvpd_toc = (struct mvpd_toc_entry *)mvpd_buf;
103+
104+
struct mvpd_toc_entry *cp00 = NULL;
105+
uint16_t cp00_offset = 0;
106+
const uint8_t *cp00_data = NULL;
107+
uint16_t cp00_size = 0;
108+
109+
const uint8_t *rings = NULL;
110+
size_t rings_size = 0;
111+
112+
struct ring_hdr *ring = NULL;
113+
uint32_t ring_size = 0;
114+
115+
mvpd_device_init();
116+
mvpd_device = mvpd_device_ro();
117+
118+
/* Copy all TOC at once */
119+
if (rdev_readat(mvpd_device, mvpd_buf, 0,
120+
sizeof(mvpd_buf)) != sizeof(mvpd_buf))
121+
die("Failed to read MVPD TOC!\n");
122+
123+
cp00 = find_record(mvpd_toc, record_name);
124+
if (cp00 == NULL)
125+
die("Failed to find %s MVPD record!\n", record_name);
126+
cp00_offset = le16toh(cp00->offset);
127+
128+
/* Read size of the record */
129+
if (rdev_readat(mvpd_device, &cp00_size, cp00_offset,
130+
sizeof(cp00_size)) != sizeof(cp00_size))
131+
die("Failed to read size of %s!\n", record_name);
132+
133+
cp00_data = rdev_mmap(mvpd_device, cp00_offset, cp00_size);
134+
if (!cp00_data)
135+
die("Failed to map %s record!\n", record_name);
136+
137+
rings = vpd_find_kwd(cp00_data, record_name, kwd_name, &rings_size);
138+
if (rings == NULL)
139+
die("Failed to find %s keyword in %s!\n", kwd_name,
140+
record_name);
141+
142+
ring = find_ring(chiplet_id, ring_id, rings, rings_size);
143+
if (ring == NULL) {
144+
if (rdev_munmap(mvpd_device, (void *)cp00_data))
145+
die("Failed to unmap %s record!\n", record_name);
146+
147+
return false;
148+
}
149+
150+
ring_size = be32toh(ring->size);
151+
if (buf_size >= ring_size)
152+
memcpy(buf, ring, ring_size);
153+
154+
if (rdev_munmap(mvpd_device, (void *)cp00_data))
155+
die("Failed to unmap %s record!\n", record_name);
156+
157+
return (buf_size >= ring_size);
158+
}

src/soc/ibm/power9/rom_media.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <arch/io.h>
66
#include <console/console.h>
77
#include <cpu/power/memd.h>
8+
#include <cpu/power/mvpd.h>
89
#include <endian.h>
910
#include <cbfs.h>
1011
#include <symbols.h>
@@ -17,6 +18,8 @@
1718

1819
#define MEMD_PARTITION_NAME "MEMD"
1920

21+
#define MVPD_PARTITION_NAME "MVPD"
22+
2023
/* ffs_entry is not complete in included ffs.h, it lacks user data layout.
2124
* See https://github.com/open-power/skiboot/blob/master/libflash/ffs.h */
2225

@@ -424,6 +427,9 @@ void mount_part_from_pnor(const char *part_name,
424427
size = size / 9 * 8;
425428
}
426429

430+
printk(BIOS_DEBUG, "%s is in 0x%08lx through 0x%08lx\n", part_name,
431+
base, base + size - 1);
432+
427433
mdev->rdev.region.offset = base;
428434
mdev->rdev.region.size = size;
429435

@@ -455,6 +461,35 @@ const struct region_device *memd_device_ro(void)
455461
return &memd_mdev.rdev;
456462
}
457463

464+
static struct mmap_helper_region_device mvpd_mdev = MMAP_HELPER_DEV_INIT(
465+
&no_ecc_rdev_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
466+
467+
void mvpd_device_init(void)
468+
{
469+
static int init_done;
470+
if (init_done)
471+
return;
472+
473+
mount_part_from_pnor(MVPD_PARTITION_NAME, &mvpd_mdev);
474+
/*
475+
* XXX: this is a workaround for unimplemented functionality in
476+
* mount_part_from_pnor()
477+
*/
478+
mvpd_mdev.rdev.region.offset -= 0x1200;
479+
480+
init_done = 1;
481+
}
482+
483+
void mvpd_device_unmount(void)
484+
{
485+
mvpd_mdev.rdev.ops = &no_rdev_ops;
486+
}
487+
488+
const struct region_device *mvpd_device_ro(void)
489+
{
490+
return &mvpd_mdev.rdev;
491+
}
492+
458493
static struct mmap_helper_region_device boot_mdev = MMAP_HELPER_DEV_INIT(
459494
&no_ecc_rdev_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
460495

0 commit comments

Comments
 (0)