From e37c1877ba5b17d4251e1688449f8d43fc090802 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 21 Feb 2019 16:31:47 -0500 Subject: scripts/selinux: modernize mdp Derived in part from a patch by Dominick Grift. The MDP example no longer works on modern systems. Fix it. While we are at it, add MLS support and enable it. NB This still does not work on systems using dbus-daemon instead of dbus-broker because dbus-daemon does not yet gracefully handle unknown classes/permissions. This appears to be a deficiency in libselinux's selinux_set_mapping() interface and underlying implementation, which was never fully updated to deal with unknown classes/permissions unlike the kernel. The same problem also occurs with XSELinux. Programs that instead use selinux_check_access() like dbus-broker should not have this problem. Changes to mdp: Add support for devtmpfs, required by modern Linux distributions. Add MLS support, with sample sensitivities, categories, and constraints. Generate fs_use and genfscon rules based on kernel configuration. Update list of filesystem types for fs_use and genfscon rules. Use object_r for object contexts. Changes to install_policy.sh: Bail immediately on any errors. Provide more helpful error messages when unable to find userspace tools. Refuse to run if SELinux is already enabled. Unconditionally move aside /etc/selinux/config and create a new one. Build policy with -U allow so that userspace object managers do not break. Build policy with MLS enabled by default. Create seusers, failsafe_context, and default_contexts for use by pam_selinux / libselinux. Create x_contexts for the SELinux X extension. Create virtual_domain_context and virtual_image_context for libvirtd. Set to permissive mode rather than enforcing to permit initial autorelabel. Update the list of filesystem types to be relabeled. Write -F to /.autorelabel to cause a forced autorelabel on reboot. Drop broken attempt to relabel the /dev mountpoint directory. Signed-off-by: Stephen Smalley Acked-by: Dominick Grift Signed-off-by: Paul Moore --- scripts/selinux/install_policy.sh | 92 ++++++++++++--------- scripts/selinux/mdp/mdp.c | 165 ++++++++++++++++++++++++++++++++------ 2 files changed, 194 insertions(+), 63 deletions(-) (limited to 'scripts') diff --git a/scripts/selinux/install_policy.sh b/scripts/selinux/install_policy.sh index 0b86c47baf7d..2dccf141241d 100755 --- a/scripts/selinux/install_policy.sh +++ b/scripts/selinux/install_policy.sh @@ -1,30 +1,61 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 +set -e if [ `id -u` -ne 0 ]; then echo "$0: must be root to install the selinux policy" exit 1 fi + SF=`which setfiles` if [ $? -eq 1 ]; then - if [ -f /sbin/setfiles ]; then - SF="/usr/setfiles" - else - echo "no selinux tools installed: setfiles" - exit 1 - fi + echo "Could not find setfiles" + echo "Do you have policycoreutils installed?" + exit 1 fi -cd mdp - CP=`which checkpolicy` +if [ $? -eq 1 ]; then + echo "Could not find checkpolicy" + echo "Do you have checkpolicy installed?" + exit 1 +fi VERS=`$CP -V | awk '{print $1}'` -./mdp policy.conf file_contexts -$CP -o policy.$VERS policy.conf +ENABLED=`which selinuxenabled` +if [ $? -eq 1 ]; then + echo "Could not find selinuxenabled" + echo "Do you have libselinux-utils installed?" + exit 1 +fi + +if selinuxenabled; then + echo "SELinux is already enabled" + echo "This prevents safely relabeling all files." + echo "Boot with selinux=0 on the kernel command-line or" + echo "SELINUX=disabled in /etc/selinux/config." + exit 1 +fi + +cd mdp +./mdp -m policy.conf file_contexts +$CP -U allow -M -o policy.$VERS policy.conf mkdir -p /etc/selinux/dummy/policy mkdir -p /etc/selinux/dummy/contexts/files +echo "__default__:user_u:s0" > /etc/selinux/dummy/seusers +echo "base_r:base_t:s0" > /etc/selinux/dummy/contexts/failsafe_context +echo "base_r:base_t:s0 base_r:base_t:s0" > /etc/selinux/dummy/default_contexts +cat > /etc/selinux/dummy/contexts/x_contexts < /etc/selinux/config << EOF -SELINUX=enforcing +if [ -f /etc/selinux/config ]; then + echo "/etc/selinux/config exists, moving to /etc/selinux/config.bak." + mv /etc/selinux/config /etc/selinux/config.bak +fi +echo "Creating new /etc/selinux/config for dummy policy." +cat > /etc/selinux/config << EOF +SELINUX=permissive SELINUXTYPE=dummy EOF -else - TYPE=`cat /etc/selinux/config | grep "^SELINUXTYPE" | tail -1 | awk -F= '{ print $2 '}` - if [ "eq$TYPE" != "eqdummy" ]; then - selinuxenabled - if [ $? -eq 0 ]; then - echo "SELinux already enabled with a non-dummy policy." - echo "Exiting. Please install policy by hand if that" - echo "is what you REALLY want." - exit 1 - fi - mv /etc/selinux/config /etc/selinux/config.mdpbak - grep -v "^SELINUXTYPE" /etc/selinux/config.mdpbak >> /etc/selinux/config - echo "SELINUXTYPE=dummy" >> /etc/selinux/config - fi -fi cd /etc/selinux/dummy/contexts/files -$SF file_contexts / +$SF -F file_contexts / -mounts=`cat /proc/$$/mounts | egrep "ext2|ext3|xfs|jfs|ext4|ext4dev|gfs2" | awk '{ print $2 '}` -$SF file_contexts $mounts +mounts=`cat /proc/$$/mounts | \ + egrep "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \ + awk '{ print $2 '}` +$SF -F file_contexts $mounts - -dodev=`cat /proc/$$/mounts | grep "/dev "` -if [ "eq$dodev" != "eq" ]; then - mount --move /dev /mnt - $SF file_contexts /dev - mount --move /mnt /dev -fi +echo "-F" > /.autorelabel diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c index 073fe7537f6c..edaba8e51651 100644 --- a/scripts/selinux/mdp/mdp.c +++ b/scripts/selinux/mdp/mdp.c @@ -33,6 +33,7 @@ #include #include #include +#include static void usage(char *name) { @@ -95,10 +96,31 @@ int main(int argc, char *argv[]) } fprintf(fout, "\n"); - /* NOW PRINT OUT MLS STUFF */ + /* print out mls declarations and constraints */ if (mls) { - printf("MLS not yet implemented\n"); - exit(1); + fprintf(fout, "sensitivity s0;\n"); + fprintf(fout, "sensitivity s1;\n"); + fprintf(fout, "dominance { s0 s1 }\n"); + fprintf(fout, "category c0;\n"); + fprintf(fout, "category c1;\n"); + fprintf(fout, "level s0:c0.c1;\n"); + fprintf(fout, "level s1:c0.c1;\n"); +#define SYSTEMLOW "s0" +#define SYSTEMHIGH "s1:c0.c1" + for (i = 0; secclass_map[i].name; i++) { + struct security_class_mapping *map = &secclass_map[i]; + + fprintf(fout, "mlsconstrain %s {\n", map->name); + for (j = 0; map->perms[j]; j++) + fprintf(fout, "\t%s\n", map->perms[j]); + /* + * This requires all subjects and objects to be + * single-level (l2 eq h2), and that the subject + * level dominate the object level (h1 dom h2) + * in order to have any permissions to it. + */ + fprintf(fout, "} (l2 eq h2 and h1 dom h2);\n\n"); + } } /* types, roles, and allows */ @@ -108,34 +130,127 @@ int main(int argc, char *argv[]) for (i = 0; secclass_map[i].name; i++) fprintf(fout, "allow base_t base_t:%s *;\n", secclass_map[i].name); - fprintf(fout, "user user_u roles { base_r };\n"); - fprintf(fout, "\n"); + fprintf(fout, "user user_u roles { base_r }"); + if (mls) + fprintf(fout, " level %s range %s - %s", SYSTEMLOW, + SYSTEMLOW, SYSTEMHIGH); + fprintf(fout, ";\n"); + +#define SUBJUSERROLETYPE "user_u:base_r:base_t" +#define OBJUSERROLETYPE "user_u:object_r:base_t" /* default sids */ for (i = 1; i < initial_sid_to_string_len; i++) - fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]); + fprintf(fout, "sid %s " SUBJUSERROLETYPE "%s\n", + initial_sid_to_string[i], mls ? ":" SYSTEMLOW : ""); fprintf(fout, "\n"); - fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n"); +#define FS_USE(behavior, fstype) \ + fprintf(fout, "fs_use_%s %s " OBJUSERROLETYPE "%s;\n", \ + behavior, fstype, mls ? ":" SYSTEMLOW : "") + + /* + * Filesystems whose inode labels can be fetched via getxattr. + */ +#ifdef CONFIG_EXT2_FS_SECURITY + FS_USE("xattr", "ext2"); +#endif +#ifdef CONFIG_EXT4_FS_SECURITY +#ifdef CONFIG_EXT4_USE_FOR_EXT2 + FS_USE("xattr", "ext2"); +#endif + FS_USE("xattr", "ext3"); + FS_USE("xattr", "ext4"); +#endif +#ifdef CONFIG_JFS_SECURITY + FS_USE("xattr", "jfs"); +#endif +#ifdef CONFIG_REISERFS_FS_SECURITY + FS_USE("xattr", "reiserfs"); +#endif +#ifdef CONFIG_JFFS2_FS_SECURITY + FS_USE("xattr", "jffs2"); +#endif +#ifdef CONFIG_XFS_FS + FS_USE("xattr", "xfs"); +#endif +#ifdef CONFIG_GFS2_FS + FS_USE("xattr", "gfs2"); +#endif +#ifdef CONFIG_BTRFS_FS + FS_USE("xattr", "btrfs"); +#endif +#ifdef CONFIG_F2FS_FS_SECURITY + FS_USE("xattr", "f2fs"); +#endif +#ifdef CONFIG_OCFS2_FS + FS_USE("xattr", "ocsfs2"); +#endif +#ifdef CONFIG_OVERLAY_FS + FS_USE("xattr", "overlay"); +#endif +#ifdef CONFIG_SQUASHFS_XATTR + FS_USE("xattr", "squashfs"); +#endif + + /* + * Filesystems whose inodes are labeled from allocating task. + */ + FS_USE("task", "pipefs"); + FS_USE("task", "sockfs"); - fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n"); + /* + * Filesystems whose inode labels are computed from both + * the allocating task and the superblock label. + */ +#ifdef CONFIG_UNIX98_PTYS + FS_USE("trans", "devpts"); +#endif +#ifdef CONFIG_HUGETLBFS + FS_USE("trans", "hugetlbfs"); +#endif +#ifdef CONFIG_TMPFS + FS_USE("trans", "tmpfs"); +#endif +#ifdef CONFIG_DEVTMPFS + FS_USE("trans", "devtmpfs"); +#endif +#ifdef CONFIG_POSIX_MQUEUE + FS_USE("trans", "mqueue"); +#endif - fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n"); - fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n"); +#define GENFSCON(fstype, prefix) \ + fprintf(fout, "genfscon %s %s " OBJUSERROLETYPE "%s\n", \ + fstype, prefix, mls ? ":" SYSTEMLOW : "") - fprintf(fout, "genfscon proc / user_u:base_r:base_t\n"); + /* + * Filesystems whose inodes are labeled from path prefix match + * relative to the filesystem root. Depending on the filesystem, + * only a single label for all inodes may be supported. Here + * we list the filesystem types for which per-file labeling is + * supported using genfscon; any other filesystem type can also + * be added by only with a single entry for all of its inodes. + */ +#ifdef CONFIG_PROC_FS + GENFSCON("proc", "/"); +#endif +#ifdef CONFIG_SECURITY_SELINUX + GENFSCON("selinuxfs", "/"); +#endif +#ifdef CONFIG_SYSFS + GENFSCON("sysfs", "/"); +#endif +#ifdef CONFIG_DEBUG_FS + GENFSCON("debugfs", "/"); +#endif +#ifdef CONFIG_TRACING + GENFSCON("tracefs", "/"); +#endif +#ifdef CONFIG_PSTORE + GENFSCON("pstore", "/"); +#endif + GENFSCON("cgroup", "/"); + GENFSCON("cgroup2", "/"); fclose(fout); @@ -144,8 +259,8 @@ int main(int argc, char *argv[]) printf("Wrote policy, but cannot open %s for writing\n", ctxout); usage(argv[0]); } - fprintf(fout, "/ user_u:base_r:base_t\n"); - fprintf(fout, "/.* user_u:base_r:base_t\n"); + fprintf(fout, "/ " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : ""); + fprintf(fout, "/.* " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : ""); fclose(fout); return 0; -- cgit v1.2.3 From ff1bf4c0714e7936330bb316090a75eaa35061e7 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Sun, 24 Feb 2019 21:55:28 -0300 Subject: selinux: use kernel linux/socket.h for genheaders and mdp When compiling genheaders and mdp from a newer host kernel, the following error happens: In file included from scripts/selinux/genheaders/genheaders.c:18: ./security/selinux/include/classmap.h:238:2: error: #error New address family defined, please update secclass_map. #error New address family defined, please update secclass_map. ^~~~~ make[3]: *** [scripts/Makefile.host:107: scripts/selinux/genheaders/genheaders] Error 1 make[2]: *** [scripts/Makefile.build:599: scripts/selinux/genheaders] Error 2 make[1]: *** [scripts/Makefile.build:599: scripts/selinux] Error 2 make[1]: *** Waiting for unfinished jobs.... Instead of relying on the host definition, include linux/socket.h in classmap.h to have PF_MAX. Signed-off-by: Paulo Alcantara Acked-by: Stephen Smalley [PM: manually merge in mdp.c, subject line tweaks] Signed-off-by: Paul Moore --- scripts/selinux/genheaders/genheaders.c | 1 - scripts/selinux/mdp/mdp.c | 1 - security/selinux/include/classmap.h | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c index 1ceedea847dd..544ca126a8a8 100644 --- a/scripts/selinux/genheaders/genheaders.c +++ b/scripts/selinux/genheaders/genheaders.c @@ -9,7 +9,6 @@ #include #include #include -#include struct security_class_mapping { const char *name; diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c index edaba8e51651..18fd6143888b 100644 --- a/scripts/selinux/mdp/mdp.c +++ b/scripts/selinux/mdp/mdp.c @@ -32,7 +32,6 @@ #include #include #include -#include #include static void usage(char *name) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index bd5fe0d3204a..201f7e588a29 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include +#include #define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append", "map" -- cgit v1.2.3 From ccd19d4cafaaf36132c372e77ee9304b707c1e70 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Tue, 19 Mar 2019 09:21:06 -0400 Subject: scripts/selinux: fix build We need to add the object tree include directory to the include path for building mdp in order to pick up generated/autoconf.h. Otherwise, make O=/path/to/objtree breaks. Fixes: e37c1877ba5b ("scripts/selinux: modernize mdp") Reported-by: Stephen Rothwell Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- scripts/selinux/mdp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/selinux/mdp/Makefile b/scripts/selinux/mdp/Makefile index e9c92db7e2a3..8a1269a9d0ba 100644 --- a/scripts/selinux/mdp/Makefile +++ b/scripts/selinux/mdp/Makefile @@ -2,7 +2,7 @@ hostprogs-y := mdp HOST_EXTRACFLAGS += \ -I$(srctree)/include/uapi -I$(srctree)/include \ - -I$(srctree)/security/selinux/include + -I$(srctree)/security/selinux/include -I$(objtree)/include always := $(hostprogs-y) clean-files := policy.* file_contexts -- cgit v1.2.3 From 6c5d24eef7be7adfcb608f2852ab69b58935133b Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 22 Mar 2019 14:11:37 -0700 Subject: checkpatch: Warn on improper usage of Co-developed-by The purpose of Co-developed-by: is to give attribution to authors who aren't already attributed by the From: tag, i.e. who aren't the nominal patch author. Because Co-developed-by: is essentially a variation of From:, it must be accompanied by a Signed-off-by: of the associated co-author. To ease the burden of determining whether or not co-authors have signed off, Co-developed-by and Signed-off-by: must be explicitly paired, i.e. on consecutive lines for a given co-author. Suggested-by: Joe Perches Signed-off-by: Sean Christopherson Signed-off-by: Jonathan Corbet --- scripts/checkpatch.pl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 5b756278df13..bbe71f017f6d 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2687,6 +2687,24 @@ sub process { } else { $signatures{$sig_nospace} = 1; } + +# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email + if ($sign_off =~ /^co-developed-by:$/i) { + if ($email eq $author) { + WARN("BAD_SIGN_OFF", + "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline); + } + if (!defined $lines[$linenr]) { + WARN("BAD_SIGN_OFF", + "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline); + } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) { + WARN("BAD_SIGN_OFF", + "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); + } elsif ($1 ne $email) { + WARN("BAD_SIGN_OFF", + "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); + } + } } # Check email subject for common tools that don't need to be mentioned -- cgit v1.2.3 From 5f6df00fd4569cf76f4e9636bbfc826ea32e2dde Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 30 Mar 2019 10:45:59 -0300 Subject: docs: scripts/sphinx-pre-install: suggest latexmk for building pdf The usage of latexmk improves the PDF output, as it re-run xelatex when it detects the need, in order to properly generate indexes and cross-references. As this is not a mandatory requirement, only suggest its addition. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- scripts/sphinx-pre-install | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install index 067459760a7b..f6a5c0bae31e 100755 --- a/scripts/sphinx-pre-install +++ b/scripts/sphinx-pre-install @@ -532,6 +532,7 @@ sub check_needs() check_program("dot", 1); check_program("convert", 1); check_program("rsvg-convert", 1) if ($pdf); + check_program("latexmk", 1) if ($pdf); check_distros(); -- cgit v1.2.3 From e07cf4fd7d72546bf46279927b28fe9d74308868 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Mar 2019 21:04:15 +0900 Subject: kbuild: mkmakefile: do not check the generated Makefile marker This hunk was added to avoid accidental overwrite of the top Makefile in case O= points to the top of the source tree. As commit 4f1127e20437 ("kbuild: fix infinite make recursion"), it caused some troubles in the past because Kbuild assumes O= as out-of-tree build, while it actually works in the source tree. Now this works more properly; if O= points to the source directory, it is handled as in-tree build. So, this sanity check is unneeded. Signed-off-by: Masahiro Yamada --- scripts/mkmakefile | 6 ------ 1 file changed, 6 deletions(-) (limited to 'scripts') diff --git a/scripts/mkmakefile b/scripts/mkmakefile index 412f13fdff52..31de46801321 100755 --- a/scripts/mkmakefile +++ b/scripts/mkmakefile @@ -7,12 +7,6 @@ # Usage # $1 - Kernel src directory -# Only overwrite automatically generated Makefiles -# (so we do not overwrite kernel Makefile) -if test -e Makefile && ! grep -q Automatically Makefile -then - exit 0 -fi if [ "${quiet}" != "silent_" ]; then echo " GEN Makefile" fi -- cgit v1.2.3 From 48b5ffd1268788afb01525e71e864e901e9aa070 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Mar 2019 21:04:16 +0900 Subject: kbuild: mkmakefile: generate a simple wrapper of top Makefile Now that Kbuild is able to start from any directory, the generated Makefile can simply wrap the top Makefile. Signed-off-by: Masahiro Yamada Reviewed-by: Kieran Bingham --- scripts/mkmakefile | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/mkmakefile b/scripts/mkmakefile index 31de46801321..4d0faebb1719 100755 --- a/scripts/mkmakefile +++ b/scripts/mkmakefile @@ -12,22 +12,6 @@ if [ "${quiet}" != "silent_" ]; then fi cat << EOF > Makefile -# Automatically generated by $0: don't edit - -ifeq ("\$(origin V)", "command line") -VERBOSE := \$(V) -endif -ifneq (\$(VERBOSE),1) -Q := @ -endif - -MAKEFLAGS += --no-print-directory - -.PHONY: __sub-make \$(MAKECMDGOALS) - -__sub-make: - \$(Q)\$(MAKE) -C $1 O=\$(CURDIR) \$(MAKECMDGOALS) - -\$(filter-out __sub-make, \$(MAKECMDGOALS)): __sub-make - @: +# Automatically generated by $(realpath $0): don't edit +include $(realpath $1/Makefile) EOF -- cgit v1.2.3 From a9a49c2ad9b9b8ee20668c15ca2b806dbed8ea40 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Mar 2019 21:04:17 +0900 Subject: kbuild: use $(srctree) instead of KBUILD_SRC to check out-of-tree build KBUILD_SRC was conventionally used for some different purposes: [1] To remember the source tree path [2] As a flag to check if sub-make is already done [3] As a flag to check if Kbuild runs out of tree For [1], we do not need to remember it because the top Makefile can compute it by $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) [2] has been replaced with self-commenting 'sub_make_done'. For [3], we can distinguish in-tree/out-of-tree by comparing $(srctree) and '.' This commit converts [3] to prepare for the KBUILD_SRC removal. Signed-off-by: Masahiro Yamada --- Makefile | 6 +++--- scripts/Makefile.build | 2 +- scripts/Makefile.host | 2 +- scripts/Makefile.lib | 2 +- scripts/Makefile.modbuiltin | 2 +- scripts/gdb/linux/Makefile | 2 +- scripts/tags.sh | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/Makefile b/Makefile index 4929c1f41cfa..72fad444f3e8 100644 --- a/Makefile +++ b/Makefile @@ -448,7 +448,7 @@ USERINCLUDE := \ LINUXINCLUDE := \ -I$(srctree)/arch/$(SRCARCH)/include \ -I$(objtree)/arch/$(SRCARCH)/include/generated \ - $(if $(KBUILD_SRC), -I$(srctree)/include) \ + $(if $(filter .,$(srctree)),,-I$(srctree)/include) \ -I$(objtree)/include \ $(USERINCLUDE) @@ -509,7 +509,7 @@ PHONY += outputmakefile # At the same time when output Makefile generated, generate .gitignore to # ignore whole output directory outputmakefile: -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) $(Q)ln -fsn $(srctree) source $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) $(Q)test -e .gitignore || \ @@ -1089,7 +1089,7 @@ PHONY += prepare archprepare prepare1 prepare3 # and if so do: # 1) Check that make has not been executed in the kernel src $(srctree) prepare3: include/config/kernel.release -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) @$(kecho) ' Using $(srctree) as source for kernel' $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ echo >&2 " $(srctree) is not clean, please run 'make mrproper'"; \ diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 76ca30cc4791..9dddfb6f554e 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -501,7 +501,7 @@ existing-targets := $(wildcard $(sort $(targets))) -include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) # Create directories for object files if they do not exist obj-dirs := $(sort $(obj) $(patsubst %/,%, $(dir $(targets)))) # If targets exist, their directories apparently exist. Skip mkdir. diff --git a/scripts/Makefile.host b/scripts/Makefile.host index a115259b57e7..73b804197fca 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -71,7 +71,7 @@ __hostc_flags = $(_hostc_flags) __hostcxx_flags = $(_hostcxx_flags) ifeq ($(KBUILD_EXTMOD),) -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) __hostc_flags = -I$(obj) $(call flags,_hostc_flags) __hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags) endif diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 8a1f64f17740..41e98fa66b91 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -144,7 +144,7 @@ __cpp_flags = $(_cpp_flags) # If building the kernel in a separate objtree expand all occurrences # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). ifeq ($(KBUILD_EXTMOD),) -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) # -I$(obj) locates generated .h files # $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin index a072a4267746..ea90a90b41a0 100644 --- a/scripts/Makefile.modbuiltin +++ b/scripts/Makefile.modbuiltin @@ -15,7 +15,7 @@ include include/config/tristate.conf include scripts/Kbuild.include -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) # Create output directory if not already present _dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) endif diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile index 3df395a9c2ce..9fd3d8ed731a 100644 --- a/scripts/gdb/linux/Makefile +++ b/scripts/gdb/linux/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -ifneq ($(KBUILD_SRC),) +ifneq ($(srctree),.) symlinks := $(patsubst $(srctree)/$(src)/%,%,$(wildcard $(srctree)/$(src)/*.py)) diff --git a/scripts/tags.sh b/scripts/tags.sh index f470d9919ed7..6a551805db52 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -19,7 +19,7 @@ ignore="$ignore ( -name *.mod.c ) -prune -o" # Do not use full path if we do not use O=.. builds # Use make O=. {tags|cscope} # to force full paths for a non-O= build -if [ "${KBUILD_SRC}" = "" ]; then +if [ "${srctree}" = "." ]; then tree= else tree=${srctree}/ -- cgit v1.2.3 From e83b9f55448afce3fe1abcd1d10db9584f8042a6 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 2 Apr 2019 09:49:50 -0700 Subject: kbuild: add ability to generate BTF type info for vmlinux This patch adds new config option to trigger generation of BTF type information from DWARF debuginfo for vmlinux and kernel modules through pahole, which in turn relies on libbpf for btf_dedup() algorithm. The intent is to record compact type information of all types used inside kernel, including all the structs/unions/typedefs/etc. This enables BPF's compile-once-run-everywhere ([0]) approach, in which tracing programs that are inspecting kernel's internal data (e.g., struct task_struct) can be compiled on a system running some kernel version, but would be possible to run on other kernel versions (and configurations) without recompilation, even if the layout of structs changed and/or some of the fields were added, removed, or renamed. This is only possible if BPF loader can get kernel type info to adjust all the offsets correctly. This patch is a first time in this direction, making sure that BTF type info is part of Linux kernel image in non-loadable ELF section. BTF deduplication ([1]) algorithm typically provides 100x savings compared to DWARF data, so resulting .BTF section is not big as is typically about 2MB in size. [0] http://vger.kernel.org/lpc-bpf2018.html#session-2 [1] https://facebookmicrosites.github.io/bpf/blog/2018/11/14/btf-enhancement.html Cc: Masahiro Yamada Cc: Arnaldo Carvalho de Melo Cc: Daniel Borkmann Cc: Alexei Starovoitov Cc: Yonghong Song Cc: Martin KaFai Lau Signed-off-by: Andrii Nakryiko Acked-by: David S. Miller Acked-by: Alexei Starovoitov Acked-by: Daniel Borkmann Signed-off-by: Daniel Borkmann --- Makefile | 3 ++- lib/Kconfig.debug | 8 ++++++++ scripts/link-vmlinux.sh | 20 +++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/Makefile b/Makefile index c0a34064c574..73c013378559 100644 --- a/Makefile +++ b/Makefile @@ -399,6 +399,7 @@ NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump +PAHOLE = pahole LEX = flex YACC = bison AWK = awk @@ -453,7 +454,7 @@ KBUILD_LDFLAGS := GCC_PLUGINS_CFLAGS := export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC -export CPP AR NM STRIP OBJCOPY OBJDUMP KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS +export CPP AR NM STRIP OBJCOPY OBJDUMP PAHOLE KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS export MAKE LEX YACC AWK INSTALLKERNEL PERL PYTHON PYTHON2 PYTHON3 UTS_MACHINE export HOSTCXX KBUILD_HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0d9e81779e37..188fc17c2202 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -219,6 +219,14 @@ config DEBUG_INFO_DWARF4 But it significantly improves the success of resolving variables in gdb on optimized code. +config DEBUG_INFO_BTF + bool "Generate BTF typeinfo" + depends on DEBUG_INFO + help + Generate deduplicated BTF type information from DWARF debug info. + Turning this on expects presence of pahole tool, which will convert + DWARF type info into equivalent deduplicated BTF type info. + config GDB_SCRIPTS bool "Provide GDB scripts for kernel debugging" depends on DEBUG_INFO diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index dc0e8c5a1402..dd2b31ccca6a 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -35,7 +35,7 @@ set -e info() { if [ "${quiet}" != "silent_" ]; then - printf " %-7s %s\n" ${1} ${2} + printf " %-7s %s\n" "${1}" "${2}" fi } @@ -91,6 +91,20 @@ vmlinux_link() fi } +# generate .BTF typeinfo from DWARF debuginfo +gen_btf() +{ + local pahole_ver; + + pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') + if [ "${pahole_ver}" -lt "113" ]; then + info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" + exit 0 + fi + + info "BTF" ${1} + LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} +} # Create ${2} .o file with all symbols from the ${1} object file kallsyms() @@ -248,6 +262,10 @@ fi info LD vmlinux vmlinux_link "${kallsymso}" vmlinux +if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then + gen_btf vmlinux +fi + if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then info SORTEX vmlinux sortextable vmlinux -- cgit v1.2.3 From 83da1bed86cdfe3abb2a33c36a2a5aaf5f390ef6 Mon Sep 17 00:00:00 2001 From: "Wiebe, Wladislav (Nokia - DE/Ulm)" Date: Thu, 11 Apr 2019 09:25:08 +0000 Subject: modpost: make KBUILD_MODPOST_WARN also configurable for external modules Commit ea837f1c0503 ("kbuild: make modpost processing configurable") was intended to give KBUILD_MODPOST_WARN flexibility to be configurable. Right now KBUILD_MODPOST_WARN gets just ignored when KBUILD_EXTMOD is set which happens per default when building modules out of the tree. This change gives the opportunity to define module build behaving also in case of out of tree builds and default will become exit on error. Errors which can be detected by the build should be trapped out of the box there, unless somebody wants to notice broken stuff later at runtime. As this patch changes the default behaving from warning to error, users can consider to fix it for external module builds by: - providing module symbol table via KBUILD_EXTRA_SYMBOLS for modules which are dependent - OR getting old behaving back by passing KBUILD_MODPOST_WARN to the build Signed-off-by: Wladislav Wiebe Signed-off-by: Masahiro Yamada --- scripts/Makefile.modpost | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 6b7f354f189a..fec6ec2ffa47 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -78,7 +78,7 @@ modpost = scripts/mod/modpost \ $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_MODPOST_WARN),-w) MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS))) -- cgit v1.2.3 From 68e5ab1fc8bd9c17ed94ac172ffe0b9b7e85a59a Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 15 Apr 2019 14:58:39 -0700 Subject: kbuild: handle old pahole more gracefully when generating BTF When CONFIG_DEBUG_INFO_BTF is enabled but available version of pahole is too old to support BTF generation, build script is supposed to emit warning and proceed with the build. Due to using exit instead of return from BASH function, existing handling code prematurely exits exit code 0, not completing some of the build steps. This patch fixes issue by correctly returning just from gen_btf() function only. Fixes: e83b9f55448a ("kbuild: add ability to generate BTF type info for vmlinux") Cc: Masahiro Yamada Cc: Arnaldo Carvalho de Melo Cc: Daniel Borkmann Cc: Alexei Starovoitov Cc: Yonghong Song Cc: Martin KaFai Lau Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Daniel Borkmann --- scripts/link-vmlinux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index dd2b31ccca6a..6a148d0d51bf 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -99,7 +99,7 @@ gen_btf() pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" - exit 0 + return 0 fi info "BTF" ${1} -- cgit v1.2.3 From 28bb030f93334495ddc64ade0bff18721bf7023d Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Fri, 1 Mar 2019 08:50:36 +0800 Subject: csky/ftrace: Add dynamic function tracer (include graph tracer) Support dynamic ftrace including dynamic graph tracer. Gcc-csky with -pg will produce call site in every function prologue and we can use these call site to hook trace function. gcc with -pg origin call site: push lr jbsr _mcount nop32 nop32 If the (callee - caller)'s offset is in range of bsr instruction, we'll modify code with: push lr bsr _mcount nop32 nop32 Else if the (callee - caller)'s offset is out of bsr instrunction, we'll modify code with: push lr movih r26, ... ori r26, ... jsr r26 (r26 is reserved for jsr link reg in csky abiv2 spec.) Signed-off-by: Guo Ren --- arch/csky/Kconfig | 3 +- arch/csky/abiv2/mcount.S | 39 ++++++++++- arch/csky/include/asm/ftrace.h | 18 ++++- arch/csky/kernel/ftrace.c | 148 ++++++++++++++++++++++++++++++++++++++++- scripts/recordmcount.pl | 3 + 5 files changed, 205 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 725a115759c9..60ebaa325584 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -29,13 +29,14 @@ config CSKY select GENERIC_SCHED_CLOCK select GENERIC_SMP_IDLE_THREAD select HAVE_ARCH_TRACEHOOK + select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FTRACE_MCOUNT_RECORD select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZO select HAVE_KERNEL_LZMA select HAVE_PERF_EVENTS - select HAVE_C_RECORDMCOUNT select HAVE_DMA_API_DEBUG select HAVE_DMA_CONTIGUOUS select MAY_HAVE_SPARSE_IRQ diff --git a/arch/csky/abiv2/mcount.S b/arch/csky/abiv2/mcount.S index c633379956f5..326402e65f9e 100644 --- a/arch/csky/abiv2/mcount.S +++ b/arch/csky/abiv2/mcount.S @@ -61,10 +61,17 @@ addi sp, 16 .endm +.macro nop32_stub + nop32 + nop32 + nop32 +.endm + ENTRY(ftrace_stub) jmp lr END(ftrace_stub) +#ifndef CONFIG_DYNAMIC_FTRACE ENTRY(_mcount) mcount_enter @@ -76,7 +83,7 @@ ENTRY(_mcount) bf skip_ftrace mov a0, lr - subi a0, MCOUNT_INSN_SIZE + subi a0, 4 ldw a1, (sp, 24) jsr r26 @@ -101,13 +108,41 @@ skip_ftrace: mcount_exit #endif END(_mcount) +#else /* CONFIG_DYNAMIC_FTRACE */ +ENTRY(_mcount) + mov t1, lr + ldw lr, (sp, 0) + addi sp, 4 + jmp t1 +ENDPROC(_mcount) + +ENTRY(ftrace_caller) + mcount_enter + + ldw a0, (sp, 16) + subi a0, 4 + ldw a1, (sp, 24) + + nop +GLOBAL(ftrace_call) + nop32_stub + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + nop +GLOBAL(ftrace_graph_call) + nop32_stub +#endif + + mcount_exit +ENDPROC(ftrace_caller) +#endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER ENTRY(ftrace_graph_caller) mov a0, sp addi a0, 24 ldw a1, (sp, 16) - subi a1, MCOUNT_INSN_SIZE + subi a1, 4 mov a2, r8 lrw r26, prepare_ftrace_return jsr r26 diff --git a/arch/csky/include/asm/ftrace.h b/arch/csky/include/asm/ftrace.h index 7547c45312a8..ba35d93ecda2 100644 --- a/arch/csky/include/asm/ftrace.h +++ b/arch/csky/include/asm/ftrace.h @@ -4,10 +4,26 @@ #ifndef __ASM_CSKY_FTRACE_H #define __ASM_CSKY_FTRACE_H -#define MCOUNT_INSN_SIZE 4 +#define MCOUNT_INSN_SIZE 14 #define HAVE_FUNCTION_GRAPH_FP_TEST #define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR +#define MCOUNT_ADDR ((unsigned long)_mcount) + +#ifndef __ASSEMBLY__ + +extern void _mcount(unsigned long); + +extern void ftrace_graph_call(void); + +static inline unsigned long ftrace_call_adjust(unsigned long addr) +{ + return addr; +} + +struct dyn_arch_ftrace { +}; +#endif /* !__ASSEMBLY__ */ #endif /* __ASM_CSKY_FTRACE_H */ diff --git a/arch/csky/kernel/ftrace.c b/arch/csky/kernel/ftrace.c index 274c431f1810..44f4880179b7 100644 --- a/arch/csky/kernel/ftrace.c +++ b/arch/csky/kernel/ftrace.c @@ -3,6 +3,137 @@ #include #include +#include + +#ifdef CONFIG_DYNAMIC_FTRACE + +#define NOP 0x4000 +#define NOP32_HI 0xc400 +#define NOP32_LO 0x4820 +#define PUSH_LR 0x14d0 +#define MOVIH_LINK 0xea3a +#define ORI_LINK 0xef5a +#define JSR_LINK 0xe8fa +#define BSR_LINK 0xe000 + +/* + * Gcc-csky with -pg will insert stub in function prologue: + * push lr + * jbsr _mcount + * nop32 + * nop32 + * + * If the (callee - current_pc) is less then 64MB, we'll use bsr: + * push lr + * bsr _mcount + * nop32 + * nop32 + * else we'll use (movih + ori + jsr): + * push lr + * movih r26, ... + * ori r26, ... + * jsr r26 + * + * (r26 is our reserved link-reg) + * + */ +static inline void make_jbsr(unsigned long callee, unsigned long pc, + uint16_t *call, bool nolr) +{ + long offset; + + call[0] = nolr ? NOP : PUSH_LR; + + offset = (long) callee - (long) pc; + + if (unlikely(offset < -67108864 || offset > 67108864)) { + call[1] = MOVIH_LINK; + call[2] = callee >> 16; + call[3] = ORI_LINK; + call[4] = callee & 0xffff; + call[5] = JSR_LINK; + call[6] = 0; + } else { + offset = offset >> 1; + + call[1] = BSR_LINK | + ((uint16_t)((unsigned long) offset >> 16) & 0x3ff); + call[2] = (uint16_t)((unsigned long) offset & 0xffff); + call[3] = call[5] = NOP32_HI; + call[4] = call[6] = NOP32_LO; + } +} + +static uint16_t nops[7] = {NOP, NOP32_HI, NOP32_LO, NOP32_HI, NOP32_LO, + NOP32_HI, NOP32_LO}; +static int ftrace_check_current_nop(unsigned long hook) +{ + uint16_t olds[7]; + unsigned long hook_pos = hook - 2; + + if (probe_kernel_read((void *)olds, (void *)hook_pos, sizeof(nops))) + return -EFAULT; + + if (memcmp((void *)nops, (void *)olds, sizeof(nops))) { + pr_err("%p: nop but get (%04x %04x %04x %04x %04x %04x %04x)\n", + (void *)hook_pos, + olds[0], olds[1], olds[2], olds[3], olds[4], olds[5], + olds[6]); + + return -EINVAL; + } + + return 0; +} + +static int ftrace_modify_code(unsigned long hook, unsigned long target, + bool enable, bool nolr) +{ + uint16_t call[7]; + + unsigned long hook_pos = hook - 2; + int ret = 0; + + make_jbsr(target, hook, call, nolr); + + ret = probe_kernel_write((void *)hook_pos, enable ? call : nops, + sizeof(nops)); + if (ret) + return -EPERM; + + flush_icache_range(hook_pos, hook_pos + MCOUNT_INSN_SIZE); + + return 0; +} + +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + int ret = ftrace_check_current_nop(rec->ip); + + if (ret) + return ret; + + return ftrace_modify_code(rec->ip, addr, true, false); +} + +int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, + unsigned long addr) +{ + return ftrace_modify_code(rec->ip, addr, false, false); +} + +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + int ret = ftrace_modify_code((unsigned long)&ftrace_call, + (unsigned long)func, true, true); + return ret; +} + +int __init ftrace_dyn_arch_init(void) +{ + return 0; +} +#endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, @@ -43,8 +174,21 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, *(unsigned long *)frame_pointer = return_hooker; } } -#endif + +#ifdef CONFIG_DYNAMIC_FTRACE +int ftrace_enable_ftrace_graph_caller(void) +{ + return ftrace_modify_code((unsigned long)&ftrace_graph_call, + (unsigned long)&ftrace_graph_caller, true, true); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + return ftrace_modify_code((unsigned long)&ftrace_graph_call, + (unsigned long)&ftrace_graph_caller, false, true); +} +#endif /* CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ /* _mcount is defined in abi's mcount.S */ -extern void _mcount(void); EXPORT_SYMBOL(_mcount); diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 68841d01162c..f71666899245 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -397,6 +397,9 @@ if ($arch eq "x86_64") { } elsif ($arch eq "nds32") { $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_NDS32_HI20_RELA\\s+_mcount\$"; $alignment = 2; +} elsif ($arch eq "csky") { + $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_CKCORE_PCREL_JSR_IMM26BY2\\s+_mcount\$"; + $alignment = 2; } else { die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; } -- cgit v1.2.3 From 9f671e58159adea641f76c56d1f0bbdcb3c524ff Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Apr 2019 08:23:44 -0700 Subject: security: Create "kernel hardening" config area Right now kernel hardening options are scattered around various Kconfig files. This can be a central place to collect these kinds of options going forward. This is initially populated with the memory initialization options from the gcc-plugins. Signed-off-by: Kees Cook Acked-by: Masahiro Yamada --- scripts/gcc-plugins/Kconfig | 75 +++--------------------------------- security/Kconfig | 2 + security/Kconfig.hardening | 93 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 69 deletions(-) create mode 100644 security/Kconfig.hardening (limited to 'scripts') diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index 74271dba4f94..352f03878a1e 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -13,17 +13,19 @@ config HAVE_GCC_PLUGINS An arch should select this symbol if it supports building with GCC plugins. -menuconfig GCC_PLUGINS - bool "GCC plugins" +config GCC_PLUGINS + bool depends on HAVE_GCC_PLUGINS depends on PLUGIN_HOSTCC != "" + default y help GCC plugins are loadable modules that provide extra features to the compiler. They are useful for runtime instrumentation and static analysis. See Documentation/gcc-plugins.txt for details. -if GCC_PLUGINS +menu "GCC plugins" + depends on GCC_PLUGINS config GCC_PLUGIN_CYC_COMPLEXITY bool "Compute the cyclomatic complexity of a function" if EXPERT @@ -66,71 +68,6 @@ config GCC_PLUGIN_LATENT_ENTROPY * https://grsecurity.net/ * https://pax.grsecurity.net/ -config GCC_PLUGIN_STRUCTLEAK - bool "Zero initialize stack variables" - help - While the kernel is built with warnings enabled for any missed - stack variable initializations, this warning is silenced for - anything passed by reference to another function, under the - occasionally misguided assumption that the function will do - the initialization. As this regularly leads to exploitable - flaws, this plugin is available to identify and zero-initialize - such variables, depending on the chosen level of coverage. - - This plugin was originally ported from grsecurity/PaX. More - information at: - * https://grsecurity.net/ - * https://pax.grsecurity.net/ - -choice - prompt "Coverage" - depends on GCC_PLUGIN_STRUCTLEAK - default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL - help - This chooses the level of coverage over classes of potentially - uninitialized variables. The selected class will be - zero-initialized before use. - - config GCC_PLUGIN_STRUCTLEAK_USER - bool "structs marked for userspace" - help - Zero-initialize any structures on the stack containing - a __user attribute. This can prevent some classes of - uninitialized stack variable exploits and information - exposures, like CVE-2013-2141: - https://git.kernel.org/linus/b9e146d8eb3b9eca - - config GCC_PLUGIN_STRUCTLEAK_BYREF - bool "structs passed by reference" - help - Zero-initialize any structures on the stack that may - be passed by reference and had not already been - explicitly initialized. This can prevent most classes - of uninitialized stack variable exploits and information - exposures, like CVE-2017-1000410: - https://git.kernel.org/linus/06e7e776ca4d3654 - - config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL - bool "anything passed by reference" - help - Zero-initialize any stack variables that may be passed - by reference and had not already been explicitly - initialized. This is intended to eliminate all classes - of uninitialized stack variable exploits and information - exposures. - -endchoice - -config GCC_PLUGIN_STRUCTLEAK_VERBOSE - bool "Report forcefully initialized variables" - depends on GCC_PLUGIN_STRUCTLEAK - depends on !COMPILE_TEST # too noisy - help - This option will cause a warning to be printed each time the - structleak plugin finds a variable it thinks needs to be - initialized. Since not all existing initializers are detected - by the plugin, this can produce false positive warnings. - config GCC_PLUGIN_RANDSTRUCT bool "Randomize layout of sensitive kernel structures" select MODVERSIONS if MODULES @@ -226,4 +163,4 @@ config GCC_PLUGIN_ARM_SSP_PER_TASK bool depends on GCC_PLUGINS && ARM -endif +endmenu diff --git a/security/Kconfig b/security/Kconfig index 1d6463fb1450..7aec8d094ce2 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -249,5 +249,7 @@ config LSM If unsure, leave this as the default. +source "security/Kconfig.hardening" + endmenu diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening new file mode 100644 index 000000000000..19881341f1c2 --- /dev/null +++ b/security/Kconfig.hardening @@ -0,0 +1,93 @@ +menu "Kernel hardening options" + +config GCC_PLUGIN_STRUCTLEAK + bool + help + While the kernel is built with warnings enabled for any missed + stack variable initializations, this warning is silenced for + anything passed by reference to another function, under the + occasionally misguided assumption that the function will do + the initialization. As this regularly leads to exploitable + flaws, this plugin is available to identify and zero-initialize + such variables, depending on the chosen level of coverage. + + This plugin was originally ported from grsecurity/PaX. More + information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +menu "Memory initialization" + +choice + prompt "Initialize kernel stack variables at function entry" + default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL if COMPILE_TEST && GCC_PLUGINS + default INIT_STACK_NONE + help + This option enables initialization of stack variables at + function entry time. This has the possibility to have the + greatest coverage (since all functions can have their + variables initialized), but the performance impact depends + on the function calling complexity of a given workload's + syscalls. + + This chooses the level of coverage over classes of potentially + uninitialized variables. The selected class will be + initialized before use in a function. + + config INIT_STACK_NONE + bool "no automatic initialization (weakest)" + help + Disable automatic stack variable initialization. + This leaves the kernel vulnerable to the standard + classes of uninitialized stack variable exploits + and information exposures. + + config GCC_PLUGIN_STRUCTLEAK_USER + bool "zero-init structs marked for userspace (weak)" + depends on GCC_PLUGINS + select GCC_PLUGIN_STRUCTLEAK + help + Zero-initialize any structures on the stack containing + a __user attribute. This can prevent some classes of + uninitialized stack variable exploits and information + exposures, like CVE-2013-2141: + https://git.kernel.org/linus/b9e146d8eb3b9eca + + config GCC_PLUGIN_STRUCTLEAK_BYREF + bool "zero-init structs passed by reference (strong)" + depends on GCC_PLUGINS + select GCC_PLUGIN_STRUCTLEAK + help + Zero-initialize any structures on the stack that may + be passed by reference and had not already been + explicitly initialized. This can prevent most classes + of uninitialized stack variable exploits and information + exposures, like CVE-2017-1000410: + https://git.kernel.org/linus/06e7e776ca4d3654 + + config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL + bool "zero-init anything passed by reference (very strong)" + depends on GCC_PLUGINS + select GCC_PLUGIN_STRUCTLEAK + help + Zero-initialize any stack variables that may be passed + by reference and had not already been explicitly + initialized. This is intended to eliminate all classes + of uninitialized stack variable exploits and information + exposures. + +endchoice + +config GCC_PLUGIN_STRUCTLEAK_VERBOSE + bool "Report forcefully initialized variables" + depends on GCC_PLUGIN_STRUCTLEAK + depends on !COMPILE_TEST # too noisy + help + This option will cause a warning to be printed each time the + structleak plugin finds a variable it thinks needs to be + initialized. Since not all existing initializers are detected + by the plugin, this can produce false positive warnings. + +endmenu + +endmenu -- cgit v1.2.3 From b6a6a3772d20b8552e703bb2a651760a22167cf6 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 10 Apr 2019 09:04:40 -0700 Subject: security: Move stackleak config to Kconfig.hardening This moves the stackleak plugin options to Kconfig.hardening's memory initialization menu. Signed-off-by: Kees Cook Reviewed-by: Alexander Popov Acked-by: Masahiro Yamada --- scripts/gcc-plugins/Kconfig | 51 ---------------------------------------- security/Kconfig.hardening | 57 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 51 deletions(-) (limited to 'scripts') diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index 352f03878a1e..80220ed26a35 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -108,57 +108,6 @@ config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE in structures. This reduces the performance hit of RANDSTRUCT at the cost of weakened randomization. -config GCC_PLUGIN_STACKLEAK - bool "Erase the kernel stack before returning from syscalls" - depends on GCC_PLUGINS - depends on HAVE_ARCH_STACKLEAK - help - This option makes the kernel erase the kernel stack before - returning from system calls. That reduces the information which - kernel stack leak bugs can reveal and blocks some uninitialized - stack variable attacks. - - The tradeoff is the performance impact: on a single CPU system kernel - compilation sees a 1% slowdown, other systems and workloads may vary - and you are advised to test this feature on your expected workload - before deploying it. - - This plugin was ported from grsecurity/PaX. More information at: - * https://grsecurity.net/ - * https://pax.grsecurity.net/ - -config STACKLEAK_TRACK_MIN_SIZE - int "Minimum stack frame size of functions tracked by STACKLEAK" - default 100 - range 0 4096 - depends on GCC_PLUGIN_STACKLEAK - help - The STACKLEAK gcc plugin instruments the kernel code for tracking - the lowest border of the kernel stack (and for some other purposes). - It inserts the stackleak_track_stack() call for the functions with - a stack frame size greater than or equal to this parameter. - If unsure, leave the default value 100. - -config STACKLEAK_METRICS - bool "Show STACKLEAK metrics in the /proc file system" - depends on GCC_PLUGIN_STACKLEAK - depends on PROC_FS - help - If this is set, STACKLEAK metrics for every task are available in - the /proc file system. In particular, /proc//stack_depth - shows the maximum kernel stack consumption for the current and - previous syscalls. Although this information is not precise, it - can be useful for estimating the STACKLEAK performance impact for - your workloads. - -config STACKLEAK_RUNTIME_DISABLE - bool "Allow runtime disabling of kernel stack erasing" - depends on GCC_PLUGIN_STACKLEAK - help - This option provides 'stack_erasing' sysctl, which can be used in - runtime to control kernel stack erasing for kernels built with - CONFIG_GCC_PLUGIN_STACKLEAK. - config GCC_PLUGIN_ARM_SSP_PER_TASK bool depends on GCC_PLUGINS && ARM diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 19881341f1c2..a96d4a43ca65 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -88,6 +88,63 @@ config GCC_PLUGIN_STRUCTLEAK_VERBOSE initialized. Since not all existing initializers are detected by the plugin, this can produce false positive warnings. +config GCC_PLUGIN_STACKLEAK + bool "Poison kernel stack before returning from syscalls" + depends on GCC_PLUGINS + depends on HAVE_ARCH_STACKLEAK + help + This option makes the kernel erase the kernel stack before + returning from system calls. This has the effect of leaving + the stack initialized to the poison value, which both reduces + the lifetime of any sensitive stack contents and reduces + potential for uninitialized stack variable exploits or information + exposures (it does not cover functions reaching the same stack + depth as prior functions during the same syscall). This blocks + most uninitialized stack variable attacks, with the performance + impact being driven by the depth of the stack usage, rather than + the function calling complexity. + + The performance impact on a single CPU system kernel compilation + sees a 1% slowdown, other systems and workloads may vary and you + are advised to test this feature on your expected workload before + deploying it. + + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +config STACKLEAK_TRACK_MIN_SIZE + int "Minimum stack frame size of functions tracked by STACKLEAK" + default 100 + range 0 4096 + depends on GCC_PLUGIN_STACKLEAK + help + The STACKLEAK gcc plugin instruments the kernel code for tracking + the lowest border of the kernel stack (and for some other purposes). + It inserts the stackleak_track_stack() call for the functions with + a stack frame size greater than or equal to this parameter. + If unsure, leave the default value 100. + +config STACKLEAK_METRICS + bool "Show STACKLEAK metrics in the /proc file system" + depends on GCC_PLUGIN_STACKLEAK + depends on PROC_FS + help + If this is set, STACKLEAK metrics for every task are available in + the /proc file system. In particular, /proc//stack_depth + shows the maximum kernel stack consumption for the current and + previous syscalls. Although this information is not precise, it + can be useful for estimating the STACKLEAK performance impact for + your workloads. + +config STACKLEAK_RUNTIME_DISABLE + bool "Allow runtime disabling of kernel stack erasing" + depends on GCC_PLUGIN_STACKLEAK + help + This option provides 'stack_erasing' sysctl, which can be used in + runtime to control kernel stack erasing for kernels built with + CONFIG_GCC_PLUGIN_STACKLEAK. + endmenu endmenu -- cgit v1.2.3 From fe3e4b9c6364d3aa69eb30f44d1a44bc90f99924 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Apr 2019 08:42:02 -0300 Subject: scripts/documentation-file-ref-check: don't parse Next/ dir If one tries to run this script under linux-next, it would hit lots of false-positives, due to the tree merges that are stored under the Next/ directory. So, add a logic to ignore it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- scripts/documentation-file-ref-check | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/documentation-file-ref-check b/scripts/documentation-file-ref-check index ad9db6821824..bd7d9ab63941 100755 --- a/scripts/documentation-file-ref-check +++ b/scripts/documentation-file-ref-check @@ -38,6 +38,9 @@ while () { my $f = $1; my $ln = $2; + # On linux-next, discard the Next/ directory + next if ($f =~ m,^Next/,); + # Makefiles and scripts contain nasty expressions to parse docs next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/); -- cgit v1.2.3 From 894ee5ff83335659da5fc4a4b1f41fa246f32d1a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Apr 2019 13:25:33 -0300 Subject: scripts/documentation-file-ref-check: detect broken :doc:`foo` As we keep migrating documents to ReST, we're starting to see more of such tags. Right now, all such tags are pointing to a documentation file, but regressions may be introduced. So, add a check for such kind of issues as well. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- scripts/documentation-file-ref-check | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'scripts') diff --git a/scripts/documentation-file-ref-check b/scripts/documentation-file-ref-check index bd7d9ab63941..63e9542656f1 100755 --- a/scripts/documentation-file-ref-check +++ b/scripts/documentation-file-ref-check @@ -30,6 +30,34 @@ print "Finding broken references. This may take a while... " if ($fix); my %broken_ref; +my $doc_fix = 0; + +open IN, "git grep ':doc:\`' Documentation/|" + or die "Failed to run git grep"; +while () { + next if (!m,^([^:]+):.*\:doc\:\`([^\`]+)\`,); + + my $d = $1; + my $doc_ref = $2; + + my $f = $doc_ref; + + $d =~ s,(.*/).*,$1,; + $f =~ s,.*\<([^\>]+)\>,$1,; + + $f ="$d$f.rst"; + + next if (grep -e, glob("$f")); + + if ($fix && !$doc_fix) { + print STDERR "\nWARNING: Currently, can't fix broken :doc:`` fields\n"; + } + $doc_fix++; + + print STDERR "$f: :doc:`$doc_ref`\n"; +} +close IN; + open IN, "git grep 'Documentation/'|" or die "Failed to run git grep"; while () { @@ -103,6 +131,7 @@ while () { } } } +close IN; exit 0 if (!$fix); -- cgit v1.2.3 From e46b94d228458aefc2553ee7c34ab18c2e3288e3 Mon Sep 17 00:00:00 2001 From: Daniel Dadap Date: Sat, 27 Apr 2019 11:21:34 -0400 Subject: scripts: override locale from environment when running recordmcount.pl recordmcount.pl uses a set of regular expressions to parse the output of objdump(1). However, if objdump(1) output is localized, it may not match the regular expressions, thereby preventing recordmcount.pl from parsing object files correctly. In order to allow recordmcount.pl to function correctly regardless of the current locale settings, set LANG=C when running objdump(1). LC_ALL is already unset in the top-level Makefile, so it is not necessary to also override that environment variable. Signed-off-by: Daniel Dadap Reviewed-by: Robert Morell Signed-off-by: Masahiro Yamada --- scripts/recordmcount.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 68841d01162c..ffea46287f83 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -493,7 +493,7 @@ sub update_funcs # # Step 2: find the sections and mcount call sites # -open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump"; +open(IN, "LANG=C $objdump -hdr $inputfile|") || die "error running $objdump"; my $text; -- cgit v1.2.3 From c69ef1c87b8c35ab9cc6b7d3b9395efd5ca6bc4d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 29 Apr 2019 13:06:43 +0900 Subject: scripts/tags.sh: fix direct execution of scripts/tags.sh I thought this script was run via "make tags" etc. but some people run it directly. Prior to commit a9a49c2ad9b9 ("kbuild: use $(srctree) instead of KBUILD_SRC to check out-of-tree build"), in such a usecase, "tree" was set empty since KBUILD_SRC is undefined. Now, "tree" is set to "${srctree}/", which is evaluated to "/". Fix it by taking into account the case where "srctree" is unset. Link: https://lkml.org/lkml/2019/4/19/501 Fixes: a9a49c2ad9b9 ("kbuild: use $(srctree) instead of KBUILD_SRC to check out-of-tree build") Reported-by: Sergey Senozhatsky Signed-off-by: Masahiro Yamada --- scripts/tags.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 6a551805db52..70e14c67bde7 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -19,7 +19,7 @@ ignore="$ignore ( -name *.mod.c ) -prune -o" # Do not use full path if we do not use O=.. builds # Use make O=. {tags|cscope} # to force full paths for a non-O= build -if [ "${srctree}" = "." ]; then +if [ "${srctree}" = "." -o -z "${srctree}" ]; then tree= else tree=${srctree}/ -- cgit v1.2.3 From 581b31c36cfc58df603c415ab6f3c795611c0ca1 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 5 May 2019 17:10:33 -0700 Subject: kbuild: tolerate missing pahole when generating BTF When BTF generation is enabled through CONFIG_DEBUG_INFO_BTF, scripts/link-vmlinux.sh detects if pahole version is too old and gracefully continues build process, skipping BTF generation build step. But if pahole is not available, build will still fail. This patch adds check for whether pahole exists at all and bails out gracefully, if not. Cc: Alexei Starovoitov Reported-by: Yonghong Song Fixes: e83b9f55448a ("kbuild: add ability to generate BTF type info for vmlinux") Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann --- scripts/link-vmlinux.sh | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 6a148d0d51bf..e3c06b9482a2 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -96,6 +96,11 @@ gen_btf() { local pahole_ver; + if ! [ -x "$(command -v ${PAHOLE})" ]; then + info "BTF" "${1}: pahole (${PAHOLE}) is not available" + return 0 + fi + pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" -- cgit v1.2.3 From 898490c010b5d2e499e03b7e815fc214209ac583 Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Mon, 29 Apr 2019 18:11:14 +0200 Subject: moduleparam: Save information about built-in modules in separate file Problem: When a kernel module is compiled as a separate module, some important information about the kernel module is available via .modinfo section of the module. In contrast, when the kernel module is compiled into the kernel, that information is not available. Information about built-in modules is necessary in the following cases: 1. When it is necessary to find out what additional parameters can be passed to the kernel at boot time. 2. When you need to know which module names and their aliases are in the kernel. This is very useful for creating an initrd image. Proposal: The proposed patch does not remove .modinfo section with module information from the vmlinux at the build time and saves it into a separate file after kernel linking. So, the kernel does not increase in size and no additional information remains in it. Information is stored in the same format as in the separate modules (null-terminated string array). Because the .modinfo section is already exported with a separate modules, we are not creating a new API. It can be easily read in the userspace: $ tr '\0' '\n' < modules.builtin.modinfo ext4.softdep=pre: crc32c ext4.license=GPL ext4.description=Fourth Extended Filesystem ext4.author=Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others ext4.alias=fs-ext4 ext4.alias=ext3 ext4.alias=fs-ext3 ext4.alias=ext2 ext4.alias=fs-ext2 md_mod.alias=block-major-9-* md_mod.alias=md md_mod.description=MD RAID framework md_mod.license=GPL md_mod.parmtype=create_on_open:bool md_mod.parmtype=start_dirty_degraded:int ... Co-Developed-by: Gleb Fotengauer-Malinovskiy Signed-off-by: Gleb Fotengauer-Malinovskiy Signed-off-by: Alexey Gladkov Acked-by: Jessica Yu Signed-off-by: Masahiro Yamada --- .gitignore | 1 + Documentation/dontdiff | 1 + Documentation/kbuild/kbuild.txt | 5 +++++ Makefile | 2 ++ include/asm-generic/vmlinux.lds.h | 1 + include/linux/module.h | 1 + include/linux/moduleparam.h | 12 +++++------- scripts/link-vmlinux.sh | 3 +++ 8 files changed, 19 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/.gitignore b/.gitignore index e7bb6c6edbae..2fb1765c33b0 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ modules.builtin /vmlinuz /System.map /Module.markers +/modules.builtin.modinfo # # RPM spec file (make rpm-pkg) diff --git a/Documentation/dontdiff b/Documentation/dontdiff index ef25a066d952..512fa0239ebf 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -178,6 +178,7 @@ mktables mktree modpost modules.builtin +modules.builtin.modinfo modules.order modversions.h* nconf diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt index 8a3830b39c7d..9c230ea71963 100644 --- a/Documentation/kbuild/kbuild.txt +++ b/Documentation/kbuild/kbuild.txt @@ -11,6 +11,11 @@ modules.builtin This file lists all modules that are built into the kernel. This is used by modprobe to not fail when trying to load something builtin. +modules.builtin.modinfo +-------------------------------------------------- +This file contains modinfo from all modules that are built into the kernel. +Unlike modinfo of a separate module, all fields are prefixed with module name. + Environment variables diff --git a/Makefile b/Makefile index 85dd977f4232..9a8b3f94633d 100644 --- a/Makefile +++ b/Makefile @@ -1308,6 +1308,7 @@ _modinst_: fi @cp -f $(objtree)/modules.order $(MODLIB)/ @cp -f $(objtree)/modules.builtin $(MODLIB)/ + @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst # This depmod is only for convenience to give the initial @@ -1348,6 +1349,7 @@ endif # CONFIG_MODULES # Directories & files removed with 'make clean' CLEAN_DIRS += $(MODVERDIR) include/ksym +CLEAN_FILES += modules.builtin.modinfo # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config usr/include include/generated \ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f8f6f04c4453..bbb9e332f2fe 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -844,6 +844,7 @@ EXIT_CALL \ *(.discard) \ *(.discard.*) \ + *(.modinfo) \ } /** diff --git a/include/linux/module.h b/include/linux/module.h index 5bf5dcd91009..5f7007430d35 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -253,6 +253,7 @@ extern typeof(name) __mod_##type##__##name##_device_table \ #define MODULE_VERSION(_version) MODULE_INFO(version, _version) #else #define MODULE_VERSION(_version) \ + MODULE_INFO(version, _version); \ static struct module_version_attribute ___modver_attr = { \ .mattr = { \ .attr = { \ diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index ba36506db4fb..5ba250d9172a 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -10,23 +10,21 @@ module name. */ #ifdef MODULE #define MODULE_PARAM_PREFIX /* empty */ +#define __MODULE_INFO_PREFIX /* empty */ #else #define MODULE_PARAM_PREFIX KBUILD_MODNAME "." +/* We cannot use MODULE_PARAM_PREFIX because some modules override it. */ +#define __MODULE_INFO_PREFIX KBUILD_MODNAME "." #endif /* Chosen so that structs with an unsigned long line up. */ #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) -#ifdef MODULE #define __MODULE_INFO(tag, name, info) \ static const char __UNIQUE_ID(name)[] \ __used __attribute__((section(".modinfo"), unused, aligned(1))) \ - = __stringify(tag) "=" info -#else /* !MODULE */ -/* This struct is here for syntactic coherency, it is not used */ -#define __MODULE_INFO(tag, name, info) \ - struct __UNIQUE_ID(name) {} -#endif + = __MODULE_INFO_PREFIX __stringify(tag) "=" info + #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index dc0e8c5a1402..e4383e0f476e 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -193,6 +193,9 @@ modpost_link vmlinux.o # modpost vmlinux.o to check for section mismatches ${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o +info MODINFO modules.builtin.modinfo +${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo + kallsymso="" kallsyms_vmlinux="" if [ -n "${CONFIG_KALLSYMS}" ]; then -- cgit v1.2.3 From 259799ea5a9aa099a267f3b99e1f7078bbaf5c5e Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 10 May 2019 21:00:25 +1200 Subject: gcc-plugins: arm_ssp_per_task_plugin: Fix for older GCC < 6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use gen_rtx_set instead of gen_rtx_SET. The former is a wrapper macro that handles the difference between GCC versions implementing the latter. This fixes the following error on my system with g++ 5.4.0 as the host compiler HOSTCXX -fPIC scripts/gcc-plugins/arm_ssp_per_task_plugin.o scripts/gcc-plugins/arm_ssp_per_task_plugin.c:42:14: error: macro "gen_rtx_SET" requires 3 arguments, but only 2 given mask)), ^ scripts/gcc-plugins/arm_ssp_per_task_plugin.c: In function ‘unsigned int arm_pertask_ssp_rtl_execute()’: scripts/gcc-plugins/arm_ssp_per_task_plugin.c:39:20: error: ‘gen_rtx_SET’ was not declared in this scope emit_insn_before(gen_rtx_SET Signed-off-by: Chris Packham Fixes: 189af4657186 ("ARM: smp: add support for per-task stack canaries") Cc: stable@vger.kernel.org Tested-by: Douglas Anderson Signed-off-by: Kees Cook --- scripts/gcc-plugins/arm_ssp_per_task_plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gcc-plugins/arm_ssp_per_task_plugin.c b/scripts/gcc-plugins/arm_ssp_per_task_plugin.c index 89c47f57d1ce..8c1af9bdcb1b 100644 --- a/scripts/gcc-plugins/arm_ssp_per_task_plugin.c +++ b/scripts/gcc-plugins/arm_ssp_per_task_plugin.c @@ -36,7 +36,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void) mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode))); masked_sp = gen_reg_rtx(Pmode); - emit_insn_before(gen_rtx_SET(masked_sp, + emit_insn_before(gen_rtx_set(masked_sp, gen_rtx_AND(Pmode, stack_pointer_rtx, mask)), -- cgit v1.2.3 From 748c7c821aca5e32fab5676193365fc2705af366 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Fri, 10 May 2019 15:51:22 +0100 Subject: bpf: fix script for generating man page on BPF helpers The script broke on parsing function prototype for bpf_strtoul(). This is because the last argument for the function is a pointer to an "unsigned long". The current version of the script only accepts "const" and "struct", but not "unsigned", at the beginning of argument types made of several words. One solution could be to add "unsigned" to the list, but the issue could come up again in the future (what about "long int"?). It turns out we do not need to have such restrictions on the words: so let's simply accept any series of words instead. Reported-by: Yonghong Song Signed-off-by: Quentin Monnet Acked-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- scripts/bpf_helpers_doc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 5010a4d5bfba..894cc58c1a03 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 # SPDX-License-Identifier: GPL-2.0-only # -# Copyright (C) 2018 Netronome Systems, Inc. +# Copyright (C) 2018-2019 Netronome Systems, Inc. # In case user attempts to run with Python 2. from __future__ import print_function @@ -39,7 +39,7 @@ class Helper(object): Break down helper function protocol into smaller chunks: return type, name, distincts arguments. """ - arg_re = re.compile('((const )?(struct )?(\w+|...))( (\**)(\w+))?$') + arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$') res = {} proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$') @@ -54,8 +54,8 @@ class Helper(object): capture = arg_re.match(a) res['args'].append({ 'type' : capture.group(1), - 'star' : capture.group(6), - 'name' : capture.group(7) + 'star' : capture.group(5), + 'name' : capture.group(6) }) return res -- cgit v1.2.3 From dfe4529ee4d39d89f4725fa2599aa9bfa27e5847 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 May 2019 15:45:49 -0700 Subject: scripts/gdb: find vmlinux where it was before Patch series "gdb script for kconfig and timer list". This is a handful of changes to the kernel's gdb scripts to do some more debugging with kgdb. The first patch allows the vmlinux to be reloaded from where it was specified on the command line so that this set of scripts can be used from anywhere. The second patch adds a script to dump the config.gz to a file on the host debugging machine. The third patch adds some rb tree utilities and the last patch uses those rb tree walking utilities to dump out the contents of /proc/timer_list from a system under debug. This patch (of 5): If I run 'gdb ' and there's the vmlinux-gdb.py file there I can properly see symbols and use the lx commands provided by the GDB scripts. But once I run 'lx-symbols' at the command prompt, gdb reloads the vmlinux symbols assuming that this script was run from the directory that has vmlinux at the root. That isn't always true, but we could just look and see what symbols were already loaded and use that instead. Let's do that so this can work by being invoked anywhere. Link: http://lkml.kernel.org/r/20190325184522.260535-2-swboyd@chromium.org Signed-off-by: Stephen Boyd Cc: Douglas Anderson Cc: Nikolay Borisov Cc: Kieran Bingham Cc: Jan Kiszka Cc: Jackie Liu Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/symbols.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index 004b0ac7fa72..2f5b95f09fa0 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -139,8 +139,12 @@ lx-symbols command.""" saved_states.append({'breakpoint': bp, 'enabled': bp.enabled}) # drop all current symbols and reload vmlinux + orig_vmlinux = 'vmlinux' + for obj in gdb.objfiles(): + if obj.filename.endswith('vmlinux'): + orig_vmlinux = obj.filename gdb.execute("symbol-file", to_string=True) - gdb.execute("symbol-file vmlinux") + gdb.execute("symbol-file {0}".format(orig_vmlinux)) self.loaded_modules = [] module_list = modules.module_list() -- cgit v1.2.3 From 90cf83dbd2f08dd0513cd9f19155878c55acb445 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 May 2019 15:45:53 -0700 Subject: scripts/gdb: add kernel config dumping command lx-configdump dumps the contents of the gzipped .config to a text file when the config is included in the kernel with CONFIG_IKCONFIG. By default, the file written is called config.txt, but it can be any user supplied filename as well. If the kernel config is in a module (configs.ko), then it can be loaded along with symbols for the module loaded with 'lx-symbols' and then this command will still work. Obviously if you have the whole vmlinux then this can also be achieved with scripts/extract-ikconfig, but this gdb script can be useful to confirm that the memory contents of the config in memory and the vmlinux contents on disk match what is expected. [swboyd@chromium.org: v2] Link: http://lkml.kernel.org/r/20190329220844.38234-3-swboyd@chromium.org Link: http://lkml.kernel.org/r/20190325184522.260535-3-swboyd@chromium.org Signed-off-by: Stephen Boyd Cc: Douglas Anderson Cc: Nikolay Borisov Cc: Kieran Bingham Cc: Jan Kiszka Cc: Jackie Liu Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/config.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ scripts/gdb/vmlinux-gdb.py | 1 + 2 files changed, 45 insertions(+) create mode 100644 scripts/gdb/linux/config.py (limited to 'scripts') diff --git a/scripts/gdb/linux/config.py b/scripts/gdb/linux/config.py new file mode 100644 index 000000000000..90e1565b1967 --- /dev/null +++ b/scripts/gdb/linux/config.py @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright 2019 Google LLC. + +import gdb +import zlib + +from linux import utils + + +class LxConfigDump(gdb.Command): + """Output kernel config to the filename specified as the command + argument. Equivalent to 'zcat /proc/config.gz > config.txt' on + a running target""" + + def __init__(self): + super(LxConfigDump, self).__init__("lx-configdump", gdb.COMMAND_DATA, + gdb.COMPLETE_FILENAME) + + def invoke(self, arg, from_tty): + if len(arg) == 0: + filename = "config.txt" + else: + filename = arg + + try: + py_config_ptr = gdb.parse_and_eval("kernel_config_data + 8") + py_config_size = gdb.parse_and_eval( + "sizeof(kernel_config_data) - 1 - 8 * 2") + except gdb.error as e: + raise gdb.GdbError("Can't find config, enable CONFIG_IKCONFIG?") + + inf = gdb.inferiors()[0] + zconfig_buf = utils.read_memoryview(inf, py_config_ptr, + py_config_size).tobytes() + + config_buf = zlib.decompress(zconfig_buf, 16) + with open(filename, 'wb') as f: + f.write(config_buf) + + gdb.write("Dumped config to " + filename + "\n") + + +LxConfigDump() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 6e0b0afd888a..be0efb5dda5b 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -27,6 +27,7 @@ else: import linux.modules import linux.dmesg import linux.tasks + import linux.config import linux.cpus import linux.lists import linux.proc -- cgit v1.2.3 From 449ca0c95ea261f27b7efd4ca3970a5b4e0fd30d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 May 2019 15:45:56 -0700 Subject: scripts/gdb: add rb tree iterating utilities Implement gdb functions for rb_first(), rb_last(), rb_next(), and rb_prev(). These can be useful to iterate through the kernel's red-black trees. [swboyd@chromium.org: v2] Link: http://lkml.kernel.org/r/20190329220844.38234-4-swboyd@chromium.org Link: http://lkml.kernel.org/r/20190325184522.260535-4-swboyd@chromium.org Signed-off-by: Stephen Boyd Cc: Douglas Anderson Cc: Nikolay Borisov Cc: Kieran Bingham Cc: Jan Kiszka Cc: Jackie Liu Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/rbtree.py | 177 ++++++++++++++++++++++++++++++++++++++++++++ scripts/gdb/vmlinux-gdb.py | 1 + 2 files changed, 178 insertions(+) create mode 100644 scripts/gdb/linux/rbtree.py (limited to 'scripts') diff --git a/scripts/gdb/linux/rbtree.py b/scripts/gdb/linux/rbtree.py new file mode 100644 index 000000000000..39db889b874c --- /dev/null +++ b/scripts/gdb/linux/rbtree.py @@ -0,0 +1,177 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright 2019 Google LLC. + +import gdb + +from linux import utils + +rb_root_type = utils.CachedType("struct rb_root") +rb_node_type = utils.CachedType("struct rb_node") + + +def rb_first(root): + if root.type == rb_root_type.get_type(): + node = node.address.cast(rb_root_type.get_type().pointer()) + elif root.type != rb_root_type.get_type().pointer(): + raise gdb.GdbError("Must be struct rb_root not {}".format(root.type)) + + node = root['rb_node'] + if node is 0: + return None + + while node['rb_left']: + node = node['rb_left'] + + return node + + +def rb_last(root): + if root.type == rb_root_type.get_type(): + node = node.address.cast(rb_root_type.get_type().pointer()) + elif root.type != rb_root_type.get_type().pointer(): + raise gdb.GdbError("Must be struct rb_root not {}".format(root.type)) + + node = root['rb_node'] + if node is 0: + return None + + while node['rb_right']: + node = node['rb_right'] + + return node + + +def rb_parent(node): + parent = gdb.Value(node['__rb_parent_color'] & ~3) + return parent.cast(rb_node_type.get_type().pointer()) + + +def rb_empty_node(node): + return node['__rb_parent_color'] == node.address + + +def rb_next(node): + if node.type == rb_node_type.get_type(): + node = node.address.cast(rb_node_type.get_type().pointer()) + elif node.type != rb_node_type.get_type().pointer(): + raise gdb.GdbError("Must be struct rb_node not {}".format(node.type)) + + if rb_empty_node(node): + return None + + if node['rb_right']: + node = node['rb_right'] + while node['rb_left']: + node = node['rb_left'] + return node + + parent = rb_parent(node) + while parent and node == parent['rb_right']: + node = parent + parent = rb_parent(node) + + return parent + + +def rb_prev(node): + if node.type == rb_node_type.get_type(): + node = node.address.cast(rb_node_type.get_type().pointer()) + elif node.type != rb_node_type.get_type().pointer(): + raise gdb.GdbError("Must be struct rb_node not {}".format(node.type)) + + if rb_empty_node(node): + return None + + if node['rb_left']: + node = node['rb_left'] + while node['rb_right']: + node = node['rb_right'] + return node.dereference() + + parent = rb_parent(node) + while parent and node == parent['rb_left'].dereference(): + node = parent + parent = rb_parent(node) + + return parent + + +class LxRbFirst(gdb.Function): + """Lookup and return a node from an RBTree + +$lx_rb_first(root): Return the node at the given index. +If index is omitted, the root node is dereferenced and returned.""" + + def __init__(self): + super(LxRbFirst, self).__init__("lx_rb_first") + + def invoke(self, root): + result = rb_first(root) + if result is None: + raise gdb.GdbError("No entry in tree") + + return result + + +LxRbFirst() + + +class LxRbLast(gdb.Function): + """Lookup and return a node from an RBTree. + +$lx_rb_last(root): Return the node at the given index. +If index is omitted, the root node is dereferenced and returned.""" + + def __init__(self): + super(LxRbLast, self).__init__("lx_rb_last") + + def invoke(self, root): + result = rb_last(root) + if result is None: + raise gdb.GdbError("No entry in tree") + + return result + + +LxRbLast() + + +class LxRbNext(gdb.Function): + """Lookup and return a node from an RBTree. + +$lx_rb_next(node): Return the node at the given index. +If index is omitted, the root node is dereferenced and returned.""" + + def __init__(self): + super(LxRbNext, self).__init__("lx_rb_next") + + def invoke(self, node): + result = rb_next(node) + if result is None: + raise gdb.GdbError("No entry in tree") + + return result + + +LxRbNext() + + +class LxRbPrev(gdb.Function): + """Lookup and return a node from an RBTree. + +$lx_rb_prev(node): Return the node at the given index. +If index is omitted, the root node is dereferenced and returned.""" + + def __init__(self): + super(LxRbPrev, self).__init__("lx_rb_prev") + + def invoke(self, node): + result = rb_prev(node) + if result is None: + raise gdb.GdbError("No entry in tree") + + return result + + +LxRbPrev() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index be0efb5dda5b..89e4aa4f8966 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -30,5 +30,6 @@ else: import linux.config import linux.cpus import linux.lists + import linux.rbtree import linux.proc import linux.constants -- cgit v1.2.3 From 442284a89a65965b044df00345c193fcc3c53ad2 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 May 2019 15:45:59 -0700 Subject: scripts/gdb: add a timer list command Implement a command to print the timer list, much like how /proc/timer_list is implemented. This can be used to look at the pending timers on a crashed system. [swboyd@chromium.org: v2] Link: http://lkml.kernel.org/r/20190329220844.38234-5-swboyd@chromium.org Link: http://lkml.kernel.org/r/20190325184522.260535-5-swboyd@chromium.org Signed-off-by: Stephen Boyd Cc: Douglas Anderson Cc: Nikolay Borisov Cc: Kieran Bingham Cc: Jan Kiszka Cc: Jackie Liu Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/constants.py.in | 13 +++ scripts/gdb/linux/timerlist.py | 219 ++++++++++++++++++++++++++++++++++++++ scripts/gdb/vmlinux-gdb.py | 1 + 3 files changed, 233 insertions(+) create mode 100644 scripts/gdb/linux/timerlist.py (limited to 'scripts') diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in index d3319a80788a..76f46f427b96 100644 --- a/scripts/gdb/linux/constants.py.in +++ b/scripts/gdb/linux/constants.py.in @@ -13,8 +13,10 @@ */ #include +#include #include #include +#include /* We need to stringify expanded macros so that they can be parsed */ @@ -44,6 +46,9 @@ LX_VALUE(SB_DIRSYNC) LX_VALUE(SB_NOATIME) LX_VALUE(SB_NODIRATIME) +/* linux/htimer.h */ +LX_GDBPARSED(hrtimer_resolution) + /* linux/mount.h */ LX_VALUE(MNT_NOSUID) LX_VALUE(MNT_NODEV) @@ -52,8 +57,16 @@ LX_VALUE(MNT_NOATIME) LX_VALUE(MNT_NODIRATIME) LX_VALUE(MNT_RELATIME) +/* linux/threads.h */ +LX_VALUE(NR_CPUS) + /* linux/of_fdt.h> */ LX_VALUE(OF_DT_HEADER) /* Kernel Configs */ +LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS) +LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) +LX_CONFIG(CONFIG_HIGH_RES_TIMERS) +LX_CONFIG(CONFIG_NR_CPUS) LX_CONFIG(CONFIG_OF) +LX_CONFIG(CONFIG_TICK_ONESHOT) diff --git a/scripts/gdb/linux/timerlist.py b/scripts/gdb/linux/timerlist.py new file mode 100644 index 000000000000..071d0dd5a634 --- /dev/null +++ b/scripts/gdb/linux/timerlist.py @@ -0,0 +1,219 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright 2019 Google LLC. + +import binascii +import gdb + +from linux import constants +from linux import cpus +from linux import rbtree +from linux import utils + +timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type() +hrtimer_type = utils.CachedType("struct hrtimer").get_type() + + +def ktime_get(): + """Returns the current time, but not very accurately + + We can't read the hardware timer itself to add any nanoseconds + that need to be added since we last stored the time in the + timekeeper. But this is probably good enough for debug purposes.""" + tk_core = gdb.parse_and_eval("&tk_core") + + return tk_core['timekeeper']['tkr_mono']['base'] + + +def print_timer(rb_node, idx): + timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(), + "node") + timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node") + + function = str(timer['function']).split(" ")[1].strip("<>") + softexpires = timer['_softexpires'] + expires = timer['node']['expires'] + now = ktime_get() + + text = " #{}: <{}>, {}, ".format(idx, timer, function) + text += "S:{:02x}\n".format(int(timer['state'])) + text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format( + softexpires, expires, softexpires - now, expires - now) + return text + + +def print_active_timers(base): + curr = base['active']['next']['node'] + curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer()) + idx = 0 + while curr: + yield print_timer(curr, idx) + curr = rbtree.rb_next(curr) + idx += 1 + + +def print_base(base): + text = " .base: {}\n".format(base.address) + text += " .index: {}\n".format(base['index']) + + text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution) + + text += " .get_time: {}\n".format(base['get_time']) + if constants.LX_CONFIG_HIGH_RES_TIMERS: + text += " .offset: {} nsecs\n".format(base['offset']) + text += "active timers:\n" + text += "".join([x for x in print_active_timers(base)]) + return text + + +def print_cpu(hrtimer_bases, cpu, max_clock_bases): + cpu_base = cpus.per_cpu(hrtimer_bases, cpu) + jiffies = gdb.parse_and_eval("jiffies_64") + tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched") + ts = cpus.per_cpu(tick_sched_ptr, cpu) + + text = "cpu: {}\n".format(cpu) + for i in xrange(max_clock_bases): + text += " clock {}:\n".format(i) + text += print_base(cpu_base['clock_base'][i]) + + if constants.LX_CONFIG_HIGH_RES_TIMERS: + fmts = [(" .{} : {} nsecs", 'expires_next'), + (" .{} : {}", 'hres_active'), + (" .{} : {}", 'nr_events'), + (" .{} : {}", 'nr_retries'), + (" .{} : {}", 'nr_hangs'), + (" .{} : {}", 'max_hang_time')] + text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts]) + text += "\n" + + if constants.LX_CONFIG_TICK_ONESHOT: + fmts = [(" .{} : {}", 'nohz_mode'), + (" .{} : {} nsecs", 'last_tick'), + (" .{} : {}", 'tick_stopped'), + (" .{} : {}", 'idle_jiffies'), + (" .{} : {}", 'idle_calls'), + (" .{} : {}", 'idle_sleeps'), + (" .{} : {} nsecs", 'idle_entrytime'), + (" .{} : {} nsecs", 'idle_waketime'), + (" .{} : {} nsecs", 'idle_exittime'), + (" .{} : {} nsecs", 'idle_sleeptime'), + (" .{}: {} nsecs", 'iowait_sleeptime'), + (" .{} : {}", 'last_jiffies'), + (" .{} : {}", 'next_timer'), + (" .{} : {} nsecs", 'idle_expires')] + text += "\n".join([s.format(f, ts[f]) for s, f in fmts]) + text += "\njiffies: {}\n".format(jiffies) + + text += "\n" + + return text + + +def print_tickdevice(td, cpu): + dev = td['evtdev'] + text = "Tick Device: mode: {}\n".format(td['mode']) + if cpu < 0: + text += "Broadcast device\n" + else: + text += "Per CPU device: {}\n".format(cpu) + + text += "Clock Event Device: " + if dev == 0: + text += "\n" + return text + + text += "{}\n".format(dev['name']) + text += " max_delta_ns: {}\n".format(dev['max_delta_ns']) + text += " min_delta_ns: {}\n".format(dev['min_delta_ns']) + text += " mult: {}\n".format(dev['mult']) + text += " shift: {}\n".format(dev['shift']) + text += " mode: {}\n".format(dev['state_use_accessors']) + text += " next_event: {} nsecs\n".format(dev['next_event']) + + text += " set_next_event: {}\n".format(dev['set_next_event']) + + members = [('set_state_shutdown', " shutdown: {}\n"), + ('set_state_periodic', " periodic: {}\n"), + ('set_state_oneshot', " oneshot: {}\n"), + ('set_state_oneshot_stopped', " oneshot stopped: {}\n"), + ('tick_resume', " resume: {}\n")] + for member, fmt in members: + if dev[member]: + text += fmt.format(dev[member]) + + text += " event_handler: {}\n".format(dev['event_handler']) + text += " retries: {}\n".format(dev['retries']) + + return text + + +def pr_cpumask(mask): + nr_cpu_ids = 1 + if constants.LX_NR_CPUS > 1: + nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids") + + inf = gdb.inferiors()[0] + bits = mask['bits'] + num_bytes = (nr_cpu_ids + 7) / 8 + buf = utils.read_memoryview(inf, bits, num_bytes).tobytes() + buf = binascii.b2a_hex(buf) + + chunks = [] + i = num_bytes + while i > 0: + i -= 1 + start = i * 2 + end = start + 2 + chunks.append(buf[start:end]) + if i != 0 and i % 4 == 0: + chunks.append(',') + + extra = nr_cpu_ids % 8 + if 0 < extra <= 4: + chunks[0] = chunks[0][0] # Cut off the first 0 + + return "".join(chunks) + + +class LxTimerList(gdb.Command): + """Print /proc/timer_list""" + + def __init__(self): + super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases") + max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES") + + text = "Timer List Version: gdb scripts\n" + text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases) + text += "now at {} nsecs\n".format(ktime_get()) + + for cpu in cpus.each_online_cpu(): + text += print_cpu(hrtimer_bases, cpu, max_clock_bases) + + if constants.LX_CONFIG_GENERIC_CLOCKEVENTS: + if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST: + bc_dev = gdb.parse_and_eval("&tick_broadcast_device") + text += print_tickdevice(bc_dev, -1) + text += "\n" + mask = gdb.parse_and_eval("tick_broadcast_mask") + mask = pr_cpumask(mask) + text += "tick_broadcast_mask: {}\n".format(mask) + if constants.LX_CONFIG_TICK_ONESHOT: + mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask") + mask = pr_cpumask(mask) + text += "tick_broadcast_oneshot_mask: {}\n".format(mask) + text += "\n" + + tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device") + for cpu in cpus.each_online_cpu(): + tick_dev = cpus.per_cpu(tick_cpu_devices, cpu) + text += print_tickdevice(tick_dev, cpu) + text += "\n" + + gdb.write(text) + + +LxTimerList() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 89e4aa4f8966..033578cc4cd7 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -33,3 +33,4 @@ else: import linux.rbtree import linux.proc import linux.constants + import linux.timerlist -- cgit v1.2.3 From 494dbe02b6df0bd98f7353c21e0b9849a25d2dce Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 14 May 2019 15:46:02 -0700 Subject: scripts/gdb: silence pep8 checks These scripts have some pep8 style warnings. Fix them up so that this directory is all pep8 clean. Link: http://lkml.kernel.org/r/20190329220844.38234-6-swboyd@chromium.org Signed-off-by: Stephen Boyd Cc: Douglas Anderson Cc: Nikolay Borisov Cc: Kieran Bingham Cc: Jan Kiszka Cc: Jackie Liu Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/cpus.py | 1 + scripts/gdb/linux/lists.py | 1 + scripts/gdb/linux/proc.py | 10 ++++++++-- scripts/gdb/linux/tasks.py | 2 ++ scripts/gdb/linux/utils.py | 7 ++++--- 5 files changed, 16 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py index ca11e8df31b6..008e62f3190d 100644 --- a/scripts/gdb/linux/cpus.py +++ b/scripts/gdb/linux/cpus.py @@ -135,6 +135,7 @@ and can help identify the state of hotplugged CPUs""" gdb.write("Online CPUs : {}\n".format(list(each_online_cpu()))) gdb.write("Active CPUs : {}\n".format(list(each_active_cpu()))) + LxCpus() diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py index 2f335fbd86fd..1987d756b36b 100644 --- a/scripts/gdb/linux/lists.py +++ b/scripts/gdb/linux/lists.py @@ -110,4 +110,5 @@ class LxListChk(gdb.Command): raise gdb.GdbError("lx-list-check takes one argument") list_check(gdb.parse_and_eval(argv[0])) + LxListChk() diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py index 2f01a958eb22..6a56bba233a9 100644 --- a/scripts/gdb/linux/proc.py +++ b/scripts/gdb/linux/proc.py @@ -29,6 +29,7 @@ class LxCmdLine(gdb.Command): def invoke(self, arg, from_tty): gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n") + LxCmdLine() @@ -43,6 +44,7 @@ class LxVersion(gdb.Command): # linux_banner should contain a newline gdb.write(gdb.parse_and_eval("(char *)linux_banner").string()) + LxVersion() @@ -86,6 +88,7 @@ Equivalent to cat /proc/iomem on a running target""" def invoke(self, arg, from_tty): return show_lx_resources("iomem_resource") + LxIOMem() @@ -100,6 +103,7 @@ Equivalent to cat /proc/ioports on a running target""" def invoke(self, arg, from_tty): return show_lx_resources("ioport_resource") + LxIOPorts() @@ -149,7 +153,7 @@ values of that process namespace""" if len(argv) >= 1: try: pid = int(argv[0]) - except: + except gdb.error: raise gdb.GdbError("Provide a PID as integer value") else: pid = 1 @@ -195,6 +199,7 @@ values of that process namespace""" info_opts(FS_INFO, s_flags), info_opts(MNT_INFO, m_flags))) + LxMounts() @@ -259,7 +264,7 @@ class LxFdtDump(gdb.Command): try: f = open(filename, 'wb') - except: + except gdb.error: raise gdb.GdbError("Could not open file to dump fdt") f.write(fdt_buf) @@ -267,4 +272,5 @@ class LxFdtDump(gdb.Command): gdb.write("Dumped fdt blob to " + filename + "\n") + LxFdtDump() diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py index f6ab3ccf698f..0301dc1e0138 100644 --- a/scripts/gdb/linux/tasks.py +++ b/scripts/gdb/linux/tasks.py @@ -79,6 +79,7 @@ class LxPs(gdb.Command): pid=task["pid"], comm=task["comm"].string())) + LxPs() @@ -134,4 +135,5 @@ variable.""" else: raise gdb.GdbError("No task of PID " + str(pid)) + LxThreadInfoByPidFunc() diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index 50805874cfc3..bc67126118c4 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -66,6 +66,7 @@ Note that TYPE and ELEMENT have to be quoted as strings.""" return container_of(ptr, gdb.lookup_type(typename.string()).pointer(), elementname.string()) + ContainerOf() @@ -148,14 +149,14 @@ def get_gdbserver_type(): def probe_qemu(): try: return gdb.execute("monitor info version", to_string=True) != "" - except: + except gdb.error: return False def probe_kgdb(): try: thread_info = gdb.execute("info thread 2", to_string=True) return "shadowCPU0" in thread_info - except: + except gdb.error: return False global gdbserver_type @@ -172,7 +173,7 @@ def get_gdbserver_type(): def gdb_eval_or_none(expresssion): try: return gdb.parse_and_eval(expresssion) - except: + except gdb.error: return None -- cgit v1.2.3 From 47d0d12855c9eee9dac72d2359f2ccfac3f7f501 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 14 May 2019 15:46:05 -0700 Subject: scripts/gdb: add hlist utilities This allows easily examining kernel hlists in python. Link: http://lkml.kernel.org/r/Message-ID: Signed-off-by: Leonard Crestez Reviewed-by: Stephen Boyd Cc: Jason Wessel Cc: Jan Kiszka Cc: Kieran Bingham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/lists.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'scripts') diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py index 1987d756b36b..55356b66f8ea 100644 --- a/scripts/gdb/linux/lists.py +++ b/scripts/gdb/linux/lists.py @@ -16,6 +16,8 @@ import gdb from linux import utils list_head = utils.CachedType("struct list_head") +hlist_head = utils.CachedType("struct hlist_head") +hlist_node = utils.CachedType("struct hlist_node") def list_for_each(head): @@ -39,6 +41,27 @@ def list_for_each_entry(head, gdbtype, member): yield utils.container_of(node, gdbtype, member) +def hlist_for_each(head): + if head.type == hlist_head.get_type().pointer(): + head = head.dereference() + elif head.type != hlist_head.get_type(): + raise gdb.GdbError("Must be struct hlist_head not {}" + .format(head.type)) + + node = head['first'].dereference() + while node.address: + yield node.address + node = node['next'].dereference() + + +def hlist_for_each_entry(head, gdbtype, member): + for node in hlist_for_each(head): + if node.type != hlist_node.get_type().pointer(): + raise TypeError("Type {} found. Expected struct hlist_head *." + .format(node.type)) + yield utils.container_of(node, gdbtype, member) + + def list_check(head): nb = 0 if (head.type == list_head.get_type().pointer()): -- cgit v1.2.3 From d1e9710b63d87209e1a14d6e6d8cf1431d8daa31 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 14 May 2019 15:46:08 -0700 Subject: scripts/gdb: initial clk support: lx-clk-summary Add an lx-clk-summary command which prints a subset of /sys/kernel/debug/clk/clk_summary. This can be used to examine hangs caused by clk not being enabled. Link: http://lkml.kernel.org/r/Message-ID: Signed-off-by: Leonard Crestez Cc: Jan Kiszka Cc: Jason Wessel Cc: Kieran Bingham Cc: Stephen Boyd Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/clk.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/gdb/vmlinux-gdb.py | 1 + 2 files changed, 47 insertions(+) create mode 100644 scripts/gdb/linux/clk.py (limited to 'scripts') diff --git a/scripts/gdb/linux/clk.py b/scripts/gdb/linux/clk.py new file mode 100644 index 000000000000..a9129d865c5d --- /dev/null +++ b/scripts/gdb/linux/clk.py @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) NXP 2019 + +import gdb +import sys + +from linux import utils, lists + +clk_core_type = utils.CachedType("struct clk_core") + + +def clk_core_for_each_child(hlist_head): + return lists.hlist_for_each_entry(hlist_head, + clk_core_type.get_type().pointer(), "child_node") + + +class LxClkSummary(gdb.Command): + """Print Linux kernel log buffer.""" + + def __init__(self): + super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA) + + def show_subtree(self, clk, level): + gdb.write("%*s%-*s %7d %8d %8d\n" % ( + level * 3 + 1, "", + 30 - level * 3, + clk['name'].string(), + clk['enable_count'], + clk['prepare_count'], + clk['protect_count'])) + + for child in clk_core_for_each_child(clk['children']): + self.show_subtree(child, level + 1) + + def invoke(self, arg, from_tty): + gdb.write(" enable prepare protect\n") + gdb.write(" clock count count count\n") + gdb.write("---------------------------------------------------------\n") + for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_root_list")): + self.show_subtree(clk, 0) + for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_orphan_list")): + self.show_subtree(clk, 0) + + +LxClkSummary() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 033578cc4cd7..eff5a48ac026 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -34,3 +34,4 @@ else: import linux.proc import linux.constants import linux.timerlist + import linux.clk -- cgit v1.2.3 From 988b2686159759401a4549d0fc30ff9a8758391a Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 14 May 2019 15:46:11 -0700 Subject: scripts/gdb: add $lx_clk_core_lookup function Finding an individual clk_core requires walking the tree which can be quite complicated so add a helper for easy access. (gdb) print *(struct clk_scu*)$lx_clk_core_lookup("uart0_clk")->hw Link: http://lkml.kernel.org/r/Message-ID: Signed-off-by: Leonard Crestez Cc: Jan Kiszka Cc: Jason Wessel Cc: Kieran Bingham Cc: Stephen Boyd Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/clk.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'scripts') diff --git a/scripts/gdb/linux/clk.py b/scripts/gdb/linux/clk.py index a9129d865c5d..6bf71976b55d 100644 --- a/scripts/gdb/linux/clk.py +++ b/scripts/gdb/linux/clk.py @@ -44,3 +44,26 @@ class LxClkSummary(gdb.Command): LxClkSummary() + + +class LxClkCoreLookup(gdb.Function): + """Find struct clk_core by name""" + + def __init__(self): + super(LxClkCoreLookup, self).__init__("lx_clk_core_lookup") + + def lookup_hlist(self, hlist_head, name): + for child in clk_core_for_each_child(hlist_head): + if child['name'].string() == name: + return child + result = self.lookup_hlist(child['children'], name) + if result: + return result + + def invoke(self, name): + name = name.string() + return (self.lookup_hlist(gdb.parse_and_eval("clk_root_list"), name) or + self.lookup_hlist(gdb.parse_and_eval("clk_orphan_list"), name)) + + +LxClkCoreLookup() -- cgit v1.2.3 From 66d5c7c60acfeb21d80ff03a349e3b6600caa117 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 14 May 2019 15:46:14 -0700 Subject: scripts/gdb: clean up error handling in list helpers An incorrect argument to list_for_each is an internal error in gdb scripts so a TypeError should be raised. The gdb.GdbError exception type is intended for user errors such as incorrect invocation. Drop the type assertion in list_for_each_entry because list_for_each isn't going to suddenly yield something else. Applies to both list and hlist Link: http://lkml.kernel.org/r/c1d3fd4db13d999a3ba57f5bbc1924862d824f61.1556881728.git.leonard.crestez@nxp.com Signed-off-by: Leonard Crestez Reviewed-by: Stephen Boyd Cc: Jan Kiszka Cc: Jason Wessel Cc: Kieran Bingham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/lists.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py index 55356b66f8ea..c487ddf09d38 100644 --- a/scripts/gdb/linux/lists.py +++ b/scripts/gdb/linux/lists.py @@ -24,7 +24,7 @@ def list_for_each(head): if head.type == list_head.get_type().pointer(): head = head.dereference() elif head.type != list_head.get_type(): - raise gdb.GdbError("Must be struct list_head not {}" + raise TypeError("Must be struct list_head not {}" .format(head.type)) node = head['next'].dereference() @@ -35,9 +35,6 @@ def list_for_each(head): def list_for_each_entry(head, gdbtype, member): for node in list_for_each(head): - if node.type != list_head.get_type().pointer(): - raise TypeError("Type {} found. Expected struct list_head *." - .format(node.type)) yield utils.container_of(node, gdbtype, member) @@ -45,7 +42,7 @@ def hlist_for_each(head): if head.type == hlist_head.get_type().pointer(): head = head.dereference() elif head.type != hlist_head.get_type(): - raise gdb.GdbError("Must be struct hlist_head not {}" + raise TypeError("Must be struct hlist_head not {}" .format(head.type)) node = head['first'].dereference() @@ -56,9 +53,6 @@ def hlist_for_each(head): def hlist_for_each_entry(head, gdbtype, member): for node in hlist_for_each(head): - if node.type != hlist_node.get_type().pointer(): - raise TypeError("Type {} found. Expected struct hlist_head *." - .format(node.type)) yield utils.container_of(node, gdbtype, member) -- cgit v1.2.3 From e7e6f462c1bee842b857b57826e47e4234728727 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 14 May 2019 15:46:17 -0700 Subject: scripts/gdb: print cached rate in lx-clk-summary The clk rate is always stored in clk_core but might be out of date and require calls to update from hardware. Deal with that case by printing a (c) suffix. Link: http://lkml.kernel.org/r/1a474318982a5f0125f2360c4161029b17f56bd1.1556881728.git.leonard.crestez@nxp.com Signed-off-by: Leonard Crestez Cc: Jan Kiszka Cc: Jason Wessel Cc: Kieran Bingham Cc: Stephen Boyd Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/clk.py | 21 ++++++++++++++------- scripts/gdb/linux/constants.py.in | 4 ++++ 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/clk.py b/scripts/gdb/linux/clk.py index 6bf71976b55d..061aecfa294e 100644 --- a/scripts/gdb/linux/clk.py +++ b/scripts/gdb/linux/clk.py @@ -5,7 +5,7 @@ import gdb import sys -from linux import utils, lists +from linux import utils, lists, constants clk_core_type = utils.CachedType("struct clk_core") @@ -16,27 +16,34 @@ def clk_core_for_each_child(hlist_head): class LxClkSummary(gdb.Command): - """Print Linux kernel log buffer.""" + """Print clk tree summary + +Output is a subset of /sys/kernel/debug/clk/clk_summary + +No calls are made during printing, instead a (c) if printed after values which +are cached and potentially out of date""" def __init__(self): super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA) def show_subtree(self, clk, level): - gdb.write("%*s%-*s %7d %8d %8d\n" % ( + gdb.write("%*s%-*s %7d %8d %8d %11lu%s\n" % ( level * 3 + 1, "", 30 - level * 3, clk['name'].string(), clk['enable_count'], clk['prepare_count'], - clk['protect_count'])) + clk['protect_count'], + clk['rate'], + '(c)' if clk['flags'] & constants.LX_CLK_GET_RATE_NOCACHE else ' ')) for child in clk_core_for_each_child(clk['children']): self.show_subtree(child, level + 1) def invoke(self, arg, from_tty): - gdb.write(" enable prepare protect\n") - gdb.write(" clock count count count\n") - gdb.write("---------------------------------------------------------\n") + gdb.write(" enable prepare protect \n") + gdb.write(" clock count count count rate \n") + gdb.write("------------------------------------------------------------------------\n") for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_root_list")): self.show_subtree(clk, 0) for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_orphan_list")): diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in index 76f46f427b96..1d73083da6cb 100644 --- a/scripts/gdb/linux/constants.py.in +++ b/scripts/gdb/linux/constants.py.in @@ -12,6 +12,7 @@ * */ +#include #include #include #include @@ -38,6 +39,9 @@ import gdb +/* linux/clk-provider.h */ +LX_GDBPARSED(CLK_GET_RATE_NOCACHE) + /* linux/fs.h */ LX_VALUE(SB_RDONLY) LX_VALUE(SB_SYNCHRONOUS) -- cgit v1.2.3