int __init arch_smp_prepare_cpus(void) { int rc = VMM_OK; struct vmm_devtree_node *node; virtual_addr_t ca9_scu_base; u32 ncores; int i; /* Get the SCU node in the dev tree */ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_HOSTINFO_NODE_NAME VMM_DEVTREE_PATH_SEPARATOR_STRING "scu"); if (!node) { return VMM_EFAIL; } /* map the SCU physical address to virtual address */ rc = vmm_devtree_regmap(node, &ca9_scu_base, 0); if (rc) { return rc; } /* How many ARM core do we have */ ncores = scu_get_core_count((void *)ca9_scu_base); /* Find out the number of SMP-enabled cpu cores */ for (i = 0; i < CONFIG_CPU_COUNT; i++) { /* build the possible CPU map */ if ((i >= ncores) || !scu_cpu_core_is_smp((void *)ca9_scu_base, i)) { /* Update the cpu_possible bitmap */ vmm_set_cpu_possible(i, 0); } else { vmm_set_cpu_possible(i, 1); } } /* Enable snooping through SCU */ scu_enable((void *)ca9_scu_base); /* unmap the SCU node */ rc = vmm_devtree_regunmap(node, ca9_scu_base, 0); return rc; }
int __init arch_smp_init_cpus(void) { u32 ncores; int i, rc = VMM_OK; struct vmm_devtree_node *node; /* Get the PMU node in the dev tree */ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "pmu"); if (!node) { return VMM_EFAIL; } /* Map the PMU physical address to virtual address */ rc = vmm_devtree_regmap(node, &pmu_base, 0); if (rc) { return rc; } /* Get the SCU node in the dev tree */ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "scu"); if (!node) { return VMM_EFAIL; } /* Map the SCU physical address to virtual address */ rc = vmm_devtree_regmap(node, &scu_base, 0); if (rc) { return rc; } /* How many ARM core do we have */ ncores = scu_get_core_count((void *)scu_base); /* Update the cpu_possible bitmap based on SCU */ for (i = 0; i < CONFIG_CPU_COUNT; i++) { if ((i < ncores) && scu_cpu_core_is_smp((void *)scu_base, i)) { vmm_set_cpu_possible(i, TRUE); } } return VMM_OK; }
void vmm_init(void) { int ret; #if defined(CONFIG_SMP) u32 c; #endif u32 cpu = vmm_smp_processor_id(); struct vmm_work sysinit; /* Mark this CPU possible & present */ vmm_set_cpu_possible(cpu, TRUE); vmm_set_cpu_present(cpu, TRUE); /* Print version string */ vmm_printf("\n"); vmm_printf("%s v%d.%d.%d (%s %s)\n", VMM_NAME, VMM_VERSION_MAJOR, VMM_VERSION_MINOR, VMM_VERSION_RELEASE, __DATE__, __TIME__); vmm_printf("\n"); /* Initialize host virtual address space */ vmm_printf("Initialize Host Address Space\n"); ret = vmm_host_aspace_init(); if (ret) { vmm_hang(); } /* Initialize heap */ vmm_printf("Initialize Heap Management\n"); ret = vmm_heap_init(); if (ret) { vmm_hang(); } /* Initialize per-cpu area */ vmm_printf("Initialize PerCPU Areas\n"); ret = vmm_percpu_init(); if (ret) { vmm_hang(); } /* Initialize device tree */ vmm_printf("Initialize Device Tree\n"); ret = vmm_devtree_init(); if (ret) { vmm_hang(); } /* Initialize host interrupts */ vmm_printf("Initialize Host IRQ\n"); ret = vmm_host_irq_init(); if (ret) { vmm_hang(); } /* Initialize CPU early */ vmm_printf("Initialize CPU Early\n"); ret = arch_cpu_early_init(); if (ret) { vmm_hang(); } /* Initialize Board early */ vmm_printf("Initialize Board Early\n"); ret = arch_board_early_init(); if (ret) { vmm_hang(); } /* Initialize standerd input/output */ vmm_printf("Initialize Standard I/O\n"); ret = vmm_stdio_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize clocksource manager */ vmm_printf("Initialize Clocksource Manager\n"); ret = vmm_clocksource_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize clockchip manager */ vmm_printf("Initialize Clockchip Manager\n"); ret = vmm_clockchip_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize hypervisor timer */ vmm_printf("Initialize Hypervisor Timer\n"); ret = vmm_timer_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize soft delay */ vmm_printf("Initialize Soft Delay\n"); ret = vmm_delay_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize hypervisor manager */ vmm_printf("Initialize Hypervisor Manager\n"); ret = vmm_manager_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize hypervisor scheduler */ vmm_printf("Initialize Hypervisor Scheduler\n"); ret = vmm_scheduler_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize hypervisor threads */ vmm_printf("Initialize Hypervisor Threads\n"); ret = vmm_threads_init(); if (ret) { vmm_panic("Error %d\n", ret); } #ifdef CONFIG_PROFILE /* Intialize hypervisor profiler */ vmm_printf("Initialize Hypervisor Profiler\n"); ret = vmm_profiler_init(); if (ret) { vmm_panic("Error %d\n", ret); } #endif #if defined(CONFIG_SMP) /* Initialize inter-processor interrupts */ vmm_printf("Initialize Inter Processor Interrupts\n") ret = vmm_smp_ipi_init(); if (ret) { vmm_hang(); } /* Initialize secondary CPUs */ vmm_printf("Initialize Secondary CPUs\n"); ret = arch_smp_init_cpus(); if (ret) { vmm_panic("Error %d\n", ret); } /* Prepare secondary CPUs */ ret = arch_smp_prepare_cpus(vmm_num_possible_cpus()); if (ret) { vmm_panic("Error %d\n", ret); } /* Start each present secondary CPUs */ for_each_present_cpu(c) { if (c == cpu) { continue; } ret = arch_smp_start_cpu(c); if (ret) { vmm_printf("Failed to start CPU%d\n", ret); } } /* Initialize hypervisor load balancer */ vmm_printf("Initialize Hypervisor Load Balancer\n"); ret = vmm_loadbal_init(); if (ret) { vmm_panic("Error %d\n", ret); } #endif /* Initialize workqueue framework */ vmm_printf("Initialize Workqueue Framework\n"); ret = vmm_workqueue_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Initialize wallclock */ vmm_printf("Initialize Wallclock Subsystem\n"); ret = vmm_wallclock_init(); if (ret) { vmm_panic("Error %d\n", ret); } /* Schedule system initialization work */ INIT_WORK(&sysinit, &system_init_work); vmm_workqueue_schedule_work(NULL, &sysinit); /* Start timer (Must be last step) */ vmm_timer_start(); /* Wait here till scheduler gets invoked by timer */ vmm_hang(); }