From: Masayoshi Mizuma <msys.mizuma@gmail.com>
To: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: kexec@lists.infradead.org, Bhupesh Sharma <bhsharma@redhat.com>,
Simon Horman <horms@verge.net.au>,
James Morse <james.morse@arm.com>
Subject: Re: [PATCH v2 2/3] arm64: kexec: allocate memory space avoiding reserved regions
Date: Fri, 13 Dec 2019 15:04:30 -0500 [thread overview]
Message-ID: <20191213200430.uxuebdavpq64scfh@gabell> (raw)
In-Reply-To: <20190111095946.28070-3-takahiro.akashi@linaro.org>
some nits as below:
On Fri, Jan 11, 2019 at 06:59:45PM +0900, AKASHI Takahiro wrote:
> On UEFI/ACPI-only system, some memory regions, including but not limited
> to UEFI memory map and ACPI tables, must be preserved across kexec'ing.
> Otherwise, they can be corrupted and result in early failure in booting
> a new kernel.
>
> In recent kernels, /proc/iomem now has an extended file format like:
> 40000000-5871ffff : System RAM
> 41800000-426affff : Kernel code
> 426b0000-42aaffff : reserved
> 42ab0000-42c64fff : Kernel data
> 54400000-583fffff : Crash kernel
> 58590000-585effff : reserved
> 58700000-5871ffff : reserved
> 58720000-58b5ffff : reserved
> 58b60000-5be3ffff : System RAM
> 58b61000-58b61fff : reserved
> 59a77000-59a77fff : reserved
> 5be40000-5becffff : reserved
> 5bed0000-5bedffff : System RAM
> 5bee0000-5bffffff : reserved
> 5c000000-5fffffff : System RAM
> 5da00000-5e9fffff : reserved
> 5ec00000-5edfffff : reserved
> 5ef6a000-5ef6afff : reserved
> 5ef6b000-5efcafff : reserved
> 5efcd000-5efcffff : reserved
> 5efd0000-5effffff : reserved
> 5f000000-5fffffff : reserved
>
> where the "reserved" entries at the top level or under System RAM (and
> its descendant resources) are ones of such kind and should not be regarded
> as usable memory ranges where several free spaces for loading kexec data
> will be allocated.
>
> With this patch, get_memory_ranges() will handle this format of file
> correctly. Note that, for safety, unknown regions, in addition to
> "reserved" ones, will also be excluded.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> ---
> kexec/arch/arm64/kexec-arm64.c | 146 ++++++++++++++++++++-------------
> 1 file changed, 87 insertions(+), 59 deletions(-)
>
> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> index 1cde75d1a771..2e923b54f5b1 100644
> --- a/kexec/arch/arm64/kexec-arm64.c
> +++ b/kexec/arch/arm64/kexec-arm64.c
> @@ -10,7 +10,9 @@
> #include <inttypes.h>
> #include <libfdt.h>
> #include <limits.h>
> +#include <stdio.h>
> #include <stdlib.h>
> +#include <string.h>
> #include <sys/stat.h>
> #include <linux/elf-em.h>
> #include <elf.h>
> @@ -29,6 +31,7 @@
> #include "fs2dt.h"
> #include "iomem.h"
> #include "kexec-syscall.h"
> +#include "mem_regions.h"
> #include "arch/options.h"
>
> #define ROOT_NODE_ADDR_CELLS_DEFAULT 1
> @@ -899,19 +902,33 @@ int get_phys_base_from_pt_load(unsigned long *phys_offset)
> return 0;
> }
>
> +static bool to_be_excluded(char *str)
> +{
> + if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) ||
> + !strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) ||
> + !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) ||
> + !strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)))
> + return false;
> + else
> + return true;
> +}
> +
> /**
> - * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem.
> + * get_memory_ranges - Try to get the memory ranges from
> + * /proc/iomem.
> */
> -
> -static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
> - unsigned long long base, unsigned long long length)
> +int get_memory_ranges(struct memory_range **range, int *ranges,
> + unsigned long kexec_flags)
> {
> - int ret;
> unsigned long phys_offset = UINT64_MAX;
> - struct memory_range *r;
> -
> - if (nr >= KEXEC_SEGMENT_MAX)
> - return -1;
> + FILE *fp;
> + const char *iomem = proc_iomem();
> + char line[MAX_LINE], *str;
> + unsigned long long start, end;
> + int n, consumed;
> + struct memory_ranges memranges;
> + struct memory_range *last, excl_range;
> + int ret;
>
> if (!try_read_phys_offset_from_kcore) {
> /* Since kernel version 4.19, 'kcore' contains
> @@ -945,17 +962,65 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
> try_read_phys_offset_from_kcore = true;
> }
>
> - r = (struct memory_range *)data + nr;
> + fp = fopen(iomem, "r");
> + if (!fp)
> + die("Cannot open %s\n", iomem);
> +
> + memranges.ranges = NULL;
> + memranges.size = memranges.max_size = 0;
> +
> + while (fgets(line, sizeof(line), fp) != 0) {
> + n = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed);
> + if (n != 2)
> + continue;
> + str = line + consumed;
> +
> + if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) {
> + ret = mem_regions_alloc_and_add(&memranges,
> + start, end - start + 1, RANGE_RAM);
> + if (ret) {
> + fprintf(stderr,
> + "Cannot allocate memory for ranges\n");
fclose(fp);
> + return -ENOMEM;
> + }
>
> - if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)))
> - r->type = RANGE_RAM;
> - else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED)))
> - r->type = RANGE_RESERVED;
> - else
> - return 1;
> + dbgprintf("%s:+[%d] %016llx - %016llx\n", __func__,
> + memranges.size - 1,
> + memranges.ranges[memranges.size - 1].start,
> + memranges.ranges[memranges.size - 1].end);
> + } else if (to_be_excluded(str)) {
> + if (!memranges.size)
> + continue;
> +
> + /*
> + * Note: mem_regions_exclude() doesn't guarantee
> + * that the ranges are sorted out, but as long as
> + * we cope with /proc/iomem, we only operate on
> + * the last entry and so it is safe.
> + */
>
> - r->start = base;
> - r->end = base + length - 1;
> + /* The last System RAM range */
> + last = &memranges.ranges[memranges.size - 1];
> +
> + if (last->end < start)
> + /* New resource outside of System RAM */
> + continue;
> + if (end < last->start)
> + /* Already excluded by parent resource */
> + continue;
> +
> + excl_range.start = start;
> + excl_range.end = end;
> + mem_regions_alloc_and_exclude(&memranges, &excl_range);
ret = mem_regions_alloc_and_exclude(&memranges, &excl_range);
if (ret) {
fprintf(stderr,
"Cannot allocate memory for ranges (exclude)\n");
fclose(fp);
return -ENOMEM;
}
Thanks,
Masa
> + dbgprintf("%s:- %016llx - %016llx\n",
> + __func__, start, end);
> + }
> + }
> +
> + fclose(fp);
> +
> + *range = memranges.ranges;
> + *ranges = memranges.size;
>
> /* As a fallback option, we can try determining the PHYS_OFFSET
> * value from the '/proc/iomem' entries as well.
> @@ -976,52 +1041,15 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
> * between the user-space and kernel space 'PHYS_OFFSET'
> * value.
> */
> - set_phys_offset(r->start, "iomem");
> + if (memranges.size)
> + set_phys_offset(memranges.ranges[0].start, "iomem");
>
> - dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start,
> - r->end, str);
> + dbgprint_mem_range("System RAM ranges;",
> + memranges.ranges, memranges.size);
>
> return 0;
> }
>
> -/**
> - * get_memory_ranges_iomem - Try to get the memory ranges from
> - * /proc/iomem.
> - */
> -
> -static int get_memory_ranges_iomem(struct memory_range *array,
> - unsigned int *count)
> -{
> - *count = kexec_iomem_for_each_line(NULL,
> - get_memory_ranges_iomem_cb, array);
> -
> - if (!*count) {
> - dbgprintf("%s: failed: No RAM found.\n", __func__);
> - return EFAILED;
> - }
> -
> - return 0;
> -}
> -
> -/**
> - * get_memory_ranges - Try to get the memory ranges some how.
> - */
> -
> -int get_memory_ranges(struct memory_range **range, int *ranges,
> - unsigned long kexec_flags)
> -{
> - static struct memory_range array[KEXEC_SEGMENT_MAX];
> - unsigned int count;
> - int result;
> -
> - result = get_memory_ranges_iomem(array, &count);
> -
> - *range = result ? NULL : array;
> - *ranges = result ? 0 : count;
> -
> - return result;
> -}
> -
> int arch_compat_trampoline(struct kexec_info *info)
> {
> return 0;
> --
> 2.19.1
>
>
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2019-12-13 20:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-11 9:59 [PATCH v2 0/3] arm64: handle "reserved" entries in /proc/iomem AKASHI Takahiro
2019-01-11 9:59 ` [PATCH v2 1/3] kexec: add variant helper functions for handling memory regions AKASHI Takahiro
2019-01-11 9:59 ` [PATCH v2 2/3] arm64: kexec: allocate memory space avoiding reserved regions AKASHI Takahiro
2019-12-13 20:04 ` Masayoshi Mizuma [this message]
2019-12-16 5:52 ` Bhupesh Sharma
2019-12-16 14:16 ` Masayoshi Mizuma
2019-12-18 2:48 ` AKASHI Takahiro
2019-12-18 15:08 ` Masayoshi Mizuma
2019-01-11 9:59 ` [PATCH v2 3/3] arm64: kdump: deal with a lot of resource entries in /proc/iomem AKASHI Takahiro
2019-01-13 11:36 ` [PATCH v2 0/3] arm64: handle "reserved" " Bhupesh Sharma
2019-12-13 19:53 ` Masayoshi Mizuma
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191213200430.uxuebdavpq64scfh@gabell \
--to=msys.mizuma@gmail.com \
--cc=bhsharma@redhat.com \
--cc=horms@verge.net.au \
--cc=james.morse@arm.com \
--cc=kexec@lists.infradead.org \
--cc=takahiro.akashi@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox