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

Partially addresses #1110

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 Makefile                              | 109 ++++++++++++++++++++++++--
 arch/aarch64/arch-dtb.cc              |   7 ++
 arch/aarch64/arch-setup.cc            |  41 +++++++++-
 arch/aarch64/boot.S                   |   3 +
 arch/aarch64/cpuid.cc                 |   5 ++
 arch/aarch64/xen.cc                   |   1 +
 arch/x64/apic.cc                      |   1 +
 arch/x64/arch-setup.cc                |  74 +++++++++++++++++
 arch/x64/cpuid.cc                     |  15 ++++
 arch/x64/entry-xen.S                  |   5 ++
 arch/x64/power.cc                     |   9 +++
 arch/x64/smp.cc                       |   9 +++
 arch/x64/xen.cc                       |   1 +
 conf/profiles/README.md               |  71 +++++++++++++++++
 conf/profiles/aarch64/all.mk          |   5 ++
 conf/profiles/aarch64/base.mk         |  26 ++++++
 conf/profiles/aarch64/microvm.mk      |   1 +
 conf/profiles/aarch64/virtio-mmio.mk  |   4 +
 conf/profiles/aarch64/virtio-pci.mk   |   6 ++
 conf/profiles/aarch64/xen.mk          |   2 +
 conf/profiles/x64/all.mk              |   8 ++
 conf/profiles/x64/base.mk             |  74 +++++++++++++++++
 conf/profiles/x64/cloud_hypervisor.mk |   2 +
 conf/profiles/x64/hyperv.mk           |   6 ++
 conf/profiles/x64/microvm.mk          |   1 +
 conf/profiles/x64/vbox.mk             |   8 ++
 conf/profiles/x64/virtio-mmio.mk      |   4 +
 conf/profiles/x64/virtio-pci.mk       |  10 +++
 conf/profiles/x64/vmware.mk           |  10 +++
 conf/profiles/x64/xen.mk              |   6 ++
 core/xen_intr.cc                      |   1 +
 drivers/acpi.cc                       |   9 ++-
 drivers/hpet.cc                       |   9 +++
 drivers/pci-generic.cc                |   5 ++
 drivers/virtio-blk.cc                 |   5 ++
 drivers/virtio-fs.cc                  |   5 ++
 drivers/virtio-net.cc                 |   5 ++
 drivers/xenclock.cc                   |   1 +
 drivers/xenfront-xenbus.cc            |   1 +
 drivers/xenplatform-pci.cc            |   1 +
 fs/vfs/vfs_conf.cc                    |   7 ++
 include/osv/xen.hh                    |   4 +
 loader.cc                             |   9 +++
 runtime.cc                            |   5 ++
 scripts/gen-drivers-config-header     |  40 ++++++++++
 45 files changed, 621 insertions(+), 10 deletions(-)
 create mode 100644 conf/profiles/README.md
 create mode 100644 conf/profiles/aarch64/all.mk
 create mode 100644 conf/profiles/aarch64/base.mk
 create mode 120000 conf/profiles/aarch64/microvm.mk
 create mode 100644 conf/profiles/aarch64/virtio-mmio.mk
 create mode 100644 conf/profiles/aarch64/virtio-pci.mk
 create mode 100644 conf/profiles/aarch64/xen.mk
 create mode 100644 conf/profiles/x64/all.mk
 create mode 100644 conf/profiles/x64/base.mk
 create mode 100644 conf/profiles/x64/cloud_hypervisor.mk
 create mode 100644 conf/profiles/x64/hyperv.mk
 create mode 120000 conf/profiles/x64/microvm.mk
 create mode 100644 conf/profiles/x64/vbox.mk
 create mode 100644 conf/profiles/x64/virtio-mmio.mk
 create mode 100644 conf/profiles/x64/virtio-pci.mk
 create mode 100644 conf/profiles/x64/vmware.mk
 create mode 100644 conf/profiles/x64/xen.mk
 create mode 100755 scripts/gen-drivers-config-header

diff --git a/Makefile b/Makefile
index 59cc6de4..c1c0eb84 100644
--- a/Makefile
+++ b/Makefile
@@ -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
@@ -617,10 +636,13 @@ 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
@@ -628,8 +650,11 @@ 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
@@ -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
@@ -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
 
@@ -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
@@ -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
@@ -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
@@ -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 $@)
diff --git a/arch/aarch64/arch-dtb.cc b/arch/aarch64/arch-dtb.cc
index 63db8b00..7a7ef51f 100644
--- a/arch/aarch64/arch-dtb.cc
+++ b/arch/aarch64/arch-dtb.cc
@@ -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>
@@ -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
 
@@ -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];
@@ -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.
@@ -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));
diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc
index bfa47f9f..f9854b6a 100644
--- a/arch/aarch64/arch-setup.cc
+++ b/arch/aarch64/arch-setup.cc
@@ -7,6 +7,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include "arch-setup.hh"
 #include <osv/sched.hh>
 #include <osv/mempool.hh>
@@ -16,7 +17,9 @@
 #include <osv/boot.hh>
 #include <osv/debug.hh>
 #include <osv/commands.hh>
+#if CONF_drivers_xen
 #include <osv/xen.hh>
+#endif
 
 #include "arch-mmu.hh"
 #include "arch-dtb.hh"
@@ -24,7 +27,9 @@
 #include "drivers/console.hh"
 #include "drivers/pl011.hh"
 #include "early-console.hh"
+#if CONF_drivers_pci
 #include <osv/pci.hh>
+#endif
 #include "drivers/mmio-isa-serial.hh"
 
 #include <alloca.h>
@@ -41,6 +46,7 @@ void setup_temporary_phys_map()
     mmu::flush_tlb_all();
 }
 
+#if CONF_drivers_pci
 void arch_setup_pci()
 {
     pci::set_pci_ecam(dtb_get_pci_is_ecam());
@@ -71,6 +77,7 @@ void arch_setup_pci()
     mmu::linear_map((void *)ranges[1], (mmu::phys)ranges[1], ranges_len[1],
                     mmu::page_size, mmu::mattr::dev);
 }
+#endif
 
 extern bool opt_pci_disabled;
 void arch_setup_free_memory()
@@ -101,12 +108,14 @@ void arch_setup_free_memory()
                         mmu::mattr::dev);
     }
 
+#if CONF_drivers_cadence
     if (console::Cadence_Console::active) {
         // linear_map [TTBR0 - UART]
         addr = (mmu::phys)console::aarch64_console.cadence.get_base_addr();
         mmu::linear_map((void *)addr, addr, 0x1000, mmu::page_size,
                         mmu::mattr::dev);
     }
+#endif
 
     /* linear_map [TTBR0 - GIC DIST and GIC CPU] */
     u64 dist, cpu;
@@ -120,15 +129,19 @@ void arch_setup_free_memory()
     mmu::linear_map((void *)cpu, (mmu::phys)cpu, cpu_len, mmu::page_size,
                     mmu::mattr::dev);
 
+#if CONF_drivers_pci
     if (!opt_pci_disabled) {
         arch_setup_pci();
     }
+#endif
 
     // get rid of the command line, before memory is unmapped
     console::mmio_isa_serial_console::clean_cmdline(cmdline);
     osv::parse_cmdline(cmdline);
 
+#if CONF_drivers_mmio
     dtb_collect_parsed_mmio_virtio_devices();
+#endif
 
     mmu::switch_to_runtime_page_tables();
 
@@ -155,17 +168,28 @@ void arch_init_premain()
 }
 
 #include "drivers/driver.hh"
+#if CONF_drivers_virtio
 #include "drivers/virtio.hh"
+#include "drivers/virtio-mmio.hh"
+#endif
+#if CONF_drivers_virtio_rng
 #include "drivers/virtio-rng.hh"
+#endif
+#if CONF_drivers_virtio_blk
 #include "drivers/virtio-blk.hh"
+#endif
+#if CONF_drivers_virtio_net
 #include "drivers/virtio-net.hh"
-#include "drivers/virtio-mmio.hh"
+#endif
+#if CONF_drivers_virtio_fs
 #include "drivers/virtio-fs.hh"
+#endif
 
 void arch_init_drivers()
 {
     extern boot_time_chart boot_time;
 
+#if CONF_drivers_pci
     if (!opt_pci_disabled) {
         int irqmap_count = dtb_get_pci_irqmap_count();
         if (irqmap_count > 0) {
@@ -189,16 +213,27 @@ void arch_init_drivers()
             boot_time.event("pci enumerated");
         }
     }
+#endif
 
+#if CONF_drivers_mmio
     // Register any parsed virtio-mmio devices
     virtio::register_mmio_devices(device_manager::instance());
+#endif
 
     // Initialize all drivers
     hw::driver_manager* drvman = hw::driver_manager::instance();
+#if CONF_drivers_virtio_rng
     drvman->register_driver(virtio::rng::probe);
+#endif
+#if CONF_drivers_virtio_blk
     drvman->register_driver(virtio::blk::probe);
+#endif
+#if CONF_drivers_virtio_net
     drvman->register_driver(virtio::net::probe);
+#endif
+#if CONF_drivers_virtio_fs
     drvman->register_driver(virtio::fs::probe);
+#endif
     boot_time.event("drivers probe");
     drvman->load_all();
     drvman->list_drivers();
@@ -208,11 +243,13 @@ void arch_init_early_console()
 {
     console::mmio_isa_serial_console::_phys_mmio_address = 0;
 
+#if CONF_drivers_xen
     if (is_xen()) {
         new (&console::aarch64_console.xen) console::XEN_Console();
         console::arch_early_console = console::aarch64_console.xen;
         return;
     }
+#endif
 
     int irqid;
     u64 mmio_serial_address = dtb_get_mmio_serial_console(&irqid);
@@ -225,6 +262,7 @@ void arch_init_early_console()
         return;
     }
 
+#if CONF_drivers_cadence
     mmio_serial_address = dtb_get_cadence_uart(&irqid);
     if (mmio_serial_address) {
         new (&console::aarch64_console.cadence) console::Cadence_Console();
@@ -234,6 +272,7 @@ void arch_init_early_console()
         console::Cadence_Console::active = true;
         return;
     }
+#endif
 
     new (&console::aarch64_console.pl011) console::PL011_Console();
     console::arch_early_console = console::aarch64_console.pl011;
diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S
index dc59197b..5fce7853 100644
--- a/arch/aarch64/boot.S
+++ b/arch/aarch64/boot.S
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 .text
 .align 16
 .globl start_elf
@@ -31,8 +32,10 @@ start_elf:
         adrp    x1, dtb                     // store dtb (arch-setup.cc)
         str     x5, [x1, #:lo12:dtb]
 
+#if CONF_drivers_xen
         mov     x29, xzr
         bl      init_xen
+#endif
 
         mov     x29, xzr
         bl      premain
diff --git a/arch/aarch64/cpuid.cc b/arch/aarch64/cpuid.cc
index d4da09d4..3b803afc 100644
--- a/arch/aarch64/cpuid.cc
+++ b/arch/aarch64/cpuid.cc
@@ -5,9 +5,12 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include "cpuid.hh"
 #include "processor.hh"
+#if CONF_drivers_xen
 #include "xen.hh"
+#endif
 
 namespace processor {
 
@@ -131,7 +134,9 @@ const unsigned long hwcap32()
 
 void process_cpuid(features_type& features)
 {
+#if CONF_drivers_xen
     xen::get_features(features);
+#endif
 }
 
 const features_type& features()
diff --git a/arch/aarch64/xen.cc b/arch/aarch64/xen.cc
index 47994609..50f752c4 100644
--- a/arch/aarch64/xen.cc
+++ b/arch/aarch64/xen.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#define CONF_drivers_xen 1
 #include <osv/types.h>
 #include <osv/xen.hh>
 #include <xen/interface/xen.h>
diff --git a/arch/x64/apic.cc b/arch/x64/apic.cc
index d0ea6a7d..03518deb 100644
--- a/arch/x64/apic.cc
+++ b/arch/x64/apic.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include "apic.hh"
 #include "msr.hh"
 #include <osv/xen.hh>
diff --git a/arch/x64/arch-setup.cc b/arch/x64/arch-setup.cc
index 439d0650..582cb1b5 100644
--- a/arch/x64/arch-setup.cc
+++ b/arch/x64/arch-setup.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include "arch.hh"
 #include "arch-cpu.hh"
 #include "arch-setup.hh"
@@ -13,7 +14,9 @@
 #include "processor.hh"
 #include "processor-flags.h"
 #include "msr.hh"
+#if CONF_drivers_xen
 #include <osv/xen.hh>
+#endif
 #include <osv/elf.hh>
 #include <osv/types.h>
 #include <alloca.h>
@@ -21,15 +24,21 @@
 #include <osv/boot.hh>
 #include <osv/commands.hh>
 #include "dmi.hh"
+#if CONF_drivers_acpi
 #include "drivers/acpi.hh"
+#endif
 
 osv_multiboot_info_type* osv_multiboot_info;
 
+#if CONF_drivers_mmio
 #include "drivers/virtio-mmio.hh"
+#endif
 void parse_cmdline(multiboot_info_type& mb)
 {
     auto p = reinterpret_cast<char*>(mb.cmdline);
+#if CONF_drivers_mmio
     virtio::parse_mmio_device_configuration(p);
+#endif
     osv::parse_cmdline(p);
 }
 
@@ -214,8 +223,13 @@ void arch_setup_tls(void *tls, const elf::tls_data& info)
 
 static inline void disable_pic()
 {
+#if CONF_drivers_xen
     // PIC not present in Xen
     XENPV_ALTERNATIVE({ processor::outb(0xff, 0x21); processor::outb(0xff, 
0xa1); }, {});
+#else
+    processor::outb(0xff, 0x21);
+    processor::outb(0xff, 0xa1);
+#endif
 }
 
 extern "C" void syscall_entry(void);
@@ -247,53 +261,105 @@ void arch_init_premain()
     if (omb.disk_err)
        debug_early_u64("Error reading disk (real mode): ", 
static_cast<u64>(omb.disk_err));
 
+#if CONF_drivers_acpi
     acpi::pvh_rsdp_paddr = omb.pvh_rsdp;
+#endif
 
     disable_pic();
 }
 
 #include "drivers/driver.hh"
+#if CONF_drivers_acpi
 #include "drivers/pvpanic.hh"
+#endif
+#if CONF_drivers_virtio
 #include "drivers/virtio.hh"
+#endif
+#if CONF_drivers_virtio_blk
 #include "drivers/virtio-blk.hh"
+#endif
+#if CONF_drivers_virtio_scsi
 #include "drivers/virtio-scsi.hh"
+#endif
+#if CONF_drivers_virtio_net
 #include "drivers/virtio-net.hh"
+#endif
+#if CONF_drivers_virtio_rng
 #include "drivers/virtio-rng.hh"
+#endif
+#if CONF_drivers_virtio_fs
 #include "drivers/virtio-fs.hh"
+#endif
+#if CONF_drivers_xen
 #include "drivers/xenplatform-pci.hh"
+#endif
+#if CONF_drivers_ahci
 #include "drivers/ahci.hh"
+#endif
+#if CONF_drivers_pvscsi
 #include "drivers/vmw-pvscsi.hh"
+#endif
+#if CONF_drivers_vmxnet3
 #include "drivers/vmxnet3.hh"
+#endif
+#if CONF_drivers_ide
 #include "drivers/ide.hh"
+#endif
 
 extern bool opt_pci_disabled;
 void arch_init_drivers()
 {
+#if CONF_drivers_acpi
     // initialize panic drivers
     panic::pvpanic::probe_and_setup();
     boot_time.event("pvpanic done");
+#endif
 
+#if CONF_drivers_pci
     if (!opt_pci_disabled) {
         // Enumerate PCI devices
         pci::pci_device_enumeration();
         boot_time.event("pci enumerated");
     }
+#endif
 
+#if CONF_drivers_mmio
     // Register any parsed virtio-mmio devices
     virtio::register_mmio_devices(device_manager::instance());
+#endif
 
     // Initialize all drivers
     hw::driver_manager* drvman = hw::driver_manager::instance();
+#if CONF_drivers_virtio_blk
     drvman->register_driver(virtio::blk::probe);
+#endif
+#if CONF_drivers_virtio_scsi
     drvman->register_driver(virtio::scsi::probe);
+#endif
+#if CONF_drivers_virtio_net
     drvman->register_driver(virtio::net::probe);
+#endif
+#if CONF_drivers_virtio_rng
     drvman->register_driver(virtio::rng::probe);
+#endif
+#if CONF_drivers_virtio_fs
     drvman->register_driver(virtio::fs::probe);
+#endif
+#if CONF_drivers_xen
     drvman->register_driver(xenfront::xenplatform_pci::probe);
+#endif
+#if CONF_drivers_ahci
     drvman->register_driver(ahci::hba::probe);
+#endif
+#if CONF_drivers_pvscsi
     drvman->register_driver(vmw::pvscsi::probe);
+#endif
+#if CONF_drivers_vmxnet3
     drvman->register_driver(vmw::vmxnet3::probe);
+#endif
+#if CONF_drivers_ide
     drvman->register_driver(ide::ide_drive::probe);
+#endif
     boot_time.event("drivers probe");
     drvman->load_all();
     drvman->list_drivers();
@@ -301,7 +367,9 @@ void arch_init_drivers()
 
 #include "drivers/console.hh"
 #include "drivers/isa-serial.hh"
+#if CONF_drivers_vga
 #include "drivers/vga.hh"
+#endif
 #include "early-console.hh"
 
 void arch_init_early_console()
@@ -311,15 +379,21 @@ void arch_init_early_console()
 
 bool arch_setup_console(std::string opt_console)
 {
+#if CONF_drivers_vga
     hw::driver_manager* drvman = hw::driver_manager::instance();
+#endif
 
     if (opt_console.compare("serial") == 0) {
         console::console_driver_add(&console::arch_early_console);
+#if CONF_drivers_vga
     } else if (opt_console.compare("vga") == 0) {
         drvman->register_driver(console::VGAConsole::probe);
+#endif
     } else if (opt_console.compare("all") == 0) {
         console::console_driver_add(&console::arch_early_console);
+#if CONF_drivers_vga
         drvman->register_driver(console::VGAConsole::probe);
+#endif
     } else {
         return false;
     }
diff --git a/arch/x64/cpuid.cc b/arch/x64/cpuid.cc
index 29bc8d6e..73064158 100644
--- a/arch/x64/cpuid.cc
+++ b/arch/x64/cpuid.cc
@@ -5,10 +5,15 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include "cpuid.hh"
 #include "processor.hh"
+#if CONF_drivers_xen
 #include "xen.hh"
+#endif
+#if CONF_drivers_hyperv
 #include <dev/hyperv/include/hyperv.h>
+#endif
 
 namespace processor {
 
@@ -96,6 +101,7 @@ static void process_cpuid_bit(features_type& features, const 
cpuid_bit& b)
     features.*(b.flag) = (w >> b.bit) & 1;
 }
 
+#if CONF_drivers_xen
 static void process_xen_bits(features_type &features)
 {
     signature sig = { 0x566e6558, 0x65584d4d, 0x4d4d566e };
@@ -109,20 +115,27 @@ static void process_xen_bits(features_type &features)
         break;
     }
 }
+#endif
 
+#if CONF_drivers_hyperv
 static void process_hyperv_bits(features_type &features) {
     if(hyperv_identify() && hyperv_is_timecount_available()) {
         features.hyperv_clocksource = true;
     }
 }
+#endif
 
 static void process_cpuid(features_type& features)
 {
     for (unsigned i = 0; i < nr_cpuid_bits; ++i) {
         process_cpuid_bit(features, cpuid_bits[i]);
     }
+#if CONF_drivers_xen
     process_xen_bits(features);
+#endif
+#if CONF_drivers_hyperv
     process_hyperv_bits(features);
+#endif
 }
 
 }
@@ -140,6 +153,7 @@ const std::string& features_str()
         }
     }
 
+#if CONF_drivers_xen
     // FIXME: Even though Xen does not have its features in cpuid, there has to
     // be a better way to do it, by creating a string map directly from the xen
     // PV features. But since we add features here very rarely, leave it be 
for now.
@@ -152,6 +166,7 @@ const std::string& features_str()
     if (features().xen_pci) {
         cpuid_str += std::string("xen_pci ");
     }
+#endif
     cpuid_str.pop_back();
 
     return cpuid_str;
diff --git a/arch/x64/entry-xen.S b/arch/x64/entry-xen.S
index be67b33d..451d35e4 100644
--- a/arch/x64/entry-xen.S
+++ b/arch/x64/entry-xen.S
@@ -3,6 +3,7 @@
 # This work is open source software, licensed under the terms of the
 # BSD license as described in the LICENSE file in the top-level directory.
 
+#include <osv/drivers_config.h>
 #include <xen/interface/elfnote.h>
 
 #define elfnote(type, valtype, value) \
@@ -21,6 +22,7 @@
 #define elfnote_val(type, value) elfnote(type, .quad, value)
 #define elfnote_str(type, value) elfnote(type, .asciz, value)
 
+#if CONF_drivers_xen
 elfnote_val(XEN_ELFNOTE_ENTRY, xen_start)
 elfnote_val(XEN_ELFNOTE_HYPERCALL_PAGE, hypercall_page)
 elfnote_val(XEN_ELFNOTE_VIRT_BASE, OSV_KERNEL_VM_SHIFT)
@@ -30,6 +32,7 @@ elfnote_str(XEN_ELFNOTE_GUEST_VERSION, "?.?")
 elfnote_str(XEN_ELFNOTE_LOADER, "generic")
 elfnote_str(XEN_ELFNOTE_FEATURES, "!writable_page_tables")
 elfnote_str(XEN_ELFNOTE_BSD_SYMTAB, "yes")
+#endif
 elfnote_val(XEN_ELFNOTE_PHYS32_ENTRY, hvm_xen_start-OSV_KERNEL_VM_SHIFT)
 
 .data
@@ -41,6 +44,7 @@ elfnote_val(XEN_ELFNOTE_PHYS32_ENTRY, 
hvm_xen_start-OSV_KERNEL_VM_SHIFT)
 xen_bootstrap_end: .quad 0
 
 .text
+#if CONF_drivers_xen
 .align 4096
 .globl hypercall_page
 .hidden hypercall_page
@@ -54,6 +58,7 @@ xen_start:
     call xen_init
     mov $0x0, %rdi
     jmp start64
+#endif
 
 .code32
 hvm_xen_start:
diff --git a/arch/x64/power.cc b/arch/x64/power.cc
index c9656fe0..71cba972 100644
--- a/arch/x64/power.cc
+++ b/arch/x64/power.cc
@@ -5,17 +5,20 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include <osv/power.hh>
 #include <osv/debug.hh>
 #include <smp.hh>
 #include <processor.hh>
 #include <arch.hh>
 
+#if CONF_drivers_acpi
 extern "C" {
 #include "acpi.h"
 }
 
 #include <drivers/acpi.hh>
+#endif
 
 namespace osv {
 
@@ -29,6 +32,7 @@ void halt(void)
 
 void poweroff(void)
 {
+#if CONF_drivers_acpi
     if (acpi::is_enabled()) {
         ACPI_STATUS status = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
         if (ACPI_FAILURE(status)) {
@@ -41,6 +45,7 @@ void poweroff(void)
             halt();
         }
     } else {
+#endif
         // On hypervisors that do not support ACPI like firecracker we
         // resort to a reset using the 8042 PS/2 Controller ("keyboard 
controller")
         // as a way to shutdown the VM
@@ -49,7 +54,9 @@ void poweroff(void)
         // then cause triple fault by loading a broken IDT and triggering an 
interrupt.
         processor::lidt(processor::desc_ptr(0, 0));
         __asm__ __volatile__("int3");
+#if CONF_drivers_acpi
     }
+#endif
 
     // We shouldn't get here on x86.
     halt();
@@ -71,9 +78,11 @@ static void kbd_reboot(void) {
 
 void reboot(void)
 {
+#if CONF_drivers_acpi
     // Method 1: AcpiReset, does not work on qemu or kvm now because the reset
     // register is not supported. Nevertheless, we should try it first
     AcpiReset();
+#endif
     // Method 2: "fast reset" via System Control Port A (port 0x92)
     processor::outb(1, 0x92);
     // Method 3: Reset using the 8042 PS/2 Controller ("keyboard controller")
diff --git a/arch/x64/smp.cc b/arch/x64/smp.cc
index be655881..7141c2a9 100644
--- a/arch/x64/smp.cc
+++ b/arch/x64/smp.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include <smp.hh>
 #include "processor.hh"
 #include "msr.hh"
@@ -12,10 +13,12 @@
 #include "ioapic.hh"
 #include <osv/mmu.hh>
 #include <string.h>
+#if CONF_drivers_acpi
 extern "C" {
 #include "acpi.h"
 }
 #include <drivers/acpi.hh>
+#endif
 #include <boost/intrusive/parent_from_member.hpp>
 #include <osv/debug.hh>
 #include <osv/sched.hh>
@@ -49,6 +52,7 @@ static void register_cpu(unsigned cpu_id, u32 apic_id, u32 
acpi_id = 0)
     sched::cpus.push_back(c);
 }
 
+#if CONF_drivers_acpi
 void parse_madt()
 {
     char madt_sig[] = ACPI_SIG_MADT;
@@ -88,6 +92,7 @@ void parse_madt()
     }
     debug(fmt("%d CPUs detected\n") % nr_cpus);
 }
+#endif
 
 #define MPF_IDENTIFIER (('_'<<24) | ('P'<<16) | ('M'<<8) | '_')
 struct mpf_structure {
@@ -195,11 +200,15 @@ void parse_mp_table()
 
 void smp_init()
 {
+#if CONF_drivers_acpi
     if (acpi::is_enabled()) {
         parse_madt();
     } else {
+#endif
         parse_mp_table();
+#if CONF_drivers_acpi
     }
+#endif
 
     sched::current_cpu = sched::cpus[0];
     for (auto c : sched::cpus) {
diff --git a/arch/x64/xen.cc b/arch/x64/xen.cc
index d642c4fa..2482c56a 100644
--- a/arch/x64/xen.cc
+++ b/arch/x64/xen.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#define CONF_drivers_xen 1
 #include "xen.hh"
 #include <osv/debug.hh>
 #include <osv/mmu.hh>
diff --git a/conf/profiles/README.md b/conf/profiles/README.md
new file mode 100644
index 00000000..5350fe70
--- /dev/null
+++ b/conf/profiles/README.md
@@ -0,0 +1,71 @@
+The two subdirectories `aarch64` and `x64` contain tiny makefile
+include files (`*.mk`) which specify which drivers should be linked
+and enabled into kernel.
+
+The `base.mk` is the file included last by the main makefile and is
+intended to disable all drivers unless enabled specifically in a
+given profile file. For example, each driver configuration variable
+like `conf_drivers_virtio_fs` is disabled in a line in the `base.mk` like this:
+```make
+export conf_drivers_virtio_fs?=0
+```
+but would be enabled by this line in the `virtio-pci.mk`:
+```make
+conf_drivers_virtio_fs?=1
+```
+if the profile `virtio-pci` is selected when building the kernel like so:
+```bash
+./scripts/build fs=rofs conf_hide_symbols=1 image=native-example 
drivers_profile=virtio-pci
+```
+The `base.mk` also enforces some dependencies between given driver and other 
kernel
+components. For example this line:
+```make
+ifeq ($(conf_drivers_hpet),1)
+export conf_drivers_acpi?=1
+endif
+```
+enables ACPI support if the hpet driver is selected. There is also another 
rule that
+enables PCI support if ACPI is selected. And so on.
+
+The individual files under given architecture directory other than `base.mk` 
enable
+list of drivers for each profile that typically corresponds to a hypervisor 
like `vbox.mk`
+for Virtual Box or a type of hypervisor like `microvm.mk`. One exception is 
the `all.mk`
+file which enables all drivers and is a default profile.
+
+Please note that one can build custom kernel with specific list of drivers by 
passing
+corresponding `conf_drivers_*` parameters to the build script like so:
+```bash
+./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
+```
+The kernel built using the command line above comes with enough drivers to 
mount virtio-FS filesystem and support networking over virtio-net device.
+
+Lastly if you want to verify which exact drivers were enabled, you can examine 
content of the generated `drivers-config.h` header:
+```c
+cat build/release/gen/include/osv/drivers_config.h
+/* This file is generated automatically. */
+#ifndef OSV_DRIVERS_CONFIG_H
+#define OSV_DRIVERS_CONFIG_H
+
+#define CONF_drivers_acpi 1
+#define CONF_drivers_ahci 0
+#define CONF_drivers_hpet 0
+#define CONF_drivers_hyperv 0
+#define CONF_drivers_ide 0
+#define CONF_drivers_mmio 0
+#define CONF_drivers_pci 1
+#define CONF_drivers_pvpanic 1
+#define CONF_drivers_pvscsi 0
+#define CONF_drivers_scsi 0
+#define CONF_drivers_vga 0
+#define CONF_drivers_virtio 1
+#define CONF_drivers_virtio_blk 0
+#define CONF_drivers_virtio_fs 1
+#define CONF_drivers_virtio_net 1
+#define CONF_drivers_virtio_rng 0
+#define CONF_drivers_virtio_scsi 0
+#define CONF_drivers_vmxnet3 0
+#define CONF_drivers_xen 0
+
+#endif
+```
diff --git a/conf/profiles/aarch64/all.mk b/conf/profiles/aarch64/all.mk
new file mode 100644
index 00000000..afc51954
--- /dev/null
+++ b/conf/profiles/aarch64/all.mk
@@ -0,0 +1,5 @@
+include conf/profiles/$(arch)/virtio-mmio.mk
+include conf/profiles/$(arch)/virtio-pci.mk
+include conf/profiles/$(arch)/xen.mk
+
+conf_drivers_cadence?=1
diff --git a/conf/profiles/aarch64/base.mk b/conf/profiles/aarch64/base.mk
new file mode 100644
index 00000000..a3894f54
--- /dev/null
+++ b/conf/profiles/aarch64/base.mk
@@ -0,0 +1,26 @@
+export conf_drivers_xen?=0
+
+export conf_drivers_virtio_blk?=0
+ifeq ($(conf_drivers_virtio_blk),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_virtio_fs?=0
+ifeq ($(conf_drivers_virtio_fs),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_virtio_net?=0
+ifeq ($(conf_drivers_virtio_net),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_virtio_rng?=0
+ifeq ($(conf_drivers_virtio_rng),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_cadence?=0
+export conf_drivers_virtio?=0
+export conf_drivers_pci?=0
+export conf_drivers_mmio?=0
diff --git a/conf/profiles/aarch64/microvm.mk b/conf/profiles/aarch64/microvm.mk
new file mode 120000
index 00000000..d85dd828
--- /dev/null
+++ b/conf/profiles/aarch64/microvm.mk
@@ -0,0 +1 @@
+virtio-mmio.mk
\ No newline at end of file
diff --git a/conf/profiles/aarch64/virtio-mmio.mk 
b/conf/profiles/aarch64/virtio-mmio.mk
new file mode 100644
index 00000000..d8d9669b
--- /dev/null
+++ b/conf/profiles/aarch64/virtio-mmio.mk
@@ -0,0 +1,4 @@
+conf_drivers_mmio?=1
+
+conf_drivers_virtio_blk?=1
+conf_drivers_virtio_net?=1
diff --git a/conf/profiles/aarch64/virtio-pci.mk 
b/conf/profiles/aarch64/virtio-pci.mk
new file mode 100644
index 00000000..599a530c
--- /dev/null
+++ b/conf/profiles/aarch64/virtio-pci.mk
@@ -0,0 +1,6 @@
+conf_drivers_pci?=1
+
+conf_drivers_virtio_blk?=1
+conf_drivers_virtio_fs?=1
+conf_drivers_virtio_net?=1
+conf_drivers_virtio_rng?=1
diff --git a/conf/profiles/aarch64/xen.mk b/conf/profiles/aarch64/xen.mk
new file mode 100644
index 00000000..2c5f0c87
--- /dev/null
+++ b/conf/profiles/aarch64/xen.mk
@@ -0,0 +1,2 @@
+conf_drivers_pci?=1
+conf_drivers_xen?=1
diff --git a/conf/profiles/x64/all.mk b/conf/profiles/x64/all.mk
new file mode 100644
index 00000000..c13790e2
--- /dev/null
+++ b/conf/profiles/x64/all.mk
@@ -0,0 +1,8 @@
+include conf/profiles/$(arch)/hyperv.mk
+include conf/profiles/$(arch)/vbox.mk
+include conf/profiles/$(arch)/virtio-mmio.mk
+include conf/profiles/$(arch)/virtio-pci.mk
+include conf/profiles/$(arch)/vmware.mk
+include conf/profiles/$(arch)/xen.mk
+
+conf_drivers_vga?=1
diff --git a/conf/profiles/x64/base.mk b/conf/profiles/x64/base.mk
new file mode 100644
index 00000000..26dd054e
--- /dev/null
+++ b/conf/profiles/x64/base.mk
@@ -0,0 +1,74 @@
+export conf_drivers_xen?=0
+export conf_drivers_hyperv?=0
+
+export conf_drivers_virtio_blk?=0
+ifeq ($(conf_drivers_virtio_blk),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_virtio_scsi?=0
+ifeq ($(conf_drivers_virtio_scsi),1)
+export conf_drivers_virtio?=1
+export conf_drivers_scsi?=1
+endif
+
+export conf_drivers_virtio_fs?=0
+ifeq ($(conf_drivers_virtio_fs),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_virtio_net?=0
+ifeq ($(conf_drivers_virtio_net),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_virtio_rng?=0
+ifeq ($(conf_drivers_virtio_rng),1)
+export conf_drivers_virtio?=1
+endif
+
+export conf_drivers_ahci?=0
+ifeq ($(conf_drivers_ahci),1)
+export conf_drivers_pci?=1
+endif
+
+export conf_drivers_pvscsi?=0
+ifeq ($(conf_drivers_pvscsi),1)
+export conf_drivers_pci?=1
+export conf_drivers_scsi?=1
+endif
+
+export conf_drivers_vmxnet3?=0
+ifeq ($(conf_drivers_vmxnet3),1)
+export conf_drivers_pci?=1
+endif
+
+export conf_drivers_ide?=0
+ifeq ($(conf_drivers_ide),1)
+export conf_drivers_pci?=1
+endif
+
+export conf_drivers_vga?=0
+ifeq ($(conf_drivers_vga),1)
+export conf_drivers_pci?=1
+endif
+
+export conf_drivers_pvpanic?=0
+ifeq ($(conf_drivers_pvpanic),1)
+export conf_drivers_acpi?=1
+endif
+
+export conf_drivers_hpet?=0
+ifeq ($(conf_drivers_hpet),1)
+export conf_drivers_acpi?=1
+endif
+
+export conf_drivers_acpi?=0
+ifeq ($(conf_drivers_acpi),1)
+export conf_drivers_pci?=1
+endif
+
+export conf_drivers_virtio?=0
+export conf_drivers_pci?=0
+export conf_drivers_mmio?=0
+export conf_drivers_scsi?=0
diff --git a/conf/profiles/x64/cloud_hypervisor.mk 
b/conf/profiles/x64/cloud_hypervisor.mk
new file mode 100644
index 00000000..aa8695dc
--- /dev/null
+++ b/conf/profiles/x64/cloud_hypervisor.mk
@@ -0,0 +1,2 @@
+include conf/profiles/$(arch)/virtio-pci.mk
+conf_drivers_pvpanic?=1
diff --git a/conf/profiles/x64/hyperv.mk b/conf/profiles/x64/hyperv.mk
new file mode 100644
index 00000000..69af65ca
--- /dev/null
+++ b/conf/profiles/x64/hyperv.mk
@@ -0,0 +1,6 @@
+conf_drivers_pci?=1
+conf_drivers_acpi?=1
+conf_drivers_hyperv?=1
+
+conf_drivers_pvpanic?=1
+conf_drivers_hpet?=1
diff --git a/conf/profiles/x64/microvm.mk b/conf/profiles/x64/microvm.mk
new file mode 120000
index 00000000..d85dd828
--- /dev/null
+++ b/conf/profiles/x64/microvm.mk
@@ -0,0 +1 @@
+virtio-mmio.mk
\ No newline at end of file
diff --git a/conf/profiles/x64/vbox.mk b/conf/profiles/x64/vbox.mk
new file mode 100644
index 00000000..f0a26b2d
--- /dev/null
+++ b/conf/profiles/x64/vbox.mk
@@ -0,0 +1,8 @@
+conf_drivers_pci?=1
+conf_drivers_acpi?=1
+
+conf_drivers_ahci?=1
+conf_drivers_virtio_net?=1
+
+conf_drivers_pvpanic?=1
+conf_drivers_hpet?=1
diff --git a/conf/profiles/x64/virtio-mmio.mk b/conf/profiles/x64/virtio-mmio.mk
new file mode 100644
index 00000000..d8d9669b
--- /dev/null
+++ b/conf/profiles/x64/virtio-mmio.mk
@@ -0,0 +1,4 @@
+conf_drivers_mmio?=1
+
+conf_drivers_virtio_blk?=1
+conf_drivers_virtio_net?=1
diff --git a/conf/profiles/x64/virtio-pci.mk b/conf/profiles/x64/virtio-pci.mk
new file mode 100644
index 00000000..a1d0a1ef
--- /dev/null
+++ b/conf/profiles/x64/virtio-pci.mk
@@ -0,0 +1,10 @@
+conf_drivers_pci?=1
+conf_drivers_acpi?=1
+
+conf_drivers_virtio_blk?=1
+conf_drivers_virtio_scsi?=1
+conf_drivers_virtio_fs?=1
+conf_drivers_virtio_net?=1
+conf_drivers_virtio_rng?=1
+
+conf_drivers_pvpanic?=1
diff --git a/conf/profiles/x64/vmware.mk b/conf/profiles/x64/vmware.mk
new file mode 100644
index 00000000..1a37e1d1
--- /dev/null
+++ b/conf/profiles/x64/vmware.mk
@@ -0,0 +1,10 @@
+conf_drivers_pci?=1
+conf_drivers_acpi?=1
+conf_drivers_scsi?=1
+
+conf_drivers_pvscsi?=1
+conf_drivers_vmxnet3?=1
+conf_drivers_ide?=1
+
+conf_drivers_pvpanic?=1
+conf_drivers_hpet?=1
diff --git a/conf/profiles/x64/xen.mk b/conf/profiles/x64/xen.mk
new file mode 100644
index 00000000..8a0d49fa
--- /dev/null
+++ b/conf/profiles/x64/xen.mk
@@ -0,0 +1,6 @@
+conf_drivers_pci?=1
+conf_drivers_acpi?=1
+conf_drivers_xen?=1
+
+conf_drivers_pvpanic?=1
+conf_drivers_hpet?=1
diff --git a/core/xen_intr.cc b/core/xen_intr.cc
index 16065a3d..adb4e3da 100644
--- a/core/xen_intr.cc
+++ b/core/xen_intr.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#define CONF_drivers_xen 1
 #include <osv/xen.hh>
 #include <osv/xen_intr.hh>
 #include <bsd/porting/bus.h>
diff --git a/drivers/acpi.cc b/drivers/acpi.cc
index 55ea126e..d1f5f422 100644
--- a/drivers/acpi.cc
+++ b/drivers/acpi.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include <map>
 #include <memory>
 
@@ -19,7 +20,9 @@ extern "C" {
 #include <osv/shutdown.hh>
 #include "processor.hh"
 #include <osv/align.hh>
+#if CONF_drivers_xen
 #include <osv/xen.hh>
+#endif
 
 #include <osv/debug.h>
 #include <osv/mutex.h>
@@ -635,5 +638,9 @@ void init()
 
 void __attribute__((constructor(init_prio::acpi))) acpi_init_early()
 {
-     XENPV_ALTERNATIVE({ acpi::early_init(); }, {});
+#if CONF_drivers_xen
+    XENPV_ALTERNATIVE({ acpi::early_init(); }, {});
+#else
+    acpi::early_init();
+#endif
 }
diff --git a/drivers/hpet.cc b/drivers/hpet.cc
index 6b67d8b7..8c582f80 100644
--- a/drivers/hpet.cc
+++ b/drivers/hpet.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 extern "C" {
 #include "acpi.h"
 }
@@ -15,7 +16,9 @@ extern "C" {
 #include <osv/mmu.hh>
 #include <osv/mmio.hh>
 #include "arch.hh"
+#if CONF_drivers_xen
 #include <osv/xen.hh>
+#endif
 #include <osv/irqlock.hh>
 #include "rtc.hh"
 #include <osv/percpu.hh>
@@ -146,7 +149,9 @@ s64 hpetclock::boot_time()
 
 void __attribute__((constructor(init_prio::hpet))) hpet_init()
 {
+#if CONF_drivers_xen
     XENPV_ALTERNATIVE(
+#endif
     {
         auto c = clock::get();
 
@@ -178,5 +183,9 @@ void __attribute__((constructor(init_prio::hpet))) 
hpet_init()
         else {
             clock::register_clock(new hpet_32bit_clock(hpet_mmio_address));
         }
+#if CONF_drivers_xen
     }, {});
+#else
+    }
+#endif
 }
diff --git a/drivers/pci-generic.cc b/drivers/pci-generic.cc
index 6b0a9185..ff967715 100644
--- a/drivers/pci-generic.cc
+++ b/drivers/pci-generic.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include <sstream>
 #include <iomanip>
 
@@ -16,8 +17,10 @@
 #include "drivers/pci-function.hh"
 #include "drivers/pci-bridge.hh"
 #include "drivers/pci-device.hh"
+#if CONF_drivers_virtio
 #include "drivers/virtio.hh"
 #include "drivers/virtio-pci-device.hh"
+#endif
 
 extern bool opt_pci_disabled;
 
@@ -102,6 +105,7 @@ bool check_bus(u16 bus)
             }
 
             hw_device *dev_to_register = dev;
+#if CONF_drivers_virtio
             //
             // Create virtio_device if vendor is VIRTIO_VENDOR_ID
             if (dev->get_vendor_id() == virtio::VIRTIO_VENDOR_ID) {
@@ -117,6 +121,7 @@ bool check_bus(u16 bus)
                     pci_e("Error: expected regular pci device %02x:%02x.%x",
                           bus, slot, func);
             }
+#endif
 
             if (dev_to_register && 
!device_manager::instance()->register_device(dev_to_register)) {
                 pci_e("Error: couldn't register device %02x:%02x.%x",
diff --git a/drivers/virtio-blk.cc b/drivers/virtio-blk.cc
index 91ca492e..e03d41f7 100644
--- a/drivers/virtio-blk.cc
+++ b/drivers/virtio-blk.cc
@@ -6,6 +6,7 @@
  */
 
 
+#include <osv/drivers_config.h>
 #include <sys/cdefs.h>
 
 #include "drivers/virtio.hh"
@@ -133,6 +134,7 @@ blk::blk(virtio_device& virtio_dev)
     auto queue = get_virt_queue(0);
 
     interrupt_factory int_factory;
+#if CONF_drivers_pci
     int_factory.register_msi_bindings = [queue, t](interrupt_manager &msi) {
         msi.easy_register( {{ 0, [=] { queue->disable_interrupts(); }, t }});
     };
@@ -143,6 +145,7 @@ blk::blk(virtio_device& virtio_dev)
             [=] { return this->ack_irq(); },
             [=] { t->wake(); });
     };
+#endif
 
 #ifdef __aarch64__
     int_factory.create_spi_edge_interrupt = [this,t]() {
@@ -153,11 +156,13 @@ blk::blk(virtio_device& virtio_dev)
                 [=] { t->wake(); });
     };
 #else
+#if CONF_drivers_mmio
     int_factory.create_gsi_edge_interrupt = [this,t]() {
         return new gsi_edge_interrupt(
                 _dev.get_irq(),
                 [=] { if (this->ack_irq()) t->wake(); });
     };
+#endif
 #endif
 
     _dev.register_interrupt(int_factory);
diff --git a/drivers/virtio-fs.cc b/drivers/virtio-fs.cc
index 0c5ffb4e..e87d0ce1 100644
--- a/drivers/virtio-fs.cc
+++ b/drivers/virtio-fs.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include <string>
 
 #include <osv/debug.h>
@@ -101,6 +102,7 @@ fs::fs(virtio_device& virtio_dev)
     auto* queue = get_virt_queue(VQ_REQUEST);
 
     interrupt_factory int_factory;
+#if CONF_drivers_pci
     int_factory.register_msi_bindings = [queue, t](interrupt_manager& msi) {
         msi.easy_register({
             {VQ_HIPRIO, nullptr, nullptr},
@@ -114,13 +116,16 @@ fs::fs(virtio_device& virtio_dev)
             [=] { return this->ack_irq(); },
             [=] { t->wake(); });
     };
+#endif
 
 #ifdef __x86_64__
+#if CONF_drivers_mmio
     int_factory.create_gsi_edge_interrupt = [this, t]() {
         return new gsi_edge_interrupt(
             _dev.get_irq(),
             [=] { if (this->ack_irq()) t->wake(); });
     };
+#endif
 #endif
 
     _dev.register_interrupt(int_factory);
diff --git a/drivers/virtio-net.cc b/drivers/virtio-net.cc
index 4be60f10..d2ab7c76 100644
--- a/drivers/virtio-net.cc
+++ b/drivers/virtio-net.cc
@@ -6,6 +6,7 @@
  */
 
 
+#include <osv/drivers_config.h>
 #include <sys/cdefs.h>
 
 #include "drivers/virtio.hh"
@@ -303,6 +304,7 @@ net::net(virtio_device& dev)
     ether_ifattach(_ifn, _config.mac);
 
     interrupt_factory int_factory;
+#if CONF_drivers_pci
     int_factory.register_msi_bindings = [this,poll_task](interrupt_manager 
&msi) {
        msi.easy_register({
            { 0, [&] { this->_rxq.vqueue->disable_interrupts(); }, poll_task },
@@ -316,6 +318,7 @@ net::net(virtio_device& dev)
             [=] { return this->ack_irq(); },
             [=] { poll_task->wake(); });
     };
+#endif
 
 #ifdef __aarch64__
     int_factory.create_spi_edge_interrupt = [this,poll_task]() {
@@ -326,11 +329,13 @@ net::net(virtio_device& dev)
             [=] { poll_task->wake(); });
     };
 #else
+#if CONF_drivers_mmio
     int_factory.create_gsi_edge_interrupt = [this,poll_task]() {
         return new gsi_edge_interrupt(
             _dev.get_irq(),
             [=] { if (this->ack_irq()) poll_task->wake(); });
     };
+#endif
 #endif
 
     _dev.register_interrupt(int_factory);
diff --git a/drivers/xenclock.cc b/drivers/xenclock.cc
index 6f5093cd..e9269d60 100644
--- a/drivers/xenclock.cc
+++ b/drivers/xenclock.cc
@@ -14,6 +14,7 @@
 #include "string.h"
 #include "cpuid.hh"
 #include <osv/barrier.hh>
+#define CONF_drivers_xen 1
 #include <osv/xen.hh>
 #include <osv/debug.hh>
 #include <osv/prio.hh>
diff --git a/drivers/xenfront-xenbus.cc b/drivers/xenfront-xenbus.cc
index ba143841..36e7f3dc 100644
--- a/drivers/xenfront-xenbus.cc
+++ b/drivers/xenfront-xenbus.cc
@@ -11,6 +11,7 @@
 #include "cpuid.hh"
 #include <osv/barrier.hh>
 #include <osv/debug.hh>
+#define CONF_drivers_xen 1
 #include <osv/xen.hh>
 #include "processor.hh"
 #include "xenfront.hh"
diff --git a/drivers/xenplatform-pci.cc b/drivers/xenplatform-pci.cc
index 16488cfa..15f1ea51 100644
--- a/drivers/xenplatform-pci.cc
+++ b/drivers/xenplatform-pci.cc
@@ -6,6 +6,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#define CONF_drivers_xen 1
 #include "xen.hh"
 #include "xenplatform-pci.hh"
 
diff --git a/fs/vfs/vfs_conf.cc b/fs/vfs/vfs_conf.cc
index 4a54cb97..48211e77 100644
--- a/fs/vfs/vfs_conf.cc
+++ b/fs/vfs/vfs_conf.cc
@@ -38,6 +38,7 @@
  * vfs_conf.c - File system configuration.
  */
 
+#include <osv/drivers_config.h>
 #include <limits.h>
 #include <unistd.h>
 #include <string.h>
@@ -52,11 +53,15 @@ extern struct vfsops nfs_vfsops;
 extern struct vfsops procfs_vfsops;
 extern struct vfsops sysfs_vfsops;
 extern struct vfsops zfs_vfsops;
+#if CONF_drivers_virtio_fs
 extern struct vfsops virtiofs_vfsops;
+#endif
 
 extern int ramfs_init(void);
 extern int rofs_init(void);
+#if CONF_drivers_virtio_fs
 extern int virtiofs_init(void);
+#endif
 extern int devfs_init(void);
 extern int nfs_init(void);
 extern int procfs_init(void);
@@ -74,6 +79,8 @@ const struct vfssw vfssw[] = {
        {"sysfs",       sysfs_init,     &sysfs_vfsops},
        {"zfs",         zfs_init,       &zfs_vfsops},
        {"rofs",        rofs_init,      &rofs_vfsops},
+#if CONF_drivers_virtio_fs
        {"virtiofs",    virtiofs_init,  &virtiofs_vfsops},
+#endif
        {nullptr,       fs_noop,        nullptr},
 };
diff --git a/include/osv/xen.hh b/include/osv/xen.hh
index 5b50c2b6..76ca3b49 100644
--- a/include/osv/xen.hh
+++ b/include/osv/xen.hh
@@ -24,7 +24,11 @@ extern struct start_info* xen_start_info;
 extern "C" shared_info_t *HYPERVISOR_shared_info;
 
 #define XENPV_ALTERNATIVE(x, y) ALTERNATIVE((xen_start_info != nullptr), x, y)
+#if CONF_drivers_xen
 #define is_xen() (HYPERVISOR_shared_info != nullptr)
+#else
+#define is_xen() (0)
+#endif
 
 // We don't support 32 bit
 struct xen_vcpu_info {
diff --git a/loader.cc b/loader.cc
index da254492..48716587 100644
--- a/loader.cc
+++ b/loader.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include "fs/fs.hh"
 #include <bsd/init.hh>
 #include <bsd/net.hh>
@@ -20,7 +21,9 @@
 #include "smp.hh"
 
 #ifdef __x86_64__
+#if CONF_drivers_acpi
 #include "drivers/acpi.hh"
+#endif
 #endif /* __x86_64__ */
 
 #include <osv/sched.hh>
@@ -43,7 +46,9 @@
 #include <osv/sampler.hh>
 #include <osv/app.hh>
 #include <osv/firmware.hh>
+#if CONF_drivers_xen
 #include <osv/xen.hh>
+#endif
 #include <osv/options.hh>
 #include <dirent.h>
 #include <iostream>
@@ -672,7 +677,9 @@ void main_cont(int loader_argc, char** loader_argv)
 
     setenv("OSV_VERSION", osv::version().c_str(), 1);
 
+#if CONF_drivers_xen
     xen::irq_init();
+#endif
     smp_launch();
     setenv("OSV_CPUS", std::to_string(sched::cpus.size()).c_str(), 1);
     boot_time.event("SMP launched");
@@ -685,7 +692,9 @@ void main_cont(int loader_argc, char** loader_argv)
     memory::enable_debug_allocator();
 
 #ifdef __x86_64__
+#if CONF_drivers_acpi
     acpi::init();
+#endif
 #endif /* __x86_64__ */
 
     if (sched::cpus.size() > sched::max_cpus) {
diff --git a/runtime.cc b/runtime.cc
index 10c72cca..3942982c 100644
--- a/runtime.cc
+++ b/runtime.cc
@@ -5,6 +5,7 @@
  * BSD license as described in the LICENSE file in the top-level directory.
  */
 
+#include <osv/drivers_config.h>
 #include <osv/sched.hh>
 #include <osv/elf.hh>
 #include <stdlib.h>
@@ -48,7 +49,9 @@
 #include <boost/range/adaptor/reversed.hpp>
 #include <osv/align.hh>
 #include <osv/stubbing.hh>
+#if CONF_drivers_acpi
 #include "drivers/pvpanic.hh"
+#endif
 #include <api/sys/resource.h>
 #include <api/math.h>
 #include <osv/shutdown.hh>
@@ -128,7 +131,9 @@ void abort(const char *fmt, ...)
         debug_early("Halting.\n");
     }
 #ifndef AARCH64_PORT_STUB
+#if CONF_drivers_acpi
     panic::pvpanic::panicked();
+#endif
 #endif /* !AARCH64_PORT_STUB */
 
     if (opt_power_off_on_abort) {
diff --git a/scripts/gen-drivers-config-header 
b/scripts/gen-drivers-config-header
new file mode 100755
index 00000000..daa0f373
--- /dev/null
+++ b/scripts/gen-drivers-config-header
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+if [ "$#" -ne 2 ]; then
+  echo "usage: $(basename $0) ARCH OUTPUT" >&2
+  exit 1
+fi
+
+arch=$1
+
+output=$2
+
+drivers_config_base_file=`dirname $0`/../conf/profiles/$arch/base.mk
+
+tmp=$(mktemp)
+
+cat >$tmp <<EOL
+/* This file is generated automatically. */
+#ifndef OSV_DRIVERS_CONFIG_H
+#define OSV_DRIVERS_CONFIG_H
+
+EOL
+
+template_tmp=$(mktemp)
+cat $drivers_config_base_file | grep "export conf" | cut --delimiter=_ -f 2- | 
cut --delimiter=? -f 1 | \
+  sort | uniq | awk '{ printf("echo define CONF_%s $conf_%s\n", $0, $0) }' > 
$template_tmp
+. $template_tmp | awk '{printf("#%s\n",$0)}' >> $tmp
+rm $template_tmp
+
+cat >>$tmp <<EOL
+
+#endif
+EOL
+
+if cmp -s $tmp $output
+then
+    rm $tmp
+else
+    mkdir -p $(dirname $output)
+    mv $tmp $output
+fi
-- 
2.31.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20220209021905.514779-1-jwkozaczuk%40gmail.com.

Reply via email to