summaryrefslogtreecommitdiffstats
path: root/src/kernel/cpumgr.C
blob: d43b28ca802626e7936b4298a0269f24a09ea5a5 (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
#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>

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

cpu_t* CpuManager::getCurrentCPU()
{
    register task_t* current_task = NULL;
    asm volatile("mfsprg3 %0" : "=r" (current_task) );
    return current_task->cpu;
}

void CpuManager::init()
{
    Singleton<CpuManager>::instance().startCPU();
}

void CpuManager::startCPU(ssize_t i)
{
    bool currentCPU = false;
    if (i < 0)
    {
	// TODO: Determine position of this CPU, somehow.
	i = 0;

	currentCPU = true;
    }

    printk("Starting CPU %d...", i);    

    // Initialize CPU structure.
    if (NULL == iv_cpus[i])
    {
	cpu_t* cpu = iv_cpus[i] = new cpu_t;
	
	// Initialize CPU.
	cpu->cpu = i;
	cpu->scheduler = new Scheduler(cpu);
	cpu->kernel_stack = 
	    (void*) (((uint64_t)PageManager::allocatePage(4)) + 16320);
	
	// Create idle task.
	task_t * idle_task = TaskManager::createIdleTask();
	idle_task->cpu = cpu;
	
	// Add to scheduler.
	cpu->scheduler->setIdleTask(idle_task);
    }

    if (currentCPU)
    {
	register task_t* idle_task = iv_cpus[i]->scheduler->getIdleTask();
	asm volatile("mtsprg3 %0" :: "r" (idle_task));

	// TODO: Set up decrementer properly.
	register uint64_t decrementer = 0x0f000000;
	asm volatile("mtdec %0" :: "r"(decrementer));

    }
    else
    {
	// TODO once we get to SMP.
    }
    
    printk("done\n");

    return;
}
OpenPOWER on IntegriCloud