From ca6dd51bdcbedda73e1ea194c6c8c0d772c188e9 Mon Sep 17 00:00:00 2001 From: yangzhenyu Date: Wed, 27 Nov 2024 14:54:11 +0800 Subject: [PATCH] Add pstore segment support Signed-off-by: yangzhenyu --- ...nt-thus-it-is-able-to-record-log-of-.patch | 215 ++++++++++++++++++ kdumpctl | 36 ++- kexec-tools.spec | 5 + 3 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 Add-pstore-segment-thus-it-is-able-to-record-log-of-.patch diff --git a/Add-pstore-segment-thus-it-is-able-to-record-log-of-.patch b/Add-pstore-segment-thus-it-is-able-to-record-log-of-.patch new file mode 100644 index 0000000..807219a --- /dev/null +++ b/Add-pstore-segment-thus-it-is-able-to-record-log-of-.patch @@ -0,0 +1,215 @@ +From bc26427db2a54001c79f2ae343f23637f08e5873 Mon Sep 17 00:00:00 2001 +From: Yangzhenyu +Date: Wed, 27 Nov 2024 11:26:35 +0800 +Subject: [PATCH] Add pstore segment thus it is able to record log of kdump + process + +--- + kexec/arch/arm64/crashdump-arm64.c | 5 ++ + kexec/arch/i386/crashdump-x86.c | 12 ++++- + kexec/kexec.c | 81 ++++++++++++++++++++++++++++++ + kexec/kexec.h | 5 ++ + 4 files changed, 101 insertions(+), 2 deletions(-) + +diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c +index 3098315..6aa954c 100644 +--- a/kexec/arch/arm64/crashdump-arm64.c ++++ b/kexec/arch/arm64/crashdump-arm64.c +@@ -125,6 +125,11 @@ static int crash_get_memory_ranges(void) + if (!usablemem_rgns.size) + return -EINVAL; + ++ usablemem_rgns.ranges[usablemem_rgns.size - 1].end -= PSTORE_SIZE; ++ ++ dbgprintf("Created pstore segment at 0x%lx\n", ++ usablemem_rgns.ranges[usablemem_rgns.size - 1].end); ++ + dbgprint_mem_range("Reserved memory range", + usablemem_rgns.ranges, usablemem_rgns.size); + +diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c +index df1f24c..3614007 100644 +--- a/kexec/arch/i386/crashdump-x86.c ++++ b/kexec/arch/i386/crashdump-x86.c +@@ -823,7 +823,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, + unsigned long max_addr, unsigned long min_base) + { + void *tmp; +- unsigned long sz, bufsz, memsz, elfcorehdr; ++ unsigned long sz, bufsz, memsz, elfcorehdr, pstore_sz, pstore_start; + int nr_ranges = 0, nr_memmap = 0, align = 1024, i; + struct memory_range *mem_range, *memmap_p; + struct crash_elf_info elf_info; +@@ -923,6 +923,14 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, + } + } + ++ pstore_sz = _ALIGN(PSTORE_SIZE, align); ++ pstore_start = (unsigned long)crash_reserved_mem[crash_reserved_mem_nr - 1].start; ++ dbgprintf("Created pstore segment at 0x%lx\n", pstore_start); ++ if (delete_memmap(memmap_p, &nr_memmap, pstore_start, pstore_sz) < 0) { ++ free(memmap_p); ++ return EFAILED; ++ } ++ + /* Create elf header segment and store crash image data. */ + if (arch_options.core_header_type == CORE_TYPE_ELF64) { + if (crash_create_elf64_headers(info, &elf_info, mem_range, +@@ -1004,7 +1012,7 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) + if (!crash_reserved_mem_nr) + return -1; + +- *start = crash_reserved_mem[crash_reserved_mem_nr - 1].start; ++ *start = crash_reserved_mem[crash_reserved_mem_nr - 1].start + PSTORE_SIZE; + *end = crash_reserved_mem[crash_reserved_mem_nr - 1].end; + + return 0; +diff --git a/kexec/kexec.c b/kexec/kexec.c +index 447dc7a..ecfc29d 100644 +--- a/kexec/kexec.c ++++ b/kexec/kexec.c +@@ -40,6 +40,7 @@ + #endif + #include + #include ++#include + + #include "config.h" + +@@ -638,6 +639,80 @@ char *slurp_decompress_file(const char *filename, off_t *r_size) + return kernel_buf; + } + ++static int readlog(unsigned long long paddrbase) ++{ ++ const char kcore[] = "/proc/kcore"; ++ Elf64_Ehdr *elf64; ++ Elf64_Phdr *load64, *notes64, *lp64; ++ char eheader[MAX_KCORE_ELF_HEADER_SIZE], console_buf[1000000], tty_buf[100000]; ++ int fd, i, segments; ++ unsigned long long console_offset, tty_offset, console_vaddr, tty_vaddr, ++ console_paddr, tty_paddr, page_offset; ++ const unsigned long long pud_mask = ~((1 << 30) - 1); ++ ++ #ifdef __x86_64__ ++ page_offset = 0; ++ #endif ++ #ifdef __aarch64__ ++ page_offset = 0xfffeffffc0000000; ++ #endif ++ console_paddr = paddrbase + 0xe00c; ++ tty_paddr = paddrbase + 0x5000c; ++ ++ if ((fd = open(kcore, O_RDONLY)) < 0) { ++ fprintf(stderr, "Cannot open %s: %s\n", kcore, strerror(errno)); ++ return -1; ++ } ++ ++ if (read(fd, eheader, MAX_KCORE_ELF_HEADER_SIZE) != MAX_KCORE_ELF_HEADER_SIZE) { ++ fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno)); ++ return -1; ++ } ++ ++ elf64 = (Elf64_Ehdr *)&eheader[0]; ++ ++ notes64 = (Elf64_Phdr *)&eheader[elf64->e_phoff]; ++ load64 = notes64 + 1; ++ ++ segments = elf64->e_phnum - 1; ++ ++ if (page_offset == 0) { ++ for ( i = 0; i < segments; i++) { ++ lp64 = load64 + i; ++ if (lp64->p_type == PT_LOAD) ++ if ((page_offset == 0) | page_offset > (lp64->p_vaddr & pud_mask)) ++ page_offset = lp64->p_vaddr & pud_mask; ++ } ++ } ++ console_vaddr = console_paddr + page_offset; ++ tty_vaddr = tty_paddr + page_offset; ++ ++ for ( i = 0; i < segments; i++) { ++ lp64 = load64 + i; ++ if ((console_vaddr >= lp64->p_vaddr) && (console_vaddr < (lp64->p_vaddr + lp64->p_memsz))) { ++ console_offset = console_vaddr - lp64->p_vaddr + lp64->p_offset; ++ tty_offset = tty_vaddr - lp64->p_vaddr + lp64->p_offset; ++ break; ++ } ++ } ++ ++ memset(console_buf, 0, sizeof(console_buf)); ++ memset(tty_buf, 0, sizeof(tty_buf)); ++ ++ off_t c_offset = lseek(fd, console_offset, SEEK_SET); ++ size_t c_size = read(fd, console_buf, 1000000); ++ ++ off_t t_offset = lseek(fd, tty_offset, SEEK_SET); ++ size_t t_size = read(fd, tty_buf, 100000); ++ ++ printf("console log: \n%s\nttylog:\n%s\n", console_buf, tty_buf); ++ ++ close(fd); ++ ++ return 0; ++} ++ ++ + static void update_purgatory(struct kexec_info *info) + { + static const uint8_t null_buf[256]; +@@ -1016,6 +1091,7 @@ void usage(void) + "\n" + " -h, --help Print this help.\n" + " -v, --version Print the version of kexec.\n" ++ " -r, --read Print the logs of kdump process.\n" + " -f, --force Force an immediate kexec,\n" + " don't call shutdown.\n" + " -i, --no-checks Fast reboot, no memory integrity checks.\n" +@@ -1419,6 +1495,7 @@ int main(int argc, char *argv[]) + int opt; + int result = 0; + int fileind; ++ unsigned long long phy_addr; + static const struct option options[] = { + KEXEC_ALL_OPTIONS + { 0, 0, 0, 0}, +@@ -1441,6 +1518,10 @@ int main(int argc, char *argv[]) + case OPT_VERSION: + version(); + return 0; ++ case OPT_READ: ++ phy_addr = strtoul(optarg, &endptr, 0); ++ readlog(phy_addr); ++ return 0; + case OPT_DEBUG: + kexec_debug = 1; + break; +diff --git a/kexec/kexec.h b/kexec/kexec.h +index 3209d09..424b739 100644 +--- a/kexec/kexec.h ++++ b/kexec/kexec.h +@@ -233,9 +233,11 @@ extern int file_types; + #define OPT_LOAD_LIVE_UPDATE 263 + #define OPT_EXEC_LIVE_UPDATE 264 + #define OPT_MAX 265 ++#define OPT_READ 266 + #define KEXEC_OPTIONS \ + { "help", 0, 0, OPT_HELP }, \ + { "version", 0, 0, OPT_VERSION }, \ ++ { "read", 1, 0, OPT_READ }, \ + { "force", 0, 0, OPT_FORCE }, \ + { "no-checks", 0, 0, OPT_NOCHECKS }, \ + { "no-ifdown", 0, 0, OPT_NOIFDOWN }, \ +@@ -320,6 +322,9 @@ int parse_iomem_single(char *str, uint64_t *start, uint64_t *end); + const char * proc_iomem(void); + + #define MAX_LINE 160 ++#define PSTORE_SIZE 0x60000 ++#define MAX_KCORE_ELF_HEADER_SIZE (32768) ++ + + char *concat_cmdline(const char *base, const char *append); + void cmdline_add_liveupdate(char **base); +-- +2.43.0 + diff --git a/kdumpctl b/kdumpctl index 00c0064..7dfe33c 100755 --- a/kdumpctl +++ b/kdumpctl @@ -28,6 +28,7 @@ standard_kexec_args="-p" # Some default values in case /etc/sysconfig/kdump doesn't include KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug" +PSTORE_COMMANDLINE_TMP="ramoops.mem_address=0xtmp ramoops.mem_size=0x60000 ramoops.console_size=0x48000 ramoops.ttyprobe_size=0x10000 ramoops.ecc=0 ramoops.dump_oops=0" if [ -f /etc/sysconfig/kdump ]; then . /etc/sysconfig/kdump @@ -677,6 +678,8 @@ check_rebuild() # as the currently running kernel. load_kdump() { + local PSTORE_START + local OLD_START KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}") KDUMP_COMMANDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}") @@ -685,6 +688,22 @@ load_kdump() KEXEC_ARGS="$KEXEC_ARGS -s" fi + if [[ $(uname -m) == x86_64 ]]; then + PSTORE_START="0x$(grep Crash /proc/iomem | tail -n 1 | cut -d'-' -f1 | sed -e 's/^[[:space:]]*//')" + else + PSTORE_START="0x$(printf "%x" $(( "0x$(grep Crash /proc/iomem | tail -n 1 | cut -d'-' -f2 | cut -d' ' -f1)" - 0x60000 + 1 )))" + fi + + if [[ $KDUMP_COMMANDLINE == *"ramoops.mem_address"* ]]; then + OLD_START=$(echo $KDUMP_COMMANDLINE | awk -F "ramoops.mem_address=" '{print $2}') + if [[ $OLD_START != $PSTORE_START ]]; then + KDUMP_COMMANDLINE=${KDUMP_COMMANDLINE/"mem_address=${OLD_START}"/"mem_address=${PSTORE_START}"} + fi + else + PSTORE_COMMANDLINE_TMP=${PSTORE_COMMANDLINE_TMP/"0xtmp"/"${PSTORE_START}"} + KDUMP_COMMANDLINE="$KDUMP_COMMANDLINE $PSTORE_COMMANDLINE_TMP" + fi + $KEXEC $KEXEC_ARGS $standard_kexec_args \ --command-line="$KDUMP_COMMANDLINE" \ --initrd=$TARGET_INITRD $kdump_kernel @@ -1230,6 +1249,18 @@ rebuild() { return $? } +read_log() +{ + local PSTORE_START + LOG_ARGS="--read" + if [[ $(uname -m) == x86_64 ]]; then + PSTORE_START="0x$(grep Crash /proc/iomem | tail -n 1 | cut -d'-' -f1 | sed -e 's/^[[:space:]]*//')" + else + PSTORE_START="0x$(printf "%x" $(( "0x$(grep Crash /proc/iomem | tail -n 1 | cut -d'-' -f2 | cut -d' ' -f1)" - 0x60000 + 1 )))" + fi + $KEXEC $LOG_ARGS $PSTORE_START +} + if [ ! -f "$KDUMP_CONFIG_FILE" ]; then echo "Error: No kdump config file found!" >&2 exit 1 @@ -1285,8 +1316,11 @@ main () showmem) show_reserved_mem ;; + readlog) + read_log + ;; *) - echo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem}" + echo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem|readlod}" exit 1 esac } diff --git a/kexec-tools.spec b/kexec-tools.spec index aed1acc..6e24c50 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -88,6 +88,8 @@ Patch0007: kexec-tools-fix-riscv-support.patch Patch0008: Add-loongarch-iomem.h.patch %endif +Patch0009: Add-pstore-segment-thus-it-is-able-to-record-log-of-.patch + %description kexec-tools provides /sbin/kexec binary that facilitates a new kernel to boot using the kernel's kexec feature either on a @@ -295,6 +297,9 @@ done %endif %changelog +* Wed Nov 27 2024 Yangzhenyu - 2.0.26-9 +- Add pstore segment thus it is able to record log of kdump process + * Fri Sep 20 2024 chenguokai - 2.0.26-8 - Fix multiple issues of riscv image format & initrd support -- Gitee