19703d9d7SCatalin Marinas /* 29703d9d7SCatalin Marinas * Based on arch/arm/kernel/setup.c 39703d9d7SCatalin Marinas * 49703d9d7SCatalin Marinas * Copyright (C) 1995-2001 Russell King 59703d9d7SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 69703d9d7SCatalin Marinas * 79703d9d7SCatalin Marinas * This program is free software; you can redistribute it and/or modify 89703d9d7SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 99703d9d7SCatalin Marinas * published by the Free Software Foundation. 109703d9d7SCatalin Marinas * 119703d9d7SCatalin Marinas * This program is distributed in the hope that it will be useful, 129703d9d7SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 139703d9d7SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 149703d9d7SCatalin Marinas * GNU General Public License for more details. 159703d9d7SCatalin Marinas * 169703d9d7SCatalin Marinas * You should have received a copy of the GNU General Public License 179703d9d7SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 189703d9d7SCatalin Marinas */ 199703d9d7SCatalin Marinas 2037655163SAl Stone #include <linux/acpi.h> 219703d9d7SCatalin Marinas #include <linux/export.h> 229703d9d7SCatalin Marinas #include <linux/kernel.h> 239703d9d7SCatalin Marinas #include <linux/stddef.h> 249703d9d7SCatalin Marinas #include <linux/ioport.h> 259703d9d7SCatalin Marinas #include <linux/delay.h> 269703d9d7SCatalin Marinas #include <linux/utsname.h> 279703d9d7SCatalin Marinas #include <linux/initrd.h> 289703d9d7SCatalin Marinas #include <linux/console.h> 29a41dc0e8SCatalin Marinas #include <linux/cache.h> 309703d9d7SCatalin Marinas #include <linux/bootmem.h> 319703d9d7SCatalin Marinas #include <linux/screen_info.h> 329703d9d7SCatalin Marinas #include <linux/init.h> 339703d9d7SCatalin Marinas #include <linux/kexec.h> 349703d9d7SCatalin Marinas #include <linux/crash_dump.h> 359703d9d7SCatalin Marinas #include <linux/root_dev.h> 369703d9d7SCatalin Marinas #include <linux/cpu.h> 379703d9d7SCatalin Marinas #include <linux/interrupt.h> 389703d9d7SCatalin Marinas #include <linux/smp.h> 399703d9d7SCatalin Marinas #include <linux/fs.h> 409703d9d7SCatalin Marinas #include <linux/proc_fs.h> 419703d9d7SCatalin Marinas #include <linux/memblock.h> 429703d9d7SCatalin Marinas #include <linux/of_fdt.h> 43f84d0275SMark Salter #include <linux/efi.h> 44bff60792SMark Rutland #include <linux/psci.h> 459703d9d7SCatalin Marinas 4637655163SAl Stone #include <asm/acpi.h> 47bf4b558eSMark Salter #include <asm/fixmap.h> 48df857416SMark Rutland #include <asm/cpu.h> 499703d9d7SCatalin Marinas #include <asm/cputype.h> 509703d9d7SCatalin Marinas #include <asm/elf.h> 51930da09fSAndre Przywara #include <asm/cpufeature.h> 52e8765b26SMark Rutland #include <asm/cpu_ops.h> 5339d114ddSAndrey Ryabinin #include <asm/kasan.h> 541a2db300SGanapatrao Kulkarni #include <asm/numa.h> 559703d9d7SCatalin Marinas #include <asm/sections.h> 569703d9d7SCatalin Marinas #include <asm/setup.h> 574c7aa002SJavi Merino #include <asm/smp_plat.h> 589703d9d7SCatalin Marinas #include <asm/cacheflush.h> 599703d9d7SCatalin Marinas #include <asm/tlbflush.h> 609703d9d7SCatalin Marinas #include <asm/traps.h> 619703d9d7SCatalin Marinas #include <asm/memblock.h> 62f84d0275SMark Salter #include <asm/efi.h> 635882bfefSStefano Stabellini #include <asm/xen/hypervisor.h> 649e8e865bSMark Rutland #include <asm/mmu_context.h> 659703d9d7SCatalin Marinas 669703d9d7SCatalin Marinas phys_addr_t __fdt_pointer __initdata; 679703d9d7SCatalin Marinas 689703d9d7SCatalin Marinas /* 699703d9d7SCatalin Marinas * Standard memory resources 709703d9d7SCatalin Marinas */ 719703d9d7SCatalin Marinas static struct resource mem_res[] = { 729703d9d7SCatalin Marinas { 739703d9d7SCatalin Marinas .name = "Kernel code", 749703d9d7SCatalin Marinas .start = 0, 759703d9d7SCatalin Marinas .end = 0, 7635d98e93SToshi Kani .flags = IORESOURCE_SYSTEM_RAM 779703d9d7SCatalin Marinas }, 789703d9d7SCatalin Marinas { 799703d9d7SCatalin Marinas .name = "Kernel data", 809703d9d7SCatalin Marinas .start = 0, 819703d9d7SCatalin Marinas .end = 0, 8235d98e93SToshi Kani .flags = IORESOURCE_SYSTEM_RAM 839703d9d7SCatalin Marinas } 849703d9d7SCatalin Marinas }; 859703d9d7SCatalin Marinas 869703d9d7SCatalin Marinas #define kernel_code mem_res[0] 879703d9d7SCatalin Marinas #define kernel_data mem_res[1] 889703d9d7SCatalin Marinas 89da9c177dSArd Biesheuvel /* 90da9c177dSArd Biesheuvel * The recorded values of x0 .. x3 upon kernel entry. 91da9c177dSArd Biesheuvel */ 92da9c177dSArd Biesheuvel u64 __cacheline_aligned boot_args[4]; 93da9c177dSArd Biesheuvel 9471586276SWill Deacon void __init smp_setup_processor_id(void) 9571586276SWill Deacon { 9680708677SMark Rutland u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; 9780708677SMark Rutland cpu_logical_map(0) = mpidr; 9880708677SMark Rutland 9971586276SWill Deacon /* 10071586276SWill Deacon * clear __my_cpu_offset on boot CPU to avoid hang caused by 10171586276SWill Deacon * using percpu variable early, for example, lockdep will 10271586276SWill Deacon * access percpu variable inside lock_release 10371586276SWill Deacon */ 10471586276SWill Deacon set_my_cpu_offset(0); 10580708677SMark Rutland pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr); 10671586276SWill Deacon } 10771586276SWill Deacon 1086e15d0e0SSudeep KarkadaNagesha bool arch_match_cpu_phys_id(int cpu, u64 phys_id) 1096e15d0e0SSudeep KarkadaNagesha { 1106e15d0e0SSudeep KarkadaNagesha return phys_id == cpu_logical_map(cpu); 1116e15d0e0SSudeep KarkadaNagesha } 1126e15d0e0SSudeep KarkadaNagesha 113976d7d3fSLorenzo Pieralisi struct mpidr_hash mpidr_hash; 114976d7d3fSLorenzo Pieralisi /** 115976d7d3fSLorenzo Pieralisi * smp_build_mpidr_hash - Pre-compute shifts required at each affinity 116976d7d3fSLorenzo Pieralisi * level in order to build a linear index from an 117976d7d3fSLorenzo Pieralisi * MPIDR value. Resulting algorithm is a collision 118976d7d3fSLorenzo Pieralisi * free hash carried out through shifting and ORing 119976d7d3fSLorenzo Pieralisi */ 120976d7d3fSLorenzo Pieralisi static void __init smp_build_mpidr_hash(void) 121976d7d3fSLorenzo Pieralisi { 122976d7d3fSLorenzo Pieralisi u32 i, affinity, fs[4], bits[4], ls; 123976d7d3fSLorenzo Pieralisi u64 mask = 0; 124976d7d3fSLorenzo Pieralisi /* 125976d7d3fSLorenzo Pieralisi * Pre-scan the list of MPIDRS and filter out bits that do 126976d7d3fSLorenzo Pieralisi * not contribute to affinity levels, ie they never toggle. 127976d7d3fSLorenzo Pieralisi */ 128976d7d3fSLorenzo Pieralisi for_each_possible_cpu(i) 129976d7d3fSLorenzo Pieralisi mask |= (cpu_logical_map(i) ^ cpu_logical_map(0)); 130976d7d3fSLorenzo Pieralisi pr_debug("mask of set bits %#llx\n", mask); 131976d7d3fSLorenzo Pieralisi /* 132976d7d3fSLorenzo Pieralisi * Find and stash the last and first bit set at all affinity levels to 133976d7d3fSLorenzo Pieralisi * check how many bits are required to represent them. 134976d7d3fSLorenzo Pieralisi */ 135976d7d3fSLorenzo Pieralisi for (i = 0; i < 4; i++) { 136976d7d3fSLorenzo Pieralisi affinity = MPIDR_AFFINITY_LEVEL(mask, i); 137976d7d3fSLorenzo Pieralisi /* 138976d7d3fSLorenzo Pieralisi * Find the MSB bit and LSB bits position 139976d7d3fSLorenzo Pieralisi * to determine how many bits are required 140976d7d3fSLorenzo Pieralisi * to express the affinity level. 141976d7d3fSLorenzo Pieralisi */ 142976d7d3fSLorenzo Pieralisi ls = fls(affinity); 143976d7d3fSLorenzo Pieralisi fs[i] = affinity ? ffs(affinity) - 1 : 0; 144976d7d3fSLorenzo Pieralisi bits[i] = ls - fs[i]; 145976d7d3fSLorenzo Pieralisi } 146976d7d3fSLorenzo Pieralisi /* 147976d7d3fSLorenzo Pieralisi * An index can be created from the MPIDR_EL1 by isolating the 148976d7d3fSLorenzo Pieralisi * significant bits at each affinity level and by shifting 149976d7d3fSLorenzo Pieralisi * them in order to compress the 32 bits values space to a 150976d7d3fSLorenzo Pieralisi * compressed set of values. This is equivalent to hashing 151976d7d3fSLorenzo Pieralisi * the MPIDR_EL1 through shifting and ORing. It is a collision free 152976d7d3fSLorenzo Pieralisi * hash though not minimal since some levels might contain a number 153976d7d3fSLorenzo Pieralisi * of CPUs that is not an exact power of 2 and their bit 154976d7d3fSLorenzo Pieralisi * representation might contain holes, eg MPIDR_EL1[7:0] = {0x2, 0x80}. 155976d7d3fSLorenzo Pieralisi */ 156976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0] = MPIDR_LEVEL_SHIFT(0) + fs[0]; 157976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1] = MPIDR_LEVEL_SHIFT(1) + fs[1] - bits[0]; 158976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2] = MPIDR_LEVEL_SHIFT(2) + fs[2] - 159976d7d3fSLorenzo Pieralisi (bits[1] + bits[0]); 160976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3] = MPIDR_LEVEL_SHIFT(3) + 161976d7d3fSLorenzo Pieralisi fs[3] - (bits[2] + bits[1] + bits[0]); 162976d7d3fSLorenzo Pieralisi mpidr_hash.mask = mask; 163976d7d3fSLorenzo Pieralisi mpidr_hash.bits = bits[3] + bits[2] + bits[1] + bits[0]; 164976d7d3fSLorenzo Pieralisi pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] aff3[%u] mask[%#llx] bits[%u]\n", 165976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[0], 166976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[1], 167976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[2], 168976d7d3fSLorenzo Pieralisi mpidr_hash.shift_aff[3], 169976d7d3fSLorenzo Pieralisi mpidr_hash.mask, 170976d7d3fSLorenzo Pieralisi mpidr_hash.bits); 171976d7d3fSLorenzo Pieralisi /* 172976d7d3fSLorenzo Pieralisi * 4x is an arbitrary value used to warn on a hash table much bigger 173976d7d3fSLorenzo Pieralisi * than expected on most systems. 174976d7d3fSLorenzo Pieralisi */ 175976d7d3fSLorenzo Pieralisi if (mpidr_hash_size() > 4 * num_possible_cpus()) 176976d7d3fSLorenzo Pieralisi pr_warn("Large number of MPIDR hash buckets detected\n"); 177976d7d3fSLorenzo Pieralisi } 178137650aaSMark Rutland 1799703d9d7SCatalin Marinas static void __init setup_machine_fdt(phys_addr_t dt_phys) 1809703d9d7SCatalin Marinas { 18161bd93ceSArd Biesheuvel void *dt_virt = fixmap_remap_fdt(dt_phys); 18261bd93ceSArd Biesheuvel 18361bd93ceSArd Biesheuvel if (!dt_virt || !early_init_dt_scan(dt_virt)) { 18461bd93ceSArd Biesheuvel pr_crit("\n" 18561bd93ceSArd Biesheuvel "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" 18661bd93ceSArd Biesheuvel "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" 18761bd93ceSArd Biesheuvel "\nPlease check your bootloader.", 18861bd93ceSArd Biesheuvel &dt_phys, dt_virt); 1899703d9d7SCatalin Marinas 1909703d9d7SCatalin Marinas while (true) 1919703d9d7SCatalin Marinas cpu_relax(); 1929703d9d7SCatalin Marinas } 1935e39977eSWill Deacon 19444b82b77SMark Rutland dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name()); 1959703d9d7SCatalin Marinas } 1969703d9d7SCatalin Marinas 1979703d9d7SCatalin Marinas static void __init request_standard_resources(void) 1989703d9d7SCatalin Marinas { 1999703d9d7SCatalin Marinas struct memblock_region *region; 2009703d9d7SCatalin Marinas struct resource *res; 2019703d9d7SCatalin Marinas 2029703d9d7SCatalin Marinas kernel_code.start = virt_to_phys(_text); 2039fdc14c5SArd Biesheuvel kernel_code.end = virt_to_phys(__init_begin - 1); 2049703d9d7SCatalin Marinas kernel_data.start = virt_to_phys(_sdata); 2059703d9d7SCatalin Marinas kernel_data.end = virt_to_phys(_end - 1); 2069703d9d7SCatalin Marinas 2079703d9d7SCatalin Marinas for_each_memblock(memory, region) { 2089703d9d7SCatalin Marinas res = alloc_bootmem_low(sizeof(*res)); 209e7cd1903SAKASHI Takahiro if (memblock_is_nomap(region)) { 210e7cd1903SAKASHI Takahiro res->name = "reserved"; 211e7cd1903SAKASHI Takahiro res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 212e7cd1903SAKASHI Takahiro } else { 2139703d9d7SCatalin Marinas res->name = "System RAM"; 214e7cd1903SAKASHI Takahiro res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 215e7cd1903SAKASHI Takahiro } 2169703d9d7SCatalin Marinas res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); 2179703d9d7SCatalin Marinas res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; 2189703d9d7SCatalin Marinas 2199703d9d7SCatalin Marinas request_resource(&iomem_resource, res); 2209703d9d7SCatalin Marinas 2219703d9d7SCatalin Marinas if (kernel_code.start >= res->start && 2229703d9d7SCatalin Marinas kernel_code.end <= res->end) 2239703d9d7SCatalin Marinas request_resource(res, &kernel_code); 2249703d9d7SCatalin Marinas if (kernel_data.start >= res->start && 2259703d9d7SCatalin Marinas kernel_data.end <= res->end) 2269703d9d7SCatalin Marinas request_resource(res, &kernel_data); 2279703d9d7SCatalin Marinas } 2289703d9d7SCatalin Marinas } 2299703d9d7SCatalin Marinas 2304c7aa002SJavi Merino u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; 2314c7aa002SJavi Merino 2329703d9d7SCatalin Marinas void __init setup_arch(char **cmdline_p) 2339703d9d7SCatalin Marinas { 2344b998ff1SSuzuki K. Poulose pr_info("Boot CPU: AArch64 Processor [%08x]\n", read_cpuid_id()); 2359703d9d7SCatalin Marinas 236cfa88c79SMichal Marek sprintf(init_utsname()->machine, UTS_MACHINE); 2379703d9d7SCatalin Marinas init_mm.start_code = (unsigned long) _text; 2389703d9d7SCatalin Marinas init_mm.end_code = (unsigned long) _etext; 2399703d9d7SCatalin Marinas init_mm.end_data = (unsigned long) _edata; 2409703d9d7SCatalin Marinas init_mm.brk = (unsigned long) _end; 2419703d9d7SCatalin Marinas 2429703d9d7SCatalin Marinas *cmdline_p = boot_command_line; 2439703d9d7SCatalin Marinas 244af86e597SLaura Abbott early_fixmap_init(); 245bf4b558eSMark Salter early_ioremap_init(); 2460bf757c7SMark Salter 24761bd93ceSArd Biesheuvel setup_machine_fdt(__fdt_pointer); 24861bd93ceSArd Biesheuvel 2499703d9d7SCatalin Marinas parse_early_param(); 2509703d9d7SCatalin Marinas 2517a9c43beSJon Masters /* 2527a9c43beSJon Masters * Unmask asynchronous aborts after bringing up possible earlycon. 2537a9c43beSJon Masters * (Report possible System Errors once we can report this occurred) 2547a9c43beSJon Masters */ 2557a9c43beSJon Masters local_async_enable(); 2567a9c43beSJon Masters 25786ccce89SMark Rutland /* 25886ccce89SMark Rutland * TTBR0 is only used for the identity mapping at this stage. Make it 25986ccce89SMark Rutland * point to zero page to avoid speculatively fetching new entries. 26086ccce89SMark Rutland */ 26186ccce89SMark Rutland cpu_uninstall_idmap(); 26286ccce89SMark Rutland 2639b08aaa3SShannon Zhao xen_early_init(); 264f84d0275SMark Salter efi_init(); 2659703d9d7SCatalin Marinas arm64_memblock_init(); 2669703d9d7SCatalin Marinas 26738b04a74SJon Masters paging_init(); 26838b04a74SJon Masters 26938b04a74SJon Masters acpi_table_upgrade(); 27038b04a74SJon Masters 27137655163SAl Stone /* Parse the ACPI tables for possible boot-time configuration */ 27237655163SAl Stone acpi_boot_table_init(); 27337655163SAl Stone 2743194ac6eSDavid Daney if (acpi_disabled) 2753194ac6eSDavid Daney unflatten_device_tree(); 2763194ac6eSDavid Daney 2773194ac6eSDavid Daney bootmem_init(); 2783194ac6eSDavid Daney 27939d114ddSAndrey Ryabinin kasan_init(); 28039d114ddSAndrey Ryabinin 2819703d9d7SCatalin Marinas request_standard_resources(); 2829703d9d7SCatalin Marinas 2830e63ea48SArd Biesheuvel early_ioremap_reset(); 284f84d0275SMark Salter 2853194ac6eSDavid Daney if (acpi_disabled) 2867c59a3dfSGraeme Gregory psci_dt_init(); 2873194ac6eSDavid Daney else 288fccb9a81SHanjun Guo psci_acpi_init(); 2893194ac6eSDavid Daney 2900f078336SLorenzo Pieralisi cpu_read_bootcpu_ops(); 2910f078336SLorenzo Pieralisi smp_init_cpus(); 292976d7d3fSLorenzo Pieralisi smp_build_mpidr_hash(); 2939703d9d7SCatalin Marinas 2949703d9d7SCatalin Marinas #ifdef CONFIG_VT 2959703d9d7SCatalin Marinas #if defined(CONFIG_VGA_CONSOLE) 2969703d9d7SCatalin Marinas conswitchp = &vga_con; 2979703d9d7SCatalin Marinas #elif defined(CONFIG_DUMMY_CONSOLE) 2989703d9d7SCatalin Marinas conswitchp = &dummy_con; 2999703d9d7SCatalin Marinas #endif 3009703d9d7SCatalin Marinas #endif 301da9c177dSArd Biesheuvel if (boot_args[1] || boot_args[2] || boot_args[3]) { 302da9c177dSArd Biesheuvel pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n" 303da9c177dSArd Biesheuvel "\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n" 304da9c177dSArd Biesheuvel "This indicates a broken bootloader or old kernel\n", 305da9c177dSArd Biesheuvel boot_args[1], boot_args[2], boot_args[3]); 306da9c177dSArd Biesheuvel } 3079703d9d7SCatalin Marinas } 3089703d9d7SCatalin Marinas 3099703d9d7SCatalin Marinas static int __init topology_init(void) 3109703d9d7SCatalin Marinas { 3119703d9d7SCatalin Marinas int i; 3129703d9d7SCatalin Marinas 3131a2db300SGanapatrao Kulkarni for_each_online_node(i) 3141a2db300SGanapatrao Kulkarni register_one_node(i); 3151a2db300SGanapatrao Kulkarni 3169703d9d7SCatalin Marinas for_each_possible_cpu(i) { 317df857416SMark Rutland struct cpu *cpu = &per_cpu(cpu_data.cpu, i); 3189703d9d7SCatalin Marinas cpu->hotpluggable = 1; 3199703d9d7SCatalin Marinas register_cpu(cpu, i); 3209703d9d7SCatalin Marinas } 3219703d9d7SCatalin Marinas 3229703d9d7SCatalin Marinas return 0; 3239703d9d7SCatalin Marinas } 3249703d9d7SCatalin Marinas subsys_initcall(topology_init); 325f80fb3a3SArd Biesheuvel 326f80fb3a3SArd Biesheuvel /* 327f80fb3a3SArd Biesheuvel * Dump out kernel offset information on panic. 328f80fb3a3SArd Biesheuvel */ 329f80fb3a3SArd Biesheuvel static int dump_kernel_offset(struct notifier_block *self, unsigned long v, 330f80fb3a3SArd Biesheuvel void *p) 331f80fb3a3SArd Biesheuvel { 332f80fb3a3SArd Biesheuvel u64 const kaslr_offset = kimage_vaddr - KIMAGE_VADDR; 333f80fb3a3SArd Biesheuvel 334f80fb3a3SArd Biesheuvel if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset > 0) { 335f80fb3a3SArd Biesheuvel pr_emerg("Kernel Offset: 0x%llx from 0x%lx\n", 336f80fb3a3SArd Biesheuvel kaslr_offset, KIMAGE_VADDR); 337f80fb3a3SArd Biesheuvel } else { 338f80fb3a3SArd Biesheuvel pr_emerg("Kernel Offset: disabled\n"); 339f80fb3a3SArd Biesheuvel } 340f80fb3a3SArd Biesheuvel return 0; 341f80fb3a3SArd Biesheuvel } 342f80fb3a3SArd Biesheuvel 343f80fb3a3SArd Biesheuvel static struct notifier_block kernel_offset_notifier = { 344f80fb3a3SArd Biesheuvel .notifier_call = dump_kernel_offset 345f80fb3a3SArd Biesheuvel }; 346f80fb3a3SArd Biesheuvel 347f80fb3a3SArd Biesheuvel static int __init register_kernel_offset_dumper(void) 348f80fb3a3SArd Biesheuvel { 349f80fb3a3SArd Biesheuvel atomic_notifier_chain_register(&panic_notifier_list, 350f80fb3a3SArd Biesheuvel &kernel_offset_notifier); 351f80fb3a3SArd Biesheuvel return 0; 352f80fb3a3SArd Biesheuvel } 353f80fb3a3SArd Biesheuvel __initcall(register_kernel_offset_dumper); 354