aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel')
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/bridge-stp-helper.patch13
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/common-config.nix825
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.11.patch784
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.4.patch407
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.9.patch784
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/README.md21
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/default.nix11
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_4_14.patch60
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_5_3.patch42
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gen-kheaders-metadata.patch86
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generate-config.pl147
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generic.nix189
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/genksyms-fix-segfault.patch19
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gpio-utils.nix25
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc325
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix86
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json27
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch7
-rwxr-xr-xinfra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py276
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.14.nix18
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.19.nix18
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.4.nix11
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.9.nix11
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.4.nix18
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.8.nix18
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.9.nix18
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-hardkernel-4.14.nix33
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix42
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-mptcp-95.nix27
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rpi.nix70
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.4.nix41
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.6.nix41
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix23
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing.nix20
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-zen.nix24
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mac-nvme-t2.patch283
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/manual-config.nix323
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/modinst-arg-list-too-long.patch14
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mptcp-config.nix28
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/p9-fixes.patch85
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/patches.nix95
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/perf.nix78
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/randstruct-provide-seed.patch12
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper-updated.patch13
-rw-r--r--infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper.patch13
-rwxr-xr-xinfra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-libre.sh33
-rwxr-xr-xinfra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-rt.sh77
-rwxr-xr-xinfra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update.sh68
48 files changed, 5689 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/bridge-stp-helper.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/bridge-stp-helper.patch
new file mode 100644
index 000000000000..70d0f944c2a0
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/bridge-stp-helper.patch
@@ -0,0 +1,13 @@
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
+index aea3d13..8fcbf81 100644
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -39,7 +39,7 @@
+ #define BR_GROUPFWD_8021AD 0xB801u
+
+ /* Path to usermode spanning tree program */
+-#define BR_STP_PROG "/sbin/bridge-stp"
++#define BR_STP_PROG "/run/current-system/sw/bin/bridge-stp"
+
+ typedef struct bridge_id bridge_id;
+ typedef struct mac_addr mac_addr;
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/common-config.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/common-config.nix
new file mode 100644
index 000000000000..47e49dbe01d7
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/common-config.nix
@@ -0,0 +1,825 @@
+# 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.
+
+# Configuration
+{ stdenv, version
+
+, features ? { grsecurity = false; xen_dom0 = false; }
+}:
+
+with stdenv.lib;
+with stdenv.lib.kernel;
+with (stdenv.lib.kernel.whenHelpers version);
+
+let
+
+
+ # configuration items have to be part of a subattrs
+ flattenKConf = nested: mapAttrs (_: head) (zipAttrs (attrValues nested));
+
+ whenPlatformHasEBPFJit =
+ mkIf (stdenv.hostPlatform.isAarch32 ||
+ stdenv.hostPlatform.isAarch64 ||
+ stdenv.hostPlatform.isx86_64 ||
+ (stdenv.hostPlatform.isPowerPC && stdenv.hostPlatform.is64bit) ||
+ (stdenv.hostPlatform.isMips && stdenv.hostPlatform.is64bit));
+
+ 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;
+ DEBUG_STACK_USAGE = no;
+ DEBUG_STACKOVERFLOW = mkIf (!features.grsecurity) (option no);
+ RCU_TORTURE_TEST = no;
+ SCHEDSTATS = no;
+ DETECT_HUNG_TASK = yes;
+ CRASH_DUMP = option no;
+ # Easier debugging of NFS issues.
+ SUNRPC_DEBUG = yes;
+ # Provide access to tunables like sched_migration_cost_ns
+ SCHED_DEBUG = yes;
+ };
+
+ power-management = {
+ PM_ADVANCED_DEBUG = yes;
+ X86_INTEL_LPSS = yes;
+ X86_INTEL_PSTATE = yes;
+ INTEL_IDLE = yes;
+ CPU_FREQ_DEFAULT_GOV_PERFORMANCE = yes;
+ CPU_FREQ_GOV_SCHEDUTIL = whenAtLeast "4.9" yes;
+ PM_WAKELOCKS = yes;
+ # Power-capping framework and support for INTEL RAPL
+ POWERCAP = yes;
+ INTEL_RAPL = whenAtLeast "5.3" module;
+ };
+
+ 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 = whenOlder "5.0" yes; # Removed in 5.0-RC1
+ BLK_CGROUP = yes; # required by CFQ"
+ BLK_CGROUP_IOLATENCY = whenAtLeast "4.19" yes;
+ BLK_CGROUP_IOCOST = whenAtLeast "5.4" yes;
+ IOSCHED_DEADLINE = whenOlder "5.0" yes; # Removed in 5.0-RC1
+ 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_ADVANCED_ROUTER = yes;
+ IP_PNP = no;
+ IP_VS_PROTO_TCP = yes;
+ IP_VS_PROTO_UDP = yes;
+ IP_VS_PROTO_ESP = yes;
+ IP_VS_PROTO_AH = yes;
+ IP_VS_IPV6 = yes;
+ IP_DCCP_CCID3 = no; # experimental
+ CLS_U32_PERF = yes;
+ CLS_U32_MARK = yes;
+ BPF_JIT = whenPlatformHasEBPFJit yes;
+ BPF_JIT_ALWAYS_ON = whenPlatformHasEBPFJit no; # whenPlatformHasEBPFJit yes; # see https://github.com/NixOS/nixpkgs/issues/79304
+ HAVE_EBPF_JIT = whenPlatformHasEBPFJit yes;
+ BPF_STREAM_PARSER = whenAtLeast "4.19" yes;
+ XDP_SOCKETS = whenAtLeast "4.19" yes;
+ XDP_SOCKETS_DIAG = whenAtLeast "5.1" yes;
+ WAN = yes;
+ TCP_CONG_CUBIC = yes; # This is the default congestion control algorithm since 2.6.19
+ # 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;
+ IP_MULTIPLE_TABLES = yes;
+ IPV6 = 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;
+ NET_SCHED = yes;
+ 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;
+
+ # needed for nftables
+ # Networking Options
+ NETFILTER = yes;
+ NETFILTER_ADVANCED = yes;
+ # Core Netfilter Configuration
+ NF_CONNTRACK_ZONES = yes;
+ NF_CONNTRACK_EVENTS = yes;
+ NF_CONNTRACK_TIMEOUT = yes;
+ NF_CONNTRACK_TIMESTAMP = yes;
+ NETFILTER_NETLINK_GLUE_CT = yes;
+ NF_TABLES_INET = mkMerge [ (whenOlder "4.17" module)
+ (whenAtLeast "4.17" yes) ];
+ NF_TABLES_NETDEV = mkMerge [ (whenOlder "4.17" module)
+ (whenAtLeast "4.17" yes) ];
+ # IP: Netfilter Configuration
+ NF_TABLES_IPV4 = mkMerge [ (whenOlder "4.17" module)
+ (whenAtLeast "4.17" yes) ];
+ NF_TABLES_ARP = mkMerge [ (whenOlder "4.17" module)
+ (whenAtLeast "4.17" yes) ];
+ # IPv6: Netfilter Configuration
+ NF_TABLES_IPV6 = mkMerge [ (whenOlder "4.17" module)
+ (whenAtLeast "4.17" yes) ];
+ # Bridge Netfilter Configuration
+ NF_TABLES_BRIDGE = mkMerge [ (whenBetween "4.19" "5.3" yes)
+ (whenAtLeast "5.3" module) ];
+
+ # needed for `dropwatch`
+ # Builtin-only since https://github.com/torvalds/linux/commit/f4b6bcc7002f0e3a3428bac33cf1945abff95450
+ NET_DROP_MONITOR = yes;
+
+ # needed for ss
+ INET_DIAG = module;
+ INET_TCP_DIAG = module;
+ INET_UDP_DIAG = module;
+ INET_RAW_DIAG = whenAtLeast "4.14" module;
+ INET_DIAG_DESTROY = whenAtLeast "4.9" 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 yes;
+ BCMA_HOST_PCI = option yes;
+ RTW88 = whenAtLeast "5.2" module;
+ RTW88_8822BE = mkMerge [ (whenBetween "5.2" "5.8" yes) (whenAtLeast "5.8" module) ];
+ RTW88_8822CE = mkMerge [ (whenBetween "5.2" "5.8" yes) (whenAtLeast "5.8" module) ];
+ };
+
+ 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_DEFERRED_TAKEOVER = whenAtLeast "4.19" yes;
+ FRAMEBUFFER_CONSOLE_ROTATION = yes;
+ FB_GEODE = mkIf (stdenv.hostPlatform.system == "i686-linux") yes;
+ };
+
+ video = {
+ # Allow specifying custom EDID on the kernel command line
+ DRM_LOAD_EDID_FIRMWARE = yes;
+ VGA_SWITCHEROO = yes; # Hybrid graphics support
+ DRM_GMA600 = yes;
+ DRM_GMA3600 = yes;
+ DRM_VMWGFX_FBCON = 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;
+ # Allow device firmware updates
+ DRM_DP_AUX_CHARDEV = whenAtLeast "4.6" yes;
+ } // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux") {
+ # Intel GVT-g graphics virtualization supports 64-bit only
+ 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_HDA_CODEC_CA0132_DSP = whenOlder "5.7" yes; # Enable DSP firmware loading on Creative Soundblaster Z/Zx/ZxR/Recon
+ SND_OSSEMUL = yes;
+ SND_USB_CAIAQ_INPUT = yes;
+ # Enable PSS mixer (Beethoven ADSP-16 and other compatible)
+ PSS_MIXER = whenOlder "4.12" yes;
+ # Enable Sound Open Firmware support
+ } // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux" &&
+ versionAtLeast version "5.5") {
+ SND_SOC_SOF_TOPLEVEL = yes;
+ SND_SOC_SOF_ACPI = module;
+ SND_SOC_SOF_PCI = module;
+ SND_SOC_SOF_APOLLOLAKE_SUPPORT = yes;
+ SND_SOC_SOF_CANNONLAKE_SUPPORT = yes;
+ SND_SOC_SOF_COFFEELAKE_SUPPORT = yes;
+ SND_SOC_SOF_COMETLAKE_H_SUPPORT = whenOlder "5.8" yes;
+ SND_SOC_SOF_COMETLAKE_LP_SUPPORT = yes;
+ SND_SOC_SOF_ELKHARTLAKE_SUPPORT = yes;
+ SND_SOC_SOF_GEMINILAKE_SUPPORT = yes;
+ SND_SOC_SOF_HDA_AUDIO_CODEC = yes;
+ SND_SOC_SOF_HDA_COMMON_HDMI_CODEC = whenOlder "5.7" yes;
+ SND_SOC_SOF_HDA_LINK = yes;
+ SND_SOC_SOF_ICELAKE_SUPPORT = yes;
+ SND_SOC_SOF_INTEL_TOPLEVEL = yes;
+ SND_SOC_SOF_JASPERLAKE_SUPPORT = yes;
+ SND_SOC_SOF_MERRIFIELD_SUPPORT = yes;
+ SND_SOC_SOF_TIGERLAKE_SUPPORT = yes;
+ };
+
+ usb-serial = {
+ USB_SERIAL_GENERIC = yes; # USB Generic Serial Driver
+ } // optionalAttrs (versionOlder version "4.16") {
+ # 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_KEYSPAN_MPR = yes;
+ 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 = { optional = true; tristate = whenOlder "4.18" "n";};
+ USB_EHCI_ROOT_HUB_TT = yes; # Root Hub Transaction Translators
+ USB_EHCI_TT_NEWSCHED = yes; # Improved transaction translator scheduling
+ USB_HIDDEV = yes; # USB Raw HID Devices (like monitor controls and Uninterruptable Power Supplies)
+ };
+
+ # 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 = if (versionAtLeast version "5.1") then yes else whenAtLeast "4.9" (option module);
+
+ EXT2_FS_XATTR = yes;
+ EXT2_FS_POSIX_ACL = yes;
+ EXT2_FS_SECURITY = yes;
+
+ EXT3_FS_POSIX_ACL = yes;
+ EXT3_FS_SECURITY = yes;
+
+ EXT4_FS_POSIX_ACL = yes;
+ EXT4_FS_SECURITY = yes;
+ EXT4_ENCRYPTION = { optional = true; tristate = if (versionOlder version "4.8") then "m" else "y"; };
+
+ 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 = yes;
+
+ NFS_FSCACHE = yes;
+ NFS_SWAP = yes;
+ NFS_V3_ACL = yes;
+ NFS_V4_1 = yes; # NFSv4.1 client support
+ NFS_V4_2 = yes;
+ NFS_V4_SECURITY_LABEL = yes;
+
+ CIFS_XATTR = yes;
+ CIFS_POSIX = option yes;
+ CIFS_FSCACHE = yes;
+ CIFS_STATS = whenOlder "4.19" yes;
+ CIFS_WEAK_PW_HASH = yes;
+ CIFS_UPCALL = yes;
+ CIFS_ACL = whenOlder "5.3" yes;
+ CIFS_DFS_UPCALL = yes;
+ CIFS_SMB2 = whenOlder "4.13" yes;
+
+ CEPH_FSCACHE = yes;
+ CEPH_FS_POSIX_ACL = yes;
+
+ SQUASHFS_FILE_DIRECT = yes;
+ SQUASHFS_DECOMP_MULTI_PERCPU = yes;
+ SQUASHFS_XATTR = yes;
+ SQUASHFS_ZLIB = yes;
+ SQUASHFS_LZO = yes;
+ SQUASHFS_XZ = yes;
+ SQUASHFS_LZ4 = yes;
+ SQUASHFS_ZSTD = whenAtLeast "4.14" yes;
+
+ # Native Language Support modules, needed by some filesystems
+ NLS = yes;
+ NLS_DEFAULT = freeform "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 = { optional = true; tristate = whenOlder "4.11" "y"; };
+ RANDOMIZE_BASE = option yes;
+ STRICT_DEVMEM = option yes; # Filter access to /dev/mem
+ SECURITY_SELINUX_BOOTPARAM_VALUE = whenOlder "5.1" (freeform "0"); # Disable SELinux by default
+ # Prevent processes from ptracing non-children processes
+ SECURITY_YAMA = option yes;
+ DEVKMEM = mkIf (!features.grsecurity) no; # Disable /dev/kmem
+
+ USER_NS = yes; # Support for user namespaces
+
+ SECURITY_APPARMOR = yes;
+ DEFAULT_SECURITY_APPARMOR = yes;
+
+ SECURITY_LOCKDOWN_LSM = whenAtLeast "5.4" yes;
+ } // optionalAttrs (!stdenv.hostPlatform.isAarch32) {
+
+ # Detect buffer overflows on the stack
+ CC_STACKPROTECTOR_REGULAR = {optional = true; tristate = whenOlder "4.18" "y";};
+ };
+
+ microcode = {
+ MICROCODE = yes;
+ MICROCODE_INTEL = yes;
+ MICROCODE_AMD = 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 = whenOlder "5.0" yes; # Removed in 5.0-RC1
+ BLK_WBT_MQ = yes;
+ };
+
+ container = {
+ NAMESPACES = yes; # Required by 'unshare' used by 'nixos-install'
+ RT_GROUP_SCHED = no;
+ CGROUP_DEVICE = yes;
+ CGROUP_HUGETLB = yes;
+ CGROUP_PERF = yes;
+ CGROUP_RDMA = whenAtLeast "4.11" yes;
+
+ MEMCG = yes;
+ MEMCG_SWAP = yes;
+
+ DEVPTS_MULTIPLE_INSTANCES = whenOlder "4.7" yes;
+ BLK_DEV_THROTTLING = yes;
+ CFQ_GROUP_IOSCHED = whenOlder "5.0" yes; # Removed in 5.0-RC1
+ 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 = { optional = true; tristate = whenOlder "4.11" "y";};
+ UPROBE_EVENTS = { optional = true; tristate = whenAtLeast "4.11" "y";};
+ 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 = mkIf (!features.grsecurity) yes;
+ PARAVIRT_SPINLOCKS = option yes;
+
+ KVM_APIC_ARCHITECTURE = whenOlder "4.8" yes;
+ KVM_ASYNC_PF = yes;
+ KVM_COMPAT = { optional = true; tristate = whenBetween "4.0" "4.12" "y"; };
+ KVM_DEVICE_ASSIGNMENT = { optional = true; tristate = whenBetween "3.10" "4.12" "y"; };
+ KVM_GENERIC_DIRTYLOG_READ_PROTECT = whenAtLeast "4.0" yes;
+ KVM_GUEST = mkIf (!features.grsecurity) yes;
+ KVM_MMIO = yes;
+ KVM_VFIO = yes;
+ KSM = yes;
+ VIRT_DRIVERS = yes;
+ # We nneed 64 GB (PAE) support for Xen guest support
+ HIGHMEM64G = { optional = true; tristate = mkIf (!stdenv.is64bit) "y";};
+
+ VFIO_PCI_VGA = mkIf stdenv.is64bit yes;
+
+ # VirtualBox guest drivers in the kernel conflict with the ones in the
+ # official additions package and prevent the vboxsf module from loading,
+ # so disable them for now.
+ VBOXGUEST = option no;
+ DRM_VBOXVIDEO = option no;
+
+ } // 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 features.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 = 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.hostPlatform.system == "x86_64-linux") {
+ X86_X2APIC = yes;
+ IRQ_REMAP = yes;
+ };
+
+ # Disable various self-test modules that have no use in a production system
+ tests = {
+ # This menu disables all/most of them on >= 4.16
+ RUNTIME_TESTING_MENU = option no;
+ } // optionalAttrs (versionOlder version "4.16") {
+ # For older kernels, painstakingly disable each symbol.
+ 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 = { optional = true; tristate = whenOlder "4.18" "n";};
+ LNET_SELFTEST = { optional = true; tristate = whenOlder "4.18" "n";};
+ 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;
+ };
+
+ criu = 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 = {
+ HID_BATTERY_STRENGTH = yes;
+ # enabled by default in x86_64 but not arm64, so we do that here
+ HIDRAW = yes;
+
+ HID_ACRUX_FF = yes;
+ DRAGONRISE_FF = yes;
+ HOLTEK_FF = yes;
+ SONY_FF = yes;
+ SMARTJOYPLUS_FF = yes;
+ THRUSTMASTER_FF = yes;
+ ZEROPLUS_FF = yes;
+
+ MODULE_COMPRESS = yes;
+ MODULE_COMPRESS_XZ = yes;
+ KERNEL_XZ = yes;
+
+ SYSVIPC = yes; # System-V IPC
+
+ AIO = yes; # POSIX asynchronous I/O
+
+ UNIX = yes; # Unix domain sockets.
+
+ MD = yes; # Device mapper (RAID, LVM, etc.)
+
+ # 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
+
+ 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;
+ B43_PCMCIA = { optional=true; tristate = whenOlder "4.4" "y";};
+
+ BLK_DEV_INTEGRITY = yes;
+
+ BLK_SED_OPAL = whenAtLeast "4.14" 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 yes; # RFCOMM TTY support
+
+ CLEANCACHE = option yes;
+ CRASH_DUMP = option no;
+
+ DVB_DYNAMIC_MINORS = option yes; # we use udev
+
+ EFI_STUB = 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 = yes;
+ IRDA_ULTRA = whenOlder "4.17" yes; # Ultra (connectionless) protocol
+
+ JOYSTICK_IFORCE_232 = { optional = true; tristate = whenOlder "5.3" "y"; }; # I-Force Serial joysticks and wheels
+ JOYSTICK_IFORCE_USB = { optional = true; tristate = whenOlder "5.3" "y"; }; # 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
+
+ KEYBOARD_APPLESPI = whenAtLeast "5.3" module;
+
+ KEXEC_FILE = option yes;
+ KEXEC_JUMP = option yes;
+
+ PARTITION_ADVANCED = yes; # Needed for LDM_PARTITION
+ # 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 = whenOlder "4.8" yes;
+ MLX5_CORE_EN = option yes;
+
+ PSI = whenAtLeast "4.20" yes;
+
+ MODVERSIONS = whenOlder "4.9" yes;
+ MOUSE_ELAN_I2C_SMBUS = 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 = yes;
+ # 8 is default. Modern gpt tables on eMMC may go far beyond 8.
+ MMC_BLOCK_MINORS = freeform "32";
+
+ REGULATOR = yes; # Voltage and Current Regulator Support
+ RC_DEVICES = option yes; # Enable IR devices
+
+ RT2800USB_RT53XX = yes;
+ RT2800USB_RT55XX = 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
+ NVME_HWMON = whenAtLeast "5.5" yes; # NVMe drives temperature reporting
+ UEVENT_HELPER = no;
+
+ USERFAULTFD = yes;
+ X86_CHECK_BIOS_CORRUPTION = yes;
+ X86_MCE = yes;
+
+ RAS = yes; # Needed for EDAC support
+
+ # Our initrd init uses shebang scripts, so can't be modular.
+ BINFMT_SCRIPT = 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 = yes; # PCI hotplug using ACPI
+ HOTPLUG_PCI_PCIE = yes; # PCI-Expresscard hotplug support
+
+ # Enable AMD's ROCm GPU compute stack
+ HSA_AMD = mkIf stdenv.hostPlatform.is64bit (whenAtLeast "4.20" yes);
+ ZONE_DEVICE = mkIf stdenv.hostPlatform.is64bit (whenAtLeast "5.3" yes);
+ HMM_MIRROR = whenAtLeast "5.3" yes;
+ DRM_AMDGPU_USERPTR = whenAtLeast "5.3" yes;
+
+ PREEMPT = no;
+ PREEMPT_VOLUNTARY = yes;
+
+ X86_AMD_PLATFORM_DEVICE = yes;
+
+ } // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux" || stdenv.hostPlatform.system == "aarch64-linux") {
+ # Enable CPU/memory hotplug support
+ # Allows you to dynamically add & remove CPUs/memory to a VM client running NixOS without requiring a reboot
+ ACPI_HOTPLUG_CPU = yes;
+ ACPI_HOTPLUG_MEMORY = yes;
+ MEMORY_HOTPLUG = yes;
+ MEMORY_HOTREMOVE = yes;
+ HOTPLUG_CPU = yes;
+ MIGRATION = yes;
+ SPARSEMEM = yes;
+
+ # Bump the maximum number of CPUs to support systems like EC2 x1.*
+ # instances and Xeon Phi.
+ NR_CPUS = freeform "384";
+ } // optionalAttrs (stdenv.hostPlatform.system == "aarch64-linux") {
+ # Enables support for the Allwinner Display Engine 2.0
+ SUN8I_DE2_CCU = whenAtLeast "4.13" yes;
+
+ # See comments on https://github.com/NixOS/nixpkgs/commit/9b67ea9106102d882f53d62890468071900b9647
+ CRYPTO_AEGIS128_SIMD = whenAtLeast "5.4" no;
+ };
+ };
+in
+ flattenKConf options
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.11.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.11.patch
new file mode 100644
index 000000000000..38cc0532ba97
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.11.patch
@@ -0,0 +1,784 @@
+commit 827b86ad1dd21feed4c0b99faf6059f245f7dadb
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Mar 11 07:31:23 2016 -0500
+
+ sched: Misc preps for cgroup unified hierarchy interface
+
+ Make the following changes in preparation for the cpu controller
+ interface implementation for the unified hierarchy. This patch
+ doesn't cause any functional differences.
+
+ * s/cpu_stats_show()/cpu_cfs_stats_show()/
+
+ * s/cpu_files/cpu_legacy_files/
+
+ * Separate out cpuacct_stats_read() from cpuacct_stats_show(). While
+ at it, make the @val array u64 for consistency.
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: Peter Zijlstra <peterz@infradead.org>
+ Cc: Li Zefan <lizefan@huawei.com>
+ Cc: Johannes Weiner <hannes@cmpxchg.org>
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 3b31fc05a0f1..a1b95e83fa87 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -7174,7 +7174,7 @@ static int __cfs_schedulable(struct task_group *tg, u64 period, u64 quota)
+ return ret;
+ }
+
+-static int cpu_stats_show(struct seq_file *sf, void *v)
++static int cpu_cfs_stats_show(struct seq_file *sf, void *v)
+ {
+ struct task_group *tg = css_tg(seq_css(sf));
+ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
+@@ -7214,7 +7214,7 @@ static u64 cpu_rt_period_read_uint(struct cgroup_subsys_state *css,
+ }
+ #endif /* CONFIG_RT_GROUP_SCHED */
+
+-static struct cftype cpu_files[] = {
++static struct cftype cpu_legacy_files[] = {
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ {
+ .name = "shares",
+@@ -7235,7 +7235,7 @@ static struct cftype cpu_files[] = {
+ },
+ {
+ .name = "stat",
+- .seq_show = cpu_stats_show,
++ .seq_show = cpu_cfs_stats_show,
+ },
+ #endif
+ #ifdef CONFIG_RT_GROUP_SCHED
+@@ -7261,7 +7261,7 @@ struct cgroup_subsys cpu_cgrp_subsys = {
+ .fork = cpu_cgroup_fork,
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+- .legacy_cftypes = cpu_files,
++ .legacy_cftypes = cpu_legacy_files,
+ .early_init = true,
+ };
+
+diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
+index f95ab29a45d0..6151c23f722f 100644
+--- a/kernel/sched/cpuacct.c
++++ b/kernel/sched/cpuacct.c
+@@ -276,26 +276,33 @@ static int cpuacct_all_seq_show(struct seq_file *m, void *V)
+ return 0;
+ }
+
+-static int cpuacct_stats_show(struct seq_file *sf, void *v)
++static void cpuacct_stats_read(struct cpuacct *ca,
++ u64 (*val)[CPUACCT_STAT_NSTATS])
+ {
+- struct cpuacct *ca = css_ca(seq_css(sf));
+- s64 val[CPUACCT_STAT_NSTATS];
+ int cpu;
+- int stat;
+
+- memset(val, 0, sizeof(val));
++ memset(val, 0, sizeof(*val));
++
+ for_each_possible_cpu(cpu) {
+ u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat;
+
+- val[CPUACCT_STAT_USER] += cpustat[CPUTIME_USER];
+- val[CPUACCT_STAT_USER] += cpustat[CPUTIME_NICE];
+- val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SYSTEM];
+- val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_IRQ];
+- val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SOFTIRQ];
++ (*val)[CPUACCT_STAT_USER] += cpustat[CPUTIME_USER];
++ (*val)[CPUACCT_STAT_USER] += cpustat[CPUTIME_NICE];
++ (*val)[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SYSTEM];
++ (*val)[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_IRQ];
++ (*val)[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SOFTIRQ];
+ }
++}
++
++static int cpuacct_stats_show(struct seq_file *sf, void *v)
++{
++ u64 val[CPUACCT_STAT_NSTATS];
++ int stat;
++
++ cpuacct_stats_read(css_ca(seq_css(sf)), &val);
+
+ for (stat = 0; stat < CPUACCT_STAT_NSTATS; stat++) {
+- seq_printf(sf, "%s %lld\n",
++ seq_printf(sf, "%s %llu\n",
+ cpuacct_stat_desc[stat],
+ (long long)nsec_to_clock_t(val[stat]));
+ }
+
+commit fdb64d002b3a223ce4bb11aa4448a42050470052
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Mar 11 07:31:23 2016 -0500
+
+ sched: Implement interface for cgroup unified hierarchy
+
+ While the cpu controller doesn't have any functional problems, there
+ are a couple interface issues which can be addressed in the v2
+ interface.
+
+ * cpuacct being a separate controller. This separation is artificial
+ and rather pointless as demonstrated by most use cases co-mounting
+ the two controllers. It also forces certain information to be
+ accounted twice.
+
+ * Use of different time units. Writable control knobs use
+ microseconds, some stat fields use nanoseconds while other cpuacct
+ stat fields use centiseconds.
+
+ * Control knobs which can't be used in the root cgroup still show up
+ in the root.
+
+ * Control knob names and semantics aren't consistent with other
+ controllers.
+
+ This patchset implements cpu controller's interface on the unified
+ hierarchy which adheres to the controller file conventions described
+ in Documentation/cgroups/unified-hierarchy.txt. Overall, the
+ following changes are made.
+
+ * cpuacct is implictly enabled and disabled by cpu and its information
+ is reported through "cpu.stat" which now uses microseconds for all
+ time durations. All time duration fields now have "_usec" appended
+ to them for clarity. While this doesn't solve the double accounting
+ immediately, once majority of users switch to v2, cpu can directly
+ account and report the relevant stats and cpuacct can be disabled on
+ the unified hierarchy.
+
+ Note that cpuacct.usage_percpu is currently not included in
+ "cpu.stat". If this information is actually called for, it can be
+ added later.
+
+ * "cpu.shares" is replaced with "cpu.weight" and operates on the
+ standard scale defined by CGROUP_WEIGHT_MIN/DFL/MAX (1, 100, 10000).
+ The weight is scaled to scheduler weight so that 100 maps to 1024
+ and the ratio relationship is preserved - if weight is W and its
+ scaled value is S, W / 100 == S / 1024. While the mapped range is a
+ bit smaller than the orignal scheduler weight range, the dead zones
+ on both sides are relatively small and covers wider range than the
+ nice value mappings. This file doesn't make sense in the root
+ cgroup and isn't create on root.
+
+ * "cpu.cfs_quota_us" and "cpu.cfs_period_us" are replaced by "cpu.max"
+ which contains both quota and period.
+
+ * "cpu.rt_runtime_us" and "cpu.rt_period_us" are replaced by
+ "cpu.rt.max" which contains both runtime and period.
+
+ v2: cpu_stats_show() was incorrectly using CONFIG_FAIR_GROUP_SCHED for
+ CFS bandwidth stats and also using raw division for u64. Use
+ CONFIG_CFS_BANDWITH and do_div() instead.
+
+ The semantics of "cpu.rt.max" is not fully decided yet. Dropped
+ for now.
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: Peter Zijlstra <peterz@infradead.org>
+ Cc: Li Zefan <lizefan@huawei.com>
+ Cc: Johannes Weiner <hannes@cmpxchg.org>
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index a1b95e83fa87..f01d56e58a1b 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -7253,6 +7253,139 @@ static struct cftype cpu_legacy_files[] = {
+ { } /* Terminate */
+ };
+
++static int cpu_stats_show(struct seq_file *sf, void *v)
++{
++ cpuacct_cpu_stats_show(sf);
++
++#ifdef CONFIG_CFS_BANDWIDTH
++ {
++ struct task_group *tg = css_tg(seq_css(sf));
++ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
++ u64 throttled_usec;
++
++ throttled_usec = cfs_b->throttled_time;
++ do_div(throttled_usec, NSEC_PER_USEC);
++
++ seq_printf(sf, "nr_periods %d\n"
++ "nr_throttled %d\n"
++ "throttled_usec %llu\n",
++ cfs_b->nr_periods, cfs_b->nr_throttled,
++ throttled_usec);
++ }
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static u64 cpu_weight_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ struct task_group *tg = css_tg(css);
++ u64 weight = scale_load_down(tg->shares);
++
++ return DIV_ROUND_CLOSEST_ULL(weight * CGROUP_WEIGHT_DFL, 1024);
++}
++
++static int cpu_weight_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 weight)
++{
++ /*
++ * cgroup weight knobs should use the common MIN, DFL and MAX
++ * values which are 1, 100 and 10000 respectively. While it loses
++ * a bit of range on both ends, it maps pretty well onto the shares
++ * value used by scheduler and the round-trip conversions preserve
++ * the original value over the entire range.
++ */
++ if (weight < CGROUP_WEIGHT_MIN || weight > CGROUP_WEIGHT_MAX)
++ return -ERANGE;
++
++ weight = DIV_ROUND_CLOSEST_ULL(weight * 1024, CGROUP_WEIGHT_DFL);
++
++ return sched_group_set_shares(css_tg(css), scale_load(weight));
++}
++#endif
++
++static void __maybe_unused cpu_period_quota_print(struct seq_file *sf,
++ long period, long quota)
++{
++ if (quota < 0)
++ seq_puts(sf, "max");
++ else
++ seq_printf(sf, "%ld", quota);
++
++ seq_printf(sf, " %ld\n", period);
++}
++
++/* caller should put the current value in *@periodp before calling */
++static int __maybe_unused cpu_period_quota_parse(char *buf,
++ u64 *periodp, u64 *quotap)
++{
++ char tok[21]; /* U64_MAX */
++
++ if (!sscanf(buf, "%s %llu", tok, periodp))
++ return -EINVAL;
++
++ *periodp *= NSEC_PER_USEC;
++
++ if (sscanf(tok, "%llu", quotap))
++ *quotap *= NSEC_PER_USEC;
++ else if (!strcmp(tok, "max"))
++ *quotap = RUNTIME_INF;
++ else
++ return -EINVAL;
++
++ return 0;
++}
++
++#ifdef CONFIG_CFS_BANDWIDTH
++static int cpu_max_show(struct seq_file *sf, void *v)
++{
++ struct task_group *tg = css_tg(seq_css(sf));
++
++ cpu_period_quota_print(sf, tg_get_cfs_period(tg), tg_get_cfs_quota(tg));
++ return 0;
++}
++
++static ssize_t cpu_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes, loff_t off)
++{
++ struct task_group *tg = css_tg(of_css(of));
++ u64 period = tg_get_cfs_period(tg);
++ u64 quota;
++ int ret;
++
++ ret = cpu_period_quota_parse(buf, &period, &quota);
++ if (!ret)
++ ret = tg_set_cfs_bandwidth(tg, period, quota);
++ return ret ?: nbytes;
++}
++#endif
++
++static struct cftype cpu_files[] = {
++ {
++ .name = "stat",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_stats_show,
++ },
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ {
++ .name = "weight",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_weight_read_u64,
++ .write_u64 = cpu_weight_write_u64,
++ },
++#endif
++#ifdef CONFIG_CFS_BANDWIDTH
++ {
++ .name = "max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_max_show,
++ .write = cpu_max_write,
++ },
++#endif
++ { } /* terminate */
++};
++
+ struct cgroup_subsys cpu_cgrp_subsys = {
+ .css_alloc = cpu_cgroup_css_alloc,
+ .css_online = cpu_cgroup_css_online,
+@@ -7262,7 +7395,15 @@ struct cgroup_subsys cpu_cgrp_subsys = {
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+ .legacy_cftypes = cpu_legacy_files,
++ .dfl_cftypes = cpu_files,
+ .early_init = true,
++#ifdef CONFIG_CGROUP_CPUACCT
++ /*
++ * cpuacct is enabled together with cpu on the unified hierarchy
++ * and its stats are reported through "cpu.stat".
++ */
++ .depends_on = 1 << cpuacct_cgrp_id,
++#endif
+ };
+
+ #endif /* CONFIG_CGROUP_SCHED */
+diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
+index 6151c23f722f..fc1cf13c3af1 100644
+--- a/kernel/sched/cpuacct.c
++++ b/kernel/sched/cpuacct.c
+@@ -347,6 +347,31 @@ static struct cftype files[] = {
+ { } /* terminate */
+ };
+
++/* used to print cpuacct stats in cpu.stat on the unified hierarchy */
++void cpuacct_cpu_stats_show(struct seq_file *sf)
++{
++ struct cgroup_subsys_state *css;
++ u64 usage, val[CPUACCT_STAT_NSTATS];
++
++ css = cgroup_get_e_css(seq_css(sf)->cgroup, &cpuacct_cgrp_subsys);
++
++ usage = cpuusage_read(css, seq_cft(sf));
++ cpuacct_stats_read(css_ca(css), &val);
++
++ val[CPUACCT_STAT_USER] *= TICK_NSEC;
++ val[CPUACCT_STAT_SYSTEM] *= TICK_NSEC;
++ do_div(usage, NSEC_PER_USEC);
++ do_div(val[CPUACCT_STAT_USER], NSEC_PER_USEC);
++ do_div(val[CPUACCT_STAT_SYSTEM], NSEC_PER_USEC);
++
++ seq_printf(sf, "usage_usec %llu\n"
++ "user_usec %llu\n"
++ "system_usec %llu\n",
++ usage, val[CPUACCT_STAT_USER], val[CPUACCT_STAT_SYSTEM]);
++
++ css_put(css);
++}
++
+ /*
+ * charge this task's execution time to its accounting group.
+ *
+diff --git a/kernel/sched/cpuacct.h b/kernel/sched/cpuacct.h
+index ba72807c73d4..ddf7af466d35 100644
+--- a/kernel/sched/cpuacct.h
++++ b/kernel/sched/cpuacct.h
+@@ -2,6 +2,7 @@
+
+ extern void cpuacct_charge(struct task_struct *tsk, u64 cputime);
+ extern void cpuacct_account_field(struct task_struct *tsk, int index, u64 val);
++extern void cpuacct_cpu_stats_show(struct seq_file *sf);
+
+ #else
+
+@@ -14,4 +15,8 @@ cpuacct_account_field(struct task_struct *tsk, int index, u64 val)
+ {
+ }
+
++static inline void cpuacct_cpu_stats_show(struct seq_file *sf)
++{
++}
++
+ #endif
+
+commit 8dde150866b8c433216105c50b7e889d5242d583
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Aug 5 12:41:01 2016 -0400
+
+ cgroup: add documentation regarding CPU controller cgroup v2 support
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+
+diff --git a/Documentation/cgroup-v2-cpu.txt b/Documentation/cgroup-v2-cpu.txt
+new file mode 100644
+index 000000000000..1ed7032d4472
+--- /dev/null
++++ b/Documentation/cgroup-v2-cpu.txt
+@@ -0,0 +1,368 @@
++
++
++CPU Controller on Control Group v2
++
++August, 2016 Tejun Heo <tj@kernel.org>
++
++
++While most controllers have support for cgroup v2 now, the CPU
++controller support is not upstream yet due to objections from the
++scheduler maintainers on the basic designs of cgroup v2. This
++document explains the current situation as well as an interim
++solution, and details the disagreements and arguments. The latest
++version of this document can be found at the following URL.
++
++ https://git.kernel.org/cgit/linux/kernel/git/tj/cgroup.git/tree/Documentation/cgroup-v2-cpu.txt?h=cgroup-v2-cpu
++
++This document was posted to the linux-kernel and cgroup mailing lists.
++Unfortunately, no consensus was reached as of Oct, 2016. The thread
++can be found at the following URL.
++
++ http://lkml.kernel.org/r/20160805170752.GK2542@mtj.duckdns.org
++
++
++CONTENTS
++
++1. Current Situation and Interim Solution
++2. Disagreements and Arguments
++ 2-1. Contentious Restrictions
++ 2-1-1. Process Granularity
++ 2-1-2. No Internal Process Constraint
++ 2-2. Impact on CPU Controller
++ 2-2-1. Impact of Process Granularity
++ 2-2-2. Impact of No Internal Process Constraint
++ 2-3. Arguments for cgroup v2
++3. Way Forward
++4. References
++
++
++1. Current Situation and Interim Solution
++
++All objections from the scheduler maintainers apply to cgroup v2 core
++design, and there are no known objections to the specifics of the CPU
++controller cgroup v2 interface. The only blocked part is changes to
++expose the CPU controller interface on cgroup v2, which comprises the
++following two patches:
++
++ [1] sched: Misc preps for cgroup unified hierarchy interface
++ [2] sched: Implement interface for cgroup unified hierarchy
++
++The necessary changes are superficial and implement the interface
++files on cgroup v2. The combined diffstat is as follows.
++
++ kernel/sched/core.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++--
++ kernel/sched/cpuacct.c | 57 ++++++++++++------
++ kernel/sched/cpuacct.h | 5 +
++ 3 files changed, 189 insertions(+), 22 deletions(-)
++
++The patches are easy to apply and forward-port. The following git
++branch will always carry the two patches on top of the latest release
++of the upstream kernel.
++
++ git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git/cgroup-v2-cpu
++
++There also are versioned branches going back to v4.4.
++
++ git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git/cgroup-v2-cpu-$KERNEL_VER
++
++While it's difficult to tell whether the CPU controller support will
++be merged, there are crucial resource control features in cgroup v2
++that are only possible due to the design choices that are being
++objected to, and every effort will be made to ease enabling the CPU
++controller cgroup v2 support out-of-tree for parties which choose to.
++
++
++2. Disagreements and Arguments
++
++There have been several lengthy discussion threads [3][4] on LKML
++around the structural constraints of cgroup v2. The two that affect
++the CPU controller are process granularity and no internal process
++constraint. Both arise primarily from the need for common resource
++domain definition across different resources.
++
++The common resource domain is a powerful concept in cgroup v2 that
++allows controllers to make basic assumptions about the structural
++organization of processes and controllers inside the cgroup hierarchy,
++and thus solve problems spanning multiple types of resources. The
++prime example for this is page cache writeback: dirty page cache is
++regulated through throttling buffered writers based on memory
++availability, and initiating batched write outs to the disk based on
++IO capacity. Tracking and controlling writeback inside a cgroup thus
++requires the direct cooperation of the memory and the IO controller.
++
++This easily extends to other areas, such as CPU cycles consumed while
++performing memory reclaim or IO encryption.
++
++
++2-1. Contentious Restrictions
++
++For controllers of different resources to work together, they must
++agree on a common organization. This uniform model across controllers
++imposes two contentious restrictions on the CPU controller: process
++granularity and the no-internal-process constraint.
++
++
++ 2-1-1. Process Granularity
++
++ For memory, because an address space is shared between all threads
++ of a process, the terminal consumer is a process, not a thread.
++ Separating the threads of a single process into different memory
++ control domains doesn't make semantical sense. cgroup v2 ensures
++ that all controller can agree on the same organization by requiring
++ that threads of the same process belong to the same cgroup.
++
++ There are other reasons to enforce process granularity. One
++ important one is isolating system-level management operations from
++ in-process application operations. The cgroup interface, being a
++ virtual filesystem, is very unfit for multiple independent
++ operations taking place at the same time as most operations have to
++ be multi-step and there is no way to synchronize multiple accessors.
++ See also [5] Documentation/cgroup-v2.txt, "R-2. Thread Granularity"
++
++
++ 2-1-2. No Internal Process Constraint
++
++ cgroup v2 does not allow processes to belong to any cgroup which has
++ child cgroups when resource controllers are enabled on it (the
++ notable exception being the root cgroup itself). This is because,
++ for some resources, a resource domain (cgroup) is not directly
++ comparable to the terminal consumer (process/task) of said resource,
++ and so putting the two into a sibling relationship isn't meaningful.
++
++ - Differing Control Parameters and Capabilities
++
++ A cgroup controller has different resource control parameters and
++ capabilities from a terminal consumer, be that a task or process.
++ There are a couple cases where a cgroup control knob can be mapped
++ to a per-task or per-process API but they are exceptions and the
++ mappings aren't obvious even in those cases.
++
++ For example, task priorities (also known as nice values) set
++ through setpriority(2) are mapped to the CPU controller
++ "cpu.shares" values. However, how exactly the two ranges map and
++ even the fact that they map to each other at all are not obvious.
++
++ The situation gets further muddled when considering other resource
++ types and control knobs. IO priorities set through ioprio_set(2)
++ cannot be mapped to IO controller weights and most cgroup resource
++ control knobs including the bandwidth control knobs of the CPU
++ controller don't have counterparts in the terminal consumers.
++
++ - Anonymous Resource Consumption
++
++ For CPU, every time slice consumed from inside a cgroup, which
++ comprises most but not all of consumed CPU time for the cgroup,
++ can be clearly attributed to a specific task or process. Because
++ these two types of entities are directly comparable as consumers
++ of CPU time, it's theoretically possible to mix tasks and cgroups
++ on the same tree levels and let them directly compete for the time
++ quota available to their common ancestor.
++
++ However, the same can't be said for resource types like memory or
++ IO: the memory consumed by the page cache, for example, can be
++ tracked on a per-cgroup level, but due to mismatches in lifetimes
++ of involved objects (page cache can persist long after processes
++ are gone), shared usages and the implementation overhead of
++ tracking persistent state, it can no longer be attributed to
++ individual processes after instantiation. Consequently, any IO
++ incurred by page cache writeback can be attributed to a cgroup,
++ but not to the individual consumers inside the cgroup.
++
++ For memory and IO, this makes a resource domain (cgroup) an object
++ of a fundamentally different type than a terminal consumer
++ (process). A process can't be a first class object in the resource
++ distribution graph as its total resource consumption can't be
++ described without the containing resource domain.
++
++ Disallowing processes in internal cgroups avoids competition between
++ cgroups and processes which cannot be meaningfully defined for these
++ resources. All resource control takes place among cgroups and a
++ terminal consumer interacts with the containing cgroup the same way
++ it would with the system without cgroup.
++
++ Root cgroup is exempt from this constraint, which is in line with
++ how root cgroup is handled in general - it's excluded from cgroup
++ resource accounting and control.
++
++
++Enforcing process granularity and no internal process constraint
++allows all controllers to be on the same footing in terms of resource
++distribution hierarchy.
++
++
++2-2. Impact on CPU Controller
++
++As indicated earlier, the CPU controller's resource distribution graph
++is the simplest. Every schedulable resource consumption can be
++attributed to a specific task. In addition, for weight based control,
++the per-task priority set through setpriority(2) can be translated to
++and from a per-cgroup weight. As such, the CPU controller can treat a
++task and a cgroup symmetrically, allowing support for any tree layout
++of cgroups and tasks. Both process granularity and the no internal
++process constraint restrict how the CPU controller can be used.
++
++
++ 2-2-1. Impact of Process Granularity
++
++ Process granularity prevents tasks belonging to the same process to
++ be assigned to different cgroups. It was pointed out [6] that this
++ excludes the valid use case of hierarchical CPU distribution within
++ processes.
++
++ To address this issue, the rgroup (resource group) [7][8][9]
++ interface, an extension of the existing setpriority(2) API, was
++ proposed, which is in line with other programmable priority
++ mechanisms and eliminates the risk of in-application configuration
++ and system configuration stepping on each other's toes.
++ Unfortunately, the proposal quickly turned into discussions around
++ cgroup v2 design decisions [4] and no consensus could be reached.
++
++
++ 2-2-2. Impact of No Internal Process Constraint
++
++ The no internal process constraint disallows tasks from competing
++ directly against cgroups. Here is an excerpt from Peter Zijlstra
++ pointing out the issue [10] - R, L and A are cgroups; t1, t2, t3 and
++ t4 are tasks:
++
++
++ R
++ / | \
++ t1 t2 A
++ / \
++ t3 t4
++
++
++ Is fundamentally different from:
++
++
++ R
++ / \
++ L A
++ / \ / \
++ t1 t2 t3 t4
++
++
++ Because if in the first hierarchy you add a task (t5) to R, all of
++ its A will run at 1/4th of total bandwidth where before it had
++ 1/3rd, whereas with the second example, if you add our t5 to L, A
++ doesn't get any less bandwidth.
++
++
++ It is true that the trees are semantically different from each other
++ and the symmetric handling of tasks and cgroups is aesthetically
++ pleasing. However, it isn't clear what the practical usefulness of
++ a layout with direct competition between tasks and cgroups would be,
++ considering that number and behavior of tasks are controlled by each
++ application, and cgroups primarily deal with system level resource
++ distribution; changes in the number of active threads would directly
++ impact resource distribution. Real world use cases of such layouts
++ could not be established during the discussions.
++
++
++2-3. Arguments for cgroup v2
++
++There are strong demands for comprehensive hierarchical resource
++control across all major resources, and establishing a common resource
++hierarchy is an essential step. As with most engineering decisions,
++common resource hierarchy definition comes with its trade-offs. With
++cgroup v2, the trade-offs are in the form of structural constraints
++which, among others, restrict the CPU controller's space of possible
++configurations.
++
++However, even with the restrictions, cgroup v2, in combination with
++rgroup, covers most of identified real world use cases while enabling
++new important use cases of resource control across multiple resource
++types that were fundamentally broken previously.
++
++Furthermore, for resource control, treating resource domains as
++objects of a different type from terminal consumers has important
++advantages - it can account for resource consumptions which are not
++tied to any specific terminal consumer, be that a task or process, and
++allows decoupling resource distribution controls from in-application
++APIs. Even the CPU controller may benefit from it as the kernel can
++consume significant amount of CPU cycles in interrupt context or tasks
++shared across multiple resource domains (e.g. softirq).
++
++Finally, it's important to note that enabling cgroup v2 support for
++the CPU controller doesn't block use cases which require the features
++which are not available on cgroup v2. Unlikely, but should anybody
++actually rely on the CPU controller's symmetric handling of tasks and
++cgroups, backward compatibility is and will be maintained by being
++able to disconnect the controller from the cgroup v2 hierarchy and use
++it standalone. This also holds for cpuset which is often used in
++highly customized configurations which might be a poor fit for common
++resource domains.
++
++The required changes are minimal, the benefits for the target use
++cases are critical and obvious, and use cases which have to use v1 can
++continue to do so.
++
++
++3. Way Forward
++
++cgroup v2 primarily aims to solve the problem of comprehensive
++hierarchical resource control across all major computing resources,
++which is one of the core problems of modern server infrastructure
++engineering. The trade-offs that cgroup v2 took are results of
++pursuing that goal and gaining a better understanding of the nature of
++resource control in the process.
++
++I believe that real world usages will prove cgroup v2's model right,
++considering the crucial pieces of comprehensive resource control that
++cannot be implemented without common resource domains. This is not to
++say that cgroup v2 is fixed in stone and can't be updated; if there is
++an approach which better serves both comprehensive resource control
++and the CPU controller's flexibility, we will surely move towards
++that. It goes without saying that discussions around such approach
++should consider practical aspects of resource control as a whole
++rather than absolutely focusing on a particular controller.
++
++Until such consensus can be reached, the CPU controller cgroup v2
++support will be maintained out of the mainline kernel in an easily
++accessible form. If there is anything cgroup developers can do to
++ease the pain, please feel free to contact us on the cgroup mailing
++list at cgroups@vger.kernel.org.
++
++
++4. References
++
++[1] http://lkml.kernel.org/r/20160105164834.GE5995@mtj.duckdns.org
++ [PATCH 1/2] sched: Misc preps for cgroup unified hierarchy interface
++ Tejun Heo <tj@kernel.org>
++
++[2] http://lkml.kernel.org/r/20160105164852.GF5995@mtj.duckdns.org
++ [PATCH 2/2] sched: Implement interface for cgroup unified hierarchy
++ Tejun Heo <tj@kernel.org>
++
++[3] http://lkml.kernel.org/r/1438641689-14655-4-git-send-email-tj@kernel.org
++ [PATCH 3/3] sched: Implement interface for cgroup unified hierarchy
++ Tejun Heo <tj@kernel.org>
++
++[4] http://lkml.kernel.org/r/20160407064549.GH3430@twins.programming.kicks-ass.net
++ Re: [PATCHSET RFC cgroup/for-4.6] cgroup, sched: implement resource group and PRIO_RGRP
++ Peter Zijlstra <peterz@infradead.org>
++
++[5] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/cgroup-v2.txt
++ Control Group v2
++ Tejun Heo <tj@kernel.org>
++
++[6] http://lkml.kernel.org/r/CAPM31RJNy3jgG=DYe6GO=wyL4BPPxwUm1f2S6YXacQmo7viFZA@mail.gmail.com
++ Re: [PATCH 3/3] sched: Implement interface for cgroup unified hierarchy
++ Paul Turner <pjt@google.com>
++
++[7] http://lkml.kernel.org/r/20160105154503.GC5995@mtj.duckdns.org
++ [RFD] cgroup: thread granularity support for cpu controller
++ Tejun Heo <tj@kernel.org>
++
++[8] http://lkml.kernel.org/r/1457710888-31182-1-git-send-email-tj@kernel.org
++ [PATCHSET RFC cgroup/for-4.6] cgroup, sched: implement resource group and PRIO_RGRP
++ Tejun Heo <tj@kernel.org>
++
++[9] http://lkml.kernel.org/r/20160311160522.GA24046@htj.duckdns.org
++ Example program for PRIO_RGRP
++ Tejun Heo <tj@kernel.org>
++
++[10] http://lkml.kernel.org/r/20160407082810.GN3430@twins.programming.kicks-ass.net
++ Re: [PATCHSET RFC cgroup/for-4.6] cgroup, sched: implement resource
++ Peter Zijlstra <peterz@infradead.org>
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.4.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.4.patch
new file mode 100644
index 000000000000..8f2418c9efce
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.4.patch
@@ -0,0 +1,407 @@
+commit e7cae741f6d645ac68fe8823ca6ef45dbbf6891b
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Mar 11 07:31:23 2016 -0500
+
+ sched: Misc preps for cgroup unified hierarchy interface
+
+ Make the following changes in preparation for the cpu controller
+ interface implementation for the unified hierarchy. This patch
+ doesn't cause any functional differences.
+
+ * s/cpu_stats_show()/cpu_cfs_stats_show()/
+
+ * s/cpu_files/cpu_legacy_files/
+
+ * Separate out cpuacct_stats_read() from cpuacct_stats_show(). While
+ at it, remove pointless cpuacct_stat_desc[] array.
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: Peter Zijlstra <peterz@infradead.org>
+ Cc: Li Zefan <lizefan@huawei.com>
+ Cc: Johannes Weiner <hannes@cmpxchg.org>
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 732e993..77f3ddd 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -8512,7 +8512,7 @@ static int __cfs_schedulable(struct task_group *tg, u64 period, u64 quota)
+ return ret;
+ }
+
+-static int cpu_stats_show(struct seq_file *sf, void *v)
++static int cpu_cfs_stats_show(struct seq_file *sf, void *v)
+ {
+ struct task_group *tg = css_tg(seq_css(sf));
+ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
+@@ -8552,7 +8552,7 @@ static u64 cpu_rt_period_read_uint(struct cgroup_subsys_state *css,
+ }
+ #endif /* CONFIG_RT_GROUP_SCHED */
+
+-static struct cftype cpu_files[] = {
++static struct cftype cpu_legacy_files[] = {
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ {
+ .name = "shares",
+@@ -8573,7 +8573,7 @@ static struct cftype cpu_files[] = {
+ },
+ {
+ .name = "stat",
+- .seq_show = cpu_stats_show,
++ .seq_show = cpu_cfs_stats_show,
+ },
+ #endif
+ #ifdef CONFIG_RT_GROUP_SCHED
+@@ -8599,7 +8599,7 @@ struct cgroup_subsys cpu_cgrp_subsys = {
+ .fork = cpu_cgroup_fork,
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+- .legacy_cftypes = cpu_files,
++ .legacy_cftypes = cpu_legacy_files,
+ .early_init = 1,
+ };
+
+diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
+index dd7cbb5..42b2dd5 100644
+--- a/kernel/sched/cpuacct.c
++++ b/kernel/sched/cpuacct.c
+@@ -177,36 +177,33 @@ static int cpuacct_percpu_seq_show(struct seq_file *m, void *V)
+ return 0;
+ }
+
+-static const char * const cpuacct_stat_desc[] = {
+- [CPUACCT_STAT_USER] = "user",
+- [CPUACCT_STAT_SYSTEM] = "system",
+-};
+-
+-static int cpuacct_stats_show(struct seq_file *sf, void *v)
++static void cpuacct_stats_read(struct cpuacct *ca, u64 *userp, u64 *sysp)
+ {
+- struct cpuacct *ca = css_ca(seq_css(sf));
+ int cpu;
+- s64 val = 0;
+
++ *userp = 0;
+ for_each_online_cpu(cpu) {
+ struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
+- val += kcpustat->cpustat[CPUTIME_USER];
+- val += kcpustat->cpustat[CPUTIME_NICE];
++ *userp += kcpustat->cpustat[CPUTIME_USER];
++ *userp += kcpustat->cpustat[CPUTIME_NICE];
+ }
+- val = cputime64_to_clock_t(val);
+- seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val);
+
+- val = 0;
++ *sysp = 0;
+ for_each_online_cpu(cpu) {
+ struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
+- val += kcpustat->cpustat[CPUTIME_SYSTEM];
+- val += kcpustat->cpustat[CPUTIME_IRQ];
+- val += kcpustat->cpustat[CPUTIME_SOFTIRQ];
++ *sysp += kcpustat->cpustat[CPUTIME_SYSTEM];
++ *sysp += kcpustat->cpustat[CPUTIME_IRQ];
++ *sysp += kcpustat->cpustat[CPUTIME_SOFTIRQ];
+ }
++}
+
+- val = cputime64_to_clock_t(val);
+- seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
++static int cpuacct_stats_show(struct seq_file *sf, void *v)
++{
++ cputime64_t user, sys;
+
++ cpuacct_stats_read(css_ca(seq_css(sf)), &user, &sys);
++ seq_printf(sf, "user %lld\n", cputime64_to_clock_t(user));
++ seq_printf(sf, "system %lld\n", cputime64_to_clock_t(sys));
+ return 0;
+ }
+
+
+commit 1bb33e8a69f089f2d3f58a0e681d4ff352e11c97
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Mar 11 07:31:23 2016 -0500
+
+ sched: Implement interface for cgroup unified hierarchy
+
+ While the cpu controller doesn't have any functional problems, there
+ are a couple interface issues which can be addressed in the v2
+ interface.
+
+ * cpuacct being a separate controller. This separation is artificial
+ and rather pointless as demonstrated by most use cases co-mounting
+ the two controllers. It also forces certain information to be
+ accounted twice.
+
+ * Use of different time units. Writable control knobs use
+ microseconds, some stat fields use nanoseconds while other cpuacct
+ stat fields use centiseconds.
+
+ * Control knobs which can't be used in the root cgroup still show up
+ in the root.
+
+ * Control knob names and semantics aren't consistent with other
+ controllers.
+
+ This patchset implements cpu controller's interface on the unified
+ hierarchy which adheres to the controller file conventions described
+ in Documentation/cgroups/unified-hierarchy.txt. Overall, the
+ following changes are made.
+
+ * cpuacct is implictly enabled and disabled by cpu and its information
+ is reported through "cpu.stat" which now uses microseconds for all
+ time durations. All time duration fields now have "_usec" appended
+ to them for clarity. While this doesn't solve the double accounting
+ immediately, once majority of users switch to v2, cpu can directly
+ account and report the relevant stats and cpuacct can be disabled on
+ the unified hierarchy.
+
+ Note that cpuacct.usage_percpu is currently not included in
+ "cpu.stat". If this information is actually called for, it can be
+ added later.
+
+ * "cpu.shares" is replaced with "cpu.weight" and operates on the
+ standard scale defined by CGROUP_WEIGHT_MIN/DFL/MAX (1, 100, 10000).
+ The weight is scaled to scheduler weight so that 100 maps to 1024
+ and the ratio relationship is preserved - if weight is W and its
+ scaled value is S, W / 100 == S / 1024. While the mapped range is a
+ bit smaller than the orignal scheduler weight range, the dead zones
+ on both sides are relatively small and covers wider range than the
+ nice value mappings. This file doesn't make sense in the root
+ cgroup and isn't create on root.
+
+ * "cpu.cfs_quota_us" and "cpu.cfs_period_us" are replaced by "cpu.max"
+ which contains both quota and period.
+
+ * "cpu.rt_runtime_us" and "cpu.rt_period_us" are replaced by
+ "cpu.rt.max" which contains both runtime and period.
+
+ v2: cpu_stats_show() was incorrectly using CONFIG_FAIR_GROUP_SCHED for
+ CFS bandwidth stats and also using raw division for u64. Use
+ CONFIG_CFS_BANDWITH and do_div() instead.
+
+ The semantics of "cpu.rt.max" is not fully decided yet. Dropped
+ for now.
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: Peter Zijlstra <peterz@infradead.org>
+ Cc: Li Zefan <lizefan@huawei.com>
+ Cc: Johannes Weiner <hannes@cmpxchg.org>
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 77f3ddd..7aafe63 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -8591,6 +8591,139 @@ static struct cftype cpu_legacy_files[] = {
+ { } /* terminate */
+ };
+
++static int cpu_stats_show(struct seq_file *sf, void *v)
++{
++ cpuacct_cpu_stats_show(sf);
++
++#ifdef CONFIG_CFS_BANDWIDTH
++ {
++ struct task_group *tg = css_tg(seq_css(sf));
++ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
++ u64 throttled_usec;
++
++ throttled_usec = cfs_b->throttled_time;
++ do_div(throttled_usec, NSEC_PER_USEC);
++
++ seq_printf(sf, "nr_periods %d\n"
++ "nr_throttled %d\n"
++ "throttled_usec %llu\n",
++ cfs_b->nr_periods, cfs_b->nr_throttled,
++ throttled_usec);
++ }
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static u64 cpu_weight_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ struct task_group *tg = css_tg(css);
++ u64 weight = scale_load_down(tg->shares);
++
++ return DIV_ROUND_CLOSEST_ULL(weight * CGROUP_WEIGHT_DFL, 1024);
++}
++
++static int cpu_weight_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 weight)
++{
++ /*
++ * cgroup weight knobs should use the common MIN, DFL and MAX
++ * values which are 1, 100 and 10000 respectively. While it loses
++ * a bit of range on both ends, it maps pretty well onto the shares
++ * value used by scheduler and the round-trip conversions preserve
++ * the original value over the entire range.
++ */
++ if (weight < CGROUP_WEIGHT_MIN || weight > CGROUP_WEIGHT_MAX)
++ return -ERANGE;
++
++ weight = DIV_ROUND_CLOSEST_ULL(weight * 1024, CGROUP_WEIGHT_DFL);
++
++ return sched_group_set_shares(css_tg(css), scale_load(weight));
++}
++#endif
++
++static void __maybe_unused cpu_period_quota_print(struct seq_file *sf,
++ long period, long quota)
++{
++ if (quota < 0)
++ seq_puts(sf, "max");
++ else
++ seq_printf(sf, "%ld", quota);
++
++ seq_printf(sf, " %ld\n", period);
++}
++
++/* caller should put the current value in *@periodp before calling */
++static int __maybe_unused cpu_period_quota_parse(char *buf,
++ u64 *periodp, u64 *quotap)
++{
++ char tok[21]; /* U64_MAX */
++
++ if (!sscanf(buf, "%s %llu", tok, periodp))
++ return -EINVAL;
++
++ *periodp *= NSEC_PER_USEC;
++
++ if (sscanf(tok, "%llu", quotap))
++ *quotap *= NSEC_PER_USEC;
++ else if (!strcmp(tok, "max"))
++ *quotap = RUNTIME_INF;
++ else
++ return -EINVAL;
++
++ return 0;
++}
++
++#ifdef CONFIG_CFS_BANDWIDTH
++static int cpu_max_show(struct seq_file *sf, void *v)
++{
++ struct task_group *tg = css_tg(seq_css(sf));
++
++ cpu_period_quota_print(sf, tg_get_cfs_period(tg), tg_get_cfs_quota(tg));
++ return 0;
++}
++
++static ssize_t cpu_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes, loff_t off)
++{
++ struct task_group *tg = css_tg(of_css(of));
++ u64 period = tg_get_cfs_period(tg);
++ u64 quota;
++ int ret;
++
++ ret = cpu_period_quota_parse(buf, &period, &quota);
++ if (!ret)
++ ret = tg_set_cfs_bandwidth(tg, period, quota);
++ return ret ?: nbytes;
++}
++#endif
++
++static struct cftype cpu_files[] = {
++ {
++ .name = "stat",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_stats_show,
++ },
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ {
++ .name = "weight",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_weight_read_u64,
++ .write_u64 = cpu_weight_write_u64,
++ },
++#endif
++#ifdef CONFIG_CFS_BANDWIDTH
++ {
++ .name = "max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_max_show,
++ .write = cpu_max_write,
++ },
++#endif
++ { } /* terminate */
++};
++
+ struct cgroup_subsys cpu_cgrp_subsys = {
+ .css_alloc = cpu_cgroup_css_alloc,
+ .css_free = cpu_cgroup_css_free,
+@@ -8600,7 +8733,15 @@ struct cgroup_subsys cpu_cgrp_subsys = {
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+ .legacy_cftypes = cpu_legacy_files,
++ .dfl_cftypes = cpu_files,
+ .early_init = 1,
++#ifdef CONFIG_CGROUP_CPUACCT
++ /*
++ * cpuacct is enabled together with cpu on the unified hierarchy
++ * and its stats are reported through "cpu.stat".
++ */
++ .depends_on = 1 << cpuacct_cgrp_id,
++#endif
+ };
+
+ #endif /* CONFIG_CGROUP_SCHED */
+diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
+index 42b2dd5..b4d32a6 100644
+--- a/kernel/sched/cpuacct.c
++++ b/kernel/sched/cpuacct.c
+@@ -224,6 +224,30 @@ static struct cftype files[] = {
+ { } /* terminate */
+ };
+
++/* used to print cpuacct stats in cpu.stat on the unified hierarchy */
++void cpuacct_cpu_stats_show(struct seq_file *sf)
++{
++ struct cgroup_subsys_state *css;
++ u64 usage, user, sys;
++
++ css = cgroup_get_e_css(seq_css(sf)->cgroup, &cpuacct_cgrp_subsys);
++
++ usage = cpuusage_read(css, seq_cft(sf));
++ cpuacct_stats_read(css_ca(css), &user, &sys);
++
++ user *= TICK_NSEC;
++ sys *= TICK_NSEC;
++ do_div(usage, NSEC_PER_USEC);
++ do_div(user, NSEC_PER_USEC);
++ do_div(sys, NSEC_PER_USEC);
++
++ seq_printf(sf, "usage_usec %llu\n"
++ "user_usec %llu\n"
++ "system_usec %llu\n", usage, user, sys);
++
++ css_put(css);
++}
++
+ /*
+ * charge this task's execution time to its accounting group.
+ *
+diff --git a/kernel/sched/cpuacct.h b/kernel/sched/cpuacct.h
+index ed60562..44eace9 100644
+--- a/kernel/sched/cpuacct.h
++++ b/kernel/sched/cpuacct.h
+@@ -2,6 +2,7 @@
+
+ extern void cpuacct_charge(struct task_struct *tsk, u64 cputime);
+ extern void cpuacct_account_field(struct task_struct *p, int index, u64 val);
++extern void cpuacct_cpu_stats_show(struct seq_file *sf);
+
+ #else
+
+@@ -14,4 +15,8 @@ cpuacct_account_field(struct task_struct *p, int index, u64 val)
+ {
+ }
+
++static inline void cpuacct_cpu_stats_show(struct seq_file *sf)
++{
++}
++
+ #endif
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.9.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.9.patch
new file mode 100644
index 000000000000..6f0904cbce99
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/4.9.patch
@@ -0,0 +1,784 @@
+commit 280858b0bb3384b9ec06b455e196b453888bd6b8
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Mar 11 07:31:23 2016 -0500
+
+ sched: Misc preps for cgroup unified hierarchy interface
+
+ Make the following changes in preparation for the cpu controller
+ interface implementation for the unified hierarchy. This patch
+ doesn't cause any functional differences.
+
+ * s/cpu_stats_show()/cpu_cfs_stats_show()/
+
+ * s/cpu_files/cpu_legacy_files/
+
+ * Separate out cpuacct_stats_read() from cpuacct_stats_show(). While
+ at it, make the @val array u64 for consistency.
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: Peter Zijlstra <peterz@infradead.org>
+ Cc: Li Zefan <lizefan@huawei.com>
+ Cc: Johannes Weiner <hannes@cmpxchg.org>
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 154fd689fe02..57472485b79c 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -8705,7 +8705,7 @@ static int __cfs_schedulable(struct task_group *tg, u64 period, u64 quota)
+ return ret;
+ }
+
+-static int cpu_stats_show(struct seq_file *sf, void *v)
++static int cpu_cfs_stats_show(struct seq_file *sf, void *v)
+ {
+ struct task_group *tg = css_tg(seq_css(sf));
+ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
+@@ -8745,7 +8745,7 @@ static u64 cpu_rt_period_read_uint(struct cgroup_subsys_state *css,
+ }
+ #endif /* CONFIG_RT_GROUP_SCHED */
+
+-static struct cftype cpu_files[] = {
++static struct cftype cpu_legacy_files[] = {
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ {
+ .name = "shares",
+@@ -8766,7 +8766,7 @@ static struct cftype cpu_files[] = {
+ },
+ {
+ .name = "stat",
+- .seq_show = cpu_stats_show,
++ .seq_show = cpu_cfs_stats_show,
+ },
+ #endif
+ #ifdef CONFIG_RT_GROUP_SCHED
+@@ -8791,7 +8791,7 @@ struct cgroup_subsys cpu_cgrp_subsys = {
+ .fork = cpu_cgroup_fork,
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+- .legacy_cftypes = cpu_files,
++ .legacy_cftypes = cpu_legacy_files,
+ .early_init = true,
+ };
+
+diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
+index bc0b309c3f19..d1e5dd0b3a64 100644
+--- a/kernel/sched/cpuacct.c
++++ b/kernel/sched/cpuacct.c
+@@ -276,26 +276,33 @@ static int cpuacct_all_seq_show(struct seq_file *m, void *V)
+ return 0;
+ }
+
+-static int cpuacct_stats_show(struct seq_file *sf, void *v)
++static void cpuacct_stats_read(struct cpuacct *ca,
++ u64 (*val)[CPUACCT_STAT_NSTATS])
+ {
+- struct cpuacct *ca = css_ca(seq_css(sf));
+- s64 val[CPUACCT_STAT_NSTATS];
+ int cpu;
+- int stat;
+
+- memset(val, 0, sizeof(val));
++ memset(val, 0, sizeof(*val));
++
+ for_each_possible_cpu(cpu) {
+ u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat;
+
+- val[CPUACCT_STAT_USER] += cpustat[CPUTIME_USER];
+- val[CPUACCT_STAT_USER] += cpustat[CPUTIME_NICE];
+- val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SYSTEM];
+- val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_IRQ];
+- val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SOFTIRQ];
++ (*val)[CPUACCT_STAT_USER] += cpustat[CPUTIME_USER];
++ (*val)[CPUACCT_STAT_USER] += cpustat[CPUTIME_NICE];
++ (*val)[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SYSTEM];
++ (*val)[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_IRQ];
++ (*val)[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SOFTIRQ];
+ }
++}
++
++static int cpuacct_stats_show(struct seq_file *sf, void *v)
++{
++ u64 val[CPUACCT_STAT_NSTATS];
++ int stat;
++
++ cpuacct_stats_read(css_ca(seq_css(sf)), &val);
+
+ for (stat = 0; stat < CPUACCT_STAT_NSTATS; stat++) {
+- seq_printf(sf, "%s %lld\n",
++ seq_printf(sf, "%s %llu\n",
+ cpuacct_stat_desc[stat],
+ cputime64_to_clock_t(val[stat]));
+ }
+
+commit 015cbdcb90034fd566d00de9d3d405613da3cd26
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Mar 11 07:31:23 2016 -0500
+
+ sched: Implement interface for cgroup unified hierarchy
+
+ While the cpu controller doesn't have any functional problems, there
+ are a couple interface issues which can be addressed in the v2
+ interface.
+
+ * cpuacct being a separate controller. This separation is artificial
+ and rather pointless as demonstrated by most use cases co-mounting
+ the two controllers. It also forces certain information to be
+ accounted twice.
+
+ * Use of different time units. Writable control knobs use
+ microseconds, some stat fields use nanoseconds while other cpuacct
+ stat fields use centiseconds.
+
+ * Control knobs which can't be used in the root cgroup still show up
+ in the root.
+
+ * Control knob names and semantics aren't consistent with other
+ controllers.
+
+ This patchset implements cpu controller's interface on the unified
+ hierarchy which adheres to the controller file conventions described
+ in Documentation/cgroups/unified-hierarchy.txt. Overall, the
+ following changes are made.
+
+ * cpuacct is implictly enabled and disabled by cpu and its information
+ is reported through "cpu.stat" which now uses microseconds for all
+ time durations. All time duration fields now have "_usec" appended
+ to them for clarity. While this doesn't solve the double accounting
+ immediately, once majority of users switch to v2, cpu can directly
+ account and report the relevant stats and cpuacct can be disabled on
+ the unified hierarchy.
+
+ Note that cpuacct.usage_percpu is currently not included in
+ "cpu.stat". If this information is actually called for, it can be
+ added later.
+
+ * "cpu.shares" is replaced with "cpu.weight" and operates on the
+ standard scale defined by CGROUP_WEIGHT_MIN/DFL/MAX (1, 100, 10000).
+ The weight is scaled to scheduler weight so that 100 maps to 1024
+ and the ratio relationship is preserved - if weight is W and its
+ scaled value is S, W / 100 == S / 1024. While the mapped range is a
+ bit smaller than the orignal scheduler weight range, the dead zones
+ on both sides are relatively small and covers wider range than the
+ nice value mappings. This file doesn't make sense in the root
+ cgroup and isn't create on root.
+
+ * "cpu.cfs_quota_us" and "cpu.cfs_period_us" are replaced by "cpu.max"
+ which contains both quota and period.
+
+ * "cpu.rt_runtime_us" and "cpu.rt_period_us" are replaced by
+ "cpu.rt.max" which contains both runtime and period.
+
+ v2: cpu_stats_show() was incorrectly using CONFIG_FAIR_GROUP_SCHED for
+ CFS bandwidth stats and also using raw division for u64. Use
+ CONFIG_CFS_BANDWITH and do_div() instead.
+
+ The semantics of "cpu.rt.max" is not fully decided yet. Dropped
+ for now.
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+ Cc: Ingo Molnar <mingo@redhat.com>
+ Cc: Peter Zijlstra <peterz@infradead.org>
+ Cc: Li Zefan <lizefan@huawei.com>
+ Cc: Johannes Weiner <hannes@cmpxchg.org>
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 57472485b79c..c0ae869f51c4 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -8784,6 +8784,139 @@ static struct cftype cpu_legacy_files[] = {
+ { } /* terminate */
+ };
+
++static int cpu_stats_show(struct seq_file *sf, void *v)
++{
++ cpuacct_cpu_stats_show(sf);
++
++#ifdef CONFIG_CFS_BANDWIDTH
++ {
++ struct task_group *tg = css_tg(seq_css(sf));
++ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
++ u64 throttled_usec;
++
++ throttled_usec = cfs_b->throttled_time;
++ do_div(throttled_usec, NSEC_PER_USEC);
++
++ seq_printf(sf, "nr_periods %d\n"
++ "nr_throttled %d\n"
++ "throttled_usec %llu\n",
++ cfs_b->nr_periods, cfs_b->nr_throttled,
++ throttled_usec);
++ }
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static u64 cpu_weight_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ struct task_group *tg = css_tg(css);
++ u64 weight = scale_load_down(tg->shares);
++
++ return DIV_ROUND_CLOSEST_ULL(weight * CGROUP_WEIGHT_DFL, 1024);
++}
++
++static int cpu_weight_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 weight)
++{
++ /*
++ * cgroup weight knobs should use the common MIN, DFL and MAX
++ * values which are 1, 100 and 10000 respectively. While it loses
++ * a bit of range on both ends, it maps pretty well onto the shares
++ * value used by scheduler and the round-trip conversions preserve
++ * the original value over the entire range.
++ */
++ if (weight < CGROUP_WEIGHT_MIN || weight > CGROUP_WEIGHT_MAX)
++ return -ERANGE;
++
++ weight = DIV_ROUND_CLOSEST_ULL(weight * 1024, CGROUP_WEIGHT_DFL);
++
++ return sched_group_set_shares(css_tg(css), scale_load(weight));
++}
++#endif
++
++static void __maybe_unused cpu_period_quota_print(struct seq_file *sf,
++ long period, long quota)
++{
++ if (quota < 0)
++ seq_puts(sf, "max");
++ else
++ seq_printf(sf, "%ld", quota);
++
++ seq_printf(sf, " %ld\n", period);
++}
++
++/* caller should put the current value in *@periodp before calling */
++static int __maybe_unused cpu_period_quota_parse(char *buf,
++ u64 *periodp, u64 *quotap)
++{
++ char tok[21]; /* U64_MAX */
++
++ if (!sscanf(buf, "%s %llu", tok, periodp))
++ return -EINVAL;
++
++ *periodp *= NSEC_PER_USEC;
++
++ if (sscanf(tok, "%llu", quotap))
++ *quotap *= NSEC_PER_USEC;
++ else if (!strcmp(tok, "max"))
++ *quotap = RUNTIME_INF;
++ else
++ return -EINVAL;
++
++ return 0;
++}
++
++#ifdef CONFIG_CFS_BANDWIDTH
++static int cpu_max_show(struct seq_file *sf, void *v)
++{
++ struct task_group *tg = css_tg(seq_css(sf));
++
++ cpu_period_quota_print(sf, tg_get_cfs_period(tg), tg_get_cfs_quota(tg));
++ return 0;
++}
++
++static ssize_t cpu_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes, loff_t off)
++{
++ struct task_group *tg = css_tg(of_css(of));
++ u64 period = tg_get_cfs_period(tg);
++ u64 quota;
++ int ret;
++
++ ret = cpu_period_quota_parse(buf, &period, &quota);
++ if (!ret)
++ ret = tg_set_cfs_bandwidth(tg, period, quota);
++ return ret ?: nbytes;
++}
++#endif
++
++static struct cftype cpu_files[] = {
++ {
++ .name = "stat",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_stats_show,
++ },
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ {
++ .name = "weight",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_weight_read_u64,
++ .write_u64 = cpu_weight_write_u64,
++ },
++#endif
++#ifdef CONFIG_CFS_BANDWIDTH
++ {
++ .name = "max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_max_show,
++ .write = cpu_max_write,
++ },
++#endif
++ { } /* terminate */
++};
++
+ struct cgroup_subsys cpu_cgrp_subsys = {
+ .css_alloc = cpu_cgroup_css_alloc,
+ .css_released = cpu_cgroup_css_released,
+@@ -8792,7 +8925,15 @@ struct cgroup_subsys cpu_cgrp_subsys = {
+ .can_attach = cpu_cgroup_can_attach,
+ .attach = cpu_cgroup_attach,
+ .legacy_cftypes = cpu_legacy_files,
++ .dfl_cftypes = cpu_files,
+ .early_init = true,
++#ifdef CONFIG_CGROUP_CPUACCT
++ /*
++ * cpuacct is enabled together with cpu on the unified hierarchy
++ * and its stats are reported through "cpu.stat".
++ */
++ .depends_on = 1 << cpuacct_cgrp_id,
++#endif
+ };
+
+ #endif /* CONFIG_CGROUP_SCHED */
+diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
+index d1e5dd0b3a64..57f390514c39 100644
+--- a/kernel/sched/cpuacct.c
++++ b/kernel/sched/cpuacct.c
+@@ -347,6 +347,31 @@ static struct cftype files[] = {
+ { } /* terminate */
+ };
+
++/* used to print cpuacct stats in cpu.stat on the unified hierarchy */
++void cpuacct_cpu_stats_show(struct seq_file *sf)
++{
++ struct cgroup_subsys_state *css;
++ u64 usage, val[CPUACCT_STAT_NSTATS];
++
++ css = cgroup_get_e_css(seq_css(sf)->cgroup, &cpuacct_cgrp_subsys);
++
++ usage = cpuusage_read(css, seq_cft(sf));
++ cpuacct_stats_read(css_ca(css), &val);
++
++ val[CPUACCT_STAT_USER] *= TICK_NSEC;
++ val[CPUACCT_STAT_SYSTEM] *= TICK_NSEC;
++ do_div(usage, NSEC_PER_USEC);
++ do_div(val[CPUACCT_STAT_USER], NSEC_PER_USEC);
++ do_div(val[CPUACCT_STAT_SYSTEM], NSEC_PER_USEC);
++
++ seq_printf(sf, "usage_usec %llu\n"
++ "user_usec %llu\n"
++ "system_usec %llu\n",
++ usage, val[CPUACCT_STAT_USER], val[CPUACCT_STAT_SYSTEM]);
++
++ css_put(css);
++}
++
+ /*
+ * charge this task's execution time to its accounting group.
+ *
+diff --git a/kernel/sched/cpuacct.h b/kernel/sched/cpuacct.h
+index ba72807c73d4..ddf7af466d35 100644
+--- a/kernel/sched/cpuacct.h
++++ b/kernel/sched/cpuacct.h
+@@ -2,6 +2,7 @@
+
+ extern void cpuacct_charge(struct task_struct *tsk, u64 cputime);
+ extern void cpuacct_account_field(struct task_struct *tsk, int index, u64 val);
++extern void cpuacct_cpu_stats_show(struct seq_file *sf);
+
+ #else
+
+@@ -14,4 +15,8 @@ cpuacct_account_field(struct task_struct *tsk, int index, u64 val)
+ {
+ }
+
++static inline void cpuacct_cpu_stats_show(struct seq_file *sf)
++{
++}
++
+ #endif
+
+commit 5019fe3d7ec456b58d451ef06fe1f81d7d9f28a9
+Author: Tejun Heo <tj@kernel.org>
+Date: Fri Aug 5 12:41:01 2016 -0400
+
+ cgroup: add documentation regarding CPU controller cgroup v2 support
+
+ Signed-off-by: Tejun Heo <tj@kernel.org>
+
+diff --git a/Documentation/cgroup-v2-cpu.txt b/Documentation/cgroup-v2-cpu.txt
+new file mode 100644
+index 000000000000..1ed7032d4472
+--- /dev/null
++++ b/Documentation/cgroup-v2-cpu.txt
+@@ -0,0 +1,368 @@
++
++
++CPU Controller on Control Group v2
++
++August, 2016 Tejun Heo <tj@kernel.org>
++
++
++While most controllers have support for cgroup v2 now, the CPU
++controller support is not upstream yet due to objections from the
++scheduler maintainers on the basic designs of cgroup v2. This
++document explains the current situation as well as an interim
++solution, and details the disagreements and arguments. The latest
++version of this document can be found at the following URL.
++
++ https://git.kernel.org/cgit/linux/kernel/git/tj/cgroup.git/tree/Documentation/cgroup-v2-cpu.txt?h=cgroup-v2-cpu
++
++This document was posted to the linux-kernel and cgroup mailing lists.
++Unfortunately, no consensus was reached as of Oct, 2016. The thread
++can be found at the following URL.
++
++ http://lkml.kernel.org/r/20160805170752.GK2542@mtj.duckdns.org
++
++
++CONTENTS
++
++1. Current Situation and Interim Solution
++2. Disagreements and Arguments
++ 2-1. Contentious Restrictions
++ 2-1-1. Process Granularity
++ 2-1-2. No Internal Process Constraint
++ 2-2. Impact on CPU Controller
++ 2-2-1. Impact of Process Granularity
++ 2-2-2. Impact of No Internal Process Constraint
++ 2-3. Arguments for cgroup v2
++3. Way Forward
++4. References
++
++
++1. Current Situation and Interim Solution
++
++All objections from the scheduler maintainers apply to cgroup v2 core
++design, and there are no known objections to the specifics of the CPU
++controller cgroup v2 interface. The only blocked part is changes to
++expose the CPU controller interface on cgroup v2, which comprises the
++following two patches:
++
++ [1] sched: Misc preps for cgroup unified hierarchy interface
++ [2] sched: Implement interface for cgroup unified hierarchy
++
++The necessary changes are superficial and implement the interface
++files on cgroup v2. The combined diffstat is as follows.
++
++ kernel/sched/core.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++--
++ kernel/sched/cpuacct.c | 57 ++++++++++++------
++ kernel/sched/cpuacct.h | 5 +
++ 3 files changed, 189 insertions(+), 22 deletions(-)
++
++The patches are easy to apply and forward-port. The following git
++branch will always carry the two patches on top of the latest release
++of the upstream kernel.
++
++ git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git/cgroup-v2-cpu
++
++There also are versioned branches going back to v4.4.
++
++ git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git/cgroup-v2-cpu-$KERNEL_VER
++
++While it's difficult to tell whether the CPU controller support will
++be merged, there are crucial resource control features in cgroup v2
++that are only possible due to the design choices that are being
++objected to, and every effort will be made to ease enabling the CPU
++controller cgroup v2 support out-of-tree for parties which choose to.
++
++
++2. Disagreements and Arguments
++
++There have been several lengthy discussion threads [3][4] on LKML
++around the structural constraints of cgroup v2. The two that affect
++the CPU controller are process granularity and no internal process
++constraint. Both arise primarily from the need for common resource
++domain definition across different resources.
++
++The common resource domain is a powerful concept in cgroup v2 that
++allows controllers to make basic assumptions about the structural
++organization of processes and controllers inside the cgroup hierarchy,
++and thus solve problems spanning multiple types of resources. The
++prime example for this is page cache writeback: dirty page cache is
++regulated through throttling buffered writers based on memory
++availability, and initiating batched write outs to the disk based on
++IO capacity. Tracking and controlling writeback inside a cgroup thus
++requires the direct cooperation of the memory and the IO controller.
++
++This easily extends to other areas, such as CPU cycles consumed while
++performing memory reclaim or IO encryption.
++
++
++2-1. Contentious Restrictions
++
++For controllers of different resources to work together, they must
++agree on a common organization. This uniform model across controllers
++imposes two contentious restrictions on the CPU controller: process
++granularity and the no-internal-process constraint.
++
++
++ 2-1-1. Process Granularity
++
++ For memory, because an address space is shared between all threads
++ of a process, the terminal consumer is a process, not a thread.
++ Separating the threads of a single process into different memory
++ control domains doesn't make semantical sense. cgroup v2 ensures
++ that all controller can agree on the same organization by requiring
++ that threads of the same process belong to the same cgroup.
++
++ There are other reasons to enforce process granularity. One
++ important one is isolating system-level management operations from
++ in-process application operations. The cgroup interface, being a
++ virtual filesystem, is very unfit for multiple independent
++ operations taking place at the same time as most operations have to
++ be multi-step and there is no way to synchronize multiple accessors.
++ See also [5] Documentation/cgroup-v2.txt, "R-2. Thread Granularity"
++
++
++ 2-1-2. No Internal Process Constraint
++
++ cgroup v2 does not allow processes to belong to any cgroup which has
++ child cgroups when resource controllers are enabled on it (the
++ notable exception being the root cgroup itself). This is because,
++ for some resources, a resource domain (cgroup) is not directly
++ comparable to the terminal consumer (process/task) of said resource,
++ and so putting the two into a sibling relationship isn't meaningful.
++
++ - Differing Control Parameters and Capabilities
++
++ A cgroup controller has different resource control parameters and
++ capabilities from a terminal consumer, be that a task or process.
++ There are a couple cases where a cgroup control knob can be mapped
++ to a per-task or per-process API but they are exceptions and the
++ mappings aren't obvious even in those cases.
++
++ For example, task priorities (also known as nice values) set
++ through setpriority(2) are mapped to the CPU controller
++ "cpu.shares" values. However, how exactly the two ranges map and
++ even the fact that they map to each other at all are not obvious.
++
++ The situation gets further muddled when considering other resource
++ types and control knobs. IO priorities set through ioprio_set(2)
++ cannot be mapped to IO controller weights and most cgroup resource
++ control knobs including the bandwidth control knobs of the CPU
++ controller don't have counterparts in the terminal consumers.
++
++ - Anonymous Resource Consumption
++
++ For CPU, every time slice consumed from inside a cgroup, which
++ comprises most but not all of consumed CPU time for the cgroup,
++ can be clearly attributed to a specific task or process. Because
++ these two types of entities are directly comparable as consumers
++ of CPU time, it's theoretically possible to mix tasks and cgroups
++ on the same tree levels and let them directly compete for the time
++ quota available to their common ancestor.
++
++ However, the same can't be said for resource types like memory or
++ IO: the memory consumed by the page cache, for example, can be
++ tracked on a per-cgroup level, but due to mismatches in lifetimes
++ of involved objects (page cache can persist long after processes
++ are gone), shared usages and the implementation overhead of
++ tracking persistent state, it can no longer be attributed to
++ individual processes after instantiation. Consequently, any IO
++ incurred by page cache writeback can be attributed to a cgroup,
++ but not to the individual consumers inside the cgroup.
++
++ For memory and IO, this makes a resource domain (cgroup) an object
++ of a fundamentally different type than a terminal consumer
++ (process). A process can't be a first class object in the resource
++ distribution graph as its total resource consumption can't be
++ described without the containing resource domain.
++
++ Disallowing processes in internal cgroups avoids competition between
++ cgroups and processes which cannot be meaningfully defined for these
++ resources. All resource control takes place among cgroups and a
++ terminal consumer interacts with the containing cgroup the same way
++ it would with the system without cgroup.
++
++ Root cgroup is exempt from this constraint, which is in line with
++ how root cgroup is handled in general - it's excluded from cgroup
++ resource accounting and control.
++
++
++Enforcing process granularity and no internal process constraint
++allows all controllers to be on the same footing in terms of resource
++distribution hierarchy.
++
++
++2-2. Impact on CPU Controller
++
++As indicated earlier, the CPU controller's resource distribution graph
++is the simplest. Every schedulable resource consumption can be
++attributed to a specific task. In addition, for weight based control,
++the per-task priority set through setpriority(2) can be translated to
++and from a per-cgroup weight. As such, the CPU controller can treat a
++task and a cgroup symmetrically, allowing support for any tree layout
++of cgroups and tasks. Both process granularity and the no internal
++process constraint restrict how the CPU controller can be used.
++
++
++ 2-2-1. Impact of Process Granularity
++
++ Process granularity prevents tasks belonging to the same process to
++ be assigned to different cgroups. It was pointed out [6] that this
++ excludes the valid use case of hierarchical CPU distribution within
++ processes.
++
++ To address this issue, the rgroup (resource group) [7][8][9]
++ interface, an extension of the existing setpriority(2) API, was
++ proposed, which is in line with other programmable priority
++ mechanisms and eliminates the risk of in-application configuration
++ and system configuration stepping on each other's toes.
++ Unfortunately, the proposal quickly turned into discussions around
++ cgroup v2 design decisions [4] and no consensus could be reached.
++
++
++ 2-2-2. Impact of No Internal Process Constraint
++
++ The no internal process constraint disallows tasks from competing
++ directly against cgroups. Here is an excerpt from Peter Zijlstra
++ pointing out the issue [10] - R, L and A are cgroups; t1, t2, t3 and
++ t4 are tasks:
++
++
++ R
++ / | \
++ t1 t2 A
++ / \
++ t3 t4
++
++
++ Is fundamentally different from:
++
++
++ R
++ / \
++ L A
++ / \ / \
++ t1 t2 t3 t4
++
++
++ Because if in the first hierarchy you add a task (t5) to R, all of
++ its A will run at 1/4th of total bandwidth where before it had
++ 1/3rd, whereas with the second example, if you add our t5 to L, A
++ doesn't get any less bandwidth.
++
++
++ It is true that the trees are semantically different from each other
++ and the symmetric handling of tasks and cgroups is aesthetically
++ pleasing. However, it isn't clear what the practical usefulness of
++ a layout with direct competition between tasks and cgroups would be,
++ considering that number and behavior of tasks are controlled by each
++ application, and cgroups primarily deal with system level resource
++ distribution; changes in the number of active threads would directly
++ impact resource distribution. Real world use cases of such layouts
++ could not be established during the discussions.
++
++
++2-3. Arguments for cgroup v2
++
++There are strong demands for comprehensive hierarchical resource
++control across all major resources, and establishing a common resource
++hierarchy is an essential step. As with most engineering decisions,
++common resource hierarchy definition comes with its trade-offs. With
++cgroup v2, the trade-offs are in the form of structural constraints
++which, among others, restrict the CPU controller's space of possible
++configurations.
++
++However, even with the restrictions, cgroup v2, in combination with
++rgroup, covers most of identified real world use cases while enabling
++new important use cases of resource control across multiple resource
++types that were fundamentally broken previously.
++
++Furthermore, for resource control, treating resource domains as
++objects of a different type from terminal consumers has important
++advantages - it can account for resource consumptions which are not
++tied to any specific terminal consumer, be that a task or process, and
++allows decoupling resource distribution controls from in-application
++APIs. Even the CPU controller may benefit from it as the kernel can
++consume significant amount of CPU cycles in interrupt context or tasks
++shared across multiple resource domains (e.g. softirq).
++
++Finally, it's important to note that enabling cgroup v2 support for
++the CPU controller doesn't block use cases which require the features
++which are not available on cgroup v2. Unlikely, but should anybody
++actually rely on the CPU controller's symmetric handling of tasks and
++cgroups, backward compatibility is and will be maintained by being
++able to disconnect the controller from the cgroup v2 hierarchy and use
++it standalone. This also holds for cpuset which is often used in
++highly customized configurations which might be a poor fit for common
++resource domains.
++
++The required changes are minimal, the benefits for the target use
++cases are critical and obvious, and use cases which have to use v1 can
++continue to do so.
++
++
++3. Way Forward
++
++cgroup v2 primarily aims to solve the problem of comprehensive
++hierarchical resource control across all major computing resources,
++which is one of the core problems of modern server infrastructure
++engineering. The trade-offs that cgroup v2 took are results of
++pursuing that goal and gaining a better understanding of the nature of
++resource control in the process.
++
++I believe that real world usages will prove cgroup v2's model right,
++considering the crucial pieces of comprehensive resource control that
++cannot be implemented without common resource domains. This is not to
++say that cgroup v2 is fixed in stone and can't be updated; if there is
++an approach which better serves both comprehensive resource control
++and the CPU controller's flexibility, we will surely move towards
++that. It goes without saying that discussions around such approach
++should consider practical aspects of resource control as a whole
++rather than absolutely focusing on a particular controller.
++
++Until such consensus can be reached, the CPU controller cgroup v2
++support will be maintained out of the mainline kernel in an easily
++accessible form. If there is anything cgroup developers can do to
++ease the pain, please feel free to contact us on the cgroup mailing
++list at cgroups@vger.kernel.org.
++
++
++4. References
++
++[1] http://lkml.kernel.org/r/20160105164834.GE5995@mtj.duckdns.org
++ [PATCH 1/2] sched: Misc preps for cgroup unified hierarchy interface
++ Tejun Heo <tj@kernel.org>
++
++[2] http://lkml.kernel.org/r/20160105164852.GF5995@mtj.duckdns.org
++ [PATCH 2/2] sched: Implement interface for cgroup unified hierarchy
++ Tejun Heo <tj@kernel.org>
++
++[3] http://lkml.kernel.org/r/1438641689-14655-4-git-send-email-tj@kernel.org
++ [PATCH 3/3] sched: Implement interface for cgroup unified hierarchy
++ Tejun Heo <tj@kernel.org>
++
++[4] http://lkml.kernel.org/r/20160407064549.GH3430@twins.programming.kicks-ass.net
++ Re: [PATCHSET RFC cgroup/for-4.6] cgroup, sched: implement resource group and PRIO_RGRP
++ Peter Zijlstra <peterz@infradead.org>
++
++[5] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/cgroup-v2.txt
++ Control Group v2
++ Tejun Heo <tj@kernel.org>
++
++[6] http://lkml.kernel.org/r/CAPM31RJNy3jgG=DYe6GO=wyL4BPPxwUm1f2S6YXacQmo7viFZA@mail.gmail.com
++ Re: [PATCH 3/3] sched: Implement interface for cgroup unified hierarchy
++ Paul Turner <pjt@google.com>
++
++[7] http://lkml.kernel.org/r/20160105154503.GC5995@mtj.duckdns.org
++ [RFD] cgroup: thread granularity support for cpu controller
++ Tejun Heo <tj@kernel.org>
++
++[8] http://lkml.kernel.org/r/1457710888-31182-1-git-send-email-tj@kernel.org
++ [PATCHSET RFC cgroup/for-4.6] cgroup, sched: implement resource group and PRIO_RGRP
++ Tejun Heo <tj@kernel.org>
++
++[9] http://lkml.kernel.org/r/20160311160522.GA24046@htj.duckdns.org
++ Example program for PRIO_RGRP
++ Tejun Heo <tj@kernel.org>
++
++[10] http://lkml.kernel.org/r/20160407082810.GN3430@twins.programming.kicks-ass.net
++ Re: [PATCHSET RFC cgroup/for-4.6] cgroup, sched: implement resource
++ Peter Zijlstra <peterz@infradead.org>
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/README.md b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/README.md
new file mode 100644
index 000000000000..6d48fde6beef
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/README.md
@@ -0,0 +1,21 @@
+Patches for CPU Controller on Control Group v2
+===============================================
+
+See Tejun Heo's [explanation][1] for why these patches are currently
+out-of-tree.
+
+Generating the patches
+-----------------------
+
+In a linux checkout, with remote tc-cgroup pointing to
+git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git, your
+nixpkgs checkout in the same directory as your linux checkout (or
+modify the command accordingly), and setting `ver` to the appropriate
+version:
+
+```shell
+$ ver=4.7
+$ git log --reverse --patch v$ver..remotes/tc-cgroup/cgroup-v2-cpu-v$ver > ../nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/$ver.patch
+```
+
+[1]: https://git.kernel.org/cgit/linux/kernel/git/tj/cgroup.git/tree/Documentation/cgroup-v2-cpu.txt?h=cgroup-v2-cpu
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/default.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/default.nix
new file mode 100644
index 000000000000..5bef5633aa03
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/cpu-cgroup-v2-patches/default.nix
@@ -0,0 +1,11 @@
+let
+ ents = builtins.readDir ./.;
+in builtins.listToAttrs (builtins.filter (x: x != null) (map (name: let
+ match = builtins.match "(.*)\\.patch" name;
+in if match == null then null else {
+ name = builtins.head match;
+ value = {
+ name = "cpu-cgroup-v2-${name}";
+ patch = ./. + "/${name}";
+ };
+}) (builtins.attrNames ents)))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_4_14.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_4_14.patch
new file mode 100644
index 000000000000..205497aee2da
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_4_14.patch
@@ -0,0 +1,60 @@
+From 245e0f743d814c9ff2d1c748175e321301eb16cf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
+Date: Thu, 2 May 2019 05:28:08 +0100
+Subject: [PATCH] x86/fpu: Export __kernel_fpu_{begin,end}()
+
+This partially undo commit:
+
+12209993 x86/fpu: Don't export __kernel_fpu_{begin,end}()
+
+We need this symbol in zfs for AES-NI/AVX support.
+---
+ arch/x86/include/asm/fpu/api.h | 2 ++
+ arch/x86/kernel/fpu/core.c | 6 ++++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h
+index b56d504af6545..7d53388d266ea 100644
+--- a/arch/x86/include/asm/fpu/api.h
++++ b/arch/x86/include/asm/fpu/api.h
+@@ -18,6 +18,8 @@
+ * If you intend to use the FPU in softirq you need to check first with
+ * irq_fpu_usable() if it is possible.
+ */
++extern void __kernel_fpu_begin(void);
++extern void __kernel_fpu_end(void);
+ extern void kernel_fpu_begin(void);
+ extern void kernel_fpu_end(void);
+ extern bool irq_fpu_usable(void);
+diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
+index 2e5003fef51a9..2ea85b32421a0 100644
+--- a/arch/x86/kernel/fpu/core.c
++++ b/arch/x86/kernel/fpu/core.c
+@@ -93,7 +93,7 @@ bool irq_fpu_usable(void)
+ }
+ EXPORT_SYMBOL(irq_fpu_usable);
+
+-static void __kernel_fpu_begin(void)
++void __kernel_fpu_begin(void)
+ {
+ struct fpu *fpu = &current->thread.fpu;
+
+@@ -111,8 +111,9 @@ static void __kernel_fpu_begin(void)
+ __cpu_invalidate_fpregs_state();
+ }
+ }
++EXPORT_SYMBOL(__kernel_fpu_begin);
+
+-static void __kernel_fpu_end(void)
++void __kernel_fpu_end(void)
+ {
+ struct fpu *fpu = &current->thread.fpu;
+
+@@ -121,6 +122,7 @@ static void __kernel_fpu_end(void)
+
+ kernel_fpu_enable();
+ }
++EXPORT_SYMBOL(__kernel_fpu_end);
+
+ void kernel_fpu_begin(void)
+ {
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_5_3.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_5_3.patch
new file mode 100644
index 000000000000..dc9ca64bdc1f
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/export_kernel_fpu_functions_5_3.patch
@@ -0,0 +1,42 @@
+From 1e010beda2896bdf3082fb37a3e49f8ce20e04d8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
+Date: Thu, 2 May 2019 05:28:08 +0100
+Subject: [PATCH] x86/fpu: Export kernel_fpu_{begin,end}() with
+ EXPORT_SYMBOL_GPL
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We need these symbols in zfs as the fpu implementation breaks userspace:
+
+https://github.com/zfsonlinux/zfs/issues/9346
+Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
+---
+ arch/x86/kernel/fpu/core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
+index 12c70840980e..352538b3bb5d 100644
+--- a/arch/x86/kernel/fpu/core.c
++++ b/arch/x86/kernel/fpu/core.c
+@@ -102,7 +102,7 @@ void kernel_fpu_begin(void)
+ }
+ __cpu_invalidate_fpregs_state();
+ }
+-EXPORT_SYMBOL_GPL(kernel_fpu_begin);
++EXPORT_SYMBOL(kernel_fpu_begin);
+
+ void kernel_fpu_end(void)
+ {
+@@ -111,7 +111,7 @@ void kernel_fpu_end(void)
+ this_cpu_write(in_kernel_fpu, false);
+ preempt_enable();
+ }
+-EXPORT_SYMBOL_GPL(kernel_fpu_end);
++EXPORT_SYMBOL(kernel_fpu_end);
+
+ /*
+ * Save the FPU state (mark it for reload if necessary):
+--
+2.23.0
+
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gen-kheaders-metadata.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gen-kheaders-metadata.patch
new file mode 100644
index 000000000000..0639f8b4e8fb
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gen-kheaders-metadata.patch
@@ -0,0 +1,86 @@
+From 2cc99c9cdc8fde5e92e34f9655829449cebd3e00 Mon Sep 17 00:00:00 2001
+From: Dmitry Goldin <dgoldin+lkml@protonmail.ch>
+Date: Fri, 4 Oct 2019 10:40:07 +0000
+Subject: kheaders: make headers archive reproducible
+
+In commit 43d8ce9d65a5 ("Provide in-kernel headers to make
+extending kernel easier") a new mechanism was introduced, for kernels
+>=5.2, which embeds the kernel headers in the kernel image or a module
+and exposes them in procfs for use by userland tools.
+
+The archive containing the header files has nondeterminism caused by
+header files metadata. This patch normalizes the metadata and utilizes
+KBUILD_BUILD_TIMESTAMP if provided and otherwise falls back to the
+default behaviour.
+
+In commit f7b101d33046 ("kheaders: Move from proc to sysfs") it was
+modified to use sysfs and the script for generation of the archive was
+renamed to what is being patched.
+
+Signed-off-by: Dmitry Goldin <dgoldin+lkml@protonmail.ch>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
+
+---
+
+nixos note: This patch is from
+https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git/commit/?h=fixes&id=2cc99c9cdc8fde5e92e34f9655829449cebd3e00
+I commented out the documentation part here, so that it easily applies
+to linux 5.2 and 5.3, which does not ship with the reproducible build
+documentation yet, which only was introduced recently.
+
+---
+ Documentation/kbuild/reproducible-builds.rst | 13 +++++++++----
+ kernel/gen_kheaders.sh | 5 ++++-
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+#diff --git a/Documentation/kbuild/reproducible-builds.rst b/Documentation/kbuild/reproducible-builds.rst
+#index ab92e98c89c8..503393854e2e 100644
+# --- a/Documentation/kbuild/reproducible-builds.rst
+#+++ b/Documentation/kbuild/reproducible-builds.rst
+#@@ -16,16 +16,21 @@ the kernel may be unreproducible, and how to avoid them.
+# Timestamps
+# ----------
+#
+#-The kernel embeds a timestamp in two places:
+#+The kernel embeds timestamps in three places:
+#
+# * The version string exposed by ``uname()`` and included in
+# ``/proc/version``
+#
+# * File timestamps in the embedded initramfs
+#
+#-By default the timestamp is the current time. This must be overridden
+#-using the `KBUILD_BUILD_TIMESTAMP`_ variable. If you are building
+#-from a git commit, you could use its commit date.
+#+* If enabled via ``CONFIG_IKHEADERS``, file timestamps of kernel
+#+ headers embedded in the kernel or respective module,
+#+ exposed via ``/sys/kernel/kheaders.tar.xz``
+#+
+#+By default the timestamp is the current time and in the case of
+#+``kheaders`` the various files' modification times. This must
+#+be overridden using the `KBUILD_BUILD_TIMESTAMP`_ variable.
+#+If you are building from a git commit, you could use its commit date.
+#
+# The kernel does *not* use the ``__DATE__`` and ``__TIME__`` macros,
+# and enables warnings if they are used. If you incorporate external
+diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh
+index 9ff449888d9c..aff79e461fc9 100755
+--- a/kernel/gen_kheaders.sh
++++ b/kernel/gen_kheaders.sh
+@@ -71,7 +71,10 @@ done | cpio --quiet -pd $cpio_dir >/dev/null 2>&1
+ find $cpio_dir -type f -print0 |
+ xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;'
+
+-tar -Jcf $tarfile -C $cpio_dir/ . > /dev/null
++# Create archive and try to normalize metadata for reproducibility
++tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \
++ --owner=0 --group=0 --sort=name --numeric-owner \
++ -Jcf $tarfile -C $cpio_dir/ . > /dev/null
+
+ echo "$src_files_md5" > kernel/kheaders.md5
+ echo "$obj_files_md5" >> kernel/kheaders.md5
+--
+cgit 1.2-0.3.lf.el7
+
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generate-config.pl b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generate-config.pl
new file mode 100644
index 000000000000..26c559ea9086
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generate-config.pl
@@ -0,0 +1,147 @@
+# This script runs `make config' to generate a Linux kernel
+# configuration file. For each question (i.e. kernel configuration
+# option), unless an override is provided, it answers "m" if possible,
+# and otherwise uses the default answer (as determined by the default
+# config for the architecture). Overrides are read from the file
+# $KERNEL_CONFIG, which on each line contains an option name and an
+# answer, e.g. "EXT2_FS_POSIX_ACL y". The script warns about ignored
+# options in $KERNEL_CONFIG, and barfs if `make config' selects
+# another answer for an option than the one provided in
+# $KERNEL_CONFIG.
+
+use strict;
+use IPC::Open2;
+use Cwd;
+
+# exported via nix
+my $debug = $ENV{'DEBUG'};
+my $autoModules = $ENV{'AUTO_MODULES'};
+my $preferBuiltin = $ENV{'PREFER_BUILTIN'};
+my $ignoreConfigErrors = $ENV{'ignoreConfigErrors'};
+my $buildRoot = $ENV{'BUILD_ROOT'};
+$SIG{PIPE} = 'IGNORE';
+
+# Read the answers.
+my %answers;
+my %requiredAnswers;
+open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die "Could not open answer file";
+while (<ANSWERS>) {
+ chomp;
+ s/#.*//;
+ if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(.*\S)\s*$/) {
+ $answers{$1} = $3;
+ $requiredAnswers{$1} = !(defined $2);
+ } elsif (!/^\s*$/) {
+ die "invalid config line: $_";
+ }
+}
+close ANSWERS;
+
+sub runConfig {
+
+ # Run `make config'.
+ my $pid = open2(\*IN, \*OUT, "make -C $ENV{SRC} O=$buildRoot config SHELL=bash ARCH=$ENV{ARCH}");
+
+ # Parse the output, look for questions and then send an
+ # appropriate answer.
+ my $line = ""; my $s;
+ my %choices = ();
+
+ my ($prevQuestion, $prevName);
+
+ while (!eof IN) {
+ read IN, $s, 1 or next;
+ $line .= $s;
+
+ #print STDERR "LINE: $line\n";
+
+ if ($s eq "\n") {
+ print STDERR "GOT: $line" if $debug;
+
+ # Remember choice alternatives ("> 1. bla (FOO)" or " 2. bla (BAR) (NEW)").
+ if ($line =~ /^\s*>?\s*(\d+)\.\s+.*?\(([A-Za-z0-9_]+)\)(?:\s+\(NEW\))?\s*$/) {
+ $choices{$2} = $1;
+ }
+
+ $line = "";
+ }
+
+ elsif ($line =~ /###$/) {
+ # The config program is waiting for an answer.
+
+ # Is this a regular question? ("bla bla (OPTION_NAME) [Y/n/m/...] ")
+ if ($line =~ /(.*) \(([A-Za-z0-9_]+)\) \[(.*)\].*###$/) {
+ my $question = $1; my $name = $2; my $alts = $3;
+ my $answer = "";
+ # Build everything as a module if possible.
+ $answer = "m" if $autoModules && $alts =~ /\/m/ && !($preferBuiltin && $alts =~ /Y/);
+ $answer = $answers{$name} if defined $answers{$name};
+ print STDERR "QUESTION: $question, NAME: $name, ALTS: $alts, ANSWER: $answer\n" if $debug;
+ print OUT "$answer\n";
+ die "repeated question: $question" if $prevQuestion && $prevQuestion eq $question && $name eq $prevName;
+ $prevQuestion = $question;
+ $prevName = $name;
+ }
+
+ # Is this a choice? ("choice[1-N]: ")
+ elsif ($line =~ /choice\[(.*)\]: ###$/) {
+ my $answer = "";
+ foreach my $name (keys %choices) {
+ $answer = $choices{$name} if ($answers{$name} || "") eq "y";
+ }
+ print STDERR "CHOICE: $1, ANSWER: $answer\n" if $debug;
+ print OUT "$answer\n" if $1 =~ /-/;
+ }
+
+ # Some questions lack the option name ("bla bla [Y/n/m/...] ").
+ elsif ($line =~ /(.*) \[(.*)\] ###$/) {
+ print OUT "\n";
+ }
+
+ else {
+ warn "don't know how to answer this question: $line\n";
+ print OUT "\n";
+ }
+
+ $line = "";
+ %choices = ();
+ }
+ }
+
+ close IN;
+ waitpid $pid, 0;
+}
+
+# Run `make config' several times to converge on the desired result.
+# (Some options may only become available after other options are
+# set in a previous run.)
+runConfig;
+runConfig;
+
+# Read the final .config file and check that our answers are in
+# there. `make config' often overrides answers if later questions
+# cause options to be selected.
+my %config;
+open CONFIG, "<$buildRoot/.config" or die "Could not read .config";
+while (<CONFIG>) {
+ chomp;
+ if (/^CONFIG_([A-Za-z0-9_]+)="(.*)"$/) {
+ # String options have double quotes, e.g. 'CONFIG_NLS_DEFAULT="utf8"' and allow escaping.
+ ($config{$1} = $2) =~ s/\\([\\"])/$1/g;
+ } elsif (/^CONFIG_([A-Za-z0-9_]+)=(.*)$/) {
+ $config{$1} = $2;
+ } elsif (/^# CONFIG_([A-Za-z0-9_]+) is not set$/) {
+ $config{$1} = "n";
+ }
+}
+close CONFIG;
+
+my $ret = 0;
+foreach my $name (sort (keys %answers)) {
+ my $f = $requiredAnswers{$name} && $ignoreConfigErrors ne "1"
+ ? sub { warn "error: " . $_[0]; $ret = -1; } : sub { warn "warning: " . $_[0]; };
+ &$f("unused option: $name\n") unless defined $config{$name};
+ &$f("option not set correctly: $name (wanted '$answers{$name}', got '$config{$name}')\n")
+ if $config{$name} && $config{$name} ne $answers{$name};
+}
+exit $ret;
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generic.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generic.nix
new file mode 100644
index 000000000000..dd3050a93eef
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/generic.nix
@@ -0,0 +1,189 @@
+{ buildPackages
+, callPackage
+, perl
+, bison ? null
+, flex ? null
+, gmp ? null
+, libmpc ? null
+, mpfr ? null
+, stdenv
+
+, # The kernel source tarball.
+ src
+
+, # The kernel version.
+ version
+
+, # Allows overriding the default defconfig
+ defconfig ? null
+
+, # 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
+
+, # An attribute set whose attributes express the availability of
+ # certain features in this kernel. E.g. `{iwlwifi = true;}'
+ # indicates a kernel that provides Intel wireless support. Used in
+ # NixOS to implement kernel-specific behaviour.
+ features ? {}
+
+, # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
+ # automatically extended with extra per-version and per-config values.
+ randstructSeed ? ""
+
+, # A list of patches to apply to the kernel. Each element of this list
+ # should be an attribute set {name, patch} where `name' is a
+ # symbolic name and `patch' is the actual patch. The patch may
+ # optionally be compressed with gzip or bzip2.
+ kernelPatches ? []
+, ignoreConfigErrors ? stdenv.hostPlatform.platform.name != "pc" ||
+ stdenv.hostPlatform != stdenv.buildPlatform
+, extraMeta ? {}
+
+, isXen ? features.xen_dom0 or false
+, isZen ? false
+, isLibre ? false
+, isHardened ? false
+
+# easy overrides to stdenv.hostPlatform.platform members
+, autoModules ? stdenv.hostPlatform.platform.kernelAutoModules
+, preferBuiltin ? stdenv.hostPlatform.platform.kernelPreferBuiltin or false
+, kernelArch ? stdenv.hostPlatform.platform.kernelArch
+
+, ...
+}:
+
+# Note: this package is used for bootstrapping fetchurl, and thus
+# cannot use fetchpatch! All mutable patches (generated by GitHub or
+# cgit) that are needed here should be included directly in Nixpkgs as
+# files.
+
+assert stdenv.isLinux;
+
+let
+
+ lib = stdenv.lib;
+
+ # Combine the `features' attribute sets of all the kernel patches.
+ kernelFeatures = lib.fold (x: y: (x.features or {}) // y) ({
+ iwlwifi = true;
+ efiBootStub = true;
+ needsCifsUtils = true;
+ netfilterRPFilter = true;
+ grsecurity = false;
+ xen_dom0 = false;
+ ia32Emulation = true;
+ } // features) kernelPatches;
+
+ commonStructuredConfig = import ./common-config.nix {
+ inherit stdenv version ;
+
+ features = kernelFeatures; # Ensure we know of all extra patches, etc.
+ };
+
+ intermediateNixConfig = configfile.moduleStructuredConfig.intermediateNixConfig
+ # extra config in legacy string format
+ + extraConfig
+ + lib.optionalString (stdenv.hostPlatform.platform ? kernelExtraConfig) stdenv.hostPlatform.platform.kernelExtraConfig;
+
+ structuredConfigFromPatches =
+ map ({extraStructuredConfig ? {}, ...}: {settings=extraStructuredConfig;}) kernelPatches;
+
+ # appends kernel patches extraConfig
+ kernelConfigFun = baseConfigStr:
+ let
+ configFromPatches =
+ map ({extraConfig ? "", ...}: extraConfig) kernelPatches;
+ in lib.concatStringsSep "\n" ([baseConfigStr] ++ configFromPatches);
+
+ configfile = stdenv.mkDerivation {
+ inherit ignoreConfigErrors autoModules preferBuiltin kernelArch;
+ pname = "linux-config";
+ inherit version;
+
+ generateConfig = ./generate-config.pl;
+
+ kernelConfig = kernelConfigFun intermediateNixConfig;
+ passAsFile = [ "kernelConfig" ];
+
+ depsBuildBuild = [ buildPackages.stdenv.cc ];
+ nativeBuildInputs = [ perl gmp libmpc mpfr ]
+ ++ lib.optionals (stdenv.lib.versionAtLeast version "4.16") [ bison flex ];
+
+ platformName = stdenv.hostPlatform.platform.name;
+ # e.g. "defconfig"
+ kernelBaseConfig = if defconfig != null then defconfig else stdenv.hostPlatform.platform.kernelBaseConfig;
+ # e.g. "bzImage"
+ kernelTarget = stdenv.hostPlatform.platform.kernelTarget;
+
+ prePatch = kernel.prePatch + ''
+ # Patch kconfig to print "###" after every question so that
+ # generate-config.pl from the generic builder can answer them.
+ sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
+ '';
+
+ preUnpack = kernel.preUnpack or "";
+
+ inherit (kernel) src patches;
+
+ buildPhase = ''
+ export buildRoot="''${buildRoot:-build}"
+
+ # Get a basic config file for later refinement with $generateConfig.
+ make -C . O="$buildRoot" $kernelBaseConfig \
+ ARCH=$kernelArch \
+ HOSTCC=${buildPackages.stdenv.cc.targetPrefix}gcc \
+ HOSTCXX=${buildPackages.stdenv.cc.targetPrefix}g++
+
+ # Create the config file.
+ echo "generating kernel configuration..."
+ ln -s "$kernelConfigPath" "$buildRoot/kernel-config"
+ DEBUG=1 ARCH=$kernelArch KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \
+ PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. perl -w $generateConfig
+ '';
+
+ installPhase = "mv $buildRoot/.config $out";
+
+ enableParallelBuilding = true;
+
+ passthru = rec {
+
+ module = import ../../../../nixos/modules/system/boot/kernel_config.nix;
+ # used also in apache
+ # { modules = [ { options = res.options; config = svc.config or svc; } ];
+ # check = false;
+ # The result is a set of two attributes
+ moduleStructuredConfig = (lib.evalModules {
+ modules = [
+ module
+ { settings = commonStructuredConfig; _file = "pkgs/os-specific/linux/kernel/common-config.nix"; }
+ { settings = structuredExtraConfig; _file = "structuredExtraConfig"; }
+ ]
+ ++ structuredConfigFromPatches
+ ;
+ }).config;
+
+ structuredConfig = moduleStructuredConfig.settings;
+ };
+ }; # end of configfile derivation
+
+ kernel = (callPackage ./manual-config.nix {}) {
+ inherit version modDirVersion src kernelPatches randstructSeed stdenv extraMeta configfile;
+
+ config = { CONFIG_MODULES = "y"; CONFIG_FW_LOADER = "m"; };
+ };
+
+ passthru = {
+ features = kernelFeatures;
+ inherit commonStructuredConfig isXen isZen isHardened isLibre;
+ kernelOlder = lib.versionOlder version;
+ kernelAtLeast = lib.versionAtLeast version;
+ passthru = kernel.passthru // (removeAttrs passthru [ "passthru" ]);
+ };
+
+in lib.extendDerivation true passthru kernel
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/genksyms-fix-segfault.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/genksyms-fix-segfault.patch
new file mode 100644
index 000000000000..47ae77a5a54d
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/genksyms-fix-segfault.patch
@@ -0,0 +1,19 @@
+diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
+index 88632df..ba6cfa9 100644
+--- a/scripts/genksyms/genksyms.c
++++ b/scripts/genksyms/genksyms.c
+@@ -233,11 +233,11 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
+ free_list(last_enum_expr, NULL);
+ last_enum_expr = NULL;
+ enum_counter = 0;
+- if (!name)
+- /* Anonymous enum definition, nothing more to do */
+- return NULL;
+ }
+
++ if (!name)
++ return NULL;
++
+ h = crc32(name) % HASH_BUCKETS;
+ for (sym = symtab[h]; sym; sym = sym->hash_next) {
+ if (map_to_ns(sym->type) == map_to_ns(type) &&
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gpio-utils.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gpio-utils.nix
new file mode 100644
index 000000000000..e28d838efb3f
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/gpio-utils.nix
@@ -0,0 +1,25 @@
+{ lib, stdenv, linux }:
+
+with lib;
+
+assert versionAtLeast linux.version "4.6";
+
+stdenv.mkDerivation {
+ name = "gpio-utils-${linux.version}";
+
+ inherit (linux) src makeFlags;
+
+ preConfigure = ''
+ cd tools/gpio
+ '';
+
+ separateDebugInfo = true;
+ installFlags = [ "install" "DESTDIR=$(out)" "bindir=/bin" ];
+
+ meta = {
+ description = "Linux tools to inspect the gpiochip interface";
+ maintainers = with maintainers; [ kwohlfahrt ];
+ platforms = platforms.linux;
+ license = licenses.gpl2;
+ };
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc
new file mode 100644
index 000000000000..101ccfbf0f2b
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc
@@ -0,0 +1,325 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQINBE64OEUBEADPS1v+zoCdKA6zyfUtVIaBoIwMhCibqurXi30tVoC9LgM6W1ve
+HwPFukWq7DAS0mZUPE3mSV63JFLaTy0bY/6GO1D4wLdWZx4ppH7XKNCvKCbsi70k
+UozFykNVf+83WEskuF1oYzXlF3aB5suz2IWJl7ey1EXgIpehwQaTJUA5JIWYFp9A
+566LRNJefYMzUR33xc4dRKj6Etg0xdLVq7/vZoo8HpLCBGNWiP0AKqFWEwTg0xQL
+7nsJA5tfJJdwAJvrzjpFsvb63PKG6waAtdHhON4q7E2Udak9fz2tRjxA5l9l2zXk
+aqsysUzkxPhNjwMENoQ04KZg4aT+ZhhBzTowSWLp3KV2uaZ66kdPUO3s+/1bPp5/
+N/IlykaUwyL773iYOZ5dOY/9hIuX/zssihcrGEMW6yIyZR5uKhzYdaM9ExTXP637
+UccgNS9/pskPGPx/xK23NDCfeHzL9YHS5KokA2wb/b9hqpwvLaeblbMl2pt79F1R
+ac+rZlrRyX3NvlTQP4hqM9Ei2YBAU7QFDJEjH8pVIceL7grxi1Ju1iD5QiSK+je5
+Jj5EAikfwSeAttSzsqNvaXJHfABrv5mkkVt1z3icP3HIHTYnG+uj+t8kvW+o9/1i
+pD6e6LUh4w5v1aY9kaK/M3+eBH59yNYI99crPUKUBVfW4gv4DBUJAQTWRQARAQAB
+tDVMZXZlbnRlIFBvbHlhayAoYW50aHJheHgpIDxsZXZlbnRlQGxldmVudGVwb2x5
+YWsubmV0PokCQQQTAQIAKwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4ACGQEF
+AlSXU9QFCQfATw8ACgkQ/BtUfI2BcsjPbxAAs+UR/bJz/HeYTpPy+HnKwDJgI9GP
+AZlNvp+QSIhOTtKCYkQ/Iu+5scY5J0Qyv0pcJW5Rxjx+l7KGovw84jzVznnYsJoy
+UQ5H3Ev9T2xW1nrZT3abJ7j6ZIck+Q+WFHu5Plsq6doSXOXmJNoehvT3BVolvc6w
+S1+CAoyA5Wm1yfocZgVOvWPWQaa1T4XA7OwxFWrvNWEZwAzTSjkGHkwmji+DxdBd
+RPam9+qm/rcN1IJTu6xJPr38a9LydWonsUpTR2Qn7Bo4EJp8yHJLaiLEMV/Nmgrr
+1orBYw/OzDzhbdMl+2zzwEBLUMPABdgnPM6ZCZ5PWyWnCU4jsBGyVd0IC5xEu3Eg
+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
+a6MNZO/+vKN4UTlgjpjxZon+/yK8bsmT/VNie5hzqZim6tfztl3rpJ9jPUeLgr5x
+oGePYV02inapzNHdWFHk0L9zR/3KKfJ3IRJwUXp00Eya28hEepIvdxgLYcN1UqVn
+VuFuMY8zYSl/VXtPxySCLENJHxvdtClMZXZlbnRlIFBvbHlhayA8bGV2ZW50ZUBs
+ZXZlbnRlcG9seWFrLmRlPokCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwEC
+HgECF4AFAlSXU9oFCQfATw8ACgkQ/BtUfI2BcsiPxw//X2xUctIrd1O7UOk7LHBX
+/xI7xXoWQcA7l/1XMuZhM8yC8yIoAgvFrWBP1a29I0P3/yigkQXs+eTDTdvb0QP2
+q72q7Azt852v5u8+dHzoOXDpbo+4lfX+0OBDWimwJuChD8LQH7b7jO0oqWIV0AzM
+vegFJVp3cDbyqw08lBz3xZ79A9JtBeewf6PLpXKjEVS8bEAZjZKjsjAY+5ShtJAf
+PsD8r353dmkaHgC5Aji74ijZeY3PUCvGVVCGeN9isLnRpTEn7qUvN2DfHJU4w6aw
+sXu7m7zidISo6dQLUzo54dHKWPGFy6INNkzXPOgrlbYnjt7v0Ou21/R6HrhdmsSw
+lt7GALJcgAUxrcT/ljB3SZhSB0BdH0DXPcUziEdfhgMhhrXYpMjwH2XFBD1MLusW
+GaVDbpPrSoEnmPVePcDUonDHePcuLjfOl13mOER1Kf6WFapOCa+4HCLakfKcPnGY
+eyfD7Dbz3/046MmfQ8/Iyf8ipFXN6tI2WkRKj8uq9IFYrX3yoCBxZJN837DM3Grq
+h48/T3pYU1f9LiekxbsgXmcHoGNdXX5+EsuO+QILZPttlG5QLuqFdJHei77uvW+B
+4u8mgzi1Zhh0hRLm4K6UaJ/fBJ87BZSHShPKI9PI073U1O/CcYXnb8cdPLu3UgSQ
+FM/bxT70TSYKI01Dt4KXRfWIRgQQEQIABgUCTrg/KAAKCRC+dA9BPyK7GT9FAJ47
+X5+0dQaOFkfy3WnMgX3AmIXJYQCfR4XL47rZ9a66jWaD0IbcXMK4oE2JAj4EEwEC
+ACgFAk64PJ4CGwMFCQIchwAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPwb
+VHyNgXLI2U8QAJGKPv1gWLn7P1KeHVsKkfRf+zgdsoY4mF3bUjX/03z1h1OKp+S7
+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
+kekzzVjVTZxOgZE=
+=yRuG
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix
new file mode 100644
index 000000000000..c817f1044271
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix
@@ -0,0 +1,86 @@
+# Based on recommendations from:
+# http://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project#Recommended_settings
+# https://wiki.gentoo.org/wiki/Hardened/Hardened_Kernel_Project
+#
+# Dangerous features that can be permanently (for the boot session) disabled at
+# boot via sysctl or kernel cmdline are left enabled here, for improved
+# flexibility.
+#
+# See also <nixos/modules/profiles/hardened.nix>
+
+{ stdenv, version }:
+
+with stdenv.lib;
+with stdenv.lib.kernel;
+with (stdenv.lib.kernel.whenHelpers version);
+
+assert (versionAtLeast version "4.9");
+
+{
+ # Report BUG() conditions and kill the offending process.
+ BUG = yes;
+
+ # Safer page access permissions (wrt. code injection). Default on >=4.11.
+ DEBUG_RODATA = whenOlder "4.11" yes;
+ DEBUG_SET_MODULE_RONX = whenOlder "4.11" yes;
+
+ # Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n
+ # conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter
+ # implicitly marks LSM hooks read-only after init.
+ #
+ # SELinux can only be disabled at boot via selinux=0
+ #
+ # We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the
+ # config builder fails to detect that it has indeed been unset.
+ SECURITY_SELINUX_DISABLE = whenAtLeast "4.12" no;
+ SECURITY_WRITABLE_HOOKS = whenAtLeast "4.12" (option no);
+
+ STRICT_KERNEL_RWX = whenAtLeast "4.11" yes;
+
+ # Perform additional validation of commonly targeted structures.
+ DEBUG_CREDENTIALS = yes;
+ DEBUG_NOTIFIERS = yes;
+ DEBUG_PI_LIST = whenOlder "5.2" yes; # doesn't BUG()
+ DEBUG_PLIST = whenAtLeast "5.2" yes;
+ DEBUG_SG = yes;
+ SCHED_STACK_END_CHECK = yes;
+
+ REFCOUNT_FULL = whenBetween "4.13" "5.5" yes;
+
+ # Randomize page allocator when page_alloc.shuffle=1
+ SHUFFLE_PAGE_ALLOCATOR = whenAtLeast "5.2" yes;
+
+ # Allow enabling slub/slab free poisoning with slub_debug=P
+ SLUB_DEBUG = yes;
+
+ # Wipe higher-level memory allocations on free() with page_poison=1
+ PAGE_POISONING = yes;
+ PAGE_POISONING_NO_SANITY = yes;
+ PAGE_POISONING_ZERO = yes;
+
+ # Enable the SafeSetId LSM
+ SECURITY_SAFESETID = whenAtLeast "5.1" yes;
+
+ # Reboot devices immediately if kernel experiences an Oops.
+ PANIC_TIMEOUT = freeform "-1";
+
+ GCC_PLUGINS = yes; # Enable gcc plugin options
+ # Gather additional entropy at boot time for systems that may = no;ot have appropriate entropy sources.
+ GCC_PLUGIN_LATENT_ENTROPY = yes;
+
+ GCC_PLUGIN_STRUCTLEAK = whenAtLeast "4.11" yes; # A port of the PaX structleak plugin
+ GCC_PLUGIN_STRUCTLEAK_BYREF_ALL = whenAtLeast "4.14" yes; # Also cover structs passed by address
+ GCC_PLUGIN_STACKLEAK = whenAtLeast "4.20" yes; # A port of the PaX stackleak plugin
+ GCC_PLUGIN_RANDSTRUCT = whenAtLeast "4.13" yes; # A port of the PaX randstruct plugin
+ GCC_PLUGIN_RANDSTRUCT_PERFORMANCE = whenAtLeast "4.13" yes;
+
+ # Disable various dangerous settings
+ ACPI_CUSTOM_METHOD = no; # Allows writing directly to physical memory
+ PROC_KCORE = no; # Exposes kernel text image layout
+ INET_DIAG = no; # Has been used for heap based attacks in the past
+
+ # Use -fstack-protector-strong (gcc 4.9+) for best stack canary coverage.
+ CC_STACKPROTECTOR_REGULAR = whenOlder "4.18" no;
+ CC_STACKPROTECTOR_STRONG = whenOlder "4.18" yes;
+
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json
new file mode 100644
index 000000000000..c07c65d9be3f
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json
@@ -0,0 +1,27 @@
+{
+ "4.14": {
+ "name": "linux-hardened-4.14.208.a.patch",
+ "sha256": "09lmbfp6d4wpr2l7x1njq8q3sdiqz3rrjzkh6dqsdgwd9sdammb3",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.208.a/linux-hardened-4.14.208.a.patch"
+ },
+ "4.19": {
+ "name": "linux-hardened-4.19.159.a.patch",
+ "sha256": "0ma4lf97l625474xha5pfb8kph2lm3892g6z63fwd5s1vmva6ni6",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.159.a/linux-hardened-4.19.159.a.patch"
+ },
+ "5.4": {
+ "name": "linux-hardened-5.4.79.a.patch",
+ "sha256": "154i6ggj27qgsw562jcd93abcd54b4jllkr87h4k2ia6c0mfq4yb",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.79.a/linux-hardened-5.4.79.a.patch"
+ },
+ "5.8": {
+ "name": "linux-hardened-5.8.18.a.patch",
+ "sha256": "1r2n74nbyi3dp5zql9sk504xkpil6ylbyd99zqqva4nd3qg17c99",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.8.18.a/linux-hardened-5.8.18.a.patch"
+ },
+ "5.9": {
+ "name": "linux-hardened-5.9.10.a.patch",
+ "sha256": "08gdr5sq156lap08nirw4gjq26vr8k65kbjh4js2ndrb0v49f2lk",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.9.10.a/linux-hardened-5.9.10.a.patch"
+ }
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch
new file mode 100644
index 000000000000..ff8a3a127973
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch
@@ -0,0 +1,7 @@
+diff --git a/localversion-hardened b/localversion-hardened
+new file mode 100644
+index 0000000000..e578045860
+--- /dev/null
++++ b/localversion-hardened
+@@ -0,0 +1 @@
++-hardened
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py
new file mode 100755
index 000000000000..d6443d2e7511
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py
@@ -0,0 +1,276 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -i python -p "python38.withPackages (ps: [ps.PyGithub])" git gnupg
+
+# This is automatically called by ../update.sh.
+
+from __future__ import annotations
+
+import json
+import os
+import re
+import subprocess
+import sys
+from dataclasses import dataclass
+from pathlib import Path
+from tempfile import TemporaryDirectory
+from typing import (
+ Dict,
+ Iterator,
+ List,
+ Optional,
+ Sequence,
+ Tuple,
+ TypedDict,
+ Union,
+)
+
+from github import Github
+from github.GitRelease import GitRelease
+
+VersionComponent = Union[int, str]
+Version = List[VersionComponent]
+
+
+Patch = TypedDict("Patch", {"name": str, "url": str, "sha256": str})
+
+
+@dataclass
+class ReleaseInfo:
+ version: Version
+ release: GitRelease
+
+
+HERE = Path(__file__).resolve().parent
+NIXPKGS_KERNEL_PATH = HERE.parent
+NIXPKGS_PATH = HERE.parents[4]
+HARDENED_GITHUB_REPO = "anthraxx/linux-hardened"
+HARDENED_TRUSTED_KEY = HERE / "anthraxx.asc"
+HARDENED_PATCHES_PATH = HERE / "patches.json"
+MIN_KERNEL_VERSION: Version = [4, 14]
+
+
+def run(*args: Union[str, Path]) -> subprocess.CompletedProcess[bytes]:
+ try:
+ return subprocess.run(
+ args,
+ check=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ encoding="utf-8",
+ )
+ except subprocess.CalledProcessError as err:
+ print(
+ f"error: `{err.cmd}` failed unexpectedly\n"
+ f"status code: {err.returncode}\n"
+ f"stdout:\n{err.stdout.strip()}\n"
+ f"stderr:\n{err.stderr.strip()}",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+
+def nix_prefetch_url(url: str) -> Tuple[str, Path]:
+ output = run("nix-prefetch-url", "--print-path", url).stdout
+ sha256, path = output.strip().split("\n")
+ return sha256, Path(path)
+
+
+def verify_openpgp_signature(
+ *, name: str, trusted_key: Path, sig_path: Path, data_path: Path,
+) -> bool:
+ with TemporaryDirectory(suffix=".nixpkgs-gnupg-home") as gnupg_home_str:
+ gnupg_home = Path(gnupg_home_str)
+ run("gpg", "--homedir", gnupg_home, "--import", trusted_key)
+ keyring = gnupg_home / "pubring.kbx"
+ try:
+ subprocess.run(
+ ("gpgv", "--keyring", keyring, sig_path, data_path),
+ check=True,
+ stderr=subprocess.PIPE,
+ encoding="utf-8",
+ )
+ return True
+ except subprocess.CalledProcessError as err:
+ print(
+ f"error: signature for {name} failed to verify!",
+ file=sys.stderr,
+ )
+ print(err.stderr, file=sys.stderr, end="")
+ return False
+
+
+def fetch_patch(*, name: str, release: GitRelease) -> Optional[Patch]:
+ def find_asset(filename: str) -> str:
+ try:
+ it: Iterator[str] = (
+ asset.browser_download_url
+ for asset in release.get_assets()
+ if asset.name == filename
+ )
+ return next(it)
+ except StopIteration:
+ raise KeyError(filename)
+
+ patch_filename = f"{name}.patch"
+ try:
+ patch_url = find_asset(patch_filename)
+ sig_url = find_asset(patch_filename + ".sig")
+ except KeyError:
+ print(f"error: {patch_filename}{{,.sig}} not present", file=sys.stderr)
+ return None
+
+ sha256, patch_path = nix_prefetch_url(patch_url)
+ _, sig_path = nix_prefetch_url(sig_url)
+ sig_ok = verify_openpgp_signature(
+ name=name,
+ trusted_key=HARDENED_TRUSTED_KEY,
+ sig_path=sig_path,
+ data_path=patch_path,
+ )
+ if not sig_ok:
+ return None
+
+ return Patch(name=patch_filename, url=patch_url, sha256=sha256)
+
+
+def parse_version(version_str: str) -> Version:
+ version: Version = []
+ for component in version_str.split("."):
+ try:
+ version.append(int(component))
+ except ValueError:
+ version.append(component)
+ return version
+
+
+def version_string(version: Version) -> str:
+ return ".".join(str(component) for component in version)
+
+
+def major_kernel_version_key(kernel_version: Version) -> str:
+ return version_string(kernel_version[:-1])
+
+
+def commit_patches(*, kernel_key: str, message: str) -> None:
+ new_patches_path = HARDENED_PATCHES_PATH.with_suffix(".new")
+ with open(new_patches_path, "w") as new_patches_file:
+ json.dump(patches, new_patches_file, indent=4, sort_keys=True)
+ new_patches_file.write("\n")
+ os.rename(new_patches_path, HARDENED_PATCHES_PATH)
+ message = f"linux/hardened/patches/{kernel_key}: {message}"
+ print(message)
+ if os.environ.get("COMMIT"):
+ run(
+ "git",
+ "-C",
+ NIXPKGS_PATH,
+ "commit",
+ f"--message={message}",
+ HARDENED_PATCHES_PATH,
+ )
+
+
+# Load the existing patches.
+patches: Dict[str, Patch]
+with open(HARDENED_PATCHES_PATH) as patches_file:
+ patches = json.load(patches_file)
+
+# Get the set of currently packaged kernel versions.
+kernel_versions = {}
+for filename in os.listdir(NIXPKGS_KERNEL_PATH):
+ filename_match = re.fullmatch(r"linux-(\d+)\.(\d+)\.nix", filename)
+ if filename_match:
+ nix_version_expr = f"""
+ with import {NIXPKGS_PATH} {{}};
+ (callPackage {NIXPKGS_KERNEL_PATH / filename} {{}}).version
+ """
+ kernel_version_json = run(
+ "nix-instantiate", "--eval", "--json", "--expr", nix_version_expr,
+ ).stdout
+ kernel_version = parse_version(json.loads(kernel_version_json))
+ if kernel_version < MIN_KERNEL_VERSION:
+ continue
+ kernel_key = major_kernel_version_key(kernel_version)
+ kernel_versions[kernel_key] = kernel_version
+
+# Remove patches for unpackaged kernel versions.
+for kernel_key in sorted(patches.keys() - kernel_versions.keys()):
+ commit_patches(kernel_key=kernel_key, message="remove")
+
+g = Github(os.environ.get("GITHUB_TOKEN"))
+repo = g.get_repo(HARDENED_GITHUB_REPO)
+failures = False
+
+# Match each kernel version with the best patch version.
+releases = {}
+for release in repo.get_releases():
+ version = parse_version(release.tag_name)
+ # needs to look like e.g. 5.6.3.a
+ if len(version) < 4:
+ continue
+
+ kernel_version = version[:-1]
+ kernel_key = major_kernel_version_key(kernel_version)
+ try:
+ packaged_kernel_version = kernel_versions[kernel_key]
+ except KeyError:
+ continue
+
+ release_info = ReleaseInfo(version=version, release=release)
+
+ if kernel_version == packaged_kernel_version:
+ releases[kernel_key] = release_info
+ else:
+ # Fall back to the latest patch for this major kernel version,
+ # skipping patches for kernels newer than the packaged one.
+ if kernel_version > packaged_kernel_version:
+ continue
+ elif (
+ kernel_key not in releases or releases[kernel_key].version < version
+ ):
+ releases[kernel_key] = release_info
+
+# Update hardened-patches.json for each release.
+for kernel_key in sorted(releases.keys()):
+ release_info = releases[kernel_key]
+ release = release_info.release
+ version = release_info.version
+ version_str = release.tag_name
+ name = f"linux-hardened-{version_str}"
+
+ old_version: Optional[Version] = None
+ old_version_str: Optional[str] = None
+ update: bool
+ try:
+ old_filename = patches[kernel_key]["name"]
+ old_version_str = old_filename.replace("linux-hardened-", "").replace(
+ ".patch", ""
+ )
+ old_version = parse_version(old_version_str)
+ update = old_version < version
+ except KeyError:
+ update = True
+
+ if update:
+ patch = fetch_patch(name=name, release=release)
+ if patch is None:
+ failures = True
+ else:
+ patches[kernel_key] = patch
+ if old_version:
+ message = f"{old_version_str} -> {version_str}"
+ else:
+ message = f"init at {version_str}"
+ commit_patches(kernel_key=kernel_key, message=message)
+
+missing_kernel_versions = kernel_versions.keys() - patches.keys()
+
+if missing_kernel_versions:
+ print(
+ f"warning: no patches for kernel versions "
+ + ", ".join(missing_kernel_versions),
+ file=sys.stderr,
+ )
+
+if failures:
+ sys.exit(1)
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.14.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.14.nix
new file mode 100644
index 000000000000..26694d965e73
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.14.nix
@@ -0,0 +1,18 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, modDirVersionArg ? null, ... } @ args:
+
+with stdenv.lib;
+
+buildLinux (args // rec {
+ version = "4.14.210";
+
+ # modDirVersion needs to be x.y.z, will automatically add .0 if needed
+ modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg;
+
+ # branchVersion needs to be x.y
+ extraMeta.branch = versions.majorMinor version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz";
+ sha256 = "067xqi6sgf50p7s3n6y77cgf5bj5062s3bz3kqpp6f9wnk85267r";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.19.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.19.nix
new file mode 100644
index 000000000000..15a5e1972a64
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.19.nix
@@ -0,0 +1,18 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, modDirVersionArg ? null, ... } @ args:
+
+with stdenv.lib;
+
+buildLinux (args // rec {
+ version = "4.19.161";
+
+ # modDirVersion needs to be x.y.z, will automatically add .0 if needed
+ modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg;
+
+ # branchVersion needs to be x.y
+ extraMeta.branch = versions.majorMinor version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz";
+ sha256 = "0h9wskmz9wridwnicnjlcmj1112qnlvqk01bhjkxv6b8jsajjh87";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.4.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.4.nix
new file mode 100644
index 000000000000..599d68636200
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.4.nix
@@ -0,0 +1,11 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, ... } @ args:
+
+buildLinux (args // rec {
+ version = "4.4.247";
+ extraMeta.branch = "4.4";
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz";
+ sha256 = "1jh7vmyx55krk6y2r9v48liifs5wwkgns3gp8rs5sm4klfm36r2a";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.9.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.9.nix
new file mode 100644
index 000000000000..9169506536a7
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-4.9.nix
@@ -0,0 +1,11 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, ... } @ args:
+
+buildLinux (args // rec {
+ version = "4.9.247";
+ extraMeta.branch = "4.9";
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz";
+ sha256 = "1mngdbsq8pdzd0x9hif4715cc7wzc3ahgp1yrknnqk598q0fnfpp";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.4.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.4.nix
new file mode 100644
index 000000000000..8453ec0c6cb3
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.4.nix
@@ -0,0 +1,18 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, modDirVersionArg ? null, ... } @ args:
+
+with stdenv.lib;
+
+buildLinux (args // rec {
+ version = "5.4.81";
+
+ # modDirVersion needs to be x.y.z, will automatically add .0 if needed
+ modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg;
+
+ # branchVersion needs to be x.y
+ extraMeta.branch = versions.majorMinor version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz";
+ sha256 = "09w4bpr3v9rzcvxics5wddabplwbpk1mynl45lh9csbjfpjbsw4l";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.8.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.8.nix
new file mode 100644
index 000000000000..dd11359dbf41
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.8.nix
@@ -0,0 +1,18 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, modDirVersionArg ? null, ... } @ args:
+
+with stdenv.lib;
+
+buildLinux (args // rec {
+ version = "5.8.18";
+
+ # modDirVersion needs to be x.y.z, will automatically add .0 if needed
+ modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg;
+
+ # branchVersion needs to be x.y
+ extraMeta.branch = versions.majorMinor version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz";
+ sha256 = "0d2mm16mjyl2d734ak0lj8vd76h3r0san7l7g2zczd5pjkva7d2a";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.9.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.9.nix
new file mode 100644
index 000000000000..e71044b0d968
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-5.9.nix
@@ -0,0 +1,18 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, modDirVersionArg ? null, ... } @ args:
+
+with stdenv.lib;
+
+buildLinux (args // rec {
+ version = "5.9.12";
+
+ # modDirVersion needs to be x.y.z, will automatically add .0 if needed
+ modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) else modDirVersionArg;
+
+ # branchVersion needs to be x.y
+ extraMeta.branch = versions.majorMinor version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz";
+ sha256 = "1gfrn3sz3h4cbsf3r8f9jxja400qsmbrk8sclk4cjx1l5qcmczyr";
+ };
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-hardkernel-4.14.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-hardkernel-4.14.nix
new file mode 100644
index 000000000000..a272bd286f32
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-hardkernel-4.14.nix
@@ -0,0 +1,33 @@
+{ stdenv, buildPackages, fetchFromGitHub, perl, buildLinux, libelf, util-linux, ... } @ args:
+
+buildLinux (args // rec {
+ version = "4.14.165-172";
+
+ # modDirVersion needs to be x.y.z.
+ modDirVersion = "4.14.165";
+
+ # branchVersion needs to be x.y.
+ extraMeta.branch = "4.14";
+
+ src = fetchFromGitHub {
+ owner = "hardkernel";
+ repo = "linux";
+ rev = version;
+ sha256 = "10ayqjjs2hxj1q7sb0mxa3gv75q28lznjha19rpxvig2fpi8015s";
+ };
+
+ defconfig = "odroidxu4_defconfig";
+
+ # This extraConfig is (only) required because the gator module fails to build as-is.
+ extraConfig = ''
+
+ GATOR n
+
+ # This attempted fix applies correctly but does not fix the build.
+ #GATOR_MALI_MIDGARD_PATH ${src}/drivers/gpu/arm/midgard
+
+ '' + (args.extraConfig or "");
+
+ extraMeta.platforms = [ "armv7l-linux" ];
+
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix
new file mode 100644
index 000000000000..f0d362b02ce0
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix
@@ -0,0 +1,42 @@
+{ stdenv, lib, fetchsvn, linux
+, scripts ? fetchsvn {
+ url = "https://www.fsfla.org/svn/fsfla/software/linux-libre/releases/branches/";
+ rev = "17768";
+ sha256 = "0j85bjxylvl88xzf3nji1xadz3ws1kfbyhbn47haipigncvccndj";
+ }
+, ...
+}:
+
+let
+ majorMinor = lib.versions.majorMinor linux.modDirVersion;
+
+ major = lib.versions.major linux.modDirVersion;
+ minor = lib.versions.minor linux.modDirVersion;
+ patch = lib.versions.patch linux.modDirVersion;
+
+in linux.override {
+ argsOverride = {
+ modDirVersion = "${linux.modDirVersion}-gnu";
+ isLibre = true;
+
+ src = stdenv.mkDerivation {
+ name = "${linux.name}-libre-src";
+ src = linux.src;
+ buildPhase = ''
+ # --force flag to skip empty files after deblobbing
+ ${scripts}/${majorMinor}/deblob-${majorMinor} --force \
+ ${major} ${minor} ${patch}
+ '';
+ checkPhase = ''
+ ${scripts}/deblob-check
+ '';
+ installPhase = ''
+ cp -r . "$out"
+ '';
+ };
+
+ passthru.updateScript = ./update-libre.sh;
+
+ maintainers = [ lib.maintainers.qyliss ];
+ };
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-mptcp-95.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-mptcp-95.nix
new file mode 100644
index 000000000000..ad933ff63a7a
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-mptcp-95.nix
@@ -0,0 +1,27 @@
+{ stdenv, buildPackages, fetchFromGitHub, perl, buildLinux, structuredExtraConfig ? {}, ... } @ args:
+let
+ mptcpVersion = "0.95";
+ modDirVersion = "4.19.55";
+in
+buildLinux ({
+ version = "${modDirVersion}-mptcp_v${mptcpVersion}";
+ inherit modDirVersion;
+
+ extraMeta = {
+ branch = "4.19";
+ maintainers = with stdenv.lib.maintainers; [ teto layus ];
+ };
+
+ src = fetchFromGitHub {
+ owner = "multipath-tcp";
+ repo = "mptcp";
+ rev = "v${mptcpVersion}";
+ sha256 = "04a66iq5vsiz8mkpszfxmqknz7y4w3lsckrcz6q1syjpk0pdyiyw";
+ };
+
+ structuredExtraConfig = stdenv.lib.mkMerge [
+ (import ./mptcp-config.nix { inherit stdenv; })
+ structuredExtraConfig
+ ];
+
+} // args)
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rpi.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rpi.nix
new file mode 100644
index 000000000000..a3d2bfd4836c
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rpi.nix
@@ -0,0 +1,70 @@
+{ stdenv, lib, buildPackages, fetchFromGitHub, perl, buildLinux, rpiVersion, ... } @ args:
+
+let
+ modDirVersion = "4.19.118";
+ tag = "1.20200601";
+in
+lib.overrideDerivation (buildLinux (args // {
+ version = "${modDirVersion}-${tag}";
+ inherit modDirVersion;
+
+ src = fetchFromGitHub {
+ owner = "raspberrypi";
+ repo = "linux";
+ rev = "raspberrypi-kernel_${tag}-1";
+ sha256 = "11jzsmnd1qry2ir9vmsv0nfdzjpgkn5yab5ylxcz406plc073anp";
+ };
+
+ defconfig = {
+ "1" = "bcmrpi_defconfig";
+ "2" = "bcm2709_defconfig";
+ "3" = if stdenv.hostPlatform.isAarch64 then "bcmrpi3_defconfig" else "bcm2709_defconfig";
+ "4" = "bcm2711_defconfig";
+ }.${toString rpiVersion};
+
+ features = {
+ efiBootStub = false;
+ } // (args.features or {});
+
+ extraMeta = if (rpiVersion < 3) then {
+ platforms = with lib.platforms; [ arm ];
+ hydraPlatforms = [];
+ } else {
+ platforms = with lib.platforms; [ arm aarch64 ];
+ hydraPlatforms = [ "aarch64-linux" ];
+ };
+} // (args.argsOverride or {}))) (oldAttrs: {
+ postConfigure = ''
+ # The v7 defconfig has this set to '-v7' which screws up our modDirVersion.
+ sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
+ sed -i $buildRoot/include/config/auto.conf -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
+ '';
+
+ # Make copies of the DTBs named after the upstream names so that U-Boot finds them.
+ # This is ugly as heck, but I don't know a better solution so far.
+ postFixup = ''
+ dtbDir=${if stdenv.isAarch64 then "$out/dtbs/broadcom" else "$out/dtbs"}
+ rm $dtbDir/bcm283*.dtb
+ copyDTB() {
+ cp -v "$dtbDir/$1" "$dtbDir/$2"
+ }
+ '' + lib.optionalString (lib.elem stdenv.hostPlatform.system ["armv6l-linux"]) ''
+ copyDTB bcm2708-rpi-zero-w.dtb bcm2835-rpi-zero.dtb
+ copyDTB bcm2708-rpi-zero-w.dtb bcm2835-rpi-zero-w.dtb
+ copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-a.dtb
+ copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b.dtb
+ copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b-rev2.dtb
+ copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-a-plus.dtb
+ copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-b-plus.dtb
+ copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-zero.dtb
+ copyDTB bcm2708-rpi-cm.dtb bcm2835-rpi-cm.dtb
+ '' + lib.optionalString (lib.elem stdenv.hostPlatform.system ["armv7l-linux"]) ''
+ copyDTB bcm2709-rpi-2-b.dtb bcm2836-rpi-2-b.dtb
+ '' + lib.optionalString (lib.elem stdenv.hostPlatform.system ["armv7l-linux" "aarch64-linux"]) ''
+ copyDTB bcm2710-rpi-3-b.dtb bcm2837-rpi-3-b.dtb
+ copyDTB bcm2710-rpi-3-b-plus.dtb bcm2837-rpi-3-a-plus.dtb
+ copyDTB bcm2710-rpi-3-b-plus.dtb bcm2837-rpi-3-b-plus.dtb
+ copyDTB bcm2710-rpi-cm3.dtb bcm2837-rpi-cm3.dtb
+ copyDTB bcm2711-rpi-4-b.dtb bcm2838-rpi-4-b.dtb
+ '';
+})
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.4.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.4.nix
new file mode 100644
index 000000000000..3bb3ac7de27a
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.4.nix
@@ -0,0 +1,41 @@
+{ lib, buildLinux, fetchurl
+, kernelPatches ? [ ]
+, structuredExtraConfig ? {}
+, extraMeta ? {}
+, argsOverride ? {}
+, ... } @ args:
+
+let
+ version = "5.4.78-rt44"; # updated by ./update-rt.sh
+ branch = lib.versions.majorMinor version;
+ kversion = builtins.elemAt (lib.splitString "-" version) 0;
+in buildLinux (args // {
+ inherit version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v5.x/linux-${kversion}.tar.xz";
+ sha256 = "0z8skj0w9jfrz9pfxaqfzqh82l13bz5lhza2wjsxk02cyhhnm226";
+ };
+
+ kernelPatches = let rt-patch = {
+ name = "rt";
+ patch = fetchurl {
+ url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
+ sha256 = "0cvvk647cz7nckhyxrsvdnsc6hzhy09y3c1155xzhydiv5gxc56h";
+ };
+ }; in [ rt-patch ] ++ lib.remove rt-patch kernelPatches;
+
+ structuredExtraConfig = with lib.kernel; {
+ PREEMPT_RT = yes;
+ # Fix error: unused option: PREEMPT_RT.
+ EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
+ # Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
+ PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
+ # Fix error: unused option: RT_GROUP_SCHED.
+ RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
+ } // structuredExtraConfig;
+
+ extraMeta = extraMeta // {
+ inherit branch;
+ };
+} // argsOverride)
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.6.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.6.nix
new file mode 100644
index 000000000000..7c77454040d5
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-rt-5.6.nix
@@ -0,0 +1,41 @@
+{ lib, buildLinux, fetchurl
+, kernelPatches ? [ ]
+, structuredExtraConfig ? {}
+, extraMeta ? {}
+, argsOverride ? {}
+, ... } @ args:
+
+let
+ version = "5.6.19-rt12"; # updated by ./update-rt.sh
+ branch = lib.versions.majorMinor version;
+ kversion = builtins.elemAt (lib.splitString "-" version) 0;
+in buildLinux (args // {
+ inherit version;
+
+ src = fetchurl {
+ url = "mirror://kernel/linux/kernel/v5.x/linux-${kversion}.tar.xz";
+ sha256 = "1s0yc1138sglbm4vyizl4r7hnc1l7nykdjp4063ad67yayr2ylv2";
+ };
+
+ kernelPatches = let rt-patch = {
+ name = "rt";
+ patch = fetchurl {
+ url = "mirror://kernel/linux/kernel/projects/rt/${branch}/older/patch-${version}.patch.xz";
+ sha256 = "0ia8rx0615x0z2s4ppw1244crg7c5ak07c9n3wbnz7y8bk8hyxws";
+ };
+ }; in [ rt-patch ] ++ lib.remove rt-patch kernelPatches;
+
+ structuredExtraConfig = with lib.kernel; {
+ PREEMPT_RT = yes;
+ # Fix error: unused option: PREEMPT_RT.
+ EXPERT = yes; # PREEMPT_RT depends on it (in kernel/Kconfig.preempt)
+ # Fix error: option not set correctly: PREEMPT_VOLUNTARY (wanted 'y', got 'n').
+ PREEMPT_VOLUNTARY = lib.mkForce no; # PREEMPT_RT deselects it.
+ # Fix error: unused option: RT_GROUP_SCHED.
+ RT_GROUP_SCHED = lib.mkForce (option no); # Removed by sched-disable-rt-group-sched-on-rt.patch.
+ } // structuredExtraConfig;
+
+ extraMeta = extraMeta // {
+ inherit branch;
+ };
+} // argsOverride)
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix
new file mode 100644
index 000000000000..81dcb5d4563b
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing-bcachefs.nix
@@ -0,0 +1,23 @@
+{ stdenv, buildPackages, fetchFromGitHub, fetchpatch, perl, buildLinux, ... } @ args:
+
+buildLinux (args // {
+ version = "5.8.0-2020.09.07";
+ modDirVersion = "5.8.0";
+
+ src = fetchFromGitHub {
+ owner = "koverstreet";
+ repo = "bcachefs";
+ rev = "fb2821e72648f35d3cff61ac26041d634fd1dacf";
+ sha256 = "0f9hx6fz27rm8h1lk9868v727klvyzcbw6hcgm5mypbfq1nqirdy";
+ };
+
+ extraConfig = "BCACHEFS_FS m";
+
+ extraMeta = {
+ branch = "master";
+ hydraPlatforms = []; # Should the testing kernels ever be built on Hydra?
+ maintainers = with stdenv.lib.maintainers; [ davidak chiiruno ];
+ platforms = [ "x86_64-linux" ];
+ };
+
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing.nix
new file mode 100644
index 000000000000..5bf74ffd377b
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-testing.nix
@@ -0,0 +1,20 @@
+{ stdenv, buildPackages, fetchurl, perl, buildLinux, modDirVersionArg ? null, ... } @ args:
+
+with stdenv.lib;
+
+buildLinux (args // rec {
+ version = "5.10-rc6";
+ extraMeta.branch = "5.10";
+
+ # modDirVersion needs to be x.y.z, will always add .0
+ modDirVersion = if (modDirVersionArg == null) then builtins.replaceStrings ["-"] [".0-"] version else modDirVersionArg;
+
+ src = fetchurl {
+ url = "https://git.kernel.org/torvalds/t/linux-${version}.tar.gz";
+ sha256 = "14ykzs98r918sqv7lddlps4r7hza1zgw0x67mmj77cmqiv6d8ffi";
+ };
+
+ # Should the testing kernels ever be built on Hydra?
+ extraMeta.hydraPlatforms = [];
+
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-zen.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-zen.nix
new file mode 100644
index 000000000000..c4f08e568a03
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/linux-zen.nix
@@ -0,0 +1,24 @@
+{ stdenv, fetchFromGitHub, buildLinux, ... } @ args:
+
+let
+ version = "5.9.12";
+in
+
+buildLinux (args // {
+ modDirVersion = "${version}-zen1";
+ inherit version;
+ isZen = true;
+
+ src = fetchFromGitHub {
+ owner = "zen-kernel";
+ repo = "zen-kernel";
+ rev = "v${version}-zen1";
+ sha256 = "07cmcw8ib9wc4im08pbmxhj187lhsfxh2asn4jdxadxxq3f60h6w";
+ };
+
+ extraMeta = {
+ branch = "5.9/master";
+ maintainers = with stdenv.lib.maintainers; [ atemu andresilva ];
+ };
+
+} // (args.argsOverride or {}))
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mac-nvme-t2.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mac-nvme-t2.patch
new file mode 100644
index 000000000000..2f1fa6a0daec
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mac-nvme-t2.patch
@@ -0,0 +1,283 @@
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index dd10cf78f2d3..8f006638452b 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -28,8 +28,8 @@
+ #include "trace.h"
+ #include "nvme.h"
+
+-#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
+-#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion))
++#define SQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_command))
++#define CQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_completion))
+
+ #define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc))
+
+@@ -1344,16 +1344,16 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
+
+ static void nvme_free_queue(struct nvme_queue *nvmeq)
+ {
+- dma_free_coherent(nvmeq->dev->dev, CQ_SIZE(nvmeq->q_depth),
++ dma_free_coherent(nvmeq->dev->dev, CQ_SIZE(nvmeq),
+ (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+ if (!nvmeq->sq_cmds)
+ return;
+
+ if (test_and_clear_bit(NVMEQ_SQ_CMB, &nvmeq->flags)) {
+ pci_free_p2pmem(to_pci_dev(nvmeq->dev->dev),
+- nvmeq->sq_cmds, SQ_SIZE(nvmeq->q_depth));
++ nvmeq->sq_cmds, SQ_SIZE(nvmeq));
+ } else {
+- dma_free_coherent(nvmeq->dev->dev, SQ_SIZE(nvmeq->q_depth),
++ dma_free_coherent(nvmeq->dev->dev, SQ_SIZE(nvmeq),
+ nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+ }
+ }
+@@ -1433,12 +1433,12 @@ static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues,
+ }
+
+ static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
+- int qid, int depth)
++ int qid)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+ if (qid && dev->cmb_use_sqes && (dev->cmbsz & NVME_CMBSZ_SQS)) {
+- nvmeq->sq_cmds = pci_alloc_p2pmem(pdev, SQ_SIZE(depth));
++ nvmeq->sq_cmds = pci_alloc_p2pmem(pdev, SQ_SIZE(nvmeq));
+ if (nvmeq->sq_cmds) {
+ nvmeq->sq_dma_addr = pci_p2pmem_virt_to_bus(pdev,
+ nvmeq->sq_cmds);
+@@ -1447,11 +1447,11 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
+ return 0;
+ }
+
+- pci_free_p2pmem(pdev, nvmeq->sq_cmds, SQ_SIZE(depth));
++ pci_free_p2pmem(pdev, nvmeq->sq_cmds, SQ_SIZE(nvmeq));
+ }
+ }
+
+- nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth),
++ nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(nvmeq),
+ &nvmeq->sq_dma_addr, GFP_KERNEL);
+ if (!nvmeq->sq_cmds)
+ return -ENOMEM;
+@@ -1465,12 +1465,13 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
+ if (dev->ctrl.queue_count > qid)
+ return 0;
+
+- nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(depth),
++ nvmeq->q_depth = depth;
++ nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(nvmeq),
+ &nvmeq->cq_dma_addr, GFP_KERNEL);
+ if (!nvmeq->cqes)
+ goto free_nvmeq;
+
+- if (nvme_alloc_sq_cmds(dev, nvmeq, qid, depth))
++ if (nvme_alloc_sq_cmds(dev, nvmeq, qid))
+ goto free_cqdma;
+
+ nvmeq->dev = dev;
+@@ -1479,15 +1480,14 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
+ nvmeq->cq_head = 0;
+ nvmeq->cq_phase = 1;
+ nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
+- nvmeq->q_depth = depth;
+ nvmeq->qid = qid;
+ dev->ctrl.queue_count++;
+
+ return 0;
+
+ free_cqdma:
+- dma_free_coherent(dev->dev, CQ_SIZE(depth), (void *)nvmeq->cqes,
+- nvmeq->cq_dma_addr);
++ dma_free_coherent(dev->dev, CQ_SIZE(nvmeq), (void *)nvmeq->cqes,
++ nvmeq->cq_dma_addr);
+ free_nvmeq:
+ return -ENOMEM;
+ }
+@@ -1515,7 +1515,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
+ nvmeq->cq_head = 0;
+ nvmeq->cq_phase = 1;
+ nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
+- memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq->q_depth));
++ memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq));
+ nvme_dbbuf_init(dev, nvmeq, qid);
+ dev->online_queues++;
+ wmb(); /* ensure the first interrupt sees the initialization */
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index cc09b81fc7f4..716ebe87a2b8 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -1986,6 +1986,7 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl, u64 cap)
+ ctrl->ctrl_config = NVME_CC_CSS_NVM;
+ ctrl->ctrl_config |= (page_shift - 12) << NVME_CC_MPS_SHIFT;
+ ctrl->ctrl_config |= NVME_CC_AMS_RR | NVME_CC_SHN_NONE;
++ /* Use default IOSQES. We'll update it later if needed */
+ ctrl->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
+ ctrl->ctrl_config |= NVME_CC_ENABLE;
+
+@@ -2698,6 +2699,30 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
+ ctrl->hmmin = le32_to_cpu(id->hmmin);
+ ctrl->hmminds = le32_to_cpu(id->hmminds);
+ ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
++
++ /* Grab required IO queue size */
++ ctrl->iosqes = id->sqes & 0xf;
++ if (ctrl->iosqes < NVME_NVM_IOSQES) {
++ dev_err(ctrl->device,
++ "unsupported required IO queue size %d\n", ctrl->iosqes);
++ ret = -EINVAL;
++ goto out_free;
++ }
++ /*
++ * If our IO queue size isn't the default, update the setting
++ * in CC:IOSQES.
++ */
++ if (ctrl->iosqes != NVME_NVM_IOSQES) {
++ ctrl->ctrl_config &= ~(0xfu << NVME_CC_IOSQES_SHIFT);
++ ctrl->ctrl_config |= ctrl->iosqes << NVME_CC_IOSQES_SHIFT;
++ ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC,
++ ctrl->ctrl_config);
++ if (ret) {
++ dev_err(ctrl->device,
++ "error updating CC register\n");
++ goto out_free;
++ }
++ }
+ }
+
+ ret = nvme_mpath_init(ctrl, id);
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index 716a876119c8..34ef35fcd8a5 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -244,6 +244,7 @@ struct nvme_ctrl {
+ u32 hmmin;
+ u32 hmminds;
+ u16 hmmaxd;
++ u8 iosqes;
+
+ /* Fabrics only */
+ u16 sqsize;
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 8f006638452b..54b35ea4af88 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -28,7 +28,7 @@
+ #include "trace.h"
+ #include "nvme.h"
+
+-#define SQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_command))
++#define SQ_SIZE(q) ((q)->q_depth << (q)->sqes)
+ #define CQ_SIZE(q) ((q)->q_depth * sizeof(struct nvme_completion))
+
+ #define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc))
+@@ -162,7 +162,7 @@ static inline struct nvme_dev *to_nvme_dev(struct nvme_ctrl *ctrl)
+ struct nvme_queue {
+ struct nvme_dev *dev;
+ spinlock_t sq_lock;
+- struct nvme_command *sq_cmds;
++ void *sq_cmds;
+ /* only used for poll queues: */
+ spinlock_t cq_poll_lock ____cacheline_aligned_in_smp;
+ volatile struct nvme_completion *cqes;
+@@ -178,6 +178,7 @@ struct nvme_queue {
+ u16 last_cq_head;
+ u16 qid;
+ u8 cq_phase;
++ u8 sqes;
+ unsigned long flags;
+ #define NVMEQ_ENABLED 0
+ #define NVMEQ_SQ_CMB 1
+@@ -488,7 +489,8 @@ static void nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd,
+ bool write_sq)
+ {
+ spin_lock(&nvmeq->sq_lock);
+- memcpy(&nvmeq->sq_cmds[nvmeq->sq_tail], cmd, sizeof(*cmd));
++ memcpy(nvmeq->sq_cmds + (nvmeq->sq_tail << nvmeq->sqes),
++ cmd, sizeof(*cmd));
+ if (++nvmeq->sq_tail == nvmeq->q_depth)
+ nvmeq->sq_tail = 0;
+ nvme_write_sq_db(nvmeq, write_sq);
+@@ -1465,6 +1467,7 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
+ if (dev->ctrl.queue_count > qid)
+ return 0;
+
++ nvmeq->sqes = qid ? dev->ctrl.iosqes : NVME_NVM_ADMSQES;
+ nvmeq->q_depth = depth;
+ nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(nvmeq),
+ &nvmeq->cq_dma_addr, GFP_KERNEL);
+diff --git a/include/linux/nvme.h b/include/linux/nvme.h
+index 01aa6a6c241d..7af18965fb57 100644
+--- a/include/linux/nvme.h
++++ b/include/linux/nvme.h
+@@ -141,6 +141,7 @@ enum {
+ * (In bytes and specified as a power of two (2^n)).
+ */
+ #define NVME_NVM_IOSQES 6
++#define NVME_NVM_ADMSQES 6
+ #define NVME_NVM_IOCQES 4
+
+ enum {
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 716ebe87a2b8..480ea24d8cf4 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -2701,7 +2701,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
+ ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
+
+ /* Grab required IO queue size */
+- ctrl->iosqes = id->sqes & 0xf;
++ if (ctrl->quirks & NVME_QUIRK_128_BYTES_SQES)
++ ctrl->iosqes = 7;
++ else
++ ctrl->iosqes = id->sqes & 0xf;
+ if (ctrl->iosqes < NVME_NVM_IOSQES) {
+ dev_err(ctrl->device,
+ "unsupported required IO queue size %d\n", ctrl->iosqes);
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index 34ef35fcd8a5..b2a78d08b984 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -92,6 +92,16 @@ enum nvme_quirks {
+ * Broken Write Zeroes.
+ */
+ NVME_QUIRK_DISABLE_WRITE_ZEROES = (1 << 9),
++
++ /*
++ * Use only one interrupt vector for all queues
++ */
++ NVME_QUIRK_SINGLE_VECTOR = (1 << 10),
++
++ /*
++ * Use non-standard 128 bytes SQEs.
++ */
++ NVME_QUIRK_128_BYTES_SQES = (1 << 11),
+ };
+
+ /*
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 54b35ea4af88..ab2358137419 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -2080,6 +2080,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
+ dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
+ dev->io_queues[HCTX_TYPE_READ] = 0;
+
++ if (dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)
++ irq_queues = 1;
++
+ return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
+ PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
+ }
+@@ -3037,6 +3040,9 @@ static const struct pci_device_id nvme_id_table[] = {
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
++ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005),
++ .driver_data = NVME_QUIRK_SINGLE_VECTOR |
++ NVME_QUIRK_128_BYTES_SQES },
+ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, nvme_id_table);
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/manual-config.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/manual-config.nix
new file mode 100644
index 000000000000..3bdb8c4f2973
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/manual-config.nix
@@ -0,0 +1,323 @@
+{ buildPackages, runCommand, nettools, bc, bison, flex, perl, rsync, gmp, libmpc, mpfr, openssl
+, libelf, cpio, elfutils
+, writeTextFile
+}:
+
+let
+ readConfig = configfile: import (runCommand "config.nix" {} ''
+ echo "{" > "$out"
+ while IFS='=' read key val; do
+ [ "x''${key#CONFIG_}" != "x$key" ] || continue
+ no_firstquote="''${val#\"}";
+ echo ' "'"$key"'" = "'"''${no_firstquote%\"}"'";' >> "$out"
+ done < "${configfile}"
+ echo "}" >> $out
+ '').outPath;
+in {
+ # Allow overriding stdenv on each buildLinux call
+ stdenv,
+ # The kernel version
+ version,
+ # The version of the kernel module directory
+ modDirVersion ? version,
+ # The kernel source (tarball, git checkout, etc.)
+ src,
+ # a list of { name=..., patch=..., extraConfig=...} patches
+ kernelPatches ? [],
+ # The kernel .config file
+ configfile,
+ # Manually specified nixexpr representing the config
+ # If unspecified, this will be autodetected from the .config
+ config ? stdenv.lib.optionalAttrs allowImportFromDerivation (readConfig configfile),
+ # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
+ # automatically extended with extra per-version and per-config values.
+ randstructSeed ? "",
+ # Use defaultMeta // extraMeta
+ extraMeta ? {},
+
+ # for module compatibility
+ isXen ? features.xen_dom0 or false,
+ isZen ? false,
+ isLibre ? false,
+ isHardened ? false,
+
+ # Whether to utilize the controversial import-from-derivation feature to parse the config
+ allowImportFromDerivation ? false,
+ # ignored
+ features ? null,
+}:
+
+let
+ inherit (stdenv.lib)
+ hasAttr getAttr optional optionals optionalString optionalAttrs maintainers platforms;
+
+ # Dependencies that are required to build kernel modules
+ moduleBuildDependencies = optional (stdenv.lib.versionAtLeast version "4.14") libelf;
+
+ installkernel = writeTextFile { name = "installkernel"; executable=true; text = ''
+ #!${stdenv.shell} -e
+ mkdir -p $4
+ cp -av $2 $4
+ cp -av $3 $4
+ ''; };
+
+ commonMakeFlags = [
+ "O=$(buildRoot)"
+ ] ++ stdenv.lib.optionals (stdenv.hostPlatform.platform ? kernelMakeFlags)
+ stdenv.hostPlatform.platform.kernelMakeFlags;
+
+ drvAttrs = config_: platform: kernelPatches: configfile:
+ let
+ config = let attrName = attr: "CONFIG_" + attr; in {
+ isSet = attr: hasAttr (attrName attr) config;
+
+ getValue = attr: if config.isSet attr then getAttr (attrName attr) config else null;
+
+ isYes = attr: (config.getValue attr) == "y";
+
+ isNo = attr: (config.getValue attr) == "n";
+
+ isModule = attr: (config.getValue attr) == "m";
+
+ isEnabled = attr: (config.isModule attr) || (config.isYes attr);
+
+ isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
+ } // config_;
+
+ isModular = config.isYes "MODULES";
+
+ installsFirmware = (config.isEnabled "FW_LOADER") &&
+ (isModular || (config.isDisabled "FIRMWARE_IN_KERNEL")) &&
+ (stdenv.lib.versionOlder version "4.14");
+ in (optionalAttrs isModular { outputs = [ "out" "dev" ]; }) // {
+ passthru = {
+ inherit version modDirVersion config kernelPatches configfile
+ moduleBuildDependencies stdenv;
+ inherit isXen isZen isHardened isLibre;
+ kernelOlder = stdenv.lib.versionOlder version;
+ kernelAtLeast = stdenv.lib.versionAtLeast version;
+ };
+
+ inherit src;
+
+ patches =
+ map (p: p.patch) kernelPatches
+ # Required for deterministic builds along with some postPatch magic.
+ ++ optional (stdenv.lib.versionAtLeast version "4.13") ./randstruct-provide-seed.patch
+ # Fixes determinism by normalizing metadata for the archive of kheaders
+ ++ optional (stdenv.lib.versionAtLeast version "5.2" && stdenv.lib.versionOlder version "5.4") ./gen-kheaders-metadata.patch;
+
+ prePatch = ''
+ for mf in $(find -name Makefile -o -name Makefile.include -o -name install.sh); do
+ echo "stripping FHS paths in \`$mf'..."
+ sed -i "$mf" -e 's|/usr/bin/||g ; s|/bin/||g ; s|/sbin/||g'
+ done
+ sed -i Makefile -e 's|= depmod|= ${buildPackages.kmod}/bin/depmod|'
+ sed -i scripts/ld-version.sh -e "s|/usr/bin/awk|${buildPackages.gawk}/bin/awk|"
+ '';
+
+ postPatch = ''
+ # Set randstruct seed to a deterministic but diversified value. Note:
+ # we could have instead patched gen-random-seed.sh to take input from
+ # the buildFlags, but that would require also patching the kernel's
+ # toplevel Makefile to add a variable export. This would be likely to
+ # cause future patch conflicts.
+ if [ -f scripts/gcc-plugins/gen-random-seed.sh ]; then
+ substituteInPlace scripts/gcc-plugins/gen-random-seed.sh \
+ --replace NIXOS_RANDSTRUCT_SEED \
+ $(echo ${randstructSeed}${src} ${configfile} | sha256sum | cut -d ' ' -f 1 | tr -d '\n')
+ fi
+ '';
+
+ configurePhase = ''
+ runHook preConfigure
+
+ mkdir build
+ export buildRoot="$(pwd)/build"
+
+ echo "manual-config configurePhase buildRoot=$buildRoot pwd=$PWD"
+
+ if [ -f "$buildRoot/.config" ]; then
+ echo "Could not link $buildRoot/.config : file exists"
+ exit 1
+ fi
+ ln -sv ${configfile} $buildRoot/.config
+
+ # reads the existing .config file and prompts the user for options in
+ # the current kernel source that are not found in the file.
+ make $makeFlags "''${makeFlagsArray[@]}" oldconfig
+ runHook postConfigure
+
+ make $makeFlags "''${makeFlagsArray[@]}" prepare
+ actualModDirVersion="$(cat $buildRoot/include/config/kernel.release)"
+ if [ "$actualModDirVersion" != "${modDirVersion}" ]; then
+ echo "Error: modDirVersion ${modDirVersion} specified in the Nix expression is wrong, it should be: $actualModDirVersion"
+ exit 1
+ fi
+
+ # Note: we can get rid of this once http://permalink.gmane.org/gmane.linux.kbuild.devel/13800 is merged.
+ buildFlagsArray+=("KBUILD_BUILD_TIMESTAMP=$(date -u -d @$SOURCE_DATE_EPOCH)")
+
+ cd $buildRoot
+ '';
+
+ buildFlags = [
+ "KBUILD_BUILD_VERSION=1-NixOS"
+ platform.kernelTarget
+ "vmlinux" # for "perf" and things like that
+ ] ++ optional isModular "modules";
+
+ installFlags = [
+ "INSTALLKERNEL=${installkernel}"
+ "INSTALL_PATH=$(out)"
+ ] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
+ ++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware";
+
+ preInstall = ''
+ installFlagsArray+=("-j$NIX_BUILD_CORES")
+ '';
+
+ # Some image types need special install targets (e.g. uImage is installed with make uinstall)
+ installTargets = [ (
+ if platform ? kernelInstallTarget then platform.kernelInstallTarget
+ else if platform.kernelTarget == "uImage" then "uinstall"
+ else if platform.kernelTarget == "zImage" || platform.kernelTarget == "Image.gz" then "zinstall"
+ else "install"
+ ) ];
+
+ postInstall = (optionalString installsFirmware ''
+ mkdir -p $out/lib/firmware
+ '') + (if (platform ? kernelDTB && platform.kernelDTB) then ''
+ make $makeFlags "''${makeFlagsArray[@]}" dtbs dtbs_install INSTALL_DTBS_PATH=$out/dtbs
+ '' else "") + (if isModular then ''
+ mkdir -p $dev
+ cp vmlinux $dev/
+ if [ -z "''${dontStrip-}" ]; then
+ installFlagsArray+=("INSTALL_MOD_STRIP=1")
+ fi
+ make modules_install $makeFlags "''${makeFlagsArray[@]}" \
+ $installFlags "''${installFlagsArray[@]}"
+ unlink $out/lib/modules/${modDirVersion}/build
+ unlink $out/lib/modules/${modDirVersion}/source
+
+ mkdir -p $dev/lib/modules/${modDirVersion}/{build,source}
+
+ # To save space, exclude a bunch of unneeded stuff when copying.
+ (cd .. && rsync --archive --prune-empty-dirs \
+ --exclude='/build/' \
+ * $dev/lib/modules/${modDirVersion}/source/)
+
+ cd $dev/lib/modules/${modDirVersion}/source
+
+ cp $buildRoot/{.config,Module.symvers} $dev/lib/modules/${modDirVersion}/build
+ make modules_prepare $makeFlags "''${makeFlagsArray[@]}" O=$dev/lib/modules/${modDirVersion}/build
+
+ # For reproducibility, removes accidental leftovers from a `cc1` call
+ # from a `try-run` call from the Makefile
+ rm -f $dev/lib/modules/${modDirVersion}/build/.[0-9]*.d
+
+ # Keep some extra files on some arches (powerpc, aarch64)
+ for f in arch/powerpc/lib/crtsavres.o arch/arm64/kernel/ftrace-mod.o; do
+ if [ -f "$buildRoot/$f" ]; then
+ cp $buildRoot/$f $dev/lib/modules/${modDirVersion}/build/$f
+ fi
+ done
+
+ # !!! No documentation on how much of the source tree must be kept
+ # If/when kernel builds fail due to missing files, you can add
+ # them here. Note that we may see packages requiring headers
+ # from drivers/ in the future; it adds 50M to keep all of its
+ # headers on 3.10 though.
+
+ chmod u+w -R ..
+ arch=$(cd $dev/lib/modules/${modDirVersion}/build/arch; ls)
+
+ # Remove unused arches
+ for d in $(cd arch/; ls); do
+ if [ "$d" = "$arch" ]; then continue; fi
+ if [ "$arch" = arm64 ] && [ "$d" = arm ]; then continue; fi
+ rm -rf arch/$d
+ done
+
+ # Remove all driver-specific code (50M of which is headers)
+ rm -fR drivers
+
+ # Keep all headers
+ find . -type f -name '*.h' -print0 | xargs -0 -r chmod u-w
+
+ # Keep linker scripts (they are required for out-of-tree modules on aarch64)
+ find . -type f -name '*.lds' -print0 | xargs -0 -r chmod u-w
+
+ # Keep root and arch-specific Makefiles
+ chmod u-w Makefile
+ chmod u-w arch/$arch/Makefile*
+
+ # Keep whole scripts dir
+ chmod u-w -R scripts
+
+ # Delete everything not kept
+ find . -type f -perm -u=w -print0 | xargs -0 -r rm
+
+ # Delete empty directories
+ find -empty -type d -delete
+
+ # Remove reference to kmod
+ sed -i Makefile -e 's|= ${buildPackages.kmod}/bin/depmod|= depmod|'
+ '' else optionalString installsFirmware ''
+ make firmware_install $makeFlags "''${makeFlagsArray[@]}" \
+ $installFlags "''${installFlagsArray[@]}"
+ '');
+
+ requiredSystemFeatures = [ "big-parallel" ];
+
+ meta = {
+ description =
+ "The Linux kernel" +
+ (if kernelPatches == [] then "" else
+ " (with patches: "
+ + stdenv.lib.concatStringsSep ", " (map (x: x.name) kernelPatches)
+ + ")");
+ license = stdenv.lib.licenses.gpl2;
+ homepage = "https://www.kernel.org/";
+ repositories.git = "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git";
+ maintainers = [
+ maintainers.thoughtpolice
+ ];
+ platforms = platforms.linux;
+ timeout = 14400; # 4 hours
+ } // extraMeta;
+ };
+in
+
+assert (stdenv.lib.versionAtLeast version "4.14" && stdenv.lib.versionOlder version "5.8") -> libelf != null;
+assert stdenv.lib.versionAtLeast version "5.8" -> elfutils != null;
+
+stdenv.mkDerivation ((drvAttrs config stdenv.hostPlatform.platform kernelPatches configfile) // {
+ pname = "linux";
+ inherit version;
+
+ enableParallelBuilding = true;
+
+ depsBuildBuild = [ buildPackages.stdenv.cc ];
+ nativeBuildInputs = [ perl bc nettools openssl rsync gmp libmpc mpfr ]
+ ++ optional (stdenv.hostPlatform.platform.kernelTarget == "uImage") buildPackages.ubootTools
+ ++ optional (stdenv.lib.versionAtLeast version "4.14" && stdenv.lib.versionOlder version "5.8") libelf
+ # Removed util-linuxMinimal since it should not be a dependency.
+ ++ optionals (stdenv.lib.versionAtLeast version "4.16") [ bison flex ]
+ ++ optional (stdenv.lib.versionAtLeast version "5.2") cpio
+ ++ optional (stdenv.lib.versionAtLeast version "5.8") elfutils
+ ;
+
+ hardeningDisable = [ "bindnow" "format" "fortify" "stackprotector" "pic" "pie" ];
+
+ # Absolute paths for compilers avoid any PATH-clobbering issues.
+ makeFlags = commonMakeFlags ++ [
+ "CC=${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"
+ "HOSTCC=${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc"
+ "ARCH=${stdenv.hostPlatform.platform.kernelArch}"
+ ] ++ stdenv.lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) [
+ "CROSS_COMPILE=${stdenv.cc.targetPrefix}"
+ ];
+
+ karch = stdenv.hostPlatform.platform.kernelArch;
+})
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/modinst-arg-list-too-long.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/modinst-arg-list-too-long.patch
new file mode 100644
index 000000000000..58a9191989ae
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/modinst-arg-list-too-long.patch
@@ -0,0 +1,14 @@
+diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
+index 07650ee..934a7a8 100644
+--- a/scripts/Makefile.modinst
++++ b/scripts/Makefile.modinst
+@@ -9,7 +9,8 @@ include scripts/Kbuild.include
+
+ #
+
+-__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
++__modules := $(sort $(foreach f,$(wildcard $(MODVERDIR)/*.mod),$(shell \
++ grep -h '\.ko$$' '$f')))
+ modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
+
+ PHONY += $(modules)
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mptcp-config.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mptcp-config.nix
new file mode 100644
index 000000000000..9752e63d9f94
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/mptcp-config.nix
@@ -0,0 +1,28 @@
+{ stdenv }:
+with stdenv.lib.kernel;
+{
+ # DRM_AMDGPU = yes;
+
+ IPV6 = yes;
+ MPTCP = yes;
+ IP_MULTIPLE_TABLES = yes;
+
+ # Enable advanced path-managers...
+ MPTCP_PM_ADVANCED = yes;
+ MPTCP_FULLMESH = yes;
+ MPTCP_NDIFFPORTS = yes;
+ # ... but use none by default.
+ # The default is safer if source policy routing is not setup.
+ DEFAULT_DUMMY = yes;
+ DEFAULT_MPTCP_PM.freeform = "default";
+
+ # MPTCP scheduler selection.
+ MPTCP_SCHED_ADVANCED = yes;
+ DEFAULT_MPTCP_SCHED.freeform = "default";
+
+ # Smarter TCP congestion controllers
+ TCP_CONG_LIA = module;
+ TCP_CONG_OLIA = module;
+ TCP_CONG_WVEGAS = module;
+ TCP_CONG_BALIA = module;
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/p9-fixes.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/p9-fixes.patch
new file mode 100644
index 000000000000..f6061b60667a
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/p9-fixes.patch
@@ -0,0 +1,85 @@
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -483,6 +483,9 @@ static int v9fs_test_inode(struct inode *inode, void *data)
+
+ if (v9inode->qid.type != st->qid.type)
+ return 0;
++
++ if (v9inode->qid.path != st->qid.path)
++ return 0;
+ return 1;
+ }
+
+diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
+--- a/fs/9p/vfs_inode_dotl.c
++++ b/fs/9p/vfs_inode_dotl.c
+@@ -87,6 +87,9 @@ static int v9fs_test_inode_dotl(struct inode *inode, void *data)
+
+ if (v9inode->qid.type != st->qid.type)
+ return 0;
++
++ if (v9inode->qid.path != st->qid.path)
++ return 0;
+ return 1;
+ }
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 3ce672af1596..f1c8ad373f90 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -749,8 +749,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
+ }
+ again:
+ /* Wait for the response */
+- err = wait_event_interruptible(*req->wq,
+- req->status >= REQ_STATUS_RCVD);
++ err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD);
+
+ /*
+ * Make sure our req is coherent with regard to updates in other
+diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
+index f24b25c25106..f3a4efcf1456 100644
+--- a/net/9p/trans_virtio.c
++++ b/net/9p/trans_virtio.c
+@@ -286,8 +286,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
+ if (err == -ENOSPC) {
+ chan->ring_bufs_avail = 0;
+ spin_unlock_irqrestore(&chan->lock, flags);
+- err = wait_event_interruptible(*chan->vc_wq,
+- chan->ring_bufs_avail);
++ err = wait_event_killable(*chan->vc_wq,
++ chan->ring_bufs_avail);
+ if (err == -ERESTARTSYS)
+ return err;
+
+@@ -327,7 +327,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
+ * Other zc request to finish here
+ */
+ if (atomic_read(&vp_pinned) >= chan->p9_max_pages) {
+- err = wait_event_interruptible(vp_wq,
++ err = wait_event_killable(vp_wq,
+ (atomic_read(&vp_pinned) < chan->p9_max_pages));
+ if (err == -ERESTARTSYS)
+ return err;
+@@ -471,8 +471,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+ if (err == -ENOSPC) {
+ chan->ring_bufs_avail = 0;
+ spin_unlock_irqrestore(&chan->lock, flags);
+- err = wait_event_interruptible(*chan->vc_wq,
+- chan->ring_bufs_avail);
++ err = wait_event_killable(*chan->vc_wq,
++ chan->ring_bufs_avail);
+ if (err == -ERESTARTSYS)
+ goto err_out;
+
+@@ -489,8 +489,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
+ virtqueue_kick(chan->vq);
+ spin_unlock_irqrestore(&chan->lock, flags);
+ p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n");
+- err = wait_event_interruptible(*req->wq,
+- req->status >= REQ_STATUS_RCVD);
++ err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD);
+ /*
+ * Non kernel buffers are pinned, unpin them
+ */
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/patches.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/patches.nix
new file mode 100644
index 000000000000..8ce1ac2b587c
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/patches.nix
@@ -0,0 +1,95 @@
+{ lib, fetchpatch, fetchurl }:
+
+{
+ bridge_stp_helper =
+ { name = "bridge-stp-helper";
+ patch = ./bridge-stp-helper.patch;
+ };
+
+ request_key_helper =
+ { name = "request-key-helper";
+ patch = ./request-key-helper.patch;
+ };
+
+ request_key_helper_updated =
+ { name = "request-key-helper-updated";
+ patch = ./request-key-helper-updated.patch;
+ };
+
+ p9_fixes =
+ { name = "p9-fixes";
+ patch = ./p9-fixes.patch;
+ };
+
+ modinst_arg_list_too_long =
+ { name = "modinst-arglist-too-long";
+ patch = ./modinst-arg-list-too-long.patch;
+ };
+
+ genksyms_fix_segfault =
+ { name = "genksyms-fix-segfault";
+ patch = ./genksyms-fix-segfault.patch;
+ };
+
+ cpu-cgroup-v2 = import ./cpu-cgroup-v2-patches;
+
+ tag_hardened = {
+ name = "tag-hardened";
+ patch = ./hardened/tag-hardened.patch;
+ };
+
+ hardened = let
+ mkPatch = kernelVersion: src: {
+ name = lib.removeSuffix ".patch" src.name;
+ patch = fetchurl src;
+ };
+ patches = builtins.fromJSON (builtins.readFile ./hardened/patches.json);
+ in lib.mapAttrs mkPatch patches;
+
+ # https://bugzilla.kernel.org/show_bug.cgi?id=197591#c6
+ iwlwifi_mvm_support_version_7_scan_req_umac_fw_command = rec {
+ name = "iwlwifi_mvm_support_version_7_scan_req_umac_fw_command";
+ patch = fetchpatch {
+ name = name + ".patch";
+ url = "https://bugzilla.kernel.org/attachment.cgi?id=260597";
+ sha256 = "09096npxpgvlwdz3pb3m9brvxh7vy0xc9z9p8hh85xyczyzcsjhr";
+ };
+ };
+
+ # https://github.com/NixOS/nixpkgs/issues/42755
+ xen-netfront_fix_mismatched_rtnl_unlock = rec {
+ name = "xen-netfront_fix_mismatched_rtnl_unlock";
+ patch = fetchpatch {
+ name = name + ".patch";
+ url = "https://github.com/torvalds/linux/commit/cb257783c2927b73614b20f915a91ff78aa6f3e8.patch";
+ sha256 = "0xhblx2j8wi3kpnfpgjjwlcwdry97ji2aaq54r3zirk5g5p72zs8";
+ };
+ };
+
+ # https://github.com/NixOS/nixpkgs/issues/42755
+ xen-netfront_update_features_after_registering_netdev = rec {
+ name = "xen-netfront_update_features_after_registering_netdev";
+ patch = fetchpatch {
+ name = name + ".patch";
+ url = "https://github.com/torvalds/linux/commit/45c8184c1bed1ca8a7f02918552063a00b909bf5.patch";
+ sha256 = "1l8xq02rd7vakxg52xm9g4zng0ald866rpgm8kjlh88mwwyjkrwv";
+ };
+ };
+
+ export_kernel_fpu_functions = {
+ "4.14" = {
+ name = "export_kernel_fpu_functions";
+ patch = ./export_kernel_fpu_functions_4_14.patch;
+ };
+ "5.3" = {
+ name = "export_kernel_fpu_functions";
+ patch = ./export_kernel_fpu_functions_5_3.patch;
+ };
+ };
+
+ # patches from https://lkml.org/lkml/2019/7/15/1748
+ mac_nvme_t2 = rec {
+ name = "mac_nvme_t2";
+ patch = ./mac-nvme-t2.patch;
+ };
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/perf.nix b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/perf.nix
new file mode 100644
index 000000000000..a35582442979
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/perf.nix
@@ -0,0 +1,78 @@
+{ lib, stdenv, kernel, elfutils, python2, python3, perl, newt, slang, asciidoc, xmlto, makeWrapper
+, docbook_xsl, docbook_xml_dtd_45, libxslt, flex, bison, pkgconfig, libunwind, binutils
+, libiberty, audit, libbfd, libopcodes, openssl, systemtap, numactl
+, zlib, withGtk ? false, gtk2 ? null
+}:
+
+with lib;
+
+assert withGtk -> gtk2 != null;
+assert versionAtLeast kernel.version "3.12";
+
+stdenv.mkDerivation {
+ name = "perf-linux-${kernel.version}";
+
+ inherit (kernel) src;
+
+ preConfigure = ''
+ cd tools/perf
+
+ substituteInPlace Makefile \
+ --replace /usr/include/elfutils $elfutils/include/elfutils
+
+ for x in util/build-id.c util/dso.c; do
+ substituteInPlace $x --replace /usr/lib/debug /run/current-system/sw/lib/debug
+ done
+
+ if [ -f bash_completion ]; then
+ sed -i 's,^have perf,_have perf,' bash_completion
+ fi
+ '';
+
+ makeFlags = ["prefix=$(out)" "WERROR=0"] ++ kernel.makeFlags;
+
+ hardeningDisable = [ "format" ];
+
+ # perf refers both to newt and slang
+ nativeBuildInputs = [
+ asciidoc xmlto docbook_xsl docbook_xml_dtd_45 libxslt
+ flex bison libiberty audit makeWrapper pkgconfig python3
+ ];
+ buildInputs = [
+ elfutils newt slang libunwind libbfd zlib openssl systemtap.stapBuild numactl
+ libopcodes python3 perl
+ ] ++ stdenv.lib.optional withGtk gtk2
+ ++ (if (versionAtLeast kernel.version "4.19") then [ python3 ] else [ python2 ]);
+
+ # Note: we don't add elfutils to buildInputs, since it provides a
+ # bad `ld' and other stuff.
+ NIX_CFLAGS_COMPILE = toString [
+ "-Wno-error=cpp"
+ "-Wno-error=bool-compare"
+ "-Wno-error=deprecated-declarations"
+ "-DOBJDUMP_PATH=\"${binutils}/bin/objdump\""
+ "-Wno-error=stringop-truncation"
+ ];
+
+ postPatch = ''
+ patchShebangs scripts/bpf_helpers_doc.py
+ '';
+
+ doCheck = false; # requires "sparse"
+ doInstallCheck = false; # same
+
+ separateDebugInfo = true;
+ installFlags = [ "install" "install-man" "ASCIIDOC8=1" "prefix=$(out)" ];
+
+ preFixup = ''
+ wrapProgram $out/bin/perf \
+ --prefix PATH : "${binutils}/bin"
+ '';
+
+ meta = {
+ homepage = "https://perf.wiki.kernel.org/";
+ description = "Linux tools to profile with performance counters";
+ maintainers = with stdenv.lib.maintainers; [viric];
+ platforms = with stdenv.lib.platforms; linux;
+ };
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/randstruct-provide-seed.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/randstruct-provide-seed.patch
new file mode 100644
index 000000000000..1328b9cee3c9
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/randstruct-provide-seed.patch
@@ -0,0 +1,12 @@
+diff -ru a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh
+--- a/scripts/gcc-plugins/gen-random-seed.sh 2019-01-11 11:50:29.228258920 +0100
++++ b/scripts/gcc-plugins/gen-random-seed.sh 2019-01-11 12:18:33.555902720 +0100
+@@ -2,7 +2,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+
+ if [ ! -f "$1" ]; then
+- SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'`
++ SEED="NIXOS_RANDSTRUCT_SEED"
+ echo "const char *randstruct_seed = \"$SEED\";" > "$1"
+ HASH=`echo -n "$SEED" | sha256sum | cut -d" " -f1 | tr -d ' \n'`
+ echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2"
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper-updated.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper-updated.patch
new file mode 100644
index 000000000000..aabb9e801be4
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper-updated.patch
@@ -0,0 +1,13 @@
+diff --git a/security/keys/request_key.c b/security/keys/request_key.c
+index 88172c163953..4da74a1eebb2 100644
+--- a/security/keys/request_key.c
++++ b/security/keys/request_key.c
+@@ -161,7 +161,7 @@ static int call_sbin_request_key(struct key_construction *cons,
+
+ /* set up the argument list */
+ i = 0;
+- argv[i++] = "/sbin/request-key";
++ argv[i++] = "/run/current-system/sw/bin/request-key";
+ argv[i++] = (char *) op;
+ argv[i++] = key_str;
+ argv[i++] = uid_str;
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper.patch b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper.patch
new file mode 100644
index 000000000000..8264e265aedf
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/request-key-helper.patch
@@ -0,0 +1,13 @@
+diff --git a/security/keys/request_key.c b/security/keys/request_key.c
+index 957b9e3e1492..5436a0d8b81d 100644
+--- a/security/keys/request_key.c
++++ b/security/keys/request_key.c
+@@ -114,7 +114,7 @@ static int call_usermodehelper_keys(const char *path, char **argv, char **envp,
+ */
+ static int call_sbin_request_key(struct key *authkey, void *aux)
+ {
+- static char const request_key[] = "/sbin/request-key";
++ static char const request_key[] = "/run/current-system/sw/bin/request-key";
+ struct request_key_auth *rka = get_request_key_auth(authkey);
+ const struct cred *cred = current_cred();
+ key_serial_t prkey, sskey;
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-libre.sh b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-libre.sh
new file mode 100755
index 000000000000..aea12df55cc5
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-libre.sh
@@ -0,0 +1,33 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -i bash -p nix-prefetch-svn git curl
+set -euo pipefail
+
+nixpkgs="$(git rev-parse --show-toplevel)"
+path="$nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix"
+
+old_rev="$(grep -o 'rev = ".*"' "$path" | awk -F'"' '{print $2}')"
+old_sha256="$(grep -o 'sha256 = ".*"' "$path" | awk -F'"' '{print $2}')"
+
+svn_url=https://www.fsfla.org/svn/fsfla/software/linux-libre/releases/branches/
+rev="$(curl -s "$svn_url" | grep -Em 1 -o 'Revision [0-9]+' | awk '{print $2}')"
+
+if [ "$old_rev" = "$rev" ]; then
+ echo "No updates for linux-libre"
+ exit 0
+fi
+
+sha256="$(QUIET=1 nix-prefetch-svn "$svn_url" "$rev" | tail -1)"
+
+if [ "$old_sha256" = "$sha256" ]; then
+ echo "No updates for linux-libre"
+ exit 0
+fi
+
+sed -i -e "s/rev = \".*\"/rev = \"$rev\"/" \
+ -e "s/sha256 = \".*\"/sha256 = \"$sha256\"/" "$path"
+
+if [ -n "${COMMIT-}" ]; then
+ git commit -qm "linux_latest-libre: $old_rev -> $rev" "$path" \
+ $nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix
+ echo "Updated linux_latest-libre $old_rev -> $rev"
+fi
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-rt.sh b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-rt.sh
new file mode 100755
index 000000000000..bcfa494d7e7a
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update-rt.sh
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# To update all rt kernels run: ./update-rt.sh
+
+# To update just one ./linux-rt-5.X.nix run: ./update-rt.sh ./linux-rt-5.X.nix
+
+# To add a new kernel branch 5.Y run: ./update-rt.sh ./linux-rt-5.Y.nix
+# (with nonexistent .nix file) and update all-packages.nix.
+
+# To commit run with: env COMMIT=1
+
+mirror=https://kernel.org/pub/linux/kernel
+
+main() {
+ if [ $# -ge 1 ]; then
+ update-if-needed "$1"
+ else
+ update-all-if-needed
+ fi
+}
+
+update-all-if-needed() {
+ for f in "$(dirname "$0")"/linux-rt-*.nix; do
+ update-if-needed "$f"
+ done
+}
+
+file-version() {
+ file="$1" # e.g. ./linux-rt-5.4.nix
+ if [ -e "$file" ]; then
+ grep ' version = ' "$file" | grep -o '[0-9].[^"]*'
+ fi
+}
+
+latest-rt-version() {
+ branch="$1" # e.g. 5.4
+ curl -sL "$mirror/projects/rt/$branch/sha256sums.asc" |
+ sed -ne '/.patch.xz/ { s/.*patch-\(.*\).patch.xz/\1/; p; q }'
+}
+
+update-if-needed() {
+ file="$1" # e.g. ./linux-rt-5.4.nix (created if does not exist)
+ branch=$(basename "$file" .nix) # e.g. linux-rt-5.4
+ branch=${branch#linux-rt-} # e.g. 5.4
+ cur=$(file-version "$file") # e.g. 5.4.59-rt36 or empty
+ new=$(latest-rt-version "$branch") # e.g. 5.4.61-rt37
+ kversion=${new%-*} # e.g. 5.4.61
+ major=${branch%.*} # e.g 5
+ nixattr="linux-rt_${branch/./_}"
+ if [ "$new" = "$cur" ]; then
+ echo "$nixattr: $cur (up-to-date)"
+ return
+ fi
+ khash=$(nix-prefetch-url "$mirror/v${major}.x/linux-${kversion}.tar.xz")
+ phash=$(nix-prefetch-url "$mirror/projects/rt/${branch}/older/patch-${new}.patch.xz")
+ if [ "$cur" ]; then
+ msg="$nixattr: $cur -> $new"
+ else
+ msg="$nixattr: init at $new"
+ prev=$(ls "$(dirname "$0")"/linux-rt-*.nix | tail -1)
+ cp "$prev" "$file"
+ cur=$(file-version "$file")
+ fi
+ echo "$msg"
+ sed -i "$file" \
+ -e "s/$cur/$new/" \
+ -e "s|kernel/v[0-9]*|kernel/v$major|" \
+ -e "1,/.patch.xz/ s/sha256 = .*/sha256 = \"$khash\";/" \
+ -e "1,/.patch.xz/! s/sha256 = .*/sha256 = \"$phash\";/"
+ if [ "${COMMIT:-}" ]; then
+ git add "$file"
+ git commit -m "$msg"
+ fi
+}
+
+return 2>/dev/null || main "$@"
diff --git a/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update.sh b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update.sh
new file mode 100755
index 000000000000..560edced36ea
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/os-specific/linux/kernel/update.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+set -e
+
+# Get the latest versions from kernel.org
+LINUXSED='s/.*linux-\([0-9]\+\(.[0-9]\+\)*\).*/\1/p'
+KDATA="$(curl -s https://www.kernel.org | sed -n -e '/Download complete/p')"
+VERSIONS=($(sed -n -e $LINUXSED <<< "$KDATA" | sort -Vr))
+
+# Remove mainline version if there is a stable update
+# Note due to sorting these two will always exist at the bottom
+if grep -q "^${VERSIONS[1]}" <<< "${VERSIONS[0]}"; then
+ VERSIONS=(${VERSIONS[@]:0:1} ${VERSIONS[@]:2})
+fi
+
+# Inspect each file and see if it has the latest version
+NIXPKGS="$(git rev-parse --show-toplevel)"
+ls $NIXPKGS/pkgs/os-specific/linux/kernel | while read FILE; do
+ KERNEL="$(sed -n -e $LINUXSED <<< "$FILE")"
+ [ -z "$KERNEL" ] && continue
+
+ # Find the matching new kernel version
+ MATCHING=""
+ for V in "${VERSIONS[@]}"; do
+ if grep -q "^$KERNEL" <<< "$V"; then
+ MATCHING="$V"
+ break
+ fi
+ done
+ if [ -z "$MATCHING" ]; then
+ echo "Out-of-support $KERNEL"
+ continue
+ fi
+
+ # Inspect the nix expression to check for changes
+ DATA="$(<$NIXPKGS/pkgs/os-specific/linux/kernel/$FILE)"
+ URL="$(sed -n -e 's/.*url = "\(.*\)";.*/\1/p' <<< "$DATA" | sed -e "s/\${version}/$MATCHING/g")"
+ OLDVER=$(sed -n -e 's/.*version = "\(.*\)".*/\1/p' <<< "$DATA")
+ if [ "$OLDVER" = "$V" ]; then
+ echo "No updates for $KERNEL"
+ continue
+ fi
+
+ # Download the new file for the hash
+ if ! HASH="$(nix-prefetch-url $URL 2>/dev/null)"; then
+ echo "Failed to get hash of $URL"
+ continue
+ fi
+ sed -i -e "s/sha256 = \".*\"/sha256 = \"$HASH\"/g" $NIXPKGS/pkgs/os-specific/linux/kernel/$FILE
+
+ # Rewrite the expression
+ sed -i -e '/version = /d' $NIXPKGS/pkgs/os-specific/linux/kernel/$FILE
+ sed -i -e "\#buildLinux (args // rec {#a \ version = \"$V\";" $NIXPKGS/pkgs/os-specific/linux/kernel/$FILE
+
+ # Commit the changes
+ git add -u $NIXPKGS/pkgs/os-specific/linux/kernel/$FILE
+ git commit -m "linux: $OLDVER -> $V" >/dev/null 2>&1
+
+ echo "Updated $OLDVER -> $V"
+done
+
+# Update linux-rt
+COMMIT=1 $NIXPKGS/pkgs/os-specific/linux/kernel/update-rt.sh
+
+# Update linux-libre
+COMMIT=1 $NIXPKGS/pkgs/os-specific/linux/kernel/update-libre.sh
+
+# Update linux-hardened
+COMMIT=1 $NIXPKGS/pkgs/os-specific/linux/kernel/hardened/update.py