1 /* SPDX-License-Identifier: GPL-2.0-or-later */
5 * Early bringup code for an ARMv7-A with virt extensions.
7 * Tim Deegan <tim@xen.org>
8 * Copyright (c) 2011 Citrix Systems.
11 #include <xen/compile.h>
12 #include <xen/device_tree.h>
13 #include <xen/domain_page.h>
14 #include <xen/grant_table.h>
15 #include <xen/llc-coloring.h>
16 #include <xen/types.h>
17 #include <xen/string.h>
18 #include <xen/serial.h>
19 #include <xen/sched.h>
20 #include <xen/console.h>
25 #include <xen/param.h>
26 #include <xen/softirq.h>
27 #include <xen/keyhandler.h>
30 #include <xen/virtual_region.h>
31 #include <xen/version.h>
33 #include <xen/trace.h>
34 #include <xen/libfdt/libfdt-xen.h>
36 #include <xen/warning.h>
37 #include <xen/hypercall.h>
38 #include <asm/alternative.h>
39 #include <asm/dom0less-build.h>
41 #include <asm/static-evtchn.h>
42 #include <asm/current.h>
43 #include <asm/setup.h>
45 #include <asm/cpuerrata.h>
46 #include <asm/cpufeature.h>
47 #include <asm/platform.h>
48 #include <asm/procinfo.h>
49 #include <asm/setup.h>
54 * Sanitized version of cpuinfo containing only features available on all
55 * cores (only on arm64 as there is no sanitization support on arm32).
57 struct cpuinfo_arm __read_mostly system_cpuinfo;
60 bool __read_mostly acpi_disabled;
63 domid_t __read_mostly max_init_domid;
65 static __used void init_done(void)
69 /* Must be done past setting system_state. */
70 unregister_init_virtual_region();
75 * We have finished booting. Mark the section .data.ro_after_init
78 rc = modify_xen_mappings((unsigned long)&__ro_after_init_start,
79 (unsigned long)&__ro_after_init_end,
82 panic("Unable to mark the .data.ro_after_init section read-only (rc = %d)\n",
85 startup_cpu_idle_loop();
88 static void __init init_idle_domain(void)
91 set_current(idle_vcpu[0]);
92 /* TODO: setup_idle_pagetable(); */
95 static const char * __initdata processor_implementers[] = {
96 ['A'] = "ARM Limited",
97 ['B'] = "Broadcom Corporation",
98 ['C'] = "Cavium Inc.",
99 ['D'] = "Digital Equipment Corp",
100 ['M'] = "Motorola, Freescale Semiconductor Inc.",
101 ['P'] = "Applied Micro",
102 ['Q'] = "Qualcomm Inc.",
103 ['V'] = "Marvell Semiconductor Inc.",
104 ['i'] = "Intel Corporation",
107 static void __init processor_id(void)
109 const char *implementer = "Unknown";
110 struct cpuinfo_arm *c = &system_cpuinfo;
113 current_cpu_data = *c;
115 if ( c->midr.implementer < ARRAY_SIZE(processor_implementers) &&
116 processor_implementers[c->midr.implementer] )
117 implementer = processor_implementers[c->midr.implementer];
119 if ( c->midr.architecture != 0xf )
120 printk("Huh, cpu architecture %x, expected 0xf (defined by cpuid)\n",
121 c->midr.architecture);
123 printk("Processor: %"PRIregister": \"%s\", variant: 0x%x, part 0x%03x,"
124 "rev 0x%x\n", c->midr.bits, implementer,
125 c->midr.variant, c->midr.part_number, c->midr.revision);
127 #if defined(CONFIG_ARM_64)
128 printk("64-bit Execution:\n");
129 printk(" Processor Features: %016"PRIx64" %016"PRIx64"\n",
130 system_cpuinfo.pfr64.bits[0], system_cpuinfo.pfr64.bits[1]);
131 printk(" Exception Levels: EL3:%s EL2:%s EL1:%s EL0:%s\n",
132 cpu_has_el3_32 ? "64+32" : cpu_has_el3_64 ? "64" : "No",
133 cpu_has_el2_32 ? "64+32" : cpu_has_el2_64 ? "64" : "No",
134 cpu_has_el1_32 ? "64+32" : cpu_has_el1_64 ? "64" : "No",
135 cpu_has_el0_32 ? "64+32" : cpu_has_el0_64 ? "64" : "No");
136 printk(" Extensions:%s%s%s%s\n",
137 cpu_has_fp ? " FloatingPoint" : "",
138 cpu_has_simd ? " AdvancedSIMD" : "",
139 cpu_has_gicv3 ? " GICv3-SysReg" : "",
140 cpu_has_sve ? " SVE" : "");
142 /* Warn user if we find unknown floating-point features */
143 if ( cpu_has_fp && (boot_cpu_feature64(fp) >= 2) )
144 printk(XENLOG_WARNING "WARNING: Unknown Floating-point ID:%d, "
145 "this may result in corruption on the platform\n",
146 boot_cpu_feature64(fp));
148 /* Warn user if we find unknown AdvancedSIMD features */
149 if ( cpu_has_simd && (boot_cpu_feature64(simd) >= 2) )
150 printk(XENLOG_WARNING "WARNING: Unknown AdvancedSIMD ID:%d, "
151 "this may result in corruption on the platform\n",
152 boot_cpu_feature64(simd));
154 printk(" Debug Features: %016"PRIx64" %016"PRIx64"\n",
155 system_cpuinfo.dbg64.bits[0], system_cpuinfo.dbg64.bits[1]);
156 printk(" Auxiliary Features: %016"PRIx64" %016"PRIx64"\n",
157 system_cpuinfo.aux64.bits[0], system_cpuinfo.aux64.bits[1]);
158 printk(" Memory Model Features: %016"PRIx64" %016"PRIx64"\n",
159 system_cpuinfo.mm64.bits[0], system_cpuinfo.mm64.bits[1]);
160 printk(" ISA Features: %016"PRIx64" %016"PRIx64"\n",
161 system_cpuinfo.isa64.bits[0], system_cpuinfo.isa64.bits[1]);
165 * On AArch64 these refer to the capabilities when running in
168 if ( cpu_has_aarch32 )
170 printk("32-bit Execution:\n");
171 printk(" Processor Features: %"PRIregister":%"PRIregister"\n",
172 system_cpuinfo.pfr32.bits[0], system_cpuinfo.pfr32.bits[1]);
173 printk(" Instruction Sets:%s%s%s%s%s%s\n",
174 cpu_has_aarch32 ? " AArch32" : "",
175 cpu_has_arm ? " A32" : "",
176 cpu_has_thumb ? " Thumb" : "",
177 cpu_has_thumb2 ? " Thumb-2" : "",
178 cpu_has_thumbee ? " ThumbEE" : "",
179 cpu_has_jazelle ? " Jazelle" : "");
180 printk(" Extensions:%s%s\n",
181 cpu_has_gentimer ? " GenericTimer" : "",
182 cpu_has_security ? " Security" : "");
184 printk(" Debug Features: %"PRIregister"\n",
185 system_cpuinfo.dbg32.bits[0]);
186 printk(" Auxiliary Features: %"PRIregister"\n",
187 system_cpuinfo.aux32.bits[0]);
188 printk(" Memory Model Features: %"PRIregister" %"PRIregister"\n"
189 " %"PRIregister" %"PRIregister"\n",
190 system_cpuinfo.mm32.bits[0], system_cpuinfo.mm32.bits[1],
191 system_cpuinfo.mm32.bits[2], system_cpuinfo.mm32.bits[3]);
192 printk(" ISA Features: %"PRIregister" %"PRIregister" %"PRIregister"\n"
193 " %"PRIregister" %"PRIregister" %"PRIregister"\n",
194 system_cpuinfo.isa32.bits[0], system_cpuinfo.isa32.bits[1],
195 system_cpuinfo.isa32.bits[2], system_cpuinfo.isa32.bits[3],
196 system_cpuinfo.isa32.bits[4], system_cpuinfo.isa32.bits[5]);
200 printk("32-bit Execution: Unsupported\n");
206 void __init discard_initial_modules(void)
208 struct bootmodules *mi = &bootinfo.modules;
212 * When using static heap feature, don't give bootmodules memory back to
215 if ( using_static_heap )
218 for ( i = 0; i < mi->nr_mods; i++ )
220 paddr_t s = mi->module[i].start;
221 paddr_t e = s + PAGE_ALIGN(mi->module[i].size);
223 if ( mi->module[i].kind == BOOTMOD_XEN )
226 if ( !mfn_valid(maddr_to_mfn(s)) ||
227 !mfn_valid(maddr_to_mfn(e)) )
230 fw_unreserved_regions(s, e, init_domheap_pages, 0);
236 remove_early_mappings();
239 /* Relocate the FDT in Xen heap */
240 static void * __init relocate_fdt(paddr_t dtb_paddr, size_t dtb_size)
242 void *fdt = xmalloc_bytes(dtb_size);
245 panic("Unable to allocate memory for relocating the Device-Tree.\n");
247 copy_from_paddr(fdt, dtb_paddr, dtb_size);
252 void __init init_pdx(void)
254 const struct membanks *mem = bootinfo_get_mem();
255 paddr_t bank_start, bank_size, bank_end;
258 * Arm does not have any restrictions on the bits to compress. Pass 0 to
259 * let the common code further restrict the mask.
261 * If the logic changes in pfn_pdx_hole_setup we might have to
262 * update this function too.
264 uint64_t mask = pdx_init_mask(0x0);
267 for ( bank = 0 ; bank < mem->nr_banks; bank++ )
269 bank_start = mem->bank[bank].start;
270 bank_size = mem->bank[bank].size;
272 mask |= bank_start | pdx_region_mask(bank_start, bank_size);
275 for ( bank = 0 ; bank < mem->nr_banks; bank++ )
277 bank_start = mem->bank[bank].start;
278 bank_size = mem->bank[bank].size;
280 if (~mask & pdx_region_mask(bank_start, bank_size))
284 pfn_pdx_hole_setup(mask >> PAGE_SHIFT);
286 for ( bank = 0 ; bank < mem->nr_banks; bank++ )
288 bank_start = mem->bank[bank].start;
289 bank_size = mem->bank[bank].size;
290 bank_end = bank_start + bank_size;
292 set_pdx_range(paddr_to_pfn(bank_start),
293 paddr_to_pfn(bank_end));
297 size_t __read_mostly dcache_line_bytes;
299 /* C entry point for boot CPU */
300 void asmlinkage __init start_xen(unsigned long fdt_paddr)
304 struct bootmodule *xen_bootmodule;
308 dcache_line_bytes = read_dcache_line_bytes();
311 set_processor_id(0); /* needed early, for smp_processor_id() */
313 /* Initialize traps early allow us to get backtrace when an error occurred */
316 smp_clear_cpu_maps();
318 device_tree_flattened = early_fdt_map(fdt_paddr);
319 if ( !device_tree_flattened )
320 panic("Invalid device tree blob at physical address %#lx.\n"
321 "The DTB must be 8-byte aligned and must not exceed 2 MB in size.\n\n"
322 "Please check your bootloader.\n",
325 /* Register Xen's load address as a boot module. */
326 xen_bootmodule = add_boot_module(BOOTMOD_XEN,
327 virt_to_maddr(_start),
328 (paddr_t)(uintptr_t)(_end - _start), false);
329 BUG_ON(!xen_bootmodule);
331 fdt_size = boot_fdt_info(device_tree_flattened, fdt_paddr);
333 cmdline = boot_fdt_cmdline(device_tree_flattened);
334 printk("Command line: %s\n", cmdline);
335 cmdline_parse(cmdline);
340 * Page tables must be setup after LLC coloring initialization because
341 * coloring info are required in order to create colored mappings
344 /* Device-tree was mapped in boot page tables, remap it in the new tables */
345 device_tree_flattened = early_fdt_map(fdt_paddr);
351 /* Parse the ACPI tables for possible boot-time configuration */
352 acpi_boot_table_init();
354 end_boot_allocator();
357 * The memory subsystem has been initialized, we can now switch from
358 * early_boot -> boot.
360 system_state = SYS_STATE_boot;
364 printk("Booting using Device Tree\n");
365 device_tree_flattened = relocate_fdt(fdt_paddr, fdt_size);
366 dt_unflatten_host_device_tree();
370 printk("Booting using ACPI\n");
371 device_tree_flattened = NULL;
383 console_init_preirq();
389 nr_cpu_ids = smp_get_max_cpus();
390 printk(XENLOG_INFO "SMP: Allowing %u CPUs\n", nr_cpu_ids);
393 * Some errata relies on SMCCC version which is detected by psci_init()
394 * (called from smp_init_cpus()).
396 check_local_cpu_errata();
398 check_local_cpu_features();
404 tasklet_subsys_init();
406 if ( xsm_dt_init() != 1 )
407 warning_add("WARNING: SILO mode is not enabled.\n"
408 "It has implications on the security of the system,\n"
409 "unless the communications have been forbidden between\n"
410 "untrusted domains.\n");
412 init_maintenance_interrupt();
413 init_timer_interrupt();
421 setup_system_domains();
424 local_abort_enable();
428 initialize_keytable();
430 console_init_postirq();
432 do_presmp_initcalls();
434 for_each_present_cpu ( i )
436 if ( (num_online_cpus() < nr_cpu_ids) && !cpu_online(i) )
440 printk("Failed to bring up CPU %u (error %d)\n", i, ret);
444 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
445 /* TODO: smp_cpus_done(); */
447 /* This should be done in a vpmu driver but we do not have one yet. */
448 vpmu_is_available = cpu_has_pmu;
451 * The IOMMU subsystem must be initialized before P2M as we need
452 * to gather requirements regarding the maximum IPA bits supported by
456 if ( !iommu_enabled && rc != -ENODEV )
457 panic("Couldn't configure correctly all the IOMMUs.\n");
464 * It needs to be called after do_initcalls to be able to use
465 * stop_machine (tasklets initialized via an initcall).
467 #ifdef CONFIG_HAS_ALTERNATIVE
468 apply_alternatives_all();
470 enable_errata_workarounds();
471 enable_cpu_features();
473 /* Create initial domain 0. */
474 if ( !is_dom0less_mode() )
477 printk(XENLOG_INFO "Xen dom0less mode detected\n");
482 alloc_static_evtchn();
486 * This needs to be called **before** heap_init_late() so modules
487 * will be scrubbed (unless suppressed).
489 discard_initial_modules();
499 /* Hide UART from DOM0 if we're using it */
502 if ( (rc = xsm_set_system_active()) != 0 )
503 panic("xsm: unable to switch to SYSTEM_ACTIVE privilege: %d\n", rc);
505 system_state = SYS_STATE_active;
508 domain_unpause_by_systemcontroller(d);
510 /* Switch on to the dynamically allocated stack for the idle vcpu
511 * since the static one we're running on is about to be freed. */
512 memcpy(idle_vcpu[0]->arch.cpu_info, get_cpu_info(),
513 sizeof(struct cpu_info));
514 switch_stack_and_jump(idle_vcpu[0]->arch.cpu_info, init_done);
517 static int __init init_xen_cap_info(void)
519 /* Interface name is always xen-3.0-* for Xen-3.x. */
522 safe_strcat(xen_cap_info, "xen-3.0-aarch64 ");
524 if ( cpu_has_aarch32 )
525 safe_strcat(xen_cap_info, "xen-3.0-armv7l ");
529 __initcall(init_xen_cap_info);
534 * c-file-style: "BSD"
536 * indent-tabs-mode: nil