Skip to content

Commit

Permalink
build: support driver profiles
Browse files Browse the repository at this point in the history
V2: Comparing to the previous version this one improves the gen-drivers-config-header
by using awk mechanism to evaluate environment variables. It also
addresses couple of nitpicks.

This patch introduces new build mechanism that allows creating
custom kernel with specific list of device drivers intended to target
given hypervisor. Such kernel benefits from smaller size and better
security as all unneeded code is removed. This patch partially addresses
the modularization/librarization functionality as explained by the issue
#1110 and this part of the roadmap - https://github.com/cloudius-systems/osv/wiki/Roadmap#modularizationlibrarization.
This idea was also mentioned in the P99 OSv presentation - see slide 11.

In essence, we introduce new build script and makefile parameter:
`drivers_profile`. This new parameter is intended to specify a
drivers profile which is simply a list of device drivers to be linked
into kernel with some extra functionality like PCI or ACPI these drivers
depend on. Each profile is specified in a tiny make include file (*.mk)
under new conf/profiles/$(arch) directory and included by the main
makefile as requested by drivers_profile parameter. The main makefile
has number of new ifeq conditions that add given driver object file
to the linked objects list depending on the value (0 or 1) of given
conf_drivers_* variable specified in the relevant profile file.
Sometimes it is necessary to conditionally enable/disable given
code depending on the drivers selected. The good example of it is
arch-setup.cc which actually registers individual drivers and this
is where we need some kind of #if-way of registering given driver.
To that end, this patch adds new script gen-drivers-config-header and
new rule to the makefile, which automatically generates driver-config.h
header file under build/$(mode)/gen/include/osv. The driver-config.h
is comprised of the #define CONF_drivers_* macros that specify if given
driver is enabled or not (1, 0) and is included by relatively few source
file like arch-setup.cc. The extra benefit of this approach is that
every time we change value of drivers_profile, all relevant files are
recompiled and new kernel linked.

Most of the patch are changes to the relevant source file to include
new #if CONF_drivers_* conditional logic, changes to the main makefile
to conditionality link specific object files and new makefile include
file under conf/profiles/.

The benefits of using drivers are most profound when building kernel
with most symbols hidden. Below you can see examples of some build
commands along with the kernel size produced:

./scripts/build fs=rofs conf_hide_symbols=1 image=native-example #all
3632K	build/release/kernel-stripped.elf

./scripts/build fs=rofs conf_hide_symbols=1 image=native-example drivers_profile=virtio-pci
3380K	build/release/kernel-stripped.elf

./scripts/build fs=rofs conf_hide_symbols=1 image=native-example drivers_profile=vmware
3308K	build/release/kernel-stripped.elf

./scripts/build fs=rofs conf_hide_symbols=1 image=native-example drivers_profile=virtio-mmio
3120K	build/release/kernel-stripped.elf

./scripts/build fs=rofs conf_hide_symbols=1 image=native-example drivers_profile=base #most drivers out
3036K	build/release/kernel-stripped.elf

It is also possible to enable or disable individual drivers on top
of what given profiles defines like so:

./scripts/build fs=rofs conf_hide_symbols=1 image=native-example drivers_profile=base \
  conf_drivers_acpi=1 conf_drivers_virtio_fs=1 conf_drivers_virtio_net=1 conf_drivers_pvpanic=1

Partially addresses #1110

Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
  • Loading branch information
wkozaczuk committed Mar 11, 2022
1 parent 07f2324 commit ffb91b1
Show file tree
Hide file tree
Showing 45 changed files with 616 additions and 10 deletions.
109 changes: 101 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,25 @@ ifeq (,$(wildcard conf/$(arch).mk))
endif
include conf/$(arch).mk

# This parameter can be passed in to the build command to specify name of
# a drivers profile. The drivers profile allows to build custom kernel with
# a specific set of drivers enabled in the corresponding makefile include
# file - conf/profiles/$(arch)/$(drivers_profile).mk). The default profile is
# 'all' which incorporates all drivers into kernel.
# In general the profiles set variables named conf_drivers_*, which then in turn
# are used in the rules below to decide which object files are linked into
# kernel.
drivers_profile?=all
ifeq (,$(wildcard conf/profiles/$(arch)/$(drivers_profile).mk))
$(error unsupported drivers profile $(drivers_profile))
endif
include conf/profiles/$(arch)/$(drivers_profile).mk
# The base profile disables all drivers unless they are explicitly enabled
# by the profile file included in the line above. The base profile also enforces
# certain dependencies between drivers, for example the ide driver needs pci support, etc.
# For more details please read comments in the profile file.
include conf/profiles/$(arch)/base.mk

CROSS_PREFIX ?= $(if $(filter-out $(arch),$(host_arch)),$(arch)-linux-gnu-)
CXX=$(CROSS_PREFIX)g++
CC=$(CROSS_PREFIX)gcc
Expand Down Expand Up @@ -617,19 +636,25 @@ bsd += bsd/sys/netinet/cc/cc_cubic.o
bsd += bsd/sys/netinet/cc/cc_htcp.o
bsd += bsd/sys/netinet/cc/cc_newreno.o
bsd += bsd/sys/netinet/arpcache.o
ifeq ($(conf_drivers_xen),1)
bsd += bsd/sys/xen/evtchn.o
endif

ifeq ($(arch),x64)
$(out)/bsd/%.o: COMMON += -DXEN -DXENHVM
ifeq ($(conf_drivers_xen),1)
bsd += bsd/sys/xen/gnttab.o
bsd += bsd/sys/xen/xenstore/xenstore.o
bsd += bsd/sys/xen/xenbus/xenbus.o
bsd += bsd/sys/xen/xenbus/xenbusb.o
bsd += bsd/sys/xen/xenbus/xenbusb_front.o
bsd += bsd/sys/dev/xen/netfront/netfront.o
bsd += bsd/sys/dev/xen/blkfront/blkfront.o
endif
ifeq ($(conf_drivers_hyperv),1)
bsd += bsd/sys/dev/hyperv/vmbus/hyperv.o
endif
endif

bsd += bsd/sys/dev/random/hash.o
bsd += bsd/sys/dev/random/randomdev_soft.o
Expand Down Expand Up @@ -817,54 +842,101 @@ drivers += drivers/random.o
drivers += drivers/zfs.o
drivers += drivers/null.o
drivers += drivers/device.o
ifeq ($(conf_drivers_pci),1)
drivers += drivers/pci-generic.o
drivers += drivers/pci-device.o
drivers += drivers/pci-function.o
drivers += drivers/pci-bridge.o
endif
drivers += drivers/driver.o

ifeq ($(arch),x64)
ifeq ($(conf_drivers_vga),1)
drivers += $(libtsm)
drivers += drivers/vga.o drivers/kbd.o drivers/isa-serial.o
drivers += drivers/vga.o
endif
drivers += drivers/kbd.o drivers/isa-serial.o
drivers += arch/$(arch)/pvclock-abi.o

ifeq ($(conf_drivers_virtio),1)
drivers += drivers/virtio.o
ifeq ($(conf_drivers_pci),1)
drivers += drivers/virtio-pci-device.o
endif
drivers += drivers/virtio-vring.o
ifeq ($(conf_drivers_mmio),1)
drivers += drivers/virtio-mmio.o
endif
drivers += drivers/virtio-net.o
drivers += drivers/vmxnet3.o
drivers += drivers/vmxnet3-queues.o
drivers += drivers/virtio-blk.o
drivers += drivers/virtio-scsi.o
drivers += drivers/virtio-rng.o
drivers += drivers/virtio-fs.o
drivers += drivers/kvmclock.o drivers/xenclock.o drivers/hypervclock.o
endif

ifeq ($(conf_drivers_vmxnet3),1)
drivers += drivers/vmxnet3.o
drivers += drivers/vmxnet3-queues.o
endif
drivers += drivers/kvmclock.o
ifeq ($(conf_drivers_hyperv),1)
drivers += drivers/hypervclock.o
endif
ifeq ($(conf_drivers_acpi),1)
drivers += drivers/acpi.o
endif
ifeq ($(conf_drivers_hpet),1)
drivers += drivers/hpet.o
drivers += drivers/rtc.o
drivers += drivers/xenfront.o drivers/xenfront-xenbus.o drivers/xenfront-blk.o
endif
ifeq ($(conf_drivers_pvpanic),1)
drivers += drivers/pvpanic.o
endif
drivers += drivers/rtc.o
ifeq ($(conf_drivers_ahci),1)
drivers += drivers/ahci.o
drivers += drivers/ide.o
endif
ifeq ($(conf_drivers_scsi),1)
drivers += drivers/scsi-common.o
endif
ifeq ($(conf_drivers_ide),1)
drivers += drivers/ide.o
endif
ifeq ($(conf_drivers_pvscsi),1)
drivers += drivers/vmw-pvscsi.o
endif

ifeq ($(conf_drivers_xen),1)
drivers += drivers/xenclock.o
drivers += drivers/xenfront.o drivers/xenfront-xenbus.o drivers/xenfront-blk.o
drivers += drivers/xenplatform-pci.o
endif
endif # x64

ifeq ($(arch),aarch64)
drivers += drivers/mmio-isa-serial.o
drivers += drivers/pl011.o
drivers += drivers/pl031.o
ifeq ($(conf_drivers_cadence),1)
drivers += drivers/cadence-uart.o
endif
ifeq ($(conf_drivers_xen),1)
drivers += drivers/xenconsole.o
endif

ifeq ($(conf_drivers_virtio),1)
drivers += drivers/virtio.o
ifeq ($(conf_drivers_pci),1)
drivers += drivers/virtio-pci-device.o
endif
ifeq ($(conf_drivers_mmio),1)
drivers += drivers/virtio-mmio.o
endif
drivers += drivers/virtio-vring.o
drivers += drivers/virtio-rng.o
drivers += drivers/virtio-blk.o
drivers += drivers/virtio-net.o
drivers += drivers/virtio-fs.o
endif
endif # aarch64

objects += arch/$(arch)/arch-trace.o
Expand All @@ -883,11 +955,15 @@ objects += arch/$(arch)/cpuid.o
objects += arch/$(arch)/firmware.o
objects += arch/$(arch)/hypervisor.o
objects += arch/$(arch)/interrupt.o
ifeq ($(conf_drivers_pci),1)
objects += arch/$(arch)/pci.o
objects += arch/$(arch)/msi.o
endif
objects += arch/$(arch)/power.o
objects += arch/$(arch)/feexcept.o
ifeq ($(conf_drivers_xen),1)
objects += arch/$(arch)/xen.o
endif

$(out)/arch/x64/string-ssse3.o: CXXFLAGS += -mssse3

Expand Down Expand Up @@ -917,10 +993,14 @@ objects += arch/x64/entry-xen.o
objects += arch/x64/vmlinux.o
objects += arch/x64/vmlinux-boot64.o
objects += arch/x64/pvh-boot.o
ifeq ($(conf_drivers_acpi),1)
objects += $(acpi)
endif
endif # x64

ifeq ($(conf_drivers_xen),1)
objects += core/xen_intr.o
endif
objects += core/math.o
objects += core/spinlock.o
objects += core/lfmutex.o
Expand Down Expand Up @@ -1847,9 +1927,11 @@ fs_objs += rofs/rofs_vfsops.o \
rofs/rofs_cache.o \
rofs/rofs_common.o

ifeq ($(conf_drivers_virtio),1)
fs_objs += virtiofs/virtiofs_vfsops.o \
virtiofs/virtiofs_vnops.o \
virtiofs/virtiofs_dax.o
endif

fs_objs += pseudofs/pseudofs.o
fs_objs += procfs/procfs_vnops.o
Expand Down Expand Up @@ -2055,7 +2137,7 @@ $(out)/tools/cpiod/cpiod.so: $(out)/tools/cpiod/cpiod.o $(out)/tools/cpiod/cpio.
# re-created on every compilation. "generated-headers" is used as an order-
# only dependency on C compilation rules above, so we don't try to compile
# C code before generating these headers.
generated-headers: $(out)/gen/include/bits/alltypes.h perhaps-modify-version-h
generated-headers: $(out)/gen/include/bits/alltypes.h perhaps-modify-version-h perhaps-modify-drivers-config-h
.PHONY: generated-headers

# While other generated headers only need to be generated once, version.h
Expand All @@ -2066,6 +2148,17 @@ perhaps-modify-version-h:
$(call quiet, sh scripts/gen-version-header $(out)/gen/include/osv/version.h, GEN gen/include/osv/version.h)
.PHONY: perhaps-modify-version-h

# Using 'if ($(conf_drivers_*),1)' in the rules below is enough to include whole object
# files. Sometimes though we need to enable or disable portions of the code specific
# to given driver (the arch-setup.cc is best example). To that end the rule below
# generates drivers_config.h header file with the macros CONF_drivers_* which is
# then included by relevant source files.
# This allows for fairly rapid rebuilding of the kernel for specified profiles
# as only few files need to be re-compiled.
perhaps-modify-drivers-config-h:
$(call quiet, sh scripts/gen-drivers-config-header $(arch) $(out)/gen/include/osv/drivers_config.h, GEN gen/include/osv/drivers_config.h)
.PHONY: perhaps-modify-drivers-config-h

$(out)/gen/include/bits/alltypes.h: include/api/$(arch)/bits/alltypes.h.sh
$(makedir)
$(call quiet, sh $^ > $@, GEN $@)
Expand Down
7 changes: 7 additions & 0 deletions arch/aarch64/arch-dtb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* BSD license as described in the LICENSE file in the top-level directory.
*/

#include <osv/drivers_config.h>
#include <osv/types.h>
#include <osv/debug.h>
#include <stdlib.h>
Expand All @@ -16,7 +17,9 @@
#include <osv/mempool.hh>
#include <osv/commands.hh>
#include <osv/elf.hh>
#if CONF_drivers_mmio
#include "drivers/virtio-mmio.hh"
#endif

#define DTB_INTERRUPT_CELLS 3

Expand Down Expand Up @@ -279,6 +282,7 @@ u64 dtb_get_cadence_uart(int *irqid)
return addr;
}

#if CONF_drivers_mmio
#define VIRTIO_MMIO_DEV_COMPAT "virtio,mmio"
#define DTB_MAX_VIRTIO_MMIO_DEV_COUNT 8
static virtio::mmio_device_info dtb_dtb_virtio_mmio_devices_infos[DTB_MAX_VIRTIO_MMIO_DEV_COUNT];
Expand Down Expand Up @@ -321,6 +325,7 @@ void dtb_collect_parsed_mmio_virtio_devices()
virtio::add_mmio_device_configuration(dtb_dtb_virtio_mmio_devices_infos[idx]);
}
}
#endif

/* this gets the virtual timer irq, we are not interested
* about the other timers.
Expand Down Expand Up @@ -796,7 +801,9 @@ void __attribute__((constructor(init_prio::dtb))) dtb_setup()
abort("dtb_setup: failed to parse pci_irq_map.\n");
}

#if CONF_drivers_mmio
dtb_parse_mmio_virtio_devices();
#endif

register u64 edata;
asm volatile ("adrp %0, .edata" : "=r"(edata));
Expand Down
Loading

0 comments on commit ffb91b1

Please sign in to comment.