# Copyright 2023 Avishek Sen
# Distributed under the terms of the GNU General Public License v3

EAPI="8"
ETYPE="sources"
K_WANT_GENPATCHES="base extras"
K_GENPATCHES_VER="13"
K_NODRYRUN="1"
# UNIPATCH_STRICTORDER="1"

inherit kernel-2
detect_version
detect_arch

DESCRIPTION="Linux Kernel by CachyOS with different schedulers, patches and performance improvements"
HOMEPAGE="https://github.com/CachyOS/linux-cachyos"

LICENSE="GPL-3"
SLOT="0"
KEYWORDS="~amd64"

SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
MY_KV="${KV_MAJOR}.${KV_MINOR}"
MY_FILESDIR="${FILESDIR}/${MY_KV}"

# Define USE flags for CPU schedulers
CPUSCHED="bmq pds bore cfs tt eevdf"
for sched in ${CPUSCHED}; do
	if [ "${sched}" = "eevdf" ]; then IUSE_CPUSCHED+=" +cpusched_${sched}" # Set default
	else IUSE_CPUSCHED+=" cpusched_${sched}"; fi
done

# Define USE flags for HZ ticks
HZTICKS="100 250 300 500 600 750 1000"
for rate in ${HZTICKS}; do
	if [ "${rate}" = "500" ]; then IUSE_HZTICKS+=" +hzticks_${rate}" # Set default
	else IUSE_HZTICKS+=" hzticks_${rate}"; fi
done

# Define USE flags for tick rate
TICKRATE="full idle perodic"
for tick in ${TICKRATE}; do
	if [ "${tick}" = "full" ]; then IUSE_TICKRATE+=" +tickrate_${tick}" # Set default
	else IUSE_TICKRATE+=" tickrate_${tick}"; fi
done

# Define USE flags for preempt
PREEMPT="full voluntary server"
for type in ${PREEMPT}; do
	if [ "${type}" = "full" ]; then IUSE_PREEMPT+=" +preempt_${type}" # Set default
	else IUSE_PREEMPT+=" preempt_${type}"; fi
done

# Define USE flags for LRU
LRU="standard stats none"
for config in ${LRU}; do
	if [ "${config}" = "standard" ]; then IUSE_LRU+=" +lru_${config}" # Set default
	else IUSE_LRU+=" lru_${config}"; fi
done

# Define USE flags for transparent hugepage
HUGEPAGE="always madvise"
for type in ${HUGEPAGE}; do
	if [ "${type}" = "always" ]; then IUSE_HUGEPAGE+=" +hugepage_${type}" # Set default
	else IUSE_HUGEPAGE+=" hugepage_${type}"; fi
done

# Define USE flags for ZSTD compression level
ZSTDLEVEL="ultra normal"
for type in ${ZSTDLEVEL}; do
	if [ "${type}" = "normal" ]; then IUSE_ZSTDLEVEL+=" +zstdlevel_${type}" # Set default
	else IUSE_ZSTDLEVEL+=" zstdlevel_${type}"; fi
done

IUSE="+config ${IUSE_CPUSCHED} tune_bore NUMAdisable +cc_harder +per_gov +tcp_bbr2
	${IUSE_HZTICKS} ${IUSE_TICKRATE} ${IUSE_PREEMPT} +mq_deadline_disable +kyber_disable
	${IUSE_LRU} ${IUSE_HUGEPAGE} damon lrng +auto_optimization disable_debug
	zstd_compression ${IUSE_ZSTDLEVEL} bcachefs latency_nice"

REQUIRED_USE="^^ ( ${IUSE_CPUSCHED//+} )
			^^ ( ${IUSE_HZTICKS//+} )
			^^ ( ${IUSE_TICKRATE//+} )
			^^ ( ${IUSE_PREEMPT//+} )
			^^ ( ${IUSE_LRU//+} )
			^^ ( ${IUSE_HUGEPAGE//+} )
			^^ ( ${IUSE_ZSTDLEVEL//+} )"

src_unpack() {
	kernel-2_src_unpack

	PATCH_LIST+=" ${MY_FILESDIR}/0001-cachyos-base-all.patch"

	if use latency_nice; then
		if use cpusched_bore || use cpusched_cfs; 
			then PATCH_LIST+=" ${MY_FILESDIR}/misc/0001-Add-latency-priority-for-CFS-class.patch"
		fi
	fi

	if use cpusched_eevdf; then PATCH_LIST+=" ${MY_FILESDIR}/sched/0001-EEVDF.patch"; fi
	if use cpusched_pds || use cpusched_bmq; then PATCH_LIST+=" ${MY_FILESDIR}/sched/0001-prjc-cachy.patch"; fi
	if use cpusched_tt; then PATCH_LIST+=" ${MY_FILESDIR}/sched/0001-tt-cachy.patch"; fi
	if use cpusched_bore; then
		if use tune_bore; then PATCH_LIST+=" ${MY_FILESDIR}/misc/0001-bore-tuning-sysctl.patch"; fi
		PATCH_LIST+=" ${MY_FILESDIR}/sched/0001-bore-cachy.patch"
	fi

	if use bcachefs; then PATCH_LIST+=" ${MY_FILESDIR}/misc/0001-bcachefs.patch"; fi
	if use lrng; then PATCH_LIST+=" ${MY_FILESDIR}/misc/0001-lrng.patch"; fi

	# Apply all selected patches
	for patch in ${PATCH_LIST}; do
		unipatch "${patch}" || die "Patch: ${patch} failed"
	done

	if use config; then
		cp "${MY_FILESDIR}/config/config-eevdf" .config
		cp "${MY_FILESDIR}/config/config-eevdf" arch/x86/configs/cachy_defconfig
		scripts/config -e CACHY
		elog "CachyOS kernel config installed as cachy_defconfig"
	fi
	if use auto_optimization; then "${MY_FILESDIR}/auto-cpu-optimization.sh"; fi

	if use cpusched_pds; then scripts/config -e SCHED_ALT -d SCHED_BMQ -e SCHED_PDS -e PSI_DEFAULT_DISABLED; fi
	if use cpusched_bmq; then scripts/config -e SCHED_ALT -e SCHED_BMQ -d SCHED_PDS -e PSI_DEFAULT_DISABLED; fi
	if use cpusched_tt; then scripts/config -e TT_SCHED -e TT_ACCOUNTING_STATS; fi
	if use cpusched_bore || use cpusched_eevdf; then scripts/config -e SCHED_BORE; fi
	
	for rate in ${HZTICKS}; do
	      if use hzticks_300; then
                  scripts/config -e HZ_300 --set-val HZ 300
                  break
            fi
		if use "hzticks_${rate}"; then
			scripts/config -d HZ_300 -e "HZ_${rate}" --set-val HZ "${rate}"
			break
		fi
	done

	if use NUMAdisable; then
	      scripts/config -d NUMA \
                  -d AMD_NUMA \
                  -d X86_64_ACPI_NUMA \
                  -d NODES_SPAN_OTHER_NODES \
                  -d NUMA_EMU \
                  -d USE_PERCPU_NUMA_NODE_ID \
                  -d ACPI_NUMA \
                  -d ARCH_SUPPORTS_NUMA_BALANCING \
                  -d NODES_SHIFT \
                  -u NODES_SHIFT \
                  -d NEED_MULTIPLE_NODES \
                  -d NUMA_BALANCING \
                  -d NUMA_BALANCING_DEFAULT_ENABLED
	fi

      scripts/config --set-val NR_CPUS 320

	if use mq_deadline_disable; then scripts/config -d MQ_IOSCHED_DEADLINE; fi
	if use kyber_disable; then scripts/config -d MQ_IOSCHED_KYBER; fi
	if use per_gov; then 
		scripts/config -d CPU_FREQ_DEFAULT_GOV_SCHEDUTIL \
                  -e CPU_FREQ_DEFAULT_GOV_PERFORMANCE
	fi

	if use tickrate_perodic; then scripts/config -d NO_HZ_IDLE -d NO_HZ_FULL -d NO_HZ -d NO_HZ_COMMON -e HZ_PERIODIC; fi
	if use tickrate_idle; then scripts/config -d HZ_PERIODIC -d NO_HZ_FULL -e NO_HZ_IDLE  -e NO_HZ -e NO_HZ_COMMON; fi
	if use tickrate_full; then scripts/config -d HZ_PERIODIC -d NO_HZ_IDLE -d CONTEXT_TRACKING_FORCE -e NO_HZ_FULL_NODEF -e NO_HZ_FULL -e NO_HZ -e NO_HZ_COMMON -e CONTEXT_TRACKING; fi

	if use preempt_full; then scripts/config -e PREEMPT_BUILD -d PREEMPT_NONE -d PREEMPT_VOLUNTARY -e PREEMPT -e PREEMPT_COUNT -e PREEMPTION -e PREEMPT_DYNAMIC; fi
	if use preempt_voluntary; then scripts/config -e PREEMPT_BUILD -d PREEMPT_NONE -e PREEMPT_VOLUNTARY -d PREEMPT -e PREEMPT_COUNT -e PREEMPTION -d PREEMPT_DYNAMIC; fi
	if use preempt_server; then scripts/config -e PREEMPT_NONE_BUILD -e PREEMPT_NONE -d PREEMPT_VOLUNTARY -d PREEMPT -d PREEMPTION -d PREEMPT_DYNAMIC; fi

	if use cc_harder; then
		scripts/config -d CC_OPTIMIZE_FOR_PERFORMANCE \
                  -e CC_OPTIMIZE_FOR_PERFORMANCE_O3
	fi

	if use tcp_bbr2; then
		scripts/config -m TCP_CONG_CUBIC \
                  -d DEFAULT_CUBIC \
                  -e TCP_CONG_BBR2 \
                  -e DEFAULT_BBR2 \
                  --set-str DEFAULT_TCP_CONG bbr2
	fi

	if use lru_standard; then scripts/config -e LRU_GEN -e LRU_GEN_ENABLED -d LRU_GEN_STATS; fi
	if use lru_stats; then scripts/config -e LRU_GEN -e LRU_GEN_ENABLED -e LRU_GEN_STATS; fi
	if use lru_none; then scripts/config -d LRU_GEN; fi

	if use hugepage_always; then scripts/config -d TRANSPARENT_HUGEPAGE_MADVISE -e TRANSPARENT_HUGEPAGE_ALWAYS; fi
	if use hugepage_madvise; then scripts/config -d TRANSPARENT_HUGEPAGE_ALWAYS -e TRANSPARENT_HUGEPAGE_MADVISE; fi

	if use damon; then
		scripts/config -e DAMON \
                  -e DAMON_VADDR \
                  -e DAMON_DBGFS \
                  -e DAMON_SYSFS \
                  -e DAMON_PADDR \
                  -e DAMON_RECLAIM \
                  -e DAMON_LRU_SORT
	fi

	if use lrng; then
		scripts/config -d RANDOM_DEFAULT_IMPL \
                  -e LRNG \
                  -e LRNG_SHA256 \
                  -e LRNG_COMMON_DEV_IF \
                  -e LRNG_DRNG_ATOMIC \
                  -e LRNG_SYSCTL \
                  -e LRNG_RANDOM_IF \
                  -e LRNG_AIS2031_NTG1_SEEDING_STRATEGY \
                  -m LRNG_KCAPI_IF \
                  -m LRNG_HWRAND_IF \
                  -e LRNG_DEV_IF \
                  -e LRNG_RUNTIME_ES_CONFIG \
                  -e LRNG_IRQ_DFLT_TIMER_ES \
                  -d LRNG_SCHED_DFLT_TIMER_ES \
                  -e LRNG_TIMER_COMMON \
                  -d LRNG_COLLECTION_SIZE_256 \
                  -d LRNG_COLLECTION_SIZE_512 \
                  -e LRNG_COLLECTION_SIZE_1024 \
                  -d LRNG_COLLECTION_SIZE_2048 \
                  -d LRNG_COLLECTION_SIZE_4096 \
                  -d LRNG_COLLECTION_SIZE_8192 \
                  --set-val LRNG_COLLECTION_SIZE 1024 \
                  -e LRNG_HEALTH_TESTS \
                  --set-val LRNG_RCT_CUTOFF 31 \
                  --set-val LRNG_APT_CUTOFF 325 \
                  -e LRNG_IRQ \
                  -e LRNG_CONTINUOUS_COMPRESSION_ENABLED \
                  -d LRNG_CONTINUOUS_COMPRESSION_DISABLED \
                  -e LRNG_ENABLE_CONTINUOUS_COMPRESSION \
                  -e LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION \
                  --set-val LRNG_IRQ_ENTROPY_RATE 256 \
                  -e LRNG_JENT \
                  --set-val LRNG_JENT_ENTROPY_RATE 16 \
                  -e LRNG_CPU \
                  --set-val LRNG_CPU_FULL_ENT_MULTIPLIER 1 \
                  --set-val LRNG_CPU_ENTROPY_RATE 8 \
                  -e LRNG_SCHED \
                  --set-val LRNG_SCHED_ENTROPY_RATE 4294967295 \
                  -e LRNG_DRNG_CHACHA20 \
                  -m LRNG_DRBG \
                  -m LRNG_DRNG_KCAPI \
                  -e LRNG_SWITCH \
                  -e LRNG_SWITCH_HASH \
                  -m LRNG_HASH_KCAPI \
                  -e LRNG_SWITCH_DRNG \
                  -m LRNG_SWITCH_DRBG \
                  -m LRNG_SWITCH_DRNG_KCAPI \
                  -e LRNG_DFLT_DRNG_CHACHA20 \
                  -d LRNG_DFLT_DRNG_DRBG \
                  -d LRNG_DFLT_DRNG_KCAPI \
                  -e LRNG_TESTING_MENU \
                  -d LRNG_RAW_HIRES_ENTROPY \
                  -d LRNG_RAW_JIFFIES_ENTROPY \
                  -d LRNG_RAW_IRQ_ENTROPY \
                  -d LRNG_RAW_RETIP_ENTROPY \
                  -d LRNG_RAW_REGS_ENTROPY \
                  -d LRNG_RAW_ARRAY \
                  -d LRNG_IRQ_PERF \
                  -d LRNG_RAW_SCHED_HIRES_ENTROPY \
                  -d LRNG_RAW_SCHED_PID_ENTROPY \
                  -d LRNG_RAW_SCHED_START_TIME_ENTROPY \
                  -d LRNG_RAW_SCHED_NVCSW_ENTROPY \
                  -d LRNG_SCHED_PERF \
                  -d LRNG_ACVT_HASH \
                  -d LRNG_RUNTIME_MAX_WO_RESEED_CONFIG \
                  -d LRNG_TEST_CPU_ES_COMPRESSION \
                  -e LRNG_SELFTEST \
                  -d LRNG_SELFTEST_PANIC \
                  -d LRNG_RUNTIME_FORCE_SEEDING_DISABLE
	fi

	if use zstd_compression; then
		scripts/config -d ZRAM_DEF_COMP_LZORLE \
                  -e ZRAM_DEF_COMP_ZSTD \
                  --set-str ZRAM_DEF_COMP zstd \
                  -d ZSWAP_COMPRESSOR_DEFAULT_LZ4 \
                  -e ZSWAP_COMPRESSOR_DEFAULT_ZSTD \
                  --set-str ZSWAP_COMPRESSOR_DEFAULT zstd
    fi

	if use zstdlevel_ultra; then scripts/config --set-val MODULE_COMPRESS_ZSTD_LEVEL 19 -e MODULE_COMPRESS_ZSTD_ULTRA --set-val MODULE_COMPRESS_ZSTD_LEVEL_ULTRA 22 --set-val ZSTD_COMPRESSION_LEVEL 22; fi
	if use zstdlevel_normal; then scripts/config --set-val MODULE_COMPRESS_ZSTD_LEVEL 9 -d MODULE_COMPRESS_ZSTD_ULTRA --set-val ZSTD_COMPRESSION_LEVEL 19; fi

	if use disable_debug; then
		scripts/config -d DEBUG_INFO \
                  -d DEBUG_INFO_BTF \
                  -d DEBUG_INFO_DWARF4 \
                  -d DEBUG_INFO_DWARF5 \
                  -d PAHOLE_HAS_SPLIT_BTF \
                  -d DEBUG_INFO_BTF_MODULES \
                  -d SLUB_DEBUG \
                  -d PM_DEBUG \
                  -d PM_ADVANCED_DEBUG \
                  -d PM_SLEEP_DEBUG \
                  -d ACPI_DEBUG \
                  -d SCHED_DEBUG \
                  -d LATENCYTOP \
                  -d DEBUG_PREEMPT
    fi

	scripts/config -e USER_NS
}

pkg_postinst() {
	kernel-2_pkg_postinst
	einfo "For more info on this patchset, and how to report problems, see:"
	einfo "${HOMEPAGE}"
}