summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorDan Peebles <pumpkin@me.com>2016-01-05 09:22:43 -0500
committerTuomas Tynkkynen <tuomas@tuxera.com>2018-06-30 16:01:41 +0300
commitff9999ad1b19b941b275b7ec79514d04c7cdad7d (patch)
treee3167d9f1a1483d51c756cb1990bdaab76a58a2d /pkgs
parentbae87d504224d853c5548d2aa244b596569fc7f3 (diff)
downloadnixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.tar
nixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.tar.gz
nixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.tar.bz2
nixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.tar.lz
nixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.tar.xz
nixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.tar.zst
nixpkgs-ff9999ad1b19b941b275b7ec79514d04c7cdad7d.zip
linux: translate config to structured config
Instead of using a string to describe kernel config, use a nix
attribute set, then converted to a string.
- allows to override the config, aka convert 'yes' into 'modules' or
vice-versa
- while for now merging different configs is still crude (last spec wins),
at least there should be only one CONFIG_XYZ value compared to the current string
config where the first defined would be used and others ignored.

[initial idea by copumpkin in 2016, a major rebase to 2018 by teto]
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/os-specific/linux/kernel/common-config.nix1416
-rw-r--r--pkgs/os-specific/linux/kernel/generic.nix13
-rw-r--r--pkgs/os-specific/linux/kernel/manual-config.nix2
3 files changed, 708 insertions, 723 deletions
diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix
index 93732f1c6f8..3ebac03dcd7 100644
--- a/pkgs/os-specific/linux/kernel/common-config.nix
+++ b/pkgs/os-specific/linux/kernel/common-config.nix
@@ -1,726 +1,706 @@
-/*
+# WARNING/NOTE: whenever you want to add an option here you need to either
+# * mark it as an optional one with `option`,
+# * or make sure it works for all the versions in nixpkgs,
+# * or check for which kernel versions it will work (using kernel
+#   changelog, google or whatever) and mark it with `whenOlder` or
+#   `whenAtLeast`.
+# Then do test your change by building all the kernels (or at least
+# their configs) in Nixpkgs or else you will guarantee lots and lots
+# of pain to users trying to switch to an older kernel because of some
+# hardware problems with a new one.
 
-  WARNING/NOTE: whenever you want to add an option here you need to
-  either
+# Configuration
+{ stdenv, version
 
-  * mark it as an optional one with `?` suffix,
-  * or make sure it works for all the versions in nixpkgs,
-  * or check for which kernel versions it will work (using kernel
-    changelog, google or whatever) and mark it with `versionOlder` or
-    `versionAtLeast`.
+# to let user override values, aka converting modules to included and vice-versa
+, mkValueOverride ? null
 
-  Then do test your change by building all the kernels (or at least
-  their configs) in Nixpkgs or else you will guarantee lots and lots
-  of pain to users trying to switch to an older kernel because of some
-  hardware problems with a new one.
+# new extraConfig as a flattened set
+, structuredExtraConfig ? {}
 
-*/
+# legacy extraConfig as string
+, extraConfig ? ""
 
-{ stdenv, version, extraConfig, features }:
+, features ? {}
+}:
+
+assert (mkValueOverride == null) || (builtins.isFunction mkValueOverride);
 
 with stdenv.lib;
 
-''
-  # Compress kernel modules for a sizable disk space savings.
-  ${optionalString (versionAtLeast version "3.18") ''
-    MODULE_COMPRESS y
-    MODULE_COMPRESS_XZ y
-  ''}
-
-  KERNEL_XZ y
-
-  # Debugging.
-  DEBUG_KERNEL y
-  DYNAMIC_DEBUG y
-  DEBUG_DEVRES n
-  DEBUG_STACK_USAGE n
-  DEBUG_STACKOVERFLOW n
-  SCHEDSTATS n
-  DETECT_HUNG_TASK y
-
-  ${if (features.debug or false) then ''
-    DEBUG_INFO y
-  '' else ''
-    DEBUG_INFO n
-  ''}
-
-  ${optionalString (versionOlder version "4.4") ''
-    CPU_NOTIFIER_ERROR_INJECT? n
-  ''}
-
-  ${optionalString (versionOlder version "4.11") ''
-    TIMER_STATS y
-    DEBUG_NX_TEST n
-  ''}
-
-  # Bump the maximum number of CPUs to support systems like EC2 x1.*
-  # instances and Xeon Phi.
-  ${optionalString (stdenv.hostPlatform.system == "x86_64-linux" || stdenv.hostPlatform.system == "aarch64-linux") ''
-    NR_CPUS 384
-  ''}
-
-  # Unix domain sockets.
-  UNIX y
-
-  # Power management.
-  ${optionalString (versionOlder version "3.19") ''
-    PM_RUNTIME y
-  ''}
-  PM_ADVANCED_DEBUG y
-  ${optionalString (versionAtLeast version "3.11") ''
-    X86_INTEL_LPSS y
-  ''}
-  ${optionalString (versionAtLeast version "3.10") ''
-    X86_INTEL_PSTATE y
-  ''}
-  INTEL_IDLE y
-  CPU_FREQ_DEFAULT_GOV_PERFORMANCE y
-  ${optionalString (versionOlder version "3.10") ''
-    USB_SUSPEND y
-  ''}
-  PM_WAKELOCKS y
-
-  # Support drivers that need external firmware.
-  STANDALONE n
-
-  # Make /proc/config.gz available.
-  IKCONFIG y
-  IKCONFIG_PROC y
-
-  # Optimize with -O2, not -Os.
-  CC_OPTIMIZE_FOR_SIZE n
-
-  # Enable the kernel's built-in memory tester.
-  MEMTEST y
-
-  # Include the CFQ I/O scheduler in the kernel, rather than as a
-  # module, so that the initrd gets a good I/O scheduler.
-  IOSCHED_CFQ y
-  BLK_CGROUP y # required by CFQ
-  IOSCHED_DEADLINE y
-  ${optionalString (versionAtLeast version "4.11") ''
-    MQ_IOSCHED_DEADLINE y
-  ''}
-  ${optionalString (versionAtLeast version "4.12") ''
-    BFQ_GROUP_IOSCHED y
-    MQ_IOSCHED_KYBER y
-    IOSCHED_BFQ m
-  ''}
-
-  # Enable NUMA.
-  NUMA? y
-
-  # Disable some expensive (?) features.
-  PM_TRACE_RTC n
-
-  # Enable initrd support.
-  BLK_DEV_RAM y
-  BLK_DEV_INITRD y
-
-  # Enable various subsystems.
-  ACCESSIBILITY y # Accessibility support
-  AUXDISPLAY y # Auxiliary Display support
-  HIPPI y
-  MTD_COMPLEX_MAPPINGS y # needed for many devices
-  SCSI_LOWLEVEL y # enable lots of SCSI devices
-  SCSI_LOWLEVEL_PCMCIA y
-  SCSI_SAS_ATA y  # added to enable detection of hard drive
-  SPI y # needed for many devices
-  SPI_MASTER y
-  WAN y
-  ${optionalString (versionOlder version "4.17") ''
-    DONGLE y # Serial dongle support
-  ''}
-
-  # Networking options.
-  NET y
-  IP_PNP n
-  ${optionalString (versionOlder version "3.13") ''
-    IPV6_PRIVACY y
-  ''}
-  NETFILTER y
-  NETFILTER_ADVANCED y
-  CGROUP_BPF? y # Required by systemd per-cgroup firewalling
-  CGROUP_NET_PRIO y # Required by systemd
-  IP_ROUTE_VERBOSE y
-  IP_MROUTE_MULTIPLE_TABLES y
-  IP_VS_PROTO_TCP y
-  IP_VS_PROTO_UDP y
-  IP_VS_PROTO_ESP y
-  IP_VS_PROTO_AH y
-  IP_DCCP_CCID3 n # experimental
-  IP_MULTICAST y
-  IPV6_ROUTER_PREF y
-  IPV6_ROUTE_INFO y
-  IPV6_OPTIMISTIC_DAD y
-  IPV6_MULTIPLE_TABLES y
-  IPV6_SUBTREES y
-  IPV6_MROUTE y
-  IPV6_MROUTE_MULTIPLE_TABLES y
-  IPV6_PIMSM_V2 y
-  ${optionalString (versionAtLeast version "4.7") ''
-    IPV6_FOU_TUNNEL m
-  ''}
-  CLS_U32_PERF y
-  CLS_U32_MARK y
-  ${optionalString (stdenv.system == "x86_64-linux") ''
-    BPF_JIT y
-  ''}
-  ${optionalString (versionAtLeast version "4.4") ''
-    NET_CLS_BPF m
-    NET_ACT_BPF m
-  ''}
-  L2TP_V3 y
-  L2TP_IP m
-  L2TP_ETH m
-  BRIDGE_VLAN_FILTERING y
-  BONDING m
-  NET_L3_MASTER_DEV? y
-  NET_FOU_IP_TUNNELS? y
-  IP_NF_TARGET_REDIRECT m
-
-  # Wireless networking.
-  CFG80211_WEXT? y # Without it, ipw2200 drivers don't build
-  IPW2100_MONITOR? y # support promiscuous mode
-  IPW2200_MONITOR? y # support promiscuous mode
-  HOSTAP_FIRMWARE? y # Support downloading firmware images with Host AP driver
-  HOSTAP_FIRMWARE_NVRAM? y
-  ATH9K_PCI? y # Detect Atheros AR9xxx cards on PCI(e) bus
-  ATH9K_AHB? y # Ditto, AHB bus
-  B43_PHY_HT? y
-  BCMA_HOST_PCI? y
-
-  # Enable various FB devices.
-  FB y
-  FB_EFI y
-  FB_NVIDIA_I2C y # Enable DDC Support
-  FB_RIVA_I2C y
-  FB_ATY_CT y # Mach64 CT/VT/GT/LT (incl. 3D RAGE) support
-  FB_ATY_GX y # Mach64 GX support
-  FB_SAVAGE_I2C y
-  FB_SAVAGE_ACCEL y
-  FB_SIS_300 y
-  FB_SIS_315 y
-  FB_3DFX_ACCEL y
-  FB_VESA y
-  FRAMEBUFFER_CONSOLE y
-  FRAMEBUFFER_CONSOLE_ROTATION y
-  ${optionalString (stdenv.system == "i686-linux") ''
-    FB_GEODE y
-  ''}
-
-  # Video configuration.
-  # Enable KMS for devices whose X.org driver supports it.
-  ${optionalString (versionOlder version "4.3") ''
-    DRM_I915_KMS y
-  ''}
-  # iGVT-g support
-  ${optionalString (versionAtLeast version "4.16") ''
-    DRM_I915_GVT y
-    DRM_I915_GVT_KVMGT m
-  ''}
-  # Allow specifying custom EDID on the kernel command line
-  DRM_LOAD_EDID_FIRMWARE y
-  VGA_SWITCHEROO y # Hybrid graphics support
-  DRM_GMA600 y
-  DRM_GMA3600 y
-  ${optionalString (versionAtLeast version "4.5" && (versionOlder version "4.9")) ''
-    DRM_AMD_POWERPLAY y # necessary for amdgpu polaris support
-  ''}
-  ${optionalString (versionAtLeast version "4.9") ''
-    DRM_AMDGPU_SI y # (experimental) amdgpu support for verde and newer chipsets
-    DRM_AMDGPU_CIK y # (stable) amdgpu support for bonaire and newer chipsets
-  ''}
-
-  # Sound.
-  SND_DYNAMIC_MINORS y
-  SND_AC97_POWER_SAVE y # AC97 Power-Saving Mode
-  SND_HDA_INPUT_BEEP y # Support digital beep via input layer
-  SND_HDA_RECONFIG y # Support reconfiguration of jack functions
-  SND_HDA_PATCH_LOADER y # Support configuring jack functions via fw mechanism at boot
-  SND_USB_CAIAQ_INPUT y
-  ${optionalString (versionOlder version "4.12") ''
-    PSS_MIXER y # Enable PSS mixer (Beethoven ADSP-16 and other compatible)
-  ''}
-
-  # USB serial devices.
-  USB_SERIAL_GENERIC y # USB Generic Serial Driver
-
-  # Include firmware for various USB serial devices.
-  # Only applicable for kernels below 4.16, after that no firmware is shipped in the kernel tree.
-  ${optionalString (versionOlder version "4.16") ''
-    USB_SERIAL_KEYSPAN_MPR y
-    USB_SERIAL_KEYSPAN_USA28 y
-    USB_SERIAL_KEYSPAN_USA28X y
-    USB_SERIAL_KEYSPAN_USA28XA y
-    USB_SERIAL_KEYSPAN_USA28XB y
-    USB_SERIAL_KEYSPAN_USA19 y
-    USB_SERIAL_KEYSPAN_USA18X y
-    USB_SERIAL_KEYSPAN_USA19W y
-    USB_SERIAL_KEYSPAN_USA19QW y
-    USB_SERIAL_KEYSPAN_USA19QI y
-    USB_SERIAL_KEYSPAN_USA49W y
-    USB_SERIAL_KEYSPAN_USA49WLC y
-  ''}
-
-  # Device mapper (RAID, LVM, etc.)
-  MD y
-
-  # Filesystem options - in particular, enable extended attributes and
-  # ACLs for all filesystems that support them.
-  FANOTIFY y
-  TMPFS y
-  TMPFS_POSIX_ACL y
-  ${optionalString (versionAtLeast version "4.9") ''
-    FS_ENCRYPTION? m
-  ''}
-  EXT2_FS_XATTR y
-  EXT2_FS_POSIX_ACL y
-  EXT2_FS_SECURITY y
-  ${optionalString (versionOlder version "4.0") ''
-    EXT2_FS_XIP y # Ext2 execute in place support
-  ''}
-  EXT3_FS_POSIX_ACL y
-  EXT3_FS_SECURITY y
-  EXT4_FS_POSIX_ACL y
-  EXT4_ENCRYPTION? ${if versionOlder version "4.8" then "m" else "y"}
-  EXT4_FS_SECURITY y
-  REISERFS_FS_XATTR? y
-  REISERFS_FS_POSIX_ACL? y
-  REISERFS_FS_SECURITY? y
-  JFS_POSIX_ACL? y
-  JFS_SECURITY? y
-  XFS_QUOTA? y
-  XFS_POSIX_ACL? y
-  XFS_RT? y # XFS Realtime subvolume support
-  OCFS2_DEBUG_MASKLOG? n
-  BTRFS_FS_POSIX_ACL y
-  UBIFS_FS_ADVANCED_COMPR? y
-  F2FS_FS m
-  F2FS_FS_SECURITY? y
-  F2FS_FS_ENCRYPTION? y
-  UDF_FS m
-  ${optionalString (versionAtLeast version "4.0" && versionOlder version "4.6") ''
-    NFSD_PNFS y
-  ''}
-  NFSD_V2_ACL y
-  NFSD_V3 y
-  NFSD_V3_ACL y
-  NFSD_V4 y
-  ${optionalString (versionAtLeast version "3.11") ''
-    NFSD_V4_SECURITY_LABEL y
-  ''}
-  NFS_FSCACHE y
-  NFS_SWAP y
-  NFS_V3_ACL y
-  ${optionalString (versionAtLeast version "3.11") ''
-    NFS_V4_1 y  # NFSv4.1 client support
-    NFS_V4_2 y
-    NFS_V4_SECURITY_LABEL y
-  ''}
-  CIFS_XATTR y
-  CIFS_POSIX y
-  CIFS_FSCACHE y
-  CIFS_STATS y
-  CIFS_WEAK_PW_HASH y
-  CIFS_UPCALL y
-  CIFS_ACL y
-  CIFS_DFS_UPCALL y
-  ${optionalString (versionOlder version "4.13") ''
-    CIFS_SMB2 y
-  ''}
-  ${optionalString (versionAtLeast version "3.12") ''
-    CEPH_FSCACHE y
-  ''}
-  ${optionalString (versionAtLeast version "3.14") ''
-    CEPH_FS_POSIX_ACL y
-  ''}
-  ${optionalString (versionAtLeast version "3.13") ''
-    SQUASHFS_FILE_DIRECT y
-    SQUASHFS_DECOMP_MULTI_PERCPU y
-  ''}
-  SQUASHFS_XATTR y
-  SQUASHFS_ZLIB y
-  SQUASHFS_LZO y
-  SQUASHFS_XZ y
-  ${optionalString (versionAtLeast version "3.19") ''
-    SQUASHFS_LZ4 y
-  ''}
-
-  # Native Language Support modules, needed by some filesystems
-  NLS y
-  NLS_DEFAULT utf8
-  NLS_UTF8 m
-  NLS_CODEPAGE_437 m # VFAT default for the codepage= mount option
-  NLS_ISO8859_1 m    # VFAT default for the iocharset= mount option
-
-  # Runtime security tests
-  ${optionalString (versionOlder version "4.11") ''
-    DEBUG_SET_MODULE_RONX? y # Detect writes to read-only module pages
-  ''}
-
-  # Security related features.
-  RANDOMIZE_BASE? y
-  STRICT_DEVMEM? y # Filter access to /dev/mem
-  SECURITY_SELINUX_BOOTPARAM_VALUE 0 # Disable SELinux by default
-  SECURITY_YAMA? y # Prevent processes from ptracing non-children processes
-  DEVKMEM n # Disable /dev/kmem
-  ${optionalString (! stdenv.hostPlatform.isAarch32)
-    (if versionOlder version "3.14" then ''
-        CC_STACKPROTECTOR? y # Detect buffer overflows on the stack
-      '' else optionalString (versionOlder version "4.18") ''
-        CC_STACKPROTECTOR_REGULAR? y
-      '')}
-  ${optionalString (versionAtLeast version "3.12") ''
-    USER_NS y # Support for user namespaces
-  ''}
-
-  # AppArmor support
-  SECURITY_APPARMOR y
-  DEFAULT_SECURITY_APPARMOR y
-
-  # Microcode loading support
-  MICROCODE y
-  MICROCODE_INTEL y
-  MICROCODE_AMD y
-  ${optionalString (versionAtLeast version "3.11" && versionOlder version "4.4") ''
-    MICROCODE_EARLY y
-    MICROCODE_INTEL_EARLY y
-    MICROCODE_AMD_EARLY y
-  ''}
-
-  ${optionalString (versionAtLeast version "4.10") ''
-    # Write Back Throttling
-    # https://lwn.net/Articles/682582/
-    # https://bugzilla.kernel.org/show_bug.cgi?id=12309#c655
-    BLK_WBT y
-    BLK_WBT_SQ y
-    BLK_WBT_MQ y
-  ''}
-
-  # Misc. options.
-  8139TOO_8129 y
-  8139TOO_PIO n # PIO is slower
-  AIC79XX_DEBUG_ENABLE n
-  AIC7XXX_DEBUG_ENABLE n
-  AIC94XX_DEBUG n
-  ${optionalString (versionAtLeast version "3.3" && versionOlder version "3.13") ''
-    AUDIT_LOGINUID_IMMUTABLE y
-  ''}
-  ${optionalString (versionOlder version "4.4") ''
-    B43_PCMCIA? y
-  ''}
-  BLK_DEV_INITRD y
-  BLK_DEV_INTEGRITY y
-  BSD_PROCESS_ACCT_V3 y
-  BT_HCIUART_BCSP? y
-  BT_HCIUART_H4? y # UART (H4) protocol support
-  BT_HCIUART_LL? y
-  BT_RFCOMM_TTY? y # RFCOMM TTY support
-  CLEANCACHE? y
-  CRASH_DUMP? n
-  DVB_DYNAMIC_MINORS? y # we use udev
-  EFI_STUB y # EFI bootloader in the bzImage itself
-  CGROUPS y # used by systemd
-  FHANDLE y # used by systemd
-  SECCOMP y # used by systemd >= 231
-  SECCOMP_FILTER y # ditto
-  POSIX_MQUEUE y
-  FRONTSWAP y
-  FUSION y # Fusion MPT device support
-  IDE n # deprecated IDE support
-  ${optionalString (versionAtLeast version "4.3") ''
-    IDLE_PAGE_TRACKING y
-  ''}
-  ${optionalString (versionOlder version "4.17") ''
-    IRDA_ULTRA y # Ultra (connectionless) protocol
-  ''}
-  JOYSTICK_IFORCE_232? y # I-Force Serial joysticks and wheels
-  JOYSTICK_IFORCE_USB? y # I-Force USB joysticks and wheels
-  JOYSTICK_XPAD_FF? y # X-Box gamepad rumble support
-  JOYSTICK_XPAD_LEDS? y # LED Support for Xbox360 controller 'BigX' LED
-  KEXEC_FILE? y
-  KEXEC_JUMP? y
-  LDM_PARTITION y # Windows Logical Disk Manager (Dynamic Disk) support
-  LOGIRUMBLEPAD2_FF y # Logitech Rumblepad 2 force feedback
-  LOGO n # not needed
-  MEDIA_ATTACH y
-  MEGARAID_NEWGEN y
-  ${optionalString (versionAtLeast version "3.15" && versionOlder version "4.8") ''
-    MLX4_EN_VXLAN y
-  ''}
-  ${optionalString (versionOlder version "4.9") ''
-    MODVERSIONS y
-  ''}
-  MOUSE_PS2_ELANTECH y # Elantech PS/2 protocol extension
-  MTRR_SANITIZER y
-  NET_FC y # Fibre Channel driver support
-  ${optionalString (versionAtLeast version "3.11") ''
-    PINCTRL_BAYTRAIL y # GPIO on Intel Bay Trail, for some Chromebook internal eMMC disks
-  ''}
-  MMC_BLOCK_MINORS 32 # 8 is default. Modern gpt tables on eMMC may go far beyond 8.
-  PPP_MULTILINK y # PPP multilink support
-  PPP_FILTER y
-  REGULATOR y # Voltage and Current Regulator Support
-  RC_DEVICES? y # Enable IR devices
-  RT2800USB_RT53XX y
-  RT2800USB_RT55XX y
-  SCHED_AUTOGROUP y
-  CFS_BANDWIDTH y
-  SCSI_LOGGING y # SCSI logging facility
-  SERIAL_8250 y # 8250/16550 and compatible serial support
-  SLIP_COMPRESSED y # CSLIP compressed headers
-  SLIP_SMART y
-  HWMON y
-  THERMAL_HWMON y # Hardware monitoring support
-  ${optionalString (versionAtLeast version "3.15") ''
-    UEVENT_HELPER n
-  ''}
-  ${optionalString (versionOlder version "3.15") ''
-    USB_DEBUG? n
-  ''}
-  USB_EHCI_ROOT_HUB_TT y # Root Hub Transaction Translators
-  USB_EHCI_TT_NEWSCHED y # Improved transaction translator scheduling
-  ${optionalString (versionAtLeast version "4.3") ''
-    USERFAULTFD y
-  ''}
-  X86_CHECK_BIOS_CORRUPTION y
-  X86_MCE y
-
-  ${optionalString (versionAtLeast version "3.12") ''
-    HOTPLUG_PCI_ACPI y # PCI hotplug using ACPI
-    HOTPLUG_PCI_PCIE y # PCI-Expresscard hotplug support
-  ''}
-
-
-  # Linux containers.
-  NAMESPACES? y #  Required by 'unshare' used by 'nixos-install'
-  RT_GROUP_SCHED n
-  CGROUP_DEVICE? y
-  MEMCG y
-  MEMCG_SWAP y
-  ${optionalString (versionOlder version "4.7") "DEVPTS_MULTIPLE_INSTANCES y"}
-  BLK_DEV_THROTTLING y
-  CFQ_GROUP_IOSCHED y
-  ${optionalString (versionAtLeast version "4.3") ''
-    CGROUP_PIDS y
-  ''}
-
-  # Enable staging drivers.  These are somewhat experimental, but
-  # they generally don't hurt.
-  STAGING y
-
-  # PROC_EVENTS requires that the netlink connector is not built
-  # as a module.  This is required by libcgroup's cgrulesengd.
-  CONNECTOR y
-  PROC_EVENTS y
-
-  # Tracing.
-  FTRACE y
-  KPROBES y
-  FUNCTION_TRACER y
-  FTRACE_SYSCALLS y
-  SCHED_TRACER y
-  STACK_TRACER y
-
-  ${if versionOlder version "4.11" then ''
-    UPROBE_EVENT? y
-  '' else ''
-    UPROBE_EVENTS? y
-  ''}
-
-  ${optionalString (versionAtLeast version "4.4") ''
-    BPF_SYSCALL y
-    BPF_EVENTS y
-  ''}
-  FUNCTION_PROFILER y
-  RING_BUFFER_BENCHMARK n
-
-  # Devtmpfs support.
-  DEVTMPFS y
-
-  # Easier debugging of NFS issues.
-  SUNRPC_DEBUG y
-
-  # Virtualisation.
-  PARAVIRT? y
-  HYPERVISOR_GUEST y
-  PARAVIRT_SPINLOCKS? y
-  ${optionalString (versionOlder version "4.8") ''
-    KVM_APIC_ARCHITECTURE y
-  ''}
-  KVM_ASYNC_PF y
-  ${optionalString ((versionAtLeast version "4.0") && (versionOlder version "4.12")) ''
-    KVM_COMPAT? y
-  ''}
-  ${optionalString (versionOlder version "4.12") ''
-    KVM_DEVICE_ASSIGNMENT? y
-  ''}
-  ${optionalString (versionAtLeast version "4.0") ''
-    KVM_GENERIC_DIRTYLOG_READ_PROTECT y
-  ''}
-  KVM_GUEST y
-  KVM_MMIO y
-  ${optionalString (versionAtLeast version "3.13") ''
-    KVM_VFIO y
-  ''}
-  ${optionalString (stdenv.isx86_64 || stdenv.isi686) ''
-    XEN? y
-    XEN_DOM0? y
-    ${optionalString ((versionAtLeast version "3.18") && (features.xen_dom0 or false))  ''
-      PCI_XEN? y
-      HVC_XEN? y
-      HVC_XEN_FRONTEND? y
-      XEN_SYS_HYPERVISOR? y
-      SWIOTLB_XEN? y
-      XEN_BACKEND? y
-      XEN_BALLOON? y
-      XEN_BALLOON_MEMORY_HOTPLUG? y
-      XEN_EFI? y
-      XEN_HAVE_PVMMU? y
-      XEN_MCE_LOG? y
-      XEN_PVH? y
-      XEN_PVHVM? y
-      XEN_SAVE_RESTORE? y
-      XEN_SCRUB_PAGES? y
-      XEN_SELFBALLOONING? y
-      XEN_STUB? y
-      XEN_TMEM? y
-    ''}
-  ''}
-  KSM y
-  ${optionalString (!stdenv.is64bit) ''
-    HIGHMEM64G? y # We need 64 GB (PAE) support for Xen guest support.
-  ''}
-  ${optionalString (stdenv.is64bit) ''
-    VFIO_PCI_VGA y
-  ''}
-  VIRT_DRIVERS y
-
-  # Media support.
-  MEDIA_DIGITAL_TV_SUPPORT y
-  MEDIA_CAMERA_SUPPORT y
-  ${optionalString (versionOlder version "4.14") ''
-    MEDIA_RC_SUPPORT y
-  ''}
-  MEDIA_CONTROLLER y
-  MEDIA_USB_SUPPORT y
-  MEDIA_PCI_SUPPORT y
-  MEDIA_ANALOG_TV_SUPPORT y
-  VIDEO_STK1160_COMMON m
-  ${optionalString (versionOlder version "4.11") ''
-    VIDEO_STK1160_AC97 y
-  ''}
-
-  # Our initrd init uses shebang scripts, so can't be modular.
-  BINFMT_SCRIPT y
-
-  # For systemd-binfmt
-  BINFMT_MISC? y
-
-  # Enable the 9P cache to speed up NixOS VM tests.
-  9P_FSCACHE? y
-  9P_FS_POSIX_ACL? y
-
-  # Enable transparent support for huge pages.
-  TRANSPARENT_HUGEPAGE? y
-  TRANSPARENT_HUGEPAGE_ALWAYS? n
-  TRANSPARENT_HUGEPAGE_MADVISE? y
-
-  # zram support (e.g for in-memory compressed swap).
-  ZRAM m
-  ZSWAP? y
-  ZBUD? y
-  ${optionalString (versionOlder version "3.18") ''
-    ZSMALLOC y
-  ''}
-  ${optionalString (versionAtLeast version "3.18") ''
-    ZSMALLOC m
-  ''}
-
-  # Enable PCIe and USB for the brcmfmac driver
-  BRCMFMAC_USB? y
-  BRCMFMAC_PCIE? y
-
-  # Support x2APIC (which requires IRQ remapping).
-  ${optionalString (stdenv.system == "x86_64-linux") ''
-    X86_X2APIC y
-    IRQ_REMAP y
-  ''}
-
-  # needed for iwd WPS support (wpa_supplicant replacement)
-  ${optionalString (versionAtLeast version "4.7") ''
-    KEY_DH_OPERATIONS y
-  ''}
-
-  # Disable the firmware helper fallback, udev doesn't implement it any more
-  FW_LOADER_USER_HELPER_FALLBACK? n
-
-  # Disable various self-test modules that have no use in a production system
-  # This menu disables all/most of them on >= 4.16
-  RUNTIME_TESTING_MENU? n
-  # For older kernels, painstakingly disable each symbol.
-  ${optionalString (versionOlder version "4.16") ''
-    ARM_KPROBES_TEST? n
-    ASYNC_RAID6_TEST? n
-    ATOMIC64_SELFTEST? n
-    BACKTRACE_SELF_TEST? n
-    INTERVAL_TREE_TEST? n
-    PERCPU_TEST? n
-    RBTREE_TEST? n
-    TEST_BITMAP? n
-    TEST_BPF? n
-    TEST_FIRMWARE? n
-    TEST_HASH? n
-    TEST_HEXDUMP? n
-    TEST_KMOD? n
-    TEST_KSTRTOX? n
-    TEST_LIST_SORT? n
-    TEST_LKM? n
-    TEST_PARMAN? n
-    TEST_PRINTF? n
-    TEST_RHASHTABLE? n
-    TEST_SORT? n
-    TEST_STATIC_KEYS? n
-    TEST_STRING_HELPERS? n
-    TEST_UDELAY? n
-    TEST_USER_COPY? n
-    TEST_UUID? n
-  ''}
-
-  CRC32_SELFTEST? n
-  CRYPTO_TEST? n
-  ${optionalString (versionOlder version "4.18") ''
-    DRM_DEBUG_MM_SELFTEST? n
-    LNET_SELFTEST? n
-  ''}
-  EFI_TEST? n
-  GLOB_SELFTEST? n
-  LOCK_TORTURE_TEST? n
-  MTD_TESTS? n
-  NOTIFIER_ERROR_INJECTION? n
-  RCU_PERF_TEST? n
-  RCU_TORTURE_TEST? n
-  TEST_ASYNC_DRIVER_PROBE? n
-  WW_MUTEX_SELFTEST? n
-  XZ_DEC_TEST? n
-
-  ${optionalString (features.criu or false)  ''
-    EXPERT y
-    CHECKPOINT_RESTORE y
-  ''}
-
-  ${optionalString ((features.criu or false) && (features.criu_revert_expert or true))
-    # Revert some changes, introduced by EXPERT, when necessary for criu
-  ''
-    RFKILL_INPUT? y
-    HID_PICOLCD_FB? y
-    HID_PICOLCD_BACKLIGHT? y
-    HID_PICOLCD_LCD? y
-    HID_PICOLCD_LEDS? y
-    HID_PICOLCD_CIR? y
-    DEBUG_MEMORY_INIT? y
-  ''}
-
-  ${extraConfig}
-''
+with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; };
+
+let
+  # temporary hack
+  grsecurity = false;
+  xen_dom0 = false;
+
+
+  # TODO configuration items have to be part of subattrs. Remove this constraint
+  flattenKConf =  nested: mapAttrs (_: head) (zipAttrs (attrValues nested));
+
+  options = {
+
+    debug = {
+      DEBUG_INFO                = if (features.debug or false) then yes else no;
+      DEBUG_KERNEL              = yes;
+      DEBUG_DEVRES              = no;
+      DYNAMIC_DEBUG             = yes;
+      TIMER_STATS               = whenOlder "4.11" yes;
+      DEBUG_NX_TEST             = whenOlder "4.11" no;
+      CPU_NOTIFIER_ERROR_INJECT = whenOlder "4.4" (option no);
+      DEBUG_STACK_USAGE         = no;
+      DEBUG_STACKOVERFLOW       = when (!grsecurity) no;
+      RCU_TORTURE_TEST          = no;
+      SCHEDSTATS                = no;
+      DETECT_HUNG_TASK          = yes;
+      CRASH_DUMP                = option no;
+      # Easier debugging of NFS issues.
+      SUNRPC_DEBUG              = whenAtLeast "3.4" yes;
+    };
+
+    power-management = {
+      PM_RUNTIME                       = whenOlder "3.19" yes;
+      PM_ADVANCED_DEBUG                = yes;
+      X86_INTEL_LPSS                   = whenAtLeast "3.11" yes;
+      X86_INTEL_PSTATE                 = whenAtLeast "3.10" yes;
+      INTEL_IDLE                       = yes;
+      CPU_FREQ_DEFAULT_GOV_PERFORMANCE = yes;
+      USB_SUSPEND                      = whenOlder "3.10" yes;
+      PM_WAKELOCKS                     = yes;
+    };
+
+    external-firmware = {
+      # Support drivers that need external firmware.
+      STANDALONE = no;
+    };
+
+    proc-config-gz = {
+      # Make /proc/config.gz available
+      IKCONFIG      = yes;
+      IKCONFIG_PROC = yes;
+    };
+
+    optimization = {
+      # Optimize with -O2, not -Os
+      CC_OPTIMIZE_FOR_SIZE = no;
+    };
+
+    memtest = {
+      MEMTEST = yes;
+    };
+
+    # Include the CFQ I/O scheduler in the kernel, rather than as a
+    # module, so that the initrd gets a good I/O scheduler.
+    scheduler = {
+      IOSCHED_CFQ = yes;
+      BLK_CGROUP  = yes; # required by CFQ"
+      IOSCHED_DEADLINE = yes;
+      MQ_IOSCHED_DEADLINE = whenAtLeast "4.11" yes;
+      BFQ_GROUP_IOSCHED = whenAtLeast "4.12" yes;
+      MQ_IOSCHED_KYBER = whenAtLeast "4.12" yes;
+      IOSCHED_BFQ = whenAtLeast "4.12" module;
+    };
+
+    # Enable NUMA.
+    numa = {
+      NUMA  = option yes;
+    };
+
+    networking = {
+      NET                = yes;
+      IP_PNP             = no;
+      IPV6_PRIVACY       = whenOlder "3.13" yes;
+      NETFILTER          = yes;
+      NETFILTER_ADVANCED = yes;
+      IP_VS_PROTO_TCP    = yes;
+      IP_VS_PROTO_UDP    = yes;
+      IP_VS_PROTO_ESP    = yes;
+      IP_VS_PROTO_AH     = yes;
+      IP_DCCP_CCID3      = no; # experimental
+      CLS_U32_PERF       = yes;
+      CLS_U32_MARK       = yes;
+      BPF_JIT            = when (stdenv.system == "x86_64-linux") yes;
+      WAN                = yes;
+      # Required by systemd per-cgroup firewalling
+      CGROUP_BPF                  = option yes;
+      CGROUP_NET_PRIO             = yes; # Required by systemd
+      IP_ROUTE_VERBOSE            = yes;
+      IP_MROUTE_MULTIPLE_TABLES   = yes;
+      IP_MULTICAST                = yes;
+      IPV6_ROUTER_PREF            = yes;
+      IPV6_ROUTE_INFO             = yes;
+      IPV6_OPTIMISTIC_DAD         = yes;
+      IPV6_MULTIPLE_TABLES        = yes;
+      IPV6_SUBTREES               = yes;
+      IPV6_MROUTE                 = yes;
+      IPV6_MROUTE_MULTIPLE_TABLES = yes;
+      IPV6_PIMSM_V2               = yes;
+      IPV6_FOU_TUNNEL             = whenAtLeast "4.7" module;
+      NET_CLS_BPF                 = whenAtLeast "4.4" module;
+      NET_ACT_BPF                 = whenAtLeast "4.4" module;
+      L2TP_V3                     = yes;
+      L2TP_IP                     = module;
+      L2TP_ETH                    = module;
+      BRIDGE_VLAN_FILTERING       = yes;
+      BONDING                     = module;
+      NET_L3_MASTER_DEV           = option yes;
+      NET_FOU_IP_TUNNELS          = option yes;
+      IP_NF_TARGET_REDIRECT       = module;
+
+      PPP_MULTILINK = yes; # PPP multilink support
+      PPP_FILTER    = yes;
+
+      # needed for iwd WPS support (wpa_supplicant replacement)
+      KEY_DH_OPERATIONS = whenAtLeast "4.7" yes;
+    };
+
+    wireless = {
+      CFG80211_WEXT         = option yes; # Without it, ipw2200 drivers don't build
+      IPW2100_MONITOR       = option yes; # support promiscuous mode
+      IPW2200_MONITOR       = option yes; # support promiscuous mode
+      HOSTAP_FIRMWARE       = option yes; # Support downloading firmware images with Host AP driver
+      HOSTAP_FIRMWARE_NVRAM = option yes;
+      ATH9K_PCI             = option yes; # Detect Atheros AR9xxx cards on PCI(e) bus
+      ATH9K_AHB             = option yes; # Ditto, AHB bus
+      B43_PHY_HT            = option (whenAtLeast "3.2" yes);
+      BCMA_HOST_PCI         = option yes;
+    };
+
+    fb = {
+      FB                  = yes;
+      FB_EFI              = yes;
+      FB_NVIDIA_I2C       = yes; # Enable DDC Support
+      FB_RIVA_I2C         = yes;
+      FB_ATY_CT           = yes; # Mach64 CT/VT/GT/LT (incl. 3D RAGE) support
+      FB_ATY_GX           = yes; # Mach64 GX support
+      FB_SAVAGE_I2C       = yes;
+      FB_SAVAGE_ACCEL     = yes;
+      FB_SIS_300          = yes;
+      FB_SIS_315          = yes;
+      FB_3DFX_ACCEL       = yes;
+      FB_VESA             = yes;
+      FRAMEBUFFER_CONSOLE = yes;
+      FRAMEBUFFER_CONSOLE_ROTATION = yes;
+      FB_GEODE            = when (versionOlder version "3.9" || stdenv.system == "i686-linux") yes;
+    };
+
+    video = {
+      # Enable KMS for devices whose X.org driver supports it
+      DRM_I915_KMS           = whenOlder "4.3" yes;
+      # Allow specifying custom EDID on the kernel command line
+      DRM_LOAD_EDID_FIRMWARE = yes;
+      DRM_RADEON_KMS         = option (whenOlder "3.9" yes);
+      VGA_SWITCHEROO         = yes; # Hybrid graphics support
+      DRM_GMA600             = yes;
+      DRM_GMA3600            = yes;
+      # necessary for amdgpu polaris support
+      DRM_AMD_POWERPLAY = whenBetween "4.5" "4.9" yes;
+      # (experimental) amdgpu support for verde and newer chipsets
+      DRM_AMDGPU_SI = whenAtLeast "4.9" yes;
+      # (stable) amdgpu support for bonaire and newer chipsets
+      DRM_AMDGPU_CIK = whenAtLeast "4.9" yes;
+      DRM_I915_GVT = whenAtLeast "4.16" yes;
+      DRM_I915_GVT_KVMGT = whenAtLeast "4.16" module;
+    };
+
+    sound = {
+      SND_DYNAMIC_MINORS  = yes;
+      SND_AC97_POWER_SAVE = yes; # AC97 Power-Saving Mode
+      SND_HDA_INPUT_BEEP  = yes; # Support digital beep via input layer
+      SND_HDA_RECONFIG    = yes; # Support reconfiguration of jack functions
+      # Support configuring jack functions via fw mechanism at boot
+      SND_HDA_PATCH_LOADER = yes;
+      SND_USB_CAIAQ_INPUT = yes;
+      # Enable PSS mixer (Beethoven ADSP-16 and other compatible)
+      PSS_MIXER           = whenOlder "4.12" yes;
+    };
+
+    # Include firmware for various USB serial devices.
+    # Only applicable for kernels below 4.16, after that no firmware is shipped in the kernel tree.
+    usb-serial = {
+      USB_SERIAL_GENERIC          = yes; # USB Generic Serial Driver
+    } // optionalAttrs (versionOlder version "4.16") {
+      USB_SERIAL_KEYSPAN_MPR      = yes; # include firmware for various USB serial devices
+      USB_SERIAL_KEYSPAN_USA28    = yes;
+      USB_SERIAL_KEYSPAN_USA28X   = yes;
+      USB_SERIAL_KEYSPAN_USA28XA  = yes;
+      USB_SERIAL_KEYSPAN_USA28XB  = yes;
+      USB_SERIAL_KEYSPAN_USA19    = yes;
+      USB_SERIAL_KEYSPAN_USA18X   = yes;
+      USB_SERIAL_KEYSPAN_USA19W   = yes;
+      USB_SERIAL_KEYSPAN_USA19QW  = yes;
+      USB_SERIAL_KEYSPAN_USA19QI  = yes;
+      USB_SERIAL_KEYSPAN_USA49W   = yes;
+      USB_SERIAL_KEYSPAN_USA49WLC = yes;
+    };
+
+    usb = {
+      USB_DEBUG            = option (whenOlder "3.15" no);
+      USB_EHCI_ROOT_HUB_TT = yes; # Root Hub Transaction Translators
+      USB_EHCI_TT_NEWSCHED = yes; # Improved transaction translator scheduling
+    };
+
+    # Filesystem options - in particular, enable extended attributes and
+    # ACLs for all filesystems that support them.
+    filesystem = {
+      FANOTIFY        = yes;
+      TMPFS           = yes;
+      TMPFS_POSIX_ACL = yes;
+      FS_ENCRYPTION   = option (whenAtLeast "4.9" module);
+
+      EXT2_FS_XATTR     = yes;
+      EXT2_FS_POSIX_ACL = yes;
+      EXT2_FS_SECURITY  = yes;
+      EXT2_FS_XIP       = whenOlder "4.0" yes; # Ext2 execute in place support
+
+      EXT3_FS_POSIX_ACL = yes;
+      EXT3_FS_SECURITY  = yes;
+
+      EXT4_FS_POSIX_ACL = yes;
+      EXT4_FS_SECURITY  = yes;
+      EXT4_ENCRYPTION   = option ((if (versionOlder version "4.8") then module else yes));
+
+      REISERFS_FS_XATTR     = option yes;
+      REISERFS_FS_POSIX_ACL = option yes;
+      REISERFS_FS_SECURITY  = option yes;
+
+      JFS_POSIX_ACL = option yes;
+      JFS_SECURITY  = option yes;
+
+      XFS_QUOTA     = option yes;
+      XFS_POSIX_ACL = option yes;
+      XFS_RT        = option yes; # XFS Realtime subvolume support
+
+      OCFS2_DEBUG_MASKLOG = option no;
+
+      BTRFS_FS_POSIX_ACL = yes;
+
+      UBIFS_FS_ADVANCED_COMPR = option yes;
+
+      F2FS_FS             = module;
+      F2FS_FS_SECURITY    = option yes;
+      F2FS_FS_ENCRYPTION  = option yes;
+      UDF_FS              = module;
+
+      NFSD_PNFS              = whenBetween "4.0" "4.6" yes;
+      NFSD_V2_ACL            = yes;
+      NFSD_V3                = yes;
+      NFSD_V3_ACL            = yes;
+      NFSD_V4                = yes;
+      NFSD_V4_SECURITY_LABEL = whenAtLeast "3.11" yes;
+
+      NFS_FSCACHE           = yes;
+      NFS_SWAP              = whenAtLeast "3.6" yes;
+      NFS_V3_ACL            = yes;
+      NFS_V4_1              = whenAtLeast "3.11" yes;  # NFSv4.1 client support
+      NFS_V4_2              = whenAtLeast "3.11" yes;
+      NFS_V4_SECURITY_LABEL = whenAtLeast "3.11" yes;
+
+      CIFS_XATTR        = yes;
+      CIFS_POSIX        = yes;
+      CIFS_FSCACHE      = yes;
+      CIFS_STATS        = yes;
+      CIFS_WEAK_PW_HASH = yes;
+      CIFS_UPCALL       = yes;
+      CIFS_ACL          = yes;
+      CIFS_DFS_UPCALL   = yes;
+      CIFS_SMB2         = whenOlder "4.13" yes;
+
+      CEPH_FSCACHE      = whenAtLeast "3.12" yes;
+      CEPH_FS_POSIX_ACL = whenAtLeast "3.14" yes;
+
+      SQUASHFS_FILE_DIRECT         = whenAtLeast "3.13" yes;
+      SQUASHFS_DECOMP_MULTI_PERCPU = whenAtLeast "3.13" yes;
+      SQUASHFS_XATTR               = yes;
+      SQUASHFS_ZLIB                = yes;
+      SQUASHFS_LZO                 = yes;
+      SQUASHFS_XZ                  = yes;
+      SQUASHFS_LZ4                 = whenAtLeast "3.19" yes;
+
+      # Native Language Support modules, needed by some filesystems
+      NLS   = yes;
+      NLS_DEFAULT =  "utf8";
+      NLS_UTF8    = module;
+      NLS_CODEPAGE_437 = module; # VFAT default for the codepage= mount option
+      NLS_ISO8859_1 = module;    # VFAT default for the iocharset= mount option
+
+      DEVTMPFS = yes;
+    };
+
+    security = {
+      # Detect writes to read-only module pages
+      DEBUG_SET_MODULE_RONX            = option (whenOlder "4.11" yes);
+      RANDOMIZE_BASE                   = option yes;
+      STRICT_DEVMEM                    = option yes; # Filter access to /dev/mem
+      SECURITY_SELINUX_BOOTPARAM_VALUE = "0"; # Disable SELinux by default
+      # Prevent processes from ptracing non-children processes
+      SECURITY_YAMA                    = option yes;
+      DEVKMEM                          = when (!grsecurity) no; # Disable /dev/kmem
+
+      USER_NS                          = whenAtLeast "3.12" yes; # Support for user namespaces
+
+      SECURITY_APPARMOR                = yes;
+      DEFAULT_SECURITY_APPARMOR        = yes;
+
+      AUDIT_LOGINUID_IMMUTABLE = whenBetween "3.3" "3.13" yes;
+    } // optionalAttrs (!stdenv.hostPlatform.isAarch32) {
+
+      # Detect buffer overflows on the stack
+      CC_STACKPROTECTOR         = option (whenOlder "3.14" yes);
+      CC_STACKPROTECTOR_REGULAR = option (whenOlder "4.18" yes);
+    };
+
+    microcode = {
+      MICROCODE       = yes;
+      MICROCODE_INTEL = yes;
+      MICROCODE_AMD   = yes;
+
+      MICROCODE_EARLY       = whenBetween "3.11" "4.4" yes;
+      MICROCODE_INTEL_EARLY = whenBetween "3.11" "4.4" yes;
+      MICROCODE_AMD_EARLY   = whenBetween "3.11" "4.4" yes;
+    } // optionalAttrs (versionAtLeast version "4.10") {
+      # Write Back Throttling
+      # https://lwn.net/Articles/682582/
+      # https://bugzilla.kernel.org/show_bug.cgi?id=12309#c655
+      BLK_WBT    = yes;
+      BLK_WBT_SQ = yes;
+      BLK_WBT_MQ = yes;
+    };
+
+    container = {
+      NAMESPACES     = option yes; #  Required by 'unshare' used by 'nixos-install'
+      RT_GROUP_SCHED = no;
+      CGROUP_DEVICE  = option yes;
+
+      MEMCG                    = whenAtLeast "3.6" yes;
+      MEMCG_SWAP               = whenAtLeast "3.6" yes;
+      CGROUP_MEM_RES_CTLR      = whenOlder "3.6" yes;
+      CGROUP_MEM_RES_CTLR_SWAP = whenOlder "3.6" yes;
+
+      DEVPTS_MULTIPLE_INSTANCES = whenOlder "4.7" yes;
+      BLK_DEV_THROTTLING        = yes;
+      CFQ_GROUP_IOSCHED         = yes;
+      CGROUP_PIDS               = whenAtLeast "4.3" yes;
+    };
+
+    staging = {
+      # Enable staging drivers.  These are somewhat experimental, but
+      # they generally don't hurt.
+      STAGING = yes;
+    };
+
+    proc-events = {
+      # PROC_EVENTS requires that the netlink connector is not built
+      # as a module.  This is required by libcgroup's cgrulesengd.
+      CONNECTOR   = yes;
+      PROC_EVENTS = yes;
+    };
+
+    tracing = {
+      FTRACE                = yes;
+      KPROBES               = yes;
+      FUNCTION_TRACER       = yes;
+      FTRACE_SYSCALLS       = yes;
+      SCHED_TRACER          = yes;
+      STACK_TRACER          = yes;
+      UPROBE_EVENT          = option (whenOlder "4.11" yes);
+      UPROBE_EVENTS         = option (whenAtLeast "4.11" yes);
+      BPF_SYSCALL           = whenAtLeast "4.4" yes;
+      BPF_EVENTS            = whenAtLeast "4.4" yes;
+      FUNCTION_PROFILER     = yes;
+      RING_BUFFER_BENCHMARK = no;
+    };
+
+    virtualisation = {
+      PARAVIRT = option yes;
+
+      HYPERVISOR_GUEST = when (!grsecurity && versionAtLeast version "3.10") yes;
+      PARAVIRT_GUEST   = option (when (!grsecurity && versionOlder   version "3.10") yes);
+      PARAVIRT_SPINLOCKS  = option yes;
+
+      KVM_APIC_ARCHITECTURE             = whenOlder "4.8" yes;
+      KVM_ASYNC_PF                      = yes;
+      KVM_CLOCK                         = option (whenOlder   "3.7"  yes);
+      KVM_COMPAT                        = option (whenBetween "4.0" "4.12"  yes);
+      KVM_DEVICE_ASSIGNMENT             = option (whenBetween "3.10" "4.12" yes);
+      KVM_GENERIC_DIRTYLOG_READ_PROTECT = whenAtLeast "4.0"  yes;
+      KVM_GUEST                         = when (!grsecurity) yes;
+      KVM_MMIO                          = yes;
+      KVM_VFIO                          = whenAtLeast "3.13" yes;
+      KSM = yes;
+      VIRT_DRIVERS = yes;
+      # We nneed 64 GB (PAE) support for Xen guest support
+      HIGHMEM64G = option (when (!stdenv.is64bit) yes);
+
+      VFIO_PCI_VGA = when (versionAtLeast version "3.9" && stdenv.is64bit) yes;
+
+    } // optionalAttrs (stdenv.isx86_64 || stdenv.isi686) ({
+      XEN = option yes;
+
+      # XXX: why isn't this in the xen-dom0 conditional section below?
+      XEN_DOM0 = option yes;
+
+    } // optionalAttrs (versionAtLeast version "3.18" && xen_dom0) {
+      PCI_XEN                     = option yes;
+      HVC_XEN                     = option yes;
+      HVC_XEN_FRONTEND            = option yes;
+      XEN_SYS_HYPERVISOR          = option yes;
+      SWIOTLB_XEN                 = option yes;
+      XEN_BACKEND                 = option yes;
+      XEN_BALLOON                 = option yes;
+      XEN_BALLOON_MEMORY_HOTPLUG  = option yes;
+      XEN_EFI                     = option yes;
+      XEN_HAVE_PVMMU              = option yes;
+      XEN_MCE_LOG                 = option yes;
+      XEN_PVH                     = option yes;
+      XEN_PVHVM                   = option yes;
+      XEN_SAVE_RESTORE            = option yes;
+      XEN_SCRUB_PAGES             = option yes;
+      XEN_SELFBALLOONING          = option yes;
+      XEN_STUB                    = option yes;
+      XEN_TMEM                    = option yes;
+    });
+
+    media = {
+      MEDIA_DIGITAL_TV_SUPPORT = yes;
+      MEDIA_CAMERA_SUPPORT     = yes;
+      MEDIA_RC_SUPPORT         = whenOlder "4.14" yes;
+			MEDIA_CONTROLLER         = yes;
+      MEDIA_PCI_SUPPORT        = yes;
+      MEDIA_USB_SUPPORT        = yes;
+      MEDIA_ANALOG_TV_SUPPORT  = yes;
+      VIDEO_STK1160_COMMON     = module;
+      VIDEO_STK1160_AC97       = whenOlder "4.11" yes;
+    };
+
+    "9p" = {
+      # Enable the 9P cache to speed up NixOS VM tests.
+      "9P_FSCACHE"      = option yes;
+      "9P_FS_POSIX_ACL" = option yes;
+    };
+
+    huge-page = {
+      TRANSPARENT_HUGEPAGE         = option yes;
+      TRANSPARENT_HUGEPAGE_ALWAYS  = option no;
+      TRANSPARENT_HUGEPAGE_MADVISE = option yes;
+    };
+
+    zram = {
+      ZRAM     = module;
+      ZSWAP    = option yes;
+      ZBUD     = option yes;
+      ZSMALLOC = if (versionOlder version "3.18") then yes else module;
+    };
+
+    brcmfmac = {
+      # Enable PCIe and USB for the brcmfmac driver
+      BRCMFMAC_USB  = option yes;
+      BRCMFMAC_PCIE = option yes;
+    };
+
+    # Support x2APIC (which requires IRQ remapping)
+    x2apic = optionalAttrs (stdenv.system == "x86_64-linux") {
+      X86_X2APIC = yes;
+      IRQ_REMAP  = yes;
+    };
+
+
+    # For older kernels, painstakingly disable each symbol.
+    tests = {
+      # Disable various self-test modules that have no use in a production system
+      # This menu disables all/most of them on >= 4.16
+      RUNTIME_TESTING_MENU = option no;
+    } // optionalAttrs (versionOlder version "4.16") {
+      ARM_KPROBES_TEST    = option no;
+      ASYNC_RAID6_TEST    = option no;
+      ATOMIC64_SELFTEST   = option no;
+      BACKTRACE_SELF_TEST = option no;
+      INTERVAL_TREE_TEST  = option no;
+      PERCPU_TEST         = option no;
+      RBTREE_TEST         = option no;
+      TEST_BITMAP         = option no;
+      TEST_BPF            = option no;
+      TEST_FIRMWARE       = option no;
+      TEST_HASH           = option no;
+      TEST_HEXDUMP        = option no;
+      TEST_KMOD           = option no;
+      TEST_KSTRTOX        = option no;
+      TEST_LIST_SORT      = option no;
+      TEST_LKM            = option no;
+      TEST_PARMAN         = option no;
+      TEST_PRINTF         = option no;
+      TEST_RHASHTABLE     = option no;
+      TEST_SORT           = option no;
+      TEST_STATIC_KEYS    = option no;
+      TEST_STRING_HELPERS = option no;
+      TEST_UDELAY         = option no;
+      TEST_USER_COPY      = option no;
+      TEST_UUID           = option no;
+    } // {
+      CRC32_SELFTEST           = option no;
+      CRYPTO_TEST              = option no;
+      EFI_TEST                 = option no;
+      GLOB_SELFTEST            = option no;
+      DRM_DEBUG_MM_SELFTEST    = option (whenOlder "4.18" no);
+      LNET_SELFTEST            = option (whenOlder "4.18" no);
+      LOCK_TORTURE_TEST        = option no;
+      MTD_TESTS                = option no;
+      NOTIFIER_ERROR_INJECTION = option no;
+      RCU_PERF_TEST            = option no;
+      RCU_TORTURE_TEST         = option no;
+      TEST_ASYNC_DRIVER_PROBE  = option no;
+      WW_MUTEX_SELFTEST        = option no;
+      XZ_DEC_TEST              = option no;
+    } // optionalAttrs (features.criu or false) ({
+      EXPERT              = yes;
+      CHECKPOINT_RESTORE  = yes;
+    } // optionalAttrs (features.criu_revert_expert or true) {
+      RFKILL_INPUT          = option yes;
+      HID_PICOLCD_FB        = option yes;
+      HID_PICOLCD_BACKLIGHT = option yes;
+      HID_PICOLCD_LCD       = option yes;
+      HID_PICOLCD_LEDS      = option yes;
+      HID_PICOLCD_CIR       = option yes;
+      DEBUG_MEMORY_INIT     = option yes;
+    });
+
+
+    misc = {
+      MODULE_COMPRESS    = whenAtLeast "3.18" yes;
+      MODULE_COMPRESS_XZ = whenAtLeast "3.18" yes;
+      KERNEL_XZ          = yes;
+
+      # Unix domain sockets.
+      UNIX               = yes;
+
+      # Device mapper (RAID, LVM, etc.)
+      MD = yes;
+
+      # Enable initrd support.
+      BLK_DEV_RAM       = yes;
+      BLK_DEV_INITRD    = yes;
+
+
+      PM_TRACE_RTC         = no; # Disable some expensive (?) features.
+      ACCESSIBILITY        = yes; # Accessibility support
+      AUXDISPLAY           = yes; # Auxiliary Display support
+      DONGLE               = whenOlder "4.17" yes; # Serial dongle support
+      HIPPI                = yes;
+      MTD_COMPLEX_MAPPINGS = yes; # needed for many devices
+      NET_POCKET           = whenOlder "3.2" yes; # enable pocket and portable adapters
+
+      SCSI_LOWLEVEL        = yes; # enable lots of SCSI devices
+      SCSI_LOWLEVEL_PCMCIA = yes;
+      SCSI_SAS_ATA         = yes; # added to enable detection of hard drive
+
+      SPI        = yes; # needed for many devices
+      SPI_MASTER = yes;
+
+
+      "8139TOO_8129" = yes;
+      "8139TOO_PIO"  = no; # PIO is slower
+
+      AIC79XX_DEBUG_ENABLE = no;
+      AIC7XXX_DEBUG_ENABLE = no;
+      AIC94XX_DEBUG = no;
+      AUDIT_LOGINUID_IMMUTABLE = whenBetween "3.3" "3.13" yes;
+      B43_PCMCIA = option (whenOlder "4.4" yes);
+
+      BLK_DEV_INTEGRITY       = yes;
+
+      BSD_PROCESS_ACCT_V3 = yes;
+
+      BT_HCIUART_BCSP = option yes;
+      BT_HCIUART_H4   = option yes; # UART (H4) protocol support
+      BT_HCIUART_LL   = option yes;
+      BT_RFCOMM_TTY   = option (whenAtLeast "3.4" yes); # RFCOMM TTY support
+
+      CLEANCACHE = option yes;
+      CRASH_DUMP  = option no;
+
+      DMAR = option (whenOlder "3.1" no); # experimental
+
+      DVB_DYNAMIC_MINORS = option yes; # we use udev
+
+      EFI_STUB = whenAtLeast "3.3" yes; # EFI bootloader in the bzImage itself
+      CGROUPS      = yes; # used by systemd
+      FHANDLE      = yes; # used by systemd
+      SECCOMP      = yes; # used by systemd >= 231
+      SECCOMP_FILTER = yes; # ditto
+      POSIX_MQUEUE = yes;
+      FRONTSWAP    = yes;
+      FUSION       = yes; # Fusion MPT device support
+      IDE          = no; # deprecated IDE support
+      IDLE_PAGE_TRACKING  = whenAtLeast "4.3" yes;
+      IRDA_ULTRA   = whenOlder "4.17" yes; # Ultra (connectionless) protocol
+
+      JOYSTICK_IFORCE_232 = option yes; # I-Force Serial joysticks and wheels
+      JOYSTICK_IFORCE_USB = option yes; # I-Force USB joysticks and wheels
+      JOYSTICK_XPAD_FF    = option yes; # X-Box gamepad rumble support
+      JOYSTICK_XPAD_LEDS  = option yes; # LED Support for Xbox360 controller 'BigX' LED
+
+      KEXEC_FILE      = option yes;
+      KEXEC_JUMP      = option yes;
+
+      # Windows Logical Disk Manager (Dynamic Disk) support
+      LDM_PARTITION         = yes;
+      LOGIRUMBLEPAD2_FF     = yes; # Logitech Rumblepad 2 force feedback
+      LOGO                  = no; # not needed
+      MEDIA_ATTACH          = yes;
+      MEGARAID_NEWGEN       = yes;
+
+      MLX4_EN_VXLAN = whenBetween "3.15" "4.8" yes;
+
+      MODVERSIONS        = whenOlder "4.9" yes;
+      MOUSE_PS2_ELANTECH = yes; # Elantech PS/2 protocol extension
+      MTRR_SANITIZER     = yes;
+      NET_FC             = yes; # Fibre Channel driver support
+      # GPIO on Intel Bay Trail, for some Chromebook internal eMMC disks
+      PINCTRL_BAYTRAIL   = whenAtLeast "3.11" yes;
+      # 8 is default. Modern gpt tables on eMMC may go far beyond 8.
+      MMC_BLOCK_MINORS   = "32";
+
+
+      REGULATOR  = yes; # Voltage and Current Regulator Support
+      RC_DEVICES = option (whenAtLeast "3.6" yes); # Enable IR devices
+
+      RT2800USB_RT53XX = yes;
+      RT2800USB_RT55XX = whenAtLeast "3.10" yes;
+
+      SCHED_AUTOGROUP  = yes;
+      CFS_BANDWIDTH    = yes;
+
+      SCSI_LOGGING = yes; # SCSI logging facility
+      SERIAL_8250  = yes; # 8250/16550 and compatible serial support
+
+      SLIP_COMPRESSED = yes; # CSLIP compressed headers
+      SLIP_SMART      = yes;
+
+      HWMON         = yes;
+      THERMAL_HWMON = yes; # Hardware monitoring support
+      UEVENT_HELPER = whenAtLeast "3.15" no;
+
+      USERFAULTFD   = whenAtLeast "4.3" yes;
+      X86_CHECK_BIOS_CORRUPTION = yes;
+      X86_MCE                   = yes;
+
+      # Our initrd init uses shebang scripts, so can't be modular.
+      BINFMT_SCRIPT = whenAtLeast "3.10" yes;
+      # For systemd-binfmt
+      BINFMT_MISC   = option yes;
+
+      # Disable the firmware helper fallback, udev doesn't implement it any more
+      FW_LOADER_USER_HELPER_FALLBACK = option no;
+
+      HOTPLUG_PCI_ACPI  = whenAtLeast "3.12" yes; # PCI hotplug using ACPI
+      HOTPLUG_PCI_PCIE = whenAtLeast "3.12" yes; # PCI-Expresscard hotplug support
+
+    } // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux" || stdenv.hostPlatform.system == "aarch64-linux") {
+      # Bump the maximum number of CPUs to support systems like EC2 x1.*
+      # instances and Xeon Phi.
+      NR_CPUS = "384";
+    };
+  };
+in (generateNixKConf ((flattenKConf options) // structuredExtraConfig) mkValueOverride) + extraConfig
+
diff --git a/pkgs/os-specific/linux/kernel/generic.nix b/pkgs/os-specific/linux/kernel/generic.nix
index 249a1ea5cef..fde6efd797d 100644
--- a/pkgs/os-specific/linux/kernel/generic.nix
+++ b/pkgs/os-specific/linux/kernel/generic.nix
@@ -15,9 +15,12 @@
 , # Allows overriding the default defconfig
   defconfig ? null
 
-, # Overrides to the kernel config.
+, # Legacy overrides to the intermediate kernel config, as string
   extraConfig ? ""
 
+, # kernel intermediate config overrides, as a set
+ structuredExtraConfig ? {}
+
 , # The version number used for the module directory
   modDirVersion ? version
 
@@ -42,6 +45,7 @@
 , preferBuiltin ? hostPlatform.platform.kernelPreferBuiltin or false
 , kernelArch ? hostPlatform.platform.kernelArch
 
+, mkValueOverride ? null
 , ...
 } @ args:
 
@@ -59,8 +63,9 @@ let
     netfilterRPFilter = true;
   } // features) kernelPatches;
 
-  config = import ./common-config.nix {
-    inherit stdenv version ;
+  intermediateNixConfig = import ./common-config.nix {
+    inherit stdenv version structuredExtraConfig mkValueOverride;
+
     # append extraConfig for backwards compatibility but also means the user can't override the kernelExtraConfig part
     extraConfig = extraConfig + lib.optionalString (hostPlatform.platform ? kernelExtraConfig) hostPlatform.platform.kernelExtraConfig;
 
@@ -79,7 +84,7 @@ let
 
     generateConfig = ./generate-config.pl;
 
-    kernelConfig = kernelConfigFun config;
+    kernelConfig = kernelConfigFun intermediateNixConfig;
     passAsFile = [ "kernelConfig" ];
 
     depsBuildBuild = [ buildPackages.stdenv.cc ];
diff --git a/pkgs/os-specific/linux/kernel/manual-config.nix b/pkgs/os-specific/linux/kernel/manual-config.nix
index 9833bb57baf..fe46b9eab40 100644
--- a/pkgs/os-specific/linux/kernel/manual-config.nix
+++ b/pkgs/os-specific/linux/kernel/manual-config.nix
@@ -24,7 +24,7 @@ in {
   modDirVersion ? version,
   # The kernel source (tarball, git checkout, etc.)
   src,
-  # Any patches
+  # a list of { name=..., patch=..., extraConfig=...} patches
   kernelPatches ? [],
   # The kernel .config file
   configfile,