\documentclass[aspectratio=169,obeyspaces,spaces,hyphens]{beamer}
\usepackage{minted}
\usepackage{newunicodechar}
\usepackage{hyperref}

\mode<presentation>
\usetheme{Bootlin}

\title{Embedded Linux Size BoF}
\authors{Michael Opdenacker}
\email{michael.opdenacker@bootlin.com}
\slidesurl{http://bootlin.com/pub/conferences/2017/elce/}
\conference{Embedded Linux Conference Europe 2017}

\begin{document}

\begin{frame}{\insertconference}
  \begin{columns}
    \column{0.6\textwidth}
    \fontsize{19}{19}\selectfont
    Embedded Linux Size BoF\\
    \vspace{1cm}
    \fontsize{15}{15}\selectfont
    Michael Opdenacker \\
    Bootlin \\
    \normalsize
    {\em \insertemail}
    \column{0.4\textwidth}
       \includegraphics[width=1.0\textwidth]{common/logo-square.pdf}
  \end{columns}
\end{frame}

\begin{frame}{Michael Opdenacker}
    \begin{itemize}
    \item Michael Opdenacker
    \item Founder and Embedded Linux engineer at Bootlin
      \begin{itemize}
      \item Embedded Linux {\bf expertise}
      \item {\bf Development}, consulting and training
      \end{itemize}
      \item Long time interest in embedded Linux boot time,
        and one of its prerequisites: small system size.
      \item From {\bf Orange}, France.
    \end{itemize}
\end{frame}

\begin{frame}{Why reduce size?}
  There are multiple reasons for having a small kernel and system
  \begin{itemize}
    \item Run on very small systems (IoT)
    \item Run on old machines
    \item Run Linux as a bootloader
    \item Boot faster (for example on FPGAs)
    \item Reduce power consumption. Even conceivable to run the whole system in
          CPU internal RAM or cache (DRAM is power hungry and needs refreshing) 
    \item Security: reduce the attack surface
    \item Cloud workloads: optimize instances for size and boot time.
    \item Spare as much RAM as possible for applications and
	  maximizing performance.
    \item Other reasons?
  \end{itemize}
  See \url{https://tiny.wiki.kernel.org/use_cases}
\end{frame}

\begin{frame}{Compiler optimizations}
  \begin{itemize}
     \item Using a recent compiler\\
           Compiling the kernel with gcc 6.3 vs 4.7: only 0.8\% smaller size!
     \item Compiling with gcc LTO\\
	   Compiling \code{oggenc.c} with \code{-Os -flto} instead of \code{-Os}:\\
           only -2.6\% (arm) and -2.8\% (x86\_x64)
     \item Using Clang \code{-Oz} instead of gcc \code{-Os}\\
	   Compiling \code{oggenc.c}: -5.7\%
     \item ARM: compiling with \code{-mthumb} instead of \code{-marm}:\\
	   -6.8\% with \code{oggenc}
     \item {\bf Any further technique you'd like to share?}
  \end{itemize}
\end{frame}

\begin{frame}{Reduce user-space size}
  \begin{itemize}
    \item Replace BusyBox by Toybox (less configurable, mature and featureful).\\
	  Can save a few tens of KB.
    \item Replace glibc or uClibc by musl\\
	  musl vs glibc: 76\% size reduction in static BusyBox
    \item For small static executables, musl also wins vs glibc and uclibc \\
          7300 bytes (musl) vs 492792 (glibc) in static hello world.
    \item \code{sstrip} can be used to shave off an extra KB. 
    \item {\bf Any further technique you'd like to share?}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{How to get a small kernel?}
  \begin{itemize}
     \item Run \code{make tinyconfig} (since version 3.18)
     \item \code{make tinyconfig} is \code{make allnoconfig} plus
           configuration settings to reduce kernel size
     \item You will also need to add configuration settings to support
           your hardware and the system features you need.
  \end{itemize}
\begin{minted}[fontsize=\small]{make}
tinyconfig:
        $(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
\end{minted} 
\end{frame}

\begin{frame}[fragile]
   \frametitle{kernel/configs/tiny.config}
\begin{minted}[fontsize=\small]{make}
# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_KERNEL_GZIP is not set
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
CONFIG_KERNEL_XZ=y
# CONFIG_KERNEL_LZO is not set
# CONFIG_KERNEL_LZ4 is not set
CONFIG_OPTIMIZE_INLINING=y
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y
\end{minted} 
\end{frame}

\begin{frame}[fragile]
   \frametitle{arch/x86/configs/tiny.config}
\begin{minted}[fontsize=\small]{make}
CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
\end{minted} 
\end{frame}

\begin{frame}{tinyconfig Linux kernel size (arm)}
   \includegraphics[width=1.0\textwidth]{arm-size.pdf}
   Not worse than 10 years back!
\end{frame}

\begin{frame}{tinyconfig Linux kernel size (x86)}
   \includegraphics[width=1.0\textwidth]{x86-size.pdf}
\end{frame}

\begin{frame}{Demo}
   Mainline Linux 4.14-rc5 booting on QEMU\\
   ARM VersatilePB, with 3121 KB of RAM
   \begin{columns}
   \column{0.6\textwidth}
     \begin{itemize}
        \item \code{zImage}: 409240 bytes
        \item text: 986792 (program code)
        \item data: 986792 (initialized data)
        \item bss: 25772 (initialized data)
        \item total: 1129872
     \end{itemize}
   \column{0.4\textwidth}
      \includegraphics[width=1.0\textwidth]{qemu-versatile.png}
   \end{columns}
   Test it by yourself (all in a single line):\\
   \code{qemu-system-arm -M versatilepb -nographic -kernel zImage} \\
   \code{-initrd initarmfs.cpio.gz -dtb versatile-pb.dtb -m 3121k} \\
\url{http://bootlin.com/pub/conferences/2017/elce/opdenacker-size-bof/demo/4.14-rc5/}
\end{frame}

\begin{frame}{Demo with the Minitty patches}
   Mainline Linux 4.14-rc5 booting on QEMU
   ARM VersatilePB, with 2993 KB of RAM
   \begin{itemize}
      \item \code{zImage}: 393928 bytes (-15 KB!)
      \item 128 KB of RAM saved!
   \end{itemize}
   \vfill
   Try it by yourself: \url{http://bootlin.com/pub/conferences/2017/elce/opdenacker-size-bof/demo/4.14-rc5-minitty/}
\end{frame}

\begin{frame}{Ongoing mainlining efforts}
  Most (if not all) of the work is currently done by Nicolas Pitre
  (Linaro). Here are the main ideas:
  \begin{itemize}
    \item Minitty: a minimalistic tty layer for very small systems.\\
    See \url{https://lwn.net/Articles/721074/}.
    \item Nanosched: a lightweight scheduler (little chance to get
    accepted).
    \item Instead, proposed to make some scheduling classes optional: sched/deadline
    and sched/rt.
  \end{itemize}
  See his latest presentation:
  \url{http://connect.linaro.org/resource/sfo17/sfo17-100/}. Code
  available on \url{http://git.linaro.org/people/nicolas.pitre/linux.git}
\end{frame}

\begin{frame}{Reaction from upstream maintainers}

\begin{block}{Ingo Molnar, June 11th 2017}
\em But you can prove me wrong: show me a Linux kernel for a real device
that fits into 32KB of RAM (or even 256 KB) and then I’ll consider the cost/benefit equation.

Until that happens I consider most forms of additional complexity on the
non-hardware dependent side of the kernel a net negative.
\end{block}
\end{frame}

\begin{frame}{Supporting real hardware}
  To convince upstream maintainers, Nicolas' ultimate goal is to run
  Linux on the STM32F469NI MCU:
  \begin{itemize}
    \item BGA216 package
    \item ARM Cortex-M4 core
    \item 2 Mbytes of Flash
    \item 324 Kbytes of RAM
  \end{itemize}
  Nicolas started to work on the STM32F469 Discovery kit (with 16 MB of
  SDRAM, already well supported by Linux).
\end{frame}

\begin{frame}[fragile]
 \frametitle{Reducing RAM usage}
 \begin{itemize}
   \item Running the kernel and user-space in place (XIP)
   \item Reducing kernel defines to reduce the size of kernel structures
   \begin{verbatim}
fs/dcache.c
-#define IN_LOOKUP_SHIFT 10
+#define IN_LOOKUP_SHIFT 5
   \end{verbatim}
   \item Investigating the big memory consumption from device tree
         loading.
   Reducing RAM usage is easier than reducing code size!
 \end{itemize}

\end{frame}

\begin{frame}[fragile]
   \frametitle{How to help with kernel tinification (1)}
   \begin{itemize}
      \item Look for \code{obj-y} in kernel Makefiles:
\begin{minted}[fontsize=\small]{make}
obj-y     = fork.o exec_domain.o panic.o \
            cpu.o exit.o softirq.o resource.o \
            sysctl.o sysctl_binary.o capability.o ptrace.o user.o \
            signal.o sys.o kmod.o workqueue.o pid.o task_work.o \
            extable.o params.o \
            kthread.o sys_ni.o nsproxy.o \
            notifier.o ksysfs.o cred.o reboot.o \
            async.o range.o smpboot.o ucount.o
\end{minted}
      \item What about allowing to compile Linux without ptrace
            support (14K on arm) or without reboot (9K)? 
      \item Another way is to look at the compile logs and check
            whether/why everything is needed.
   \end{itemize}
\end{frame}

\begin{frame}[fragile]
   \frametitle{How to help with kernel tinification (2)}
   \begin{itemize}
       \item Look for tinification opportunities, looking for the
             biggest symbols:\\
             \code{nm --size-sort vmlinux}
       \item Look for size regressions with the {\em Bloat-O-Meter}:
\begin{minted}[fontsize=\small]{console}
> ./scripts/bloat-o-meter vmlinux-4.9 vmlinux-4.10
add/remove: 101/135 grow/shrink: 155/109 up/down: 19517/-19324 (193)
function                                     old     new   delta
page_wait_table                                -    2048   +2048
sys_call_table                                 -    1600   +1600
cpuhp_bp_states                              980    1800    +820
...
\end{minted}
   \end{itemize}
\end{frame}

\begin{frame}{Projects to follow}
  \begin{itemize}
    \item Compiling Linux with LLVM/Clang\\
	  Google (Greg Hackmann and Nick Desaulniers) managed to compile the 4.4 and 4.9
          stable kernels, opening the door to size and performance
          optimizations: \url{https://lwn.net/Articles/734071/}
    \item Compiling Linux with gcc LTO\\
          Some efforts (Andy Kleen, Nicolas Pitre) but not in mainline yet
	  Details on https://linuxplumbersconf.org/2015/ocw/system/presentations/3369/original/slides.html
  \end{itemize}
\end{frame}

\begin{frame}{Other ideas}
   \begin{itemize}
      \item Resurrect patches from Josh Triplett which didn't get in:
      \url{https://git.kernel.org/cgit/linux/kernel/git/josh/linux.git/}
      \item Simplify the filesystem layer: you don't want things like
            readahead or page writeback support when you don't have storage.
	    However, that's very difficult to remove!
      \item Remove kernel features such as ptrace, reboot support, etc.
      \item Revive single-user (\code{CONFIG_NON_ROOT}) support:
            \url{https://lwn.net/Articles/631853/}
      \item Modify the kernel binary to remove symbols that were not
	    used during runtime tests? At least, can be done without
	    hurting the mainline code! {\bf How to do that?}
      \item {\bf Other ideas?}
   \end{itemize}
\end{frame}


\begin{frame}{Another hardware platform worth supporting}
  \begin{columns}
    \column{0.8\textwidth}
      \begin{itemize}
         \item Try to support a board with no SDRAM:
	 \begin{itemize}
	    \item 512K of on-chip RAM
	    \item 2M of flash
            \item ARM Cortex M7 CPU
	    \item Cost: 23 EUR
         \end{itemize}
         Hoping to have a system with a very good battery life!
      \end{itemize}
    \column{0.2\textwidth}
       \includegraphics[width=1.0\textwidth]{stm32-nucleo-f767zi.jpg}\\
       STM32 Nucleo F767ZI
    \end{columns}
\end{frame}

\begin{frame}{Useful resources}
   \begin{itemize}
      \item Internet of Tiny Linux (IoTL): Episode IV (Nicolas Pitre, Sep 2017)
        \url{http://connect.linaro.org/resource/sfo17/sfo17-100/}
      \item My detailed presentation about reducing Linux size (with benchmark details)
	\url{http://bootlin.com/pub/conferences/2017/jdll/opdenacker-embedded-linux-in-less-than-4mb-of-ram/}
      \item Home of the Linux tinification project
        \url{https://tiny.wiki.kernel.org/}\\
      \item Ideas ideas and projects which would be worth reviving
        \url{http://elinux.org/Kernel_Size_Reduction_Work}\\
   \end{itemize}
\end{frame}

\questionslide

\end{document}
