make localmodconfig && make localyesconfig
the number of parameters decreased to 1285. It became interesting for me to try to throw out everything unnecessary from the kernel and see what happens.
I will be compiling the 5.4.0 vanilla kernel because this is the version used on my gentoo installation. To speed up the process, I compile the kernel on my working machine (i7, 8 cores, 64Gb RAM, tmpfs). I copy the finished kernel to the machine in oracle cloud. You need to start the process with the command:
make tinyconfig
This will give you a .config file for the minimum core of the current architecture. In my case, this file contains 284 non-blank lines that are not comments.
Let's compile it and look at the kernel size:
$ yes ""|make -j$(nproc)
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 441872 Jan 31 18:09 arch/x86/boot/bzImage
284
$
This kernel is completely useless. Not only can it not boot, but it does not even have the ability to report problems. Let's fix this. To activate the parameters, I will use the command:
script/config -e config_parameter_name
So, our kernel will be 64-bit, we activate the kernel diagnostic output, enable terminal support, configure the serial port and the console on it:
./scripts/config -e CONFIG_64BIT -e CONFIG_PRINTK -e CONFIG_TTY -e CONFIG_SERIAL_8250 -e CONFIG_SERIAL_8250_CONSOLE
A machine in oracle cloud will not be able to boot with this kernel, there will be no output to the console. As it turned out, you need to add support for EFI and ACPI, which is its dependency. The script ./scripts/config does not implement the logic for adding reverse dependencies i.e. if you add only CONFIG_EFI, then make will remove this parameter from the config. It is also worth noting that enabling options often includes the options below. So in the case of enabling CONFIG_ACPI, it is automatically enabled, for example, support for the on / off button.
./scripts/config -e CONFIG_ACPI -e CONFIG_EFI -e CONFIG_EFI_STUB
Putting the core together:
$ yes ""|make -j$(nproc)
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 1036960 Jan 31 18:13 arch/x86/boot/bzImage
409
$
This kernel still cannot complete the boot process, but it is at least able to report it:
Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
Kernel Offset: 0x22000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. ]---
Let's add the required parameters:
# virtual guest support and pci
./scripts/config -e CONFIG_PCI -e CONFIG_VIRTIO_PCI -e CONFIG_VIRTIO -e CONFIG_VIRTIO_MENU -e CONFIG_PARAVIRT -e CONFIG_HYPERVISOR_GUEST
# disk support
./scripts/config -e CONFIG_BLOCK -e CONFIG_SCSI -e CONFIG_BLK_DEV_SD -e CONFIG_SCSI_VIRTIO
# filesystems
./scripts/config -e CONFIG_EXT4_FS -e CONFIG_PROC_FS -e CONFIG_SYSFS -e CONFIG_DEVTMPFS -e CONFIG_DEVTMPFS_MOUNT
# executable formats
./scripts/config -e CONFIG_BINFMT_ELF -e CONFIG_BINFMT_SCRIPT
# network
./scripts/config -e CONFIG_NET -e CONFIG_VIRTIO_NET -e CONFIG_PACKET -e CONFIG_UNIX -e CONFIG_INET -e CONFIG_NET_CORE -e CONFIG_NETDEVICES -e CONFIG_VIRTIO_NET
Putting the core together:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 1950368 Jan 31 18:18 arch/x86/boot/bzImage
616
$
And we are loaded. This time, the kernel successfully finds the root disk, but we see errors in the console:
The futex facility returned an unexpected error code. ... * Call to flock failed: Function not implemented
We are trying to log in:
(none) login: root
process 182 (login) attempted a POSIX timer syscall while CONFIG_POSIX_TIMERS is not set
Password:
setgid: Function not implemented
It also does not work, but we are unambiguously prompted which parameter to add. Add it and other necessary parameters:
./scripts/config -e CONFIG_POSIX_TIMERS -e CONFIG_FUTEX -e CONFIG_FILE_LOCKING -e CONFIG_MULTIUSER
Putting the core together:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 1979040 Jan 31 18:25 arch/x86/boot/bzImage
623
$
This time we manage to log in:
instance-20210124-1735 login: root
Password:
Last login: Mon Feb 1 02:25:10 UTC 2021 from 73.239.106.74 on ssh
root@instance-20210124-1735:~#
Hooray! Ssh works too. Nevertheless, there are errors in the console again:
* Some local filesystem failed to mount
...
hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --verbose option to see the details of our search for an access method.
* Failed to set the system clock
And in dmesg we also find:
[ 2.910198] udevd[360]: inotify_init failed: Function not implemented
We add support for real time clock, vfat file system and inotify:
./scripts/config -e CONFIG_RTC_CLASS -e CONFIG_DNOTIFY -e CONFIG_INOTIFY_USER -e CONFIG_VFAT_FS
Putting the core together:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2015904 Jan 31 18:36 arch/x86/boot/bzImage
643
$
Hmmm, vfat drive still can't mount:
* Some local filesystem failed to mount
And here is the answer why in dmesg along with one more error:
[ 3.782884] udevd[527]: error creating signalfd [ 4.107698] FAT-fs (sda15): codepage cp437 not found
Add parameters:
./scripts/config -e CONFIG_SIGNALFD -e CONFIG_NLS_CODEPAGE_437 -e CONFIG_NLS_ISO8859_1
Putting the core together:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2015904 Jan 31 18:41 arch/x86/boot/bzImage
646
$
We load, there are no errors in the console, but a new error appeared in dmesg:
[ 2.756136] udevd[360]: error creating epoll fd: Function not implemented
We fix:
./scripts/config -e CONFIG_EPOLL
Putting the core together:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2020000 Jan 31 19:13 arch/x86/boot/bzImage
647
$
We reboot and this time we see no new errors!
On my working machine (i7, 8 cores, 64gb RAM, tmpfs), the final configuration is built in 1m 16s. In oracle cloud with two cores and on a regular disk, the same process takes 19m 51s.
The resulting kernel is not absolutely minimal. So, for example, enabling network support adds a bunch of different network adapters. I did not engage in perfectionism and clean out absolutely everything that is not needed. In addition, I want to warn you that although loading and quick testing did not reveal problems with the absence of additional important kernel components, most likely they exist. So if suddenly you decide to reuse my config please test the kernel thoroughly for your particular case and add the required kernel parameters if necessary.