--- zzzz-none-000/linux-4.4.271/init/main.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/init/main.c 2023-04-19 10:22:30.000000000 +0000 @@ -89,6 +89,11 @@ #include #include +#ifdef CONFIG_QCA_NMI_RESERVE +#include +#include +#endif + static int kernel_init(void *); extern void init_IRQ(void); @@ -356,6 +361,29 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { } #endif +#ifdef CONFIG_MANGLE_BOOTARGS +static void __init mangle_bootargs(char *command_line) +{ + char *rootdev; + char *rootfs; + + rootdev = strstr(command_line, "root=/dev/mtdblock"); + + if (rootdev) + strncpy(rootdev, "mangled_rootblock=", 18); + + rootfs = strstr(command_line, "rootfstype"); + + if (rootfs) + strncpy(rootfs, "mangled_fs", 10); + +} +#else +static void __init mangle_bootargs(char *command_line) +{ +} +#endif + /* * We need to store the untouched command line for future reference. * We also need to store the touched command line since the parameter @@ -477,6 +505,126 @@ } #endif +#ifdef CONFIG_QCA_NMI_RESERVE +/* + * WARNING: + * This will turn off memory mapped SPI flash access. + */ + +#define ENTRY_LO_MASK (~((1ul << 26) - 1)) +#define ENTRY_LO_V 0x2 +#define ENTRY_LO_G 0x1 +#define ENTRY_LO_C(x) (((x) & CONF_CM_CMASK) << 2) + +extern void local_flush_tlb_all(void); +extern void except_vec_nmi(void); + +static void *nmi_reserve; + +static __init bool use_nmi_relocation(void) { + int ret; + u32 relocation; + + ret = of_property_read_u32(of_root, "nmi-relocation", &relocation); + + if (ret != 0) { + return false; + } + + return relocation == 1; +} + +static __init int copy_nmi_trampoline(void) +{ + mm_segment_t old_fs; + extern char except_vec_nmi_end; + + if (!nmi_reserve) + return -1; + + memset(nmi_reserve, 0, PAGE_SIZE); + + memcpy(nmi_reserve, except_vec_nmi, + &except_vec_nmi_end - (char *)except_vec_nmi); + + old_fs = get_fs(); /* refer load_module() */ + set_fs(KERNEL_DS); + + /* + * This might not be needed as the region is marked as + * CONF_CM_UNCACHED. Better safe than sorry! (if that gets changed) + */ + local_flush_icache_range((unsigned long)nmi_reserve, (unsigned long)nmi_reserve + 256); + local_flush_data_cache_page(nmi_reserve); + + set_fs(old_fs); + + pr_info("[nmi] %s done\n", __func__); + + return 0; +} + +static __init void nmi_reserve_memory(void) +{ + unsigned long pa, lo0; + + nmi_reserve = vmalloc(PAGE_SIZE); + + if (!nmi_reserve) { + pr_err("[nmi] %s: ENOMEM\n", __func__); + return; + } + + if ((u32)nmi_reserve != (u32)VMALLOC_START) { + pr_err("[nmi] %s: NMI handler reserve area (%p) != %p\n", + __func__, nmi_reserve, (void*)VMALLOC_START); + vfree(nmi_reserve); + nmi_reserve = NULL; + return; + } + + /* + * When the CPU receives the NMI, it uses the reset TLB. + * Hence the 'vmalloc' mapping would not be available + * temporarily. Hence, wire that TLB entry + */ + pa = virt_to_phys(nmi_reserve); + + lo0 = (pa >> 12) << 6; // PFN + lo0 &= ~ENTRY_LO_MASK; + + lo0 |= ENTRY_LO_V | ENTRY_LO_G; + + lo0 |= ENTRY_LO_C(CONF_CM_UNCACHED); // Caching attributes + + /* + * TLB could already have the mapping for VMALLOC_START. Ideally, only + * that entry should be removed, but don't have the patience to figure + * it out :( And, since this is a one time operation during early boot, + * cleaning everything should be ok. + */ + local_flush_tlb_all(); + + add_wired_entry(lo0, lo0, (unsigned long)nmi_reserve, PM_4K); + + pr_info("[nmi] VA:PA %p:%p wired at entry 0x%x\n", + nmi_reserve, (void*)pa, read_c0_wired()); +} + +/* + * Probably should use 'board_nmi_handler_setup', but this works + */ +late_initcall(copy_nmi_trampoline); + +#if !defined(CONFIG_MTD_ATH_FLASH) +void ath_spi_disable_mm(void) { + ath_reg_wr_nf(ATH_SPI_FS, 1); +} +#endif + +#endif /* CONFIG_QCA_NMI_RESERVE */ + + /* * Set up kernel memory allocators */ @@ -492,6 +640,13 @@ percpu_init_late(); pgtable_init(); vmalloc_init(); +#ifdef CONFIG_QCA_NMI_RESERVE + if (use_nmi_relocation()) { + // Enable SPI soft access (and in turn disable memory mapped spi) + ath_spi_disable_mm(); + nmi_reserve_memory(); + } +#endif ioremap_huge_init(); kaiser_init(); } @@ -529,6 +684,7 @@ pr_notice("%s", linux_banner); setup_arch(&command_line); mm_init_cpumask(&init_mm); + mangle_bootargs(command_line); setup_command_line(command_line); setup_nr_cpu_ids(); setup_per_cpu_areas(); @@ -632,6 +788,7 @@ #endif page_ext_init(); debug_objects_mem_init(); + debug_mem_usage_init(); kmemleak_init(); setup_per_cpu_pageset(); numa_policy_init(); @@ -968,7 +1125,8 @@ panic("Requested init %s failed (error %d).", execute_command, ret); } - if (!try_to_run_init_process("/sbin/init") || + if (!try_to_run_init_process("/etc/preinit") || + !try_to_run_init_process("/sbin/init") || !try_to_run_init_process("/etc/init") || !try_to_run_init_process("/bin/init") || !try_to_run_init_process("/bin/sh"))