[PATCH 2/2] kexec/ppc64: add support to parse ibm, dynamic-memory-v2 property
Mahesh Jagannath Salgaonkar
mahesh at linux.vnet.ibm.com
Wed Feb 21 01:10:47 PST 2018
On 02/20/2018 07:48 PM, Hari Bathini wrote:
> Add support to parse the new 'ibm,dynamic-memory-v2' property in the
> 'ibm,dynamic-reconfiguration-memory' node. This replaces the old
> 'ibm,dynamic-memory' property and is enabled in the kernel with a
> patch series that starts with commit 0c38ed6f6f0b ("powerpc/pseries:
> Enable support of ibm,dynamic-memory-v2"). All LMBs that share the same
> flags and are adjacent are grouped together in the newer version of the
> property making it compact to represent larger memory configurations.
>
> Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
Thanks for fixing this. Patches looks good to me.
Reviewed-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> ---
> kexec/arch/ppc64/crashdump-ppc64.c | 23 +++++++--
> kexec/arch/ppc64/crashdump-ppc64.h | 16 +++++-
> kexec/arch/ppc64/kexec-ppc64.c | 35 ++++++++++----
> kexec/fs2dt.c | 92 ++++++++++++++++++++++--------------
> 4 files changed, 112 insertions(+), 54 deletions(-)
>
> diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
> index bc9f948..50e3853 100644
> --- a/kexec/arch/ppc64/crashdump-ppc64.c
> +++ b/kexec/arch/ppc64/crashdump-ppc64.c
> @@ -39,6 +39,10 @@
> #define DEVTREE_CRASHKERNEL_BASE "/proc/device-tree/chosen/linux,crashkernel-base"
> #define DEVTREE_CRASHKERNEL_SIZE "/proc/device-tree/chosen/linux,crashkernel-size"
>
> +unsigned int num_of_lmb_sets;
> +unsigned int is_dyn_mem_v2;
> +uint64_t lmb_size;
> +
> static struct crash_elf_info elf_info64 =
> {
> class: ELFCLASS64,
> @@ -127,6 +131,7 @@ static int get_dyn_reconf_crash_memory_ranges(void)
> {
> uint64_t start, end;
> uint64_t startrange, endrange;
> + uint64_t size;
> char fname[128], buf[32];
> FILE *file;
> unsigned int i;
> @@ -135,6 +140,8 @@ static int get_dyn_reconf_crash_memory_ranges(void)
>
> strcpy(fname, "/proc/device-tree/");
> strcat(fname, "ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory");
> + if (is_dyn_mem_v2)
> + strcat(fname, "-v2");
> if ((file = fopen(fname, "r")) == NULL) {
> perror(fname);
> return -1;
> @@ -142,8 +149,9 @@ static int get_dyn_reconf_crash_memory_ranges(void)
>
> fseek(file, 4, SEEK_SET);
> startrange = endrange = 0;
> - for (i = 0; i < num_of_lmbs; i++) {
> - if ((n = fread(buf, 1, 24, file)) < 0) {
> + size = lmb_size;
> + for (i = 0; i < num_of_lmb_sets; i++) {
> + if ((n = fread(buf, 1, LMB_ENTRY_SIZE, file)) < 0) {
> perror(fname);
> fclose(file);
> return -1;
> @@ -156,8 +164,15 @@ static int get_dyn_reconf_crash_memory_ranges(void)
> return -1;
> }
>
> - start = be64_to_cpu(((uint64_t *)buf)[DRCONF_ADDR]);
> - end = start + lmb_size;
> + /*
> + * If the property is ibm,dynamic-memory-v2, the first 4 bytes
> + * tell the number of sequential LMBs in this entry.
> + */
> + if (is_dyn_mem_v2)
> + size = be32_to_cpu(((unsigned int *)buf)[0]) * lmb_size;
> +
> + start = be64_to_cpu(*((uint64_t *)&buf[DRCONF_ADDR]));
> + end = start + size;
> if (start == 0 && end >= (BACKUP_SRC_END + 1))
> start = BACKUP_SRC_END + 1;
>
> diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h
> index 42ccc31..87beb39 100644
> --- a/kexec/arch/ppc64/crashdump-ppc64.h
> +++ b/kexec/arch/ppc64/crashdump-ppc64.h
> @@ -34,10 +34,18 @@ extern unsigned int rtas_size;
> extern uint64_t opal_base;
> extern uint64_t opal_size;
>
> -uint64_t lmb_size;
> -unsigned int num_of_lmbs;
> -
> -#define DRCONF_ADDR 0
> +/*
> + * In case of ibm,dynamic-memory-v2 property, this is the number of LMB
> + * sets where each set represents a group of sequential LMB entries. In
> + * case of ibm,dynamic-memory property, the number of LMB sets is nothing
> + * but the total number of LMB entries.
> + */
> +extern unsigned int num_of_lmb_sets;
> +extern unsigned int is_dyn_mem_v2;
> +extern uint64_t lmb_size;
> +
> +#define LMB_ENTRY_SIZE 24
> +#define DRCONF_ADDR (is_dyn_mem_v2 ? 4 : 0)
> #define DRCONF_FLAGS 20
>
> #endif /* CRASHDUMP_PPC64_H */
> diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
> index a7d708b..4e70b13 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-ppc64.c
> @@ -149,6 +149,7 @@ static void add_base_memory_range(uint64_t start, uint64_t end)
> static int get_dyn_reconf_base_ranges(void)
> {
> uint64_t start, end;
> + uint64_t size;
> char fname[128], buf[32];
> FILE *file;
> unsigned int i;
> @@ -166,29 +167,35 @@ static int get_dyn_reconf_base_ranges(void)
> return -1;
> }
> /*
> - * lmb_size, num_of_lmbs(global variables) are
> + * lmb_size, num_of_lmb_sets(global variables) are
> * initialized once here.
> */
> - lmb_size = be64_to_cpu(((uint64_t *)buf)[0]);
> + size = lmb_size = be64_to_cpu(((uint64_t *)buf)[0]);
> fclose(file);
>
> strcpy(fname, "/proc/device-tree/");
> strcat(fname,
> "ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory");
> if ((file = fopen(fname, "r")) == NULL) {
> - perror(fname);
> - return -1;
> + strcat(fname, "-v2");
> + if ((file = fopen(fname, "r")) == NULL) {
> + perror(fname);
> + return -1;
> + }
> +
> + is_dyn_mem_v2 = 1;
> }
> - /* first 4 bytes tell the number of lmbs */
> +
> + /* first 4 bytes tell the number of lmb set entries */
> if (fread(buf, 1, 4, file) != 4) {
> perror(fname);
> fclose(file);
> return -1;
> }
> - num_of_lmbs = be32_to_cpu(((unsigned int *)buf)[0]);
> + num_of_lmb_sets = be32_to_cpu(((unsigned int *)buf)[0]);
>
> - for (i = 0; i < num_of_lmbs; i++) {
> - if ((n = fread(buf, 1, 24, file)) < 0) {
> + for (i = 0; i < num_of_lmb_sets; i++) {
> + if ((n = fread(buf, 1, LMB_ENTRY_SIZE, file)) < 0) {
> perror(fname);
> fclose(file);
> return -1;
> @@ -196,13 +203,21 @@ static int get_dyn_reconf_base_ranges(void)
> if (nr_memory_ranges >= max_memory_ranges)
> return -1;
>
> - start = be64_to_cpu(((uint64_t *)buf)[0]);
> - end = start + lmb_size;
> + /*
> + * If the property is ibm,dynamic-memory-v2, the first 4 bytes
> + * tell the number of sequential LMBs in this entry.
> + */
> + if (is_dyn_mem_v2)
> + size = be32_to_cpu(((unsigned int *)buf)[0]) * lmb_size;
> +
> + start = be64_to_cpu(*((uint64_t *)&buf[DRCONF_ADDR]));
> + end = start + size;
> add_base_memory_range(start, end);
> }
> fclose(file);
> return 0;
> }
> +
> /* Sort the base ranges in memory - this is useful for ensuring that our
> * ranges are in ascending order, even if device-tree read of memory nodes
> * is done differently. Also, could be used for other range coalescing later
> diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
> index 550eca9..07a5e2f 100644
> --- a/kexec/fs2dt.c
> +++ b/kexec/fs2dt.c
> @@ -217,11 +217,12 @@ static uint64_t add_ranges(uint64_t **ranges, int *ranges_size, int idx,
> static void add_dyn_reconf_usable_mem_property__(int fd)
> {
> char fname[MAXPATH], *bname;
> - uint64_t buf[32];
> + char buf[32];
> + uint32_t lmbs_in_set = 1;
> uint64_t *ranges;
> int ranges_size = MEM_RANGE_CHUNK_SZ;
> uint64_t base, end, rngs_cnt;
> - size_t i;
> + size_t i, j;
> int rlen = 0;
> int tmp_indx;
>
> @@ -242,43 +243,61 @@ static void add_dyn_reconf_usable_mem_property__(int fd)
> ranges_size*8);
>
> rlen = 0;
> - for (i = 0; i < num_of_lmbs; i++) {
> - if (read(fd, buf, 24) < 0)
> + for (i = 0; i < num_of_lmb_sets; i++) {
> + if (read(fd, buf, LMB_ENTRY_SIZE) < 0)
> die("unrecoverable error: error reading \"%s\": %s\n",
> pathname, strerror(errno));
>
> - base = be64_to_cpu((uint64_t) buf[0]);
> - end = base + lmb_size;
> - if (~0ULL - base < end)
> - die("unrecoverable error: mem property overflow\n");
> -
> - tmp_indx = rlen++;
> -
> - rngs_cnt = add_ranges(&ranges, &ranges_size, rlen,
> - base, end);
> - if (rngs_cnt == 0) {
> - /* We still need to add a counter for every LMB because
> - * the kernel parsing code is dumb. We just have
> - * a zero in this case, with no following base/len.
> - */
> - ranges[tmp_indx] = 0;
> - /* rlen is already just tmp_indx+1 as we didn't write
> - * anything. Check array size here, as we'll probably
> - * go on for a while writing zeros now.
> - */
> - if (rlen >= (ranges_size-1)) {
> - ranges_size += MEM_RANGE_CHUNK_SZ;
> - ranges = realloc(ranges, ranges_size*8);
> - if (!ranges)
> - die("unrecoverable error: can't"
> - " realloc %d bytes for"
> - " ranges.\n",
> - ranges_size*8);
> + /*
> + * If the property is ibm,dynamic-memory-v2, the first 4 bytes
> + * tell the number of sequential LMBs in this entry. Else, if
> + * the property is ibm,dynamic-memory, each entry represents
> + * one LMB. Make sure to add an entry for each LMB as kernel
> + * looks for a counter for every LMB.
> + */
> + if (is_dyn_mem_v2)
> + lmbs_in_set = be32_to_cpu(((unsigned int *)buf)[0]);
> +
> + base = be64_to_cpu(*((uint64_t *)&buf[DRCONF_ADDR]));
> + for (j = 0; j < lmbs_in_set; j++) {
> + end = base + lmb_size;
> + if (~0ULL - base < end) {
> + die("unrecoverable error: mem property"
> + " overflow\n");
> }
> - } else {
> - /* Store the count of (base, size) duple */
> - ranges[tmp_indx] = cpu_to_be64(rngs_cnt);
> - rlen += rngs_cnt * 2;
> +
> + tmp_indx = rlen++;
> +
> + rngs_cnt = add_ranges(&ranges, &ranges_size, rlen,
> + base, end);
> + if (rngs_cnt == 0) {
> + /* We still need to add a counter for every LMB
> + * because the kernel parsing code is dumb. We
> + * just have a zero in this case, with no
> + * following base/len.
> + */
> + ranges[tmp_indx] = 0;
> +
> + /* rlen is already just tmp_indx+1 as we didn't
> + * write anything. Check array size here, as we
> + * will probably go on writing zeros for a while
> + */
> + if (rlen >= (ranges_size-1)) {
> + ranges_size += MEM_RANGE_CHUNK_SZ;
> + ranges = realloc(ranges, ranges_size*8);
> + if (!ranges)
> + die("unrecoverable error: can't"
> + " realloc %d bytes for"
> + " ranges.\n",
> + ranges_size*8);
> + }
> + } else {
> + /* Store the count of (base, size) duple */
> + ranges[tmp_indx] = cpu_to_be64(rngs_cnt);
> + rlen += rngs_cnt * 2;
> + }
> +
> + base = end;
> }
> }
>
> @@ -298,7 +317,8 @@ static void add_dyn_reconf_usable_mem_property__(int fd)
>
> static void add_dyn_reconf_usable_mem_property(struct dirent *dp, int fd)
> {
> - if (!strcmp(dp->d_name, "ibm,dynamic-memory") && usablemem_rgns.size)
> + if ((!strcmp(dp->d_name, "ibm,dynamic-memory-v2") ||
> + !strcmp(dp->d_name, "ibm,dynamic-memory")) && usablemem_rgns.size)
> add_dyn_reconf_usable_mem_property__(fd);
> }
> #else
>
More information about the kexec
mailing list