Date: Thu, 8 Oct 2020 15:31:29 -0300 From: Mitchell Horne <mhorne@freebsd.org> To: Ravi Pokala <rpokala@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r366542 - in head/sys: amd64/amd64 arm/arm arm64/arm64 kern riscv/riscv sys Message-ID: <CADeAsy1dykboVfBaGq3Br5bGNP2hzRaq71V7Wh9evg7=m8Y0iQ@mail.gmail.com> In-Reply-To: <3173155C-6862-4DC6-964E-4F1B1FA941E9@panasas.com> References: <202010081802.098I26Rq052294@repo.freebsd.org> <3173155C-6862-4DC6-964E-4F1B1FA941E9@panasas.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Oct 8, 2020 at 3:19 PM Ravi Pokala <rpokala@freebsd.org> wrote: > > Hi Mitchell, > > +static void > +preload_dump_internal(struct sbuf *sbp) > +{ > + uint32_t *bptr, type, len; > + > + KASSERT(preload_metadata !=3D NULL, > + ("%s called without setting up preload_metadata", __func__)); > + > + /* > + * Iterate through the TLV-encoded sections. > + */ > + bptr =3D (uint32_t *)preload_metadata; > + sbuf_putc(sbp, '\n'); > + while (bptr[0] !=3D MODINFO_END || bptr[0] !=3D 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 =3D *bptr++; > + len =3D *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 +=3D roundup(len, sizeof(u_long)) / sizeof(uint32_t)= ; > + } > +} > > > > > =EF=BB=BF-----Original Message----- > From: <owner-src-committers@freebsd.org> on behalf of Mitchell Horne <mho= rne@FreeBSD.org> > Date: 2020-10-08, Thursday at 11:02 > To: <src-committers@freebsd.org>, <svn-src-all@freebsd.org>, <svn-src-hea= d@freebsd.org> > Subject: svn commit: r366542 - in head/sys: amd64/amd64 arm/arm arm64/arm= 64 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) t= o 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 som= e > routines to parse this data and allow it to be printed to the conso= le > 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 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D > --- 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 physf= ree) > if (late_console) > cninit(); > > + /* > + * Dump the boot metadata. We have to wait for cninit() since con= sole > + * 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 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D > --- 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 =3D 0x%08x\n", (uint32_t)dtbp); > arm_print_kenv(); > > + /* > + * Dump the boot metadata. We have to wait for cninit() since con= sole > + * 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 =3D kern_getenv("kernelname"); > if (env !=3D NULL) { > strlcpy(kernelname, env, sizeof(kernelname)); > > Modified: head/sys/arm64/arm64/machdep.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D > --- 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 con= sole > + * 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 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D > --- 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 withou= t > * modification, are permitted provided that the following condition= s > @@ -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) =3D=3D 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, in= t 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 !=3D NULL, > + ("%s called without setting up preload_metadata", __func__)); > + > + /* > + * Iterate through the TLV-encoded sections. > + */ > + bptr =3D (uint32_t *)preload_metadata; > + sbuf_putc(sbp, '\n'); > + while (bptr[0] !=3D MODINFO_END || bptr[0] !=3D MODINFO_END) { > + sbuf_printf(sbp, " %p:\n", bptr); > + type =3D *bptr++; > + len =3D *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 +=3D 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 availa= ble, > + * 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 =3D=3D NULL) > + return (EINVAL); > + > + sbuf_new_for_sysctl(&sb, NULL, 512, req); > + preload_dump_internal(&sb); > + > + error =3D 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 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D > --- 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 con= sole > + * 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 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D > --- 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 _in= f); > extern void preload_delete_name(const char *_name); > extern void preload_bootstrap_relocate(vm_offset_t _o= ffset); > +extern void preload_dump(void); > > #ifdef KLD_DEBUG > > >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CADeAsy1dykboVfBaGq3Br5bGNP2hzRaq71V7Wh9evg7=m8Y0iQ>