summaryrefslogtreecommitdiffstats
path: root/src/kernel/cpumgr.C
blob: 0f225fc13302fd25a2813a0767a01ef7fc444900 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <kernel/cpumgr.H>
#include <kernel/task.H>
#include <kernel/cpu.H>
#include <kernel/scheduler.H>
#include <kernel/taskmgr.H>
#include <kernel/pagemgr.H>
#include <kernel/console.H>
#include <util/singleton.H>
#include <arch/ppc.H>
#include <kernel/timemgr.H>

cpu_t* CpuManager::cv_cpus[CpuManager::MAXCPUS] = { NULL };

CpuManager::CpuManager()
{
    for (int i = 0; i < MAXCPUS; i++)
	cv_cpus[i] = NULL;
}

cpu_t* CpuManager::getCurrentCPU()
{
    register task_t* current_task = (task_t*) getSPRG3();
    return current_task->cpu;
}

void CpuManager::init()
{
    for (int i = 0; i < KERNEL_MAX_SUPPORTED_CPUS; i++)
	Singleton<CpuManager>::instance().startCPU(i);
}

void CpuManager::init_slave_smp(cpu_t* cpu)
{
    Singleton<CpuManager>::instance().startSlaveCPU(cpu);
}

void CpuManager::startCPU(ssize_t i)
{
    bool currentCPU = false;
    if (i < 0)
    {
	i = getCpuId();
	currentCPU = true;
    }
    else if (getCpuId() == (uint64_t)i)
    {
	currentCPU = true;
    }

    // Initialize CPU structure.
    if (NULL == cv_cpus[i])
    {
	printk("Starting CPU %ld...", i);    
	cpu_t* cpu = cv_cpus[i] = new cpu_t;
	
	// Initialize CPU.
	cpu->cpu = i;
	cpu->scheduler = &Singleton<Scheduler>::instance();
	cpu->kernel_stack = 
	    (void*) (((uint64_t)PageManager::allocatePage(4)) + 16320);
	
	// Create idle task.
	cpu->idle_task = TaskManager::createIdleTask();
	cpu->idle_task->cpu = cpu;
	
	printk("done\n");
    }

    if (currentCPU)
    {
	setSPRG3((uint64_t) cv_cpus[i]->idle_task);

	register uint64_t decrementer = TimeManager::getTimeSliceCount();
	asm volatile("mtdec %0" :: "r"(decrementer));
    }
    return;
}

void CpuManager::startSlaveCPU(cpu_t* cpu)
{
    setSPRG3((uint64_t) cpu->idle_task);
    
    register uint64_t decrementer = TimeManager::getTimeSliceCount();
    asm volatile("mtdec %0" :: "r"(decrementer));

    return;
}

uint64_t isCPU0()
{
    return (0 == getCpuId());
}
OpenPOWER on IntegriCloud