svn commit: r366542 - in head/sys: amd64/amd64 arm/arm arm64/arm64 kern riscv/riscv sys
Mitchell Horne
mhorne at freebsd.org
Thu Oct 8 18:31:42 UTC 2020
On Thu, Oct 8, 2020 at 3:19 PM Ravi Pokala <rpokala at freebsd.org> wrote:
>
> Hi Mitchell,
>
> +static void
> +preload_dump_internal(struct sbuf *sbp)
> +{
> + uint32_t *bptr, type, len;
> +
> + KASSERT(preload_metadata != NULL,
> + ("%s called without setting up preload_metadata", __func__));
> +
> + /*
> + * Iterate through the TLV-encoded sections.
> + */
> + bptr = (uint32_t *)preload_metadata;
> + sbuf_putc(sbp, '\n');
> + while (bptr[0] != MODINFO_END || bptr[0] != MODINFO_END) {
>
> The same expression is on both sides of the "||" ...?
>
> Thanks,
>
> Ravi (rpokala@)
Thank you for catching this --- it should be checking bptr[0] and
bptr[1]. Fixed in r366543.
Mitchell
>
> + sbuf_printf(sbp, " %p:\n", bptr);
> + type = *bptr++;
> + len = *bptr++;
> +
> + sbuf_printf(sbp, "\ttype:\t(%#04x) ", type);
> + preload_modinfo_type(sbp, type);
> + sbuf_putc(sbp, '\n');
> + sbuf_printf(sbp, "\tlen:\t%u\n", len);
> + sbuf_cat(sbp, "\tvalue:\t");
> + preload_modinfo_value(sbp, bptr, type, len);
> + sbuf_putc(sbp, '\n');
> +
> + bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t);
> + }
> +}
>
>
>
>
> -----Original Message-----
> From: <owner-src-committers at freebsd.org> on behalf of Mitchell Horne <mhorne at FreeBSD.org>
> Date: 2020-10-08, Thursday at 11:02
> To: <src-committers at freebsd.org>, <svn-src-all at freebsd.org>, <svn-src-head at freebsd.org>
> Subject: svn commit: r366542 - in head/sys: amd64/amd64 arm/arm arm64/arm64 kern riscv/riscv sys
>
> Author: mhorne
> Date: Thu Oct 8 18:02:05 2020
> New Revision: 366542
> URL: https://svnweb.freebsd.org/changeset/base/366542
>
> Log:
> Add a routine to dump boot metadata
>
> The boot metadata (also referred to as modinfo, or preload metadata)
> provides information about the size and location of the kernel,
> pre-loaded modules, and other metadata (e.g. the EFI framebuffer) to be
> consumed during by the kernel during early boot. It is encoded as a
> series of type-length-value entries and is usually constructed by
> loader(8) and passed to the kernel. It is also faked on some
> architectures when booted by other means.
>
> Although much of the module information is available via kldstat(8),
> there is no easy way to debug the metadata in its entirety. Add some
> routines to parse this data and allow it to be printed to the console
> during early boot or output via a sysctl.
>
> Since the output can be lengthly, printing to the console is gated
> behind the debug.dump_modinfo_at_boot kenv variable as well as the
> BOOTVERBOSE flag. The sysctl to print the metadata is named
> debug.dump_modinfo.
>
> Reviewed by: tsoome
> Sponsored by: NetApp, Inc.
> Sponsored by: Klara, Inc.
> Differential Revision: https://reviews.freebsd.org/D26687
>
> Modified:
> head/sys/amd64/amd64/machdep.c
> head/sys/arm/arm/machdep.c
> head/sys/arm64/arm64/machdep.c
> head/sys/kern/subr_module.c
> head/sys/riscv/riscv/machdep.c
> head/sys/sys/linker.h
>
> Modified: head/sys/amd64/amd64/machdep.c
> ==============================================================================
> --- head/sys/amd64/amd64/machdep.c Thu Oct 8 17:30:05 2020 (r366541)
> +++ head/sys/amd64/amd64/machdep.c Thu Oct 8 18:02:05 2020 (r366542)
> @@ -1853,6 +1853,15 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
> if (late_console)
> cninit();
>
> + /*
> + * Dump the boot metadata. We have to wait for cninit() since console
> + * output is required. If it's grossly incorrect the kernel will never
> + * make it this far.
> + */
> + if ((boothowto & RB_VERBOSE) &&
> + getenv_is_true("debug.dump_modinfo_at_boot"))
> + preload_dump();
> +
> #ifdef DEV_ISA
> #ifdef DEV_ATPIC
> elcr_probe();
>
> Modified: head/sys/arm/arm/machdep.c
> ==============================================================================
> --- head/sys/arm/arm/machdep.c Thu Oct 8 17:30:05 2020 (r366541)
> +++ head/sys/arm/arm/machdep.c Thu Oct 8 18:02:05 2020 (r366542)
> @@ -1027,6 +1027,15 @@ initarm(struct arm_boot_params *abp)
> debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp);
> arm_print_kenv();
>
> + /*
> + * Dump the boot metadata. We have to wait for cninit() since console
> + * output is required. If it's grossly incorrect the kernel will never
> + * make it this far.
> + */
> + if ((boothowto & RB_VERBOSE) &&
> + getenv_is_true("debug.dump_modinfo_at_boot"))
> + preload_dump();
> +
> env = kern_getenv("kernelname");
> if (env != NULL) {
> strlcpy(kernelname, env, sizeof(kernelname));
>
> Modified: head/sys/arm64/arm64/machdep.c
> ==============================================================================
> --- head/sys/arm64/arm64/machdep.c Thu Oct 8 17:30:05 2020 (r366541)
> +++ head/sys/arm64/arm64/machdep.c Thu Oct 8 18:02:05 2020 (r366542)
> @@ -1242,6 +1242,15 @@ initarm(struct arm64_bootparams *abp)
> panic("Invalid bus configuration: %s",
> kern_getenv("kern.cfg.order"));
>
> + /*
> + * Dump the boot metadata. We have to wait for cninit() since console
> + * output is required. If it's grossly incorrect the kernel will never
> + * make it this far.
> + */
> + if ((boothowto & RB_VERBOSE) &&
> + getenv_is_true("debug.dump_modinfo_at_boot"))
> + preload_dump();
> +
> init_proc0(abp->kern_stack);
> msgbufinit(msgbufp, msgbufsize);
> mutex_init();
>
> Modified: head/sys/kern/subr_module.c
> ==============================================================================
> --- head/sys/kern/subr_module.c Thu Oct 8 17:30:05 2020 (r366541)
> +++ head/sys/kern/subr_module.c Thu Oct 8 18:02:05 2020 (r366542)
> @@ -3,6 +3,8 @@
> *
> * Copyright (c) 1998 Michael Smith
> * All rights reserved.
> + * Copyright (c) 2020 NetApp Inc.
> + * Copyright (c) 2020 Klara Inc.
> *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> @@ -32,7 +34,11 @@ __FBSDID("$FreeBSD$");
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/linker.h>
> +#include <sys/sbuf.h>
> +#include <sys/sysctl.h>
>
> +#include <machine/metadata.h>
> +
> #include <vm/vm.h>
> #include <vm/vm_extern.h>
>
> @@ -304,3 +310,249 @@ preload_bootstrap_relocate(vm_offset_t offset)
> }
> }
> }
> +
> +/*
> + * Parse the modinfo type and append to the provided sbuf.
> + */
> +static void
> +preload_modinfo_type(struct sbuf *sbp, int type)
> +{
> +
> + if ((type & MODINFO_METADATA) == 0) {
> + switch (type) {
> + case MODINFO_END:
> + sbuf_cat(sbp, "MODINFO_END");
> + break;
> + case MODINFO_NAME:
> + sbuf_cat(sbp, "MODINFO_NAME");
> + break;
> + case MODINFO_TYPE:
> + sbuf_cat(sbp, "MODINFO_TYPE");
> + break;
> + case MODINFO_ADDR:
> + sbuf_cat(sbp, "MODINFO_ADDR");
> + break;
> + case MODINFO_SIZE:
> + sbuf_cat(sbp, "MODINFO_SIZE");
> + break;
> + case MODINFO_EMPTY:
> + sbuf_cat(sbp, "MODINFO_EMPTY");
> + break;
> + case MODINFO_ARGS:
> + sbuf_cat(sbp, "MODINFO_ARGS");
> + break;
> + default:
> + sbuf_cat(sbp, "unrecognized modinfo attribute");
> + }
> +
> + return;
> + }
> +
> + sbuf_cat(sbp, "MODINFO_METADATA | ");
> + switch (type & ~MODINFO_METADATA) {
> + case MODINFOMD_ELFHDR:
> + sbuf_cat(sbp, "MODINFOMD_ELFHDR");
> + break;
> + case MODINFOMD_SSYM:
> + sbuf_cat(sbp, "MODINFOMD_SSYM");
> + break;
> + case MODINFOMD_ESYM:
> + sbuf_cat(sbp, "MODINFOMD_ESYM");
> + break;
> + case MODINFOMD_DYNAMIC:
> + sbuf_cat(sbp, "MODINFOMD_DYNAMIC");
> + break;
> + case MODINFOMD_ENVP:
> + sbuf_cat(sbp, "MODINFOMD_ENVP");
> + break;
> + case MODINFOMD_HOWTO:
> + sbuf_cat(sbp, "MODINFOMD_HOWTO");
> + break;
> + case MODINFOMD_KERNEND:
> + sbuf_cat(sbp, "MODINFOMD_KERNEND");
> + break;
> + case MODINFOMD_SHDR:
> + sbuf_cat(sbp, "MODINFOMD_SHDR");
> + break;
> + case MODINFOMD_CTORS_ADDR:
> + sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR");
> + break;
> + case MODINFOMD_CTORS_SIZE:
> + sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE");
> + break;
> + case MODINFOMD_FW_HANDLE:
> + sbuf_cat(sbp, "MODINFOMD_FW_HANDLE");
> + break;
> + case MODINFOMD_KEYBUF:
> + sbuf_cat(sbp, "MODINFOMD_KEYBUF");
> + break;
> +#ifdef MODINFOMD_SMAP
> + case MODINFOMD_SMAP:
> + sbuf_cat(sbp, "MODINFOMD_SMAP");
> + break;
> +#endif
> +#ifdef MODINFOMD_SMAP_XATTR
> + case MODINFOMD_SMAP_XATTR:
> + sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR");
> + break;
> +#endif
> +#ifdef MODINFOMD_DTBP
> + case MODINFOMD_DTBP:
> + sbuf_cat(sbp, "MODINFOMD_DTBP");
> + break;
> +#endif
> +#ifdef MODINFOMD_EFI_MAP
> + case MODINFOMD_EFI_MAP:
> + sbuf_cat(sbp, "MODINFOMD_EFI_MAP");
> + break;
> +#endif
> +#ifdef MODINFOMD_EFI_FB
> + case MODINFOMD_EFI_FB:
> + sbuf_cat(sbp, "MODINFOMD_EFI_FB");
> + break;
> +#endif
> +#ifdef MODINFOMD_MODULEP
> + case MODINFOMD_MODULEP:
> + sbuf_cat(sbp, "MODINFOMD_MODULEP");
> + break;
> +#endif
> + default:
> + sbuf_cat(sbp, "unrecognized metadata type");
> + }
> +}
> +
> +/*
> + * Print the modinfo value, depending on type.
> + */
> +static void
> +preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len)
> +{
> +#ifdef __LP64__
> +#define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%016lx", o);
> +#else
> +#define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%08x", o);
> +#endif
> +
> + switch (type) {
> + case MODINFO_NAME:
> + case MODINFO_TYPE:
> + case MODINFO_ARGS:
> + sbuf_printf(sbp, "%s", (char *)bptr);
> + break;
> + case MODINFO_SIZE:
> + case MODINFO_METADATA | MODINFOMD_CTORS_SIZE:
> + sbuf_printf(sbp, "%lu", *(u_long *)bptr);
> + break;
> + case MODINFO_ADDR:
> + case MODINFO_METADATA | MODINFOMD_SSYM:
> + case MODINFO_METADATA | MODINFOMD_ESYM:
> + case MODINFO_METADATA | MODINFOMD_DYNAMIC:
> + case MODINFO_METADATA | MODINFOMD_KERNEND:
> + case MODINFO_METADATA | MODINFOMD_ENVP:
> + case MODINFO_METADATA | MODINFOMD_CTORS_ADDR:
> +#ifdef MODINFOMD_SMAP
> + case MODINFO_METADATA | MODINFOMD_SMAP:
> +#endif
> +#ifdef MODINFOMD_SMAP_XATTR
> + case MODINFO_METADATA | MODINFOMD_SMAP_XATTR:
> +#endif
> +#ifdef MODINFOMD_DTBP
> + case MODINFO_METADATA | MODINFOMD_DTBP:
> +#endif
> +#ifdef MODINFOMD_EFI_FB
> + case MODINFO_METADATA | MODINFOMD_EFI_FB:
> +#endif
> + sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr);
> + break;
> + case MODINFO_METADATA | MODINFOMD_HOWTO:
> + sbuf_printf(sbp, "0x%08x", *bptr);
> + break;
> + case MODINFO_METADATA | MODINFOMD_SHDR:
> + case MODINFO_METADATA | MODINFOMD_ELFHDR:
> + case MODINFO_METADATA | MODINFOMD_FW_HANDLE:
> + case MODINFO_METADATA | MODINFOMD_KEYBUF:
> +#ifdef MODINFOMD_EFI_MAP
> + case MODINFO_METADATA | MODINFOMD_EFI_MAP:
> +#endif
> + /* Don't print data buffers. */
> + sbuf_cat(sbp, "buffer contents omitted");
> + break;
> + default:
> + break;
> + }
> +#undef sbuf_print_vmoffset
> +}
> +
> +static void
> +preload_dump_internal(struct sbuf *sbp)
> +{
> + uint32_t *bptr, type, len;
> +
> + KASSERT(preload_metadata != NULL,
> + ("%s called without setting up preload_metadata", __func__));
> +
> + /*
> + * Iterate through the TLV-encoded sections.
> + */
> + bptr = (uint32_t *)preload_metadata;
> + sbuf_putc(sbp, '\n');
> + while (bptr[0] != MODINFO_END || bptr[0] != MODINFO_END) {
> + sbuf_printf(sbp, " %p:\n", bptr);
> + type = *bptr++;
> + len = *bptr++;
> +
> + sbuf_printf(sbp, "\ttype:\t(%#04x) ", type);
> + preload_modinfo_type(sbp, type);
> + sbuf_putc(sbp, '\n');
> + sbuf_printf(sbp, "\tlen:\t%u\n", len);
> + sbuf_cat(sbp, "\tvalue:\t");
> + preload_modinfo_value(sbp, bptr, type, len);
> + sbuf_putc(sbp, '\n');
> +
> + bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t);
> + }
> +}
> +
> +/*
> + * Print the preloaded data to the console. Called from the machine-dependent
> + * initialization routines, e.g. hammer_time().
> + */
> +void
> +preload_dump(void)
> +{
> + char buf[512];
> + struct sbuf sb;
> +
> + /*
> + * This function is expected to be called before malloc is available,
> + * so use a static buffer and struct sbuf.
> + */
> + sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
> + sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
> + preload_dump_internal(&sb);
> +
> + sbuf_finish(&sb);
> + sbuf_delete(&sb);
> +}
> +
> +static int
> +sysctl_preload_dump(SYSCTL_HANDLER_ARGS)
> +{
> + struct sbuf sb;
> + int error;
> +
> + if (preload_metadata == NULL)
> + return (EINVAL);
> +
> + sbuf_new_for_sysctl(&sb, NULL, 512, req);
> + preload_dump_internal(&sb);
> +
> + error = sbuf_finish(&sb);
> + sbuf_delete(&sb);
> +
> + return (error);
> +}
> +SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo,
> + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
> + NULL, 0, sysctl_preload_dump, "A",
> + "pretty-print the bootloader metadata");
>
> Modified: head/sys/riscv/riscv/machdep.c
> ==============================================================================
> --- head/sys/riscv/riscv/machdep.c Thu Oct 8 17:30:05 2020 (r366541)
> +++ head/sys/riscv/riscv/machdep.c Thu Oct 8 18:02:05 2020 (r366542)
> @@ -949,6 +949,15 @@ initriscv(struct riscv_bootparams *rvbp)
>
> cninit();
>
> + /*
> + * Dump the boot metadata. We have to wait for cninit() since console
> + * output is required. If it's grossly incorrect the kernel will never
> + * make it this far.
> + */
> + if ((boothowto & RB_VERBOSE) &&
> + getenv_is_true("debug.dump_modinfo_at_boot"))
> + preload_dump();
> +
> init_proc0(rvbp->kern_stack);
>
> msgbufinit(msgbufp, msgbufsize);
>
> Modified: head/sys/sys/linker.h
> ==============================================================================
> --- head/sys/sys/linker.h Thu Oct 8 17:30:05 2020 (r366541)
> +++ head/sys/sys/linker.h Thu Oct 8 18:02:05 2020 (r366542)
> @@ -257,6 +257,7 @@ extern caddr_t preload_search_next_name(caddr_t _base
> extern caddr_t preload_search_info(caddr_t _mod, int _inf);
> extern void preload_delete_name(const char *_name);
> extern void preload_bootstrap_relocate(vm_offset_t _offset);
> +extern void preload_dump(void);
>
> #ifdef KLD_DEBUG
>
>
>
More information about the svn-src-all
mailing list