diff --git a/nix/configuration/configuration.nix b/nix/configuration/configuration.nix index 1a0d773..ec45245 100644 --- a/nix/configuration/configuration.nix +++ b/nix/configuration/configuration.nix @@ -54,6 +54,7 @@ in ./roles/iso_mount ./roles/jujutsu ./roles/kanshi + ./roles/kernel ./roles/kodi ./roles/kubernetes ./roles/latex @@ -235,12 +236,10 @@ in in [ (disableTests "deno") # Tests use too much disk space - (final: prev: { - inherit (final.unoptimized) - libtpms - ; - }) + (disableOptimizations "libtpms") (disableOptimizationsPython3 "scipy") + (disableOptimizations "assimp") + (disableOptimizations "gsl") # Works but probably sets python2's scipy to be python3: # diff --git a/nix/configuration/roles/kernel/default.nix b/nix/configuration/roles/kernel/default.nix new file mode 100644 index 0000000..2bffedb --- /dev/null +++ b/nix/configuration/roles/kernel/default.nix @@ -0,0 +1,308 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + preemption_type = with lib.kernel; { + full = { + PREEMPT_DYNAMIC = yes; + PREEMPT = yes; + PREEMPT_VOLUNTARY = lib.mkForce no; + PREEMPT_LAZY = lib.mkForce no; + PREEMPT_NONE = no; + }; + lazy = { + PREEMPT_DYNAMIC = yes; + PREEMPT = no; + PREEMPT_VOLUNTARY = lib.mkForce no; + PREEMPT_LAZY = yes; + PREEMPT_NONE = no; + }; + voluntary = { + PREEMPT_DYNAMIC = no; + PREEMPT = no; + PREEMPT_VOLUNTARY = yes; + PREEMPT_LAZY = lib.mkForce no; + PREEMPT_NONE = no; + }; + none = { + PREEMPT_DYNAMIC = no; + PREEMPT = no; + PREEMPT_VOLUNTARY = lib.mkForce no; + PREEMPT_LAZY = lib.mkForce no; + PREEMPT_NONE = yes; + }; + }; + lto_type = with lib.kernel; { + none = { + LTO_NONE = yes; + LTO_CLANG_THIN = no; + LTO_CLANG_FULL = no; + }; + thin = { + LTO_NONE = no; + LTO_CLANG_THIN = yes; + LTO_CLANG_FULL = no; + }; + full = { + LTO_NONE = no; + LTO_CLANG_THIN = no; + LTO_CLANG_FULL = yes; + }; + }; + cpu_scheduler = with lib.kernel; { + # Burst-Oriented Response Enhancer + # For interactive workloads and gaming. + bore = { + SCHED_BORE = yes; + }; + # Earliest Eligible Virtual Deadline First + # For general purpose computing. + eevdf = { }; + # BitMap Queue CPU Scheduler + # For throughput-oriented workloads. + bmq = { + SCHED_ALT = yes; + SCHED_BMQ = yes; + }; + }; + tick_hz = + with lib.kernel; + { + "1000" = { + HZ_1000 = yes; + HZ = freeform "1000"; + }; + } + // lib.genAttrs [ "100" "250" "300" "500" "600" "750" ] (hz: { + HZ_1000 = no; + "HZ_${hz}" = yes; + HZ = freeform hz; + }); + performance_governor = with lib.kernel; { + default = { + CPU_FREQ_DEFAULT_GOV_SCHEDUTIL = yes; + }; + performance = { + CPU_FREQ_DEFAULT_GOV_SCHEDUTIL = no; + CPU_FREQ_DEFAULT_GOV_PERFORMANCE = yes; + }; + }; + cpu_type = with lib.kernel; { + x86_64-v1 = { + GENERIC_CPU = yes; + MZEN4 = no; + X86_NATIVE_CPU = no; + X86_64_VERSION = freeform "1"; + }; + x86_64-v2 = { + GENERIC_CPU = yes; + MZEN4 = no; + X86_NATIVE_CPU = no; + X86_64_VERSION = freeform "2"; + }; + x86_64-v3 = { + GENERIC_CPU = yes; + MZEN4 = no; + X86_NATIVE_CPU = no; + X86_64_VERSION = freeform "3"; + }; + x86_64-v4 = { + GENERIC_CPU = yes; + MZEN4 = no; + X86_NATIVE_CPU = no; + X86_64_VERSION = freeform "4"; + }; + zen4 = { + GENERIC_CPU = no; + MZEN4 = yes; + X86_NATIVE_CPU = no; + }; + default = { }; + }; + my_cpu_type = lib.mkMerge [ + (lib.mkIf (!config.me.optimizations.enable) cpu_type.default) + (lib.mkIf ( + config.me.optimizations.enable && config.me.optimizations.arch == "x86-64-v1" + ) cpu_type.x86_64-v1) + (lib.mkIf ( + config.me.optimizations.enable && config.me.optimizations.arch == "x86-64-v2" + ) cpu_type.x86_64-v2) + (lib.mkIf ( + config.me.optimizations.enable && config.me.optimizations.arch == "x86-64-v3" + ) cpu_type.x86_64-v3) + (lib.mkIf ( + config.me.optimizations.enable && config.me.optimizations.arch == "x86-64-v4" + ) cpu_type.x86_64-v4) + (lib.mkIf ( + config.me.optimizations.enable && config.me.optimizations.arch == "znver4" + ) cpu_type.zen4) + ]; + tick_rate = with lib.kernel; { + # Always tick at the hz frequency. + periodic = { + NO_HZ_IDLE = no; + NO_HZ_FULL = no; + NO_HZ = no; + NO_HZ_COMMON = no; + HZ_PERIODIC = yes; + }; + # Idle - Do not disturb the CPU when idle. This can save power but increase latency. + idle = { + HZ_PERIODIC = no; + NO_HZ_FULL = no; + NO_HZ_IDLE = yes; + NO_HZ = yes; + NO_HZ_COMMON = yes; + }; + # Full dyntick system (tickless) - The kernel tries to shut down the tick whenever possible. + tickless = { + HZ_PERIODIC = no; + NO_HZ_IDLE = no; + CONTEXT_TRACKING_FORCE = no; + NO_HZ_FULL_NODEF = yes; + NO_HZ_FULL = yes; + NO_HZ = yes; + NO_HZ_COMMON = yes; + CONTEXT_TRACKING = yes; + }; + }; + huge_page = with lib.kernel; { + always = { + TRANSPARENT_HUGEPAGE_MADVISE = no; + TRANSPARENT_HUGEPAGE_ALWAYS = yes; + }; + madvise = { + TRANSPARENT_HUGEPAGE_ALWAYS = no; + TRANSPARENT_HUGEPAGE_MADVISE = yes; + }; + }; + io_scheduler = with lib.kernel; { + adios = { + MQ_IOSCHED_ADIOS = yes; + }; + bfq = { + IOSCHED_BFQ = mkKernelOverride yes; + }; + }; + common_config = + with lib.kernel; + { + # Google's BBRv3 TCP congestion Control + TCP_CONG_BBR = yes; + DEFAULT_BBR = yes; + + # TCP_CONG_CUBIC = module; + # DEFAULT_CUBIC = no; + # TCP_CONG_BBR = yes; + # DEFAULT_BBR = yes; + # DEFAULT_TCP_CONG = freeform "bbr"; + # NET_SCH_FQ_CODEL = module; + # NET_SCH_FQ = yes; + # CONFIG_DEFAULT_FQ_CODEL = no; + # CONFIG_DEFAULT_FQ = yes; + + # Enable the Control Flow Integrity sanitizer in clang + ARCH_SUPPORTS_CFI_CLANG = yes; + CFI_CLANG = yes; + CFI_AUTO_DEFAULT = yes; + + # Use O3 optimizations + CC_OPTIMIZE_FOR_PERFORMANCE = no; + CC_OPTIMIZE_FOR_PERFORMANCE_O3 = yes; + + # Enable Adaptive Deadline I/O Scheduler + MQ_IOSCHED_ADIOS = yes; + } + // my_cpu_type; + flavors = { + server = lib.mkMerge [ + preemption_type.none + lto_type.full + cpu_scheduler.eevdf + tick_hz."300" + performance_governor.default + tick_rate.tickless + huge_page.madvise + ]; + interactive = + with lib.kernel; + lib.mkMerge [ + { + # Enable RCU Lazy - Reduces power consumption when idle or lightly loaded. Useful for battery-powered devices like laptops. + RCU_LAZY = yes; + } + preemption_type.lazy + lto_type.full + cpu_scheduler.bore + tick_hz."300" + performance_governor.default + tick_rate.tickless + huge_page.madvise + ]; + }; +in +{ + imports = [ ]; + + options.me = { + kernel.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = true; + description = "Whether we want to install kernel."; + }; + + kernel.version = lib.mkOption { + type = lib.types.str; + default = "linux"; # LTS + example = "linux_6_18"; + description = "What version of the kernl should we use."; + }; + + kernel.flavor = lib.mkOption { + type = lib.types.str; + default = "interactive"; + example = "server"; + description = "What type of kernel should be built."; + }; + }; + + config = lib.mkIf config.me.kernel.enable ( + lib.mkMerge [ + { + boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_me; + } + (lib.mkIf (!config.me.optimizations.enable) { + nixpkgs.overlays = [ + (final: prev: { + linux_me = final."${config.me.kernel.version}"; + }) + ]; + }) + (lib.mkIf (config.me.optimizations.enable) { + nixpkgs.overlays = [ + ( + final: prev: + let + addConfig = + additionalConfig: pkg: + pkg.override (oldconfig: { + structuredExtraConfig = lib.mkMerge ([ pkg.structuredExtraConfig ] ++ additionalConfig); + }); + in + { + linux_me = addConfig ([ + common_config + flavors."${config.me.kernel.flavor}" + ]) final."${config.me.kernel.version}"; + } + ) + ]; + }) + ] + ); +} diff --git a/nix/configuration/roles/minimal_base/default.nix b/nix/configuration/roles/minimal_base/default.nix index 1654729..076d82d 100644 --- a/nix/configuration/roles/minimal_base/default.nix +++ b/nix/configuration/roles/minimal_base/default.nix @@ -19,6 +19,7 @@ config = lib.mkIf config.me.minimal_base.enable { me.doas.enable = true; + me.kernel.enable = true; me.network.enable = true; me.nvme.enable = true; me.ssh.enable = true; diff --git a/nix/configuration/roles/optimized_build/default.nix b/nix/configuration/roles/optimized_build/default.nix index 3fc944d..b8735bf 100644 --- a/nix/configuration/roles/optimized_build/default.nix +++ b/nix/configuration/roles/optimized_build/default.nix @@ -1,7 +1,6 @@ { config, lib, - pkgs, ... }: @@ -49,71 +48,13 @@ }; config = lib.mkMerge [ - (lib.mkIf (!config.me.optimizations.enable) ( - lib.mkMerge [ - { - boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_6_18; - # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux; - } - ] - )) (lib.mkIf config.me.optimizations.enable ( lib.mkMerge [ { - boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_me; - nixpkgs.hostPlatform = { gcc.arch = config.me.optimizations.arch; gcc.tune = config.me.optimizations.arch; }; - - nixpkgs.overlays = [ - ( - final: prev: - let - addConfig = - additionalConfig: pkg: - pkg.override (oldconfig: { - structuredExtraConfig = pkg.structuredExtraConfig // additionalConfig; - }); - in - { - linux_me = addConfig { - # Server | No preemption - Run until the next tick. Highest throughput but can cause stutter. - # PREEMPT = lib.mkOverride 60 lib.kernel.no; - # Desktop | Preempt kernel threads only at pre-defined places that call cond_resched(). - PREEMPT_VOLUNTARY = lib.mkOverride 60 lib.kernel.no; - # Low-latency desktop | Full preemption - Kernel threads can be preempted unless they hold a spinlock or are in a no-preemption section. - PREEMPT = lib.mkOverride 60 lib.kernel.yes; - # RT - All kernel code is preemptible except for a few critical sections. - # Middle ground | Real-time tasks preempt immediately like FULL, normal tasks run until the next tick. - PREEMPT_LAZY = lib.mkOverride 90 lib.kernel.no; - - # Google's BBRv3 TCP congestion Control - TCP_CONG_BBR = lib.kernel.yes; - DEFAULT_BBR = lib.kernel.yes; - - # Preemptive Full Tickless Kernel at 300Hz - HZ = lib.kernel.freeform "300"; - HZ_300 = lib.kernel.yes; - HZ_1000 = lib.kernel.no; - } prev.linux_6_18; # or prev.linux - } - ) - (final: prev: { - inherit (final.unoptimized) - assimp - binaryen - gsl - rapidjson - ffmpeg-headless - ffmpeg - pipewire - chromaprint - gtkmm - ; - }) - ]; } ] ))