Start multi cores in imx6q
This commit is contained in:
@@ -37,5 +37,6 @@ struct XiziBootNode {
|
||||
};
|
||||
|
||||
bool hardkernel_init(struct TraceTag*);
|
||||
bool secondary_cpu_hardkernel_init(int cpu_id, struct TraceTag* _hardkernel_tag);
|
||||
bool softkernel_init(struct TraceTag* _hardkernel_tag, struct TraceTag* _softkernel_tag);
|
||||
void show_xizi_bar(void);
|
||||
|
||||
@@ -30,6 +30,7 @@ Modification:
|
||||
#pragma once
|
||||
|
||||
#include "core.h"
|
||||
#include "spinlock.h"
|
||||
#include "trap_common.h"
|
||||
|
||||
struct CPU {
|
||||
@@ -44,4 +45,6 @@ extern struct CPU global_cpus[NR_CPU];
|
||||
static inline struct CPU* cur_cpu(void)
|
||||
{
|
||||
return &global_cpus[cur_cpuid()];
|
||||
}
|
||||
}
|
||||
|
||||
struct spinlock whole_kernel_lock;
|
||||
@@ -72,6 +72,7 @@ uintptr_t* _page_walk(uintptr_t* pgdir, uintptr_t vaddr, bool alloc);
|
||||
|
||||
extern struct TopLevelPageDirectory kern_pgdir;
|
||||
void load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driver_tag);
|
||||
void secondary_cpu_load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driver_tag);
|
||||
|
||||
extern struct XiziPageManager xizi_pager;
|
||||
bool module_pager_init(struct PagerRightGroup*);
|
||||
@@ -27,37 +27,130 @@ Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. first version
|
||||
*************************************************/
|
||||
/// @todo use hardkernel
|
||||
#include "cortex_a9.h"
|
||||
#include "regssrc.h"
|
||||
|
||||
#include "kern_init.h"
|
||||
#include "multicores.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "trap_common.h"
|
||||
|
||||
void configure_cpu(uint32_t cpu)
|
||||
{
|
||||
const unsigned int all_ways = 0xf;
|
||||
|
||||
disable_strict_align_check();
|
||||
|
||||
// Enable branch prediction
|
||||
arm_branch_target_cache_invalidate();
|
||||
arm_branch_prediction_enable();
|
||||
|
||||
// Enable L1 caches
|
||||
// arm_dcache_enable();
|
||||
// arm_dcache_invalidate();
|
||||
// arm_icache_enable();
|
||||
// arm_icache_invalidate();
|
||||
|
||||
// Invalidate SCU copy of TAG RAMs
|
||||
scu_secure_invalidate(cpu, all_ways);
|
||||
|
||||
// Join SMP
|
||||
scu_join_smp();
|
||||
scu_enable_maintenance_broadcast();
|
||||
}
|
||||
|
||||
typedef void (*cpu_entry_point_t)(void* arg);
|
||||
typedef struct _core_startup_info {
|
||||
cpu_entry_point_t entry; //!< Function to call after starting a core.
|
||||
void* arg; //!< Argument to pass core entry point.
|
||||
} core_startup_info_t;
|
||||
static core_startup_info_t s_core_info[NR_CPU] = { { 0 } };
|
||||
|
||||
static void common_cpu_entry(void)
|
||||
{
|
||||
uint32_t myCoreNumber = cpu_get_current();
|
||||
core_startup_info_t* info = &s_core_info[myCoreNumber];
|
||||
|
||||
// Call the requested entry point for this CPU number.
|
||||
if (info->entry) {
|
||||
info->entry(info->arg);
|
||||
}
|
||||
}
|
||||
|
||||
extern void _boot_start();
|
||||
void cpu_start_secondary(uint8_t coreNumber, cpu_entry_point_t entryPoint, void* arg)
|
||||
{
|
||||
// Save entry point and arg.
|
||||
s_core_info[coreNumber].entry = entryPoint;
|
||||
s_core_info[coreNumber].arg = arg;
|
||||
|
||||
// Prepare pointers for ROM code. The entry point is always _start, which does some
|
||||
// basic preparatory work and then calls the common_cpu_entry function, which itself
|
||||
// calls the entry point saved in s_core_info.
|
||||
switch (coreNumber) {
|
||||
case 1:
|
||||
HW_SRC_GPR3_WR((uint32_t)&_boot_start);
|
||||
// HW_SRC_GPR4_WR((uint32_t)common_cpu_entry);
|
||||
|
||||
HW_SRC_SCR.B.CORE1_ENABLE = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HW_SRC_GPR5_WR((uint32_t)&_boot_start);
|
||||
// HW_SRC_GPR6_WR((uint32_t)common_cpu_entry);
|
||||
|
||||
HW_SRC_SCR.B.CORE2_ENABLE = 1;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
HW_SRC_GPR7_WR((uint32_t)&_boot_start);
|
||||
// HW_SRC_GPR8_WR((uint32_t)common_cpu_entry);
|
||||
|
||||
HW_SRC_SCR.B.CORE3_ENABLE = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern uint32_t _binary_init_start[], _binary_default_fs_start[];
|
||||
extern int sys_spawn(char* path, char** argv);
|
||||
static struct TraceTag hardkernel_tag, softkernel_tag;
|
||||
|
||||
static bool init = false;
|
||||
int main(void)
|
||||
{
|
||||
/* init tracer */
|
||||
// clang-format off
|
||||
tracer_init(); // init tracer system
|
||||
struct TraceTag hardkernel_tag, softkernel_tag;
|
||||
if (!CreateResourceTag(&hardkernel_tag, RequireRootTag(), "hardkernel", TRACER_OWNER, NULL) ||
|
||||
!CreateResourceTag(&softkernel_tag, RequireRootTag(), "softkernel", TRACER_OWNER, NULL)) {
|
||||
ERROR("Failed to create hardkernel owner and softkernel owner.\n");
|
||||
return -1;
|
||||
}
|
||||
// clang-format on
|
||||
uint32_t cpu_id = cur_cpuid();
|
||||
|
||||
/* init hardkernel */
|
||||
if (!hardkernel_init(&hardkernel_tag)) {
|
||||
return -1;
|
||||
if (cpu_id == 0) {
|
||||
tracer_init(); // init tracer system
|
||||
// clang-format off
|
||||
if (!CreateResourceTag(&hardkernel_tag, RequireRootTag(), "hardkernel", TRACER_OWNER, NULL) ||
|
||||
!CreateResourceTag(&softkernel_tag, RequireRootTag(), "softkernel", TRACER_OWNER, NULL)) {
|
||||
ERROR("Failed to create hardkernel owner and softkernel owner.\n");
|
||||
return -1;
|
||||
}
|
||||
// clang-format on
|
||||
/* init hardkernel */
|
||||
if (!hardkernel_init(&hardkernel_tag)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
spinlock_init(&whole_kernel_lock, "wklock");
|
||||
} else {
|
||||
configure_cpu(cpu_id);
|
||||
DEBUG_PRINTF("CPU %d started init: %d(at %x).\n", cur_cpuid(), init, &init);
|
||||
spinlock_lock(&whole_kernel_lock);
|
||||
secondary_cpu_hardkernel_init(cpu_id, &hardkernel_tag);
|
||||
spinlock_unlock(&whole_kernel_lock);
|
||||
DEBUG_PRINTF("CPU %d started done.\n", cur_cpuid());
|
||||
}
|
||||
|
||||
struct TraceTag main_intr_tag;
|
||||
AchieveResourceTag(&main_intr_tag, &hardkernel_tag, "intr-ac-resource");
|
||||
struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&main_intr_tag);
|
||||
int cpu_id = p_intr_driver->cur_cpu_id();
|
||||
// struct TraceTag main_intr_tag;
|
||||
// AchieveResourceTag(&main_intr_tag, &hardkernel_tag, "intr-ac-resource");
|
||||
// struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&main_intr_tag);
|
||||
if (cpu_id == 0) {
|
||||
/* init softkernel */
|
||||
if (!softkernel_init(&hardkernel_tag, &softkernel_tag)) {
|
||||
@@ -66,18 +159,30 @@ int main(void)
|
||||
show_xizi_bar();
|
||||
|
||||
int cpu_count = NR_CPU;
|
||||
scu_enable();
|
||||
configure_cpu(cpu_id);
|
||||
for (int i = 1; i < cpu_count; i++) {
|
||||
// start secondary cpus
|
||||
cpu_start_secondary(i, NULL, 0);
|
||||
}
|
||||
|
||||
/* start first task */
|
||||
char* init_task_param[2] = { "/app/init", 0 };
|
||||
spawn_embedded_task((char*)_binary_init_start, "init", init_task_param);
|
||||
char* fs_server_task_param[2] = { "/app/fs_server", 0 };
|
||||
spawn_embedded_task((char*)_binary_default_fs_start, "memfs", fs_server_task_param);
|
||||
|
||||
init = true;
|
||||
}
|
||||
|
||||
/* start first task */
|
||||
char* init_task_param[2] = { "/app/init", 0 };
|
||||
spawn_embedded_task((char*)_binary_init_start, "init", init_task_param);
|
||||
char* fs_server_task_param[2] = { "/app/fs_server", 0 };
|
||||
spawn_embedded_task((char*)_binary_default_fs_start, "memfs", fs_server_task_param);
|
||||
while (!init)
|
||||
;
|
||||
|
||||
/* start scheduler */
|
||||
struct SchedulerRightGroup scheduler_rights;
|
||||
assert(AchieveResourceTag(&scheduler_rights.mmu_driver_tag, &hardkernel_tag, "mmu-ac-resource"));
|
||||
assert(AchieveResourceTag(&scheduler_rights.intr_driver_tag, &hardkernel_tag, "intr-ac-resource"));
|
||||
// while (true) { }
|
||||
xizi_task_manager.task_scheduler(scheduler_rights);
|
||||
|
||||
// never reached
|
||||
|
||||
@@ -293,6 +293,12 @@ void load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driv
|
||||
// dev mem
|
||||
_map_pages((uintptr_t*)kern_pgdir.pd_addr, DEV_VRTMEM_BASE, DEV_PHYMEM_BASE, DEV_MEM_SZ, dev_attr);
|
||||
|
||||
// _p_pgtbl_mmu_access->LoadPgdir((uintptr_t)V2P(kern_pgdir.pd_addr));
|
||||
_p_pgtbl_mmu_access->LoadPgdirCrit((uintptr_t)V2P(kern_pgdir.pd_addr), intr_driver_tag);
|
||||
}
|
||||
|
||||
void secondary_cpu_load_kern_pgdir(struct TraceTag* mmu_driver_tag, struct TraceTag* intr_driver_tag)
|
||||
{
|
||||
// _p_pgtbl_mmu_access->LoadPgdir((uintptr_t)V2P(kern_pgdir.pd_addr));
|
||||
_p_pgtbl_mmu_access->LoadPgdirCrit((uintptr_t)V2P(kern_pgdir.pd_addr), intr_driver_tag);
|
||||
}
|
||||
@@ -49,6 +49,9 @@ bool clock_intr_handler_init(struct TraceTag* p_clock_driver_tag)
|
||||
uint64_t global_tick = 0;
|
||||
int xizi_clock_handler(int irq, void* tf, void* arg)
|
||||
{
|
||||
// spinlock_lock(&whole_kernel_lock);
|
||||
// DEBUG_PRINTF("CPU %d\n", cpu_get_current());
|
||||
// spinlock_unlock(&whole_kernel_lock);
|
||||
/* handle clock interrupt using driver */
|
||||
if (p_clock_driver->is_timer_expired()) {
|
||||
p_clock_driver->clear_clock_intr();
|
||||
|
||||
@@ -77,7 +77,9 @@ void intr_irq_dispatch(struct trapframe* tf)
|
||||
// distribute irq
|
||||
irq_handler_t isr = p_intr_driver->sw_irqtbl[irq].handler;
|
||||
if (isr) {
|
||||
// spinlock_lock(&whole_kernel_lock);
|
||||
isr(irq, tf, NULL);
|
||||
// spinlock_unlock(&whole_kernel_lock);
|
||||
} else {
|
||||
default_interrupt_routine();
|
||||
}
|
||||
|
||||
@@ -48,6 +48,11 @@ bool swi_distributer_init(struct SwiDispatcherRightGroup* _right_group)
|
||||
extern void context_switch(struct context**, struct context*);
|
||||
void software_irq_dispatch(struct trapframe* tf)
|
||||
{
|
||||
bool is_my_lock = false;
|
||||
if (whole_kernel_lock.owner_cpu != cur_cpuid()) {
|
||||
spinlock_lock(&whole_kernel_lock);
|
||||
is_my_lock = true;
|
||||
}
|
||||
assert(p_intr_driver != NULL);
|
||||
|
||||
p_intr_driver->cpu_irq_disable();
|
||||
@@ -59,6 +64,7 @@ void software_irq_dispatch(struct trapframe* tf)
|
||||
if (cur_task && cur_task->state != DEAD) {
|
||||
cur_task->main_thread.trapframe = tf;
|
||||
// call syscall
|
||||
|
||||
int ret = arch_syscall(cur_task->main_thread.trapframe, &syscall_num);
|
||||
|
||||
if (syscall_num != SYSCALL_EXEC) {
|
||||
@@ -75,5 +81,9 @@ void software_irq_dispatch(struct trapframe* tf)
|
||||
if (syscall_num == SYSCALL_EXIT) {
|
||||
ERROR("Exit reaches");
|
||||
}
|
||||
|
||||
if (is_my_lock) {
|
||||
spinlock_unlock(&whole_kernel_lock);
|
||||
}
|
||||
p_intr_driver->cpu_irq_enable();
|
||||
}
|
||||
Reference in New Issue
Block a user