1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0+ 3# 4# Create an initrd directory if one does not already exist. 5# 6# Copyright (C) IBM Corporation, 2013 7# 8# Author: Connor Shu <Connor.Shu@ibm.com> 9 10D=tools/testing/selftests/rcutorture 11 12# Prerequisite checks 13[ -z "$D" ] && echo >&2 "No argument supplied" && exit 1 14if [ ! -d "$D" ]; then 15 echo >&2 "$D does not exist: Malformed kernel source tree?" 16 exit 1 17fi 18if [ -s "$D/initrd/init" ]; then 19 echo "$D/initrd/init already exists, no need to create it" 20 exit 0 21fi 22 23T=${TMPDIR-/tmp}/mkinitrd.sh.$$ 24trap 'rm -rf $T' 0 2 25mkdir $T 26 27cat > $T/init << '__EOF___' 28#!/bin/sh 29# Run in userspace a few milliseconds every second. This helps to 30# exercise the NO_HZ_FULL portions of RCU. The 192 instances of "a" was 31# empirically shown to give a nice multi-millisecond burst of user-mode 32# execution on a 2GHz CPU, as desired. Modern CPUs will vary from a 33# couple of milliseconds up to perhaps 100 milliseconds, which is an 34# acceptable range. 35# 36# Why not calibrate an exact delay? Because within this initrd, we 37# are restricted to Bourne-shell builtins, which as far as I know do not 38# provide any means of obtaining a fine-grained timestamp. 39 40a4="a a a a" 41a16="$a4 $a4 $a4 $a4" 42a64="$a16 $a16 $a16 $a16" 43a192="$a64 $a64 $a64" 44while : 45do 46 q= 47 for i in $a192 48 do 49 q="$q $i" 50 done 51 sleep 1 52done 53__EOF___ 54 55# Try using dracut to create initrd 56if command -v dracut >/dev/null 2>&1 57then 58 echo Creating $D/initrd using dracut. 59 # Filesystem creation 60 dracut --force --no-hostonly --no-hostonly-cmdline --module "base" $T/initramfs.img 61 cd $D 62 mkdir -p initrd 63 cd initrd 64 zcat $T/initramfs.img | cpio -id 65 cp $T/init init 66 chmod +x init 67 echo Done creating $D/initrd using dracut 68 exit 0 69fi 70 71# No dracut, so create a C-language initrd/init program and statically 72# link it. This results in a very small initrd, but might be a bit less 73# future-proof than dracut. 74echo "Could not find dracut, attempting C initrd" 75cd $D 76mkdir -p initrd 77cd initrd 78cat > init.c << '___EOF___' 79#ifndef NOLIBC 80#include <unistd.h> 81#include <sys/time.h> 82#endif 83 84volatile unsigned long delaycount; 85 86int main(int argc, int argv[]) 87{ 88 int i; 89 struct timeval tv; 90 struct timeval tvb; 91 92 for (;;) { 93 sleep(1); 94 /* Need some userspace time. */ 95 if (gettimeofday(&tvb, NULL)) 96 continue; 97 do { 98 for (i = 0; i < 1000 * 100; i++) 99 delaycount = i * i; 100 if (gettimeofday(&tv, NULL)) 101 break; 102 tv.tv_sec -= tvb.tv_sec; 103 if (tv.tv_sec > 1) 104 break; 105 tv.tv_usec += tv.tv_sec * 1000 * 1000; 106 tv.tv_usec -= tvb.tv_usec; 107 } while (tv.tv_usec < 1000); 108 } 109 return 0; 110} 111___EOF___ 112 113# build using nolibc on supported archs (smaller executable) and fall 114# back to regular glibc on other ones. 115if echo -e "#if __x86_64__||__i386__||__i486__||__i586__||__i686__" \ 116 "||__ARM_EABI__||__aarch64__\nyes\n#endif" \ 117 | ${CROSS_COMPILE}gcc -E -nostdlib -xc - \ 118 | grep -q '^yes'; then 119 # architecture supported by nolibc 120 ${CROSS_COMPILE}gcc -fno-asynchronous-unwind-tables -fno-ident \ 121 -nostdlib -include ../../../../include/nolibc/nolibc.h \ 122 -lgcc -s -static -Os -o init init.c 123else 124 ${CROSS_COMPILE}gcc -s -static -Os -o init init.c 125fi 126 127rm init.c 128echo "Done creating a statically linked C-language initrd" 129 130exit 0 131