Loading [MathJax]/extensions/tex2jax.js
CS350 COS
COS
All Data Structures Files Functions Variables Typedefs Macros
mp.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/kassert.h>
#include <sys/kconfig.h>
#include <sys/kdebug.h>
#include <sys/kmem.h>
#include <sys/ktime.h>
#include <sys/mp.h>
#include <machine/amd64.h>
#include <machine/amd64op.h>
#include <machine/pmap.h>
#include <machine/lapic.h>
#include <machine/mp.h>
#include <machine/trap.h>
Include dependency graph for mp.c:

Go to the source code of this file.

Data Structures

struct  CrossCallFrame
 
struct  CPUState
 

Macros

#define MP_WAITTIME   250000000ULL
 

Typedefs

typedef struct CrossCallFrame CrossCallFrame
 
typedef struct CPUState CPUState
 

Functions

static int MPBootAP (int procNo)
 
void MP_Init ()
 
void MP_InitAP ()
 
void MP_SetState (int state)
 
int MP_GetCPUs ()
 
void MP_CrossCallTrap ()
 
int MP_CrossCall (CrossCallCB cb, void *arg)
 
static int MPPing (void *arg)
 
static void Debug_CrossCall (int argc, const char *argv[])
 
 REGISTER_DBGCMD (crosscall, "Ping crosscall", Debug_CrossCall)
 
static void Debug_CPUS (int argc, const char *argv[])
 
 REGISTER_DBGCMD (cpus, "Show MP information", Debug_CPUS)
 
static void Debug_CPU (int argc, const char *argv[])
 
 REGISTER_DBGCMD (cpu, "Current CPU number", Debug_CPU)
 

Variables

uint8_t mpstart_begin []
 
uint8_t mpstart_end []
 
AS systemAS
 
const char * CPUStateToString []
 
static volatile bool booted
 
static volatile int lastCPU
 
static volatile CPUState cpus [MAX_CPUS]
 

Data Structure Documentation

◆ CrossCallFrame

struct CrossCallFrame

Definition at line 27 of file mp.c.

Collaboration diagram for CrossCallFrame:
[legend]
Data Fields
void * arg
CrossCallCB cb
volatile int count
volatile int done[MAX_CPUS]
volatile int status[MAX_CPUS]

◆ CPUState

struct CPUState

Definition at line 41 of file mp.c.

Collaboration diagram for CPUState:
[legend]
Data Fields
CrossCallFrame * frame
UnixEpochNS heartbeat
int state

Macro Definition Documentation

◆ MP_WAITTIME

#define MP_WAITTIME   250000000ULL

Definition at line 25 of file mp.c.

Typedef Documentation

◆ CPUState

typedef struct CPUState CPUState

◆ CrossCallFrame

Function Documentation

◆ Debug_CPU()

static void Debug_CPU ( int  argc,
const char *  argv[] 
)
static

Definition at line 247 of file mp.c.

248{
249 kprintf("CPU %d\n", CPU());
250}
#define CPU
Definition: mp.h:7
int kprintf(const char *fmt,...)
Definition: printf.c:210
Here is the call graph for this function:

◆ Debug_CPUS()

static void Debug_CPUS ( int  argc,
const char *  argv[] 
)
static

Definition at line 233 of file mp.c.

234{
235 int c;
236
237 for (c = 0; c < MAX_CPUS; c++) {
238 if (cpus[c].state != CPUSTATE_NOT_PRESENT) {
239 kprintf("CPU %d: %s\n", c, CPUStateToString[cpus[c].state]);
240 }
241 }
242}
#define CPUSTATE_NOT_PRESENT
Definition: mp.h:5
#define MAX_CPUS
Definition: kconfig.h:8
static volatile CPUState cpus[MAX_CPUS]
Definition: mp.c:49
const char * CPUStateToString[]
Definition: mp.c:35
Here is the call graph for this function:

◆ Debug_CrossCall()

static void Debug_CrossCall ( int  argc,
const char *  argv[] 
)
static

Definition at line 212 of file mp.c.

213{
214 int i;
215 UnixEpochNS startTS, stopTS;
216
217 startTS = KTime_GetEpochNS();
218 for (i = 0; i < 32; i++) {
220 }
221 stopTS = KTime_GetEpochNS();
222
223 // XXX: Print min and max
224 kprintf("Average CrossCall Latency: %llu ns\n",
225 (stopTS - startTS) / 32ULL);
226
227 return;
228}
UnixEpochNS KTime_GetEpochNS()
Definition: ktime.c:194
uint64_t UnixEpochNS
Definition: ktime.h:19
static int MPPing(void *arg)
Definition: mp.c:205
int MP_CrossCall(CrossCallCB cb, void *arg)
Definition: mp.c:168
#define NULL
Definition: stddef.h:6
Here is the call graph for this function:

◆ MP_CrossCall()

int MP_CrossCall ( CrossCallCB  cb,
void *  arg 
)

Definition at line 168 of file mp.c.

169{
170 volatile CrossCallFrame frame;
171
172 // Setup frame
173 memset((void *)&frame, 0, sizeof(frame));
174 frame.cb = cb;
175 frame.arg = arg;
176 frame.count = 1;
177
179
180 cpus[CPU()].frame = (CrossCallFrame *)&frame;
181 cpuid(0, 0, 0, 0, 0);
182
184 return -1;
185
186 // Run on the local CPU
187 frame.status[CPU()] = cb(arg);
188 frame.done[CPU()] = 1;
189
190 // Wait for all to respond
191 while (frame.count < lastCPU) {
192 // Check for timeout
193
194 // XXX: Should dump the crosscall frame
195 }
196 cpus[CPU()].frame = NULL;
197 cpuid(0, 0, 0, 0, 0);
198
200
201 return 0;
202}
static INLINE void cpuid(uint32_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Definition: amd64op.h:85
void Critical_Exit()
Definition: critical.c:35
void Critical_Enter()
Definition: critical.c:28
int LAPIC_Broadcast(int vector)
Definition: lapic.c:143
static volatile int lastCPU
Definition: mp.c:48
CrossCallFrame * frame
Definition: mp.c:44
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
#define T_CROSSCALL
Definition: trap.h:43
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MP_CrossCallTrap()

void MP_CrossCallTrap ( )

Definition at line 140 of file mp.c.

141{
142 int c;
143
144 cpuid(0, 0, 0, 0, 0);
145
147
148 for (c = 0; c <= lastCPU; c++) {
149 CrossCallFrame *frame = cpus[c].frame;
150 if (frame == NULL)
151 continue;
152
153 if (frame->done[CPU()] == 1)
154 continue;
155
156 frame->status[CPU()] = (frame->cb)(frame->arg);
157 frame->done[CPU()] = 1;
158
159 // Increment
160 __sync_add_and_fetch(&frame->count, 1);
161 }
162
164}
volatile int status[MAX_CPUS]
Definition: mp.c:32
volatile int done[MAX_CPUS]
Definition: mp.c:31
volatile int count
Definition: mp.c:30
void * arg
Definition: mp.c:29
CrossCallCB cb
Definition: mp.c:28
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MP_GetCPUs()

int MP_GetCPUs ( )

Definition at line 134 of file mp.c.

135{
136 return lastCPU;
137}
Here is the caller graph for this function:

◆ MP_Init()

void MP_Init ( )

Definition at line 91 of file mp.c.

92{
93 int i;
94 kprintf("Booting on CPU %u\n", CPU());
95
97 cpus[CPU()].frame = NULL;
98
99 for (i = 1; i < MAX_CPUS; i++) {
101 cpus[i].frame = NULL;
102 }
103
104 /*
105 * XXX: We really should read from the MP Table, but this appears to be
106 * reliable for now.
107 */
108 lastCPU = 0;
109 for (i = 1; i < MAX_CPUS; i++) {
110 if (MPBootAP(i) < 0)
111 break;
112
113 lastCPU = i;
114 }
115 lastCPU++;
116}
#define CPUSTATE_BOOTED
Definition: mp.h:6
int state
Definition: mp.c:42
static int MPBootAP(int procNo)
Definition: mp.c:52
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MP_InitAP()

void MP_InitAP ( )

Definition at line 119 of file mp.c.

120{
121 kprintf("AP %d booted!\n", CPU());
123 booted = 1;
124}
static volatile bool booted
Definition: mp.c:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MP_SetState()

void MP_SetState ( int  state)

Definition at line 127 of file mp.c.

128{
129 ASSERT(state > 0 && state <= CPUSTATE_MAX);
130 cpus[CPU()].state = state;
131}
#define CPUSTATE_MAX
Definition: mp.h:8
#define ASSERT(_x)
Definition: kassert.h:8
Here is the caller graph for this function:

◆ MPBootAP()

static int MPBootAP ( int  procNo)
static

Definition at line 52 of file mp.c.

53{
54 UnixEpochNS startTS, stopTS;
55 /*
56 * Arguments to mpstart are stored at 0x6F00
57 * arg[0] = CR3
58 * arg[1] = RSP
59 */
60 volatile uint64_t *args = (uint64_t *)DMPA2VA(0x6F00);
61
62 kprintf("Starting processor %d\n", procNo);
64
65 args[0] = DMVA2PA((uint64_t)systemAS.root);
66 args[1] = PGSIZE + (uint64_t)PAlloc_AllocPage();
67
68 kprintf("CR3: %016llx RSP: %016llx\n", args[0], args[1]);
69
70 booted = 0;
71 LAPIC_StartAP(procNo, 0x7000);
72
73 startTS = KTime_GetEpochNS();
74 while (1) {
75 if (booted == 1)
76 break;
77
78 stopTS = KTime_GetEpochNS();
79 if ((stopTS - startTS) > MP_WAITTIME) {
80 kprintf("Processor %d did not respond in %d ms\n",
81 procNo, MP_WAITTIME / 1000000ULL);
82 PAlloc_Release((void *)(args[1] - PGSIZE));
83 return -1;
84 }
85 }
86
87 return 0;
88}
void PAlloc_Release(void *pg)
Definition: palloc.c:265
void * PAlloc_AllocPage()
Definition: palloc.c:188
void LAPIC_StartAP(uint8_t apicid, uint32_t addr)
Definition: lapic.c:116
#define PGSIZE
Definition: malloc.c:21
AS systemAS
Definition: pmap.c:15
uint8_t mpstart_begin[]
#define MP_WAITTIME
Definition: mp.c:25
uint8_t mpstart_end[]
#define DMVA2PA(dmva)
Definition: pmap.h:47
PageTable * root
Definition: pmap.h:53
#define DMPA2VA(pa)
Definition: pmap.h:48
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:177
unsigned long uint64_t
Definition: types.h:13
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MPPing()

static int MPPing ( void *  arg)
static

Definition at line 205 of file mp.c.

206{
207 //kprintf("CPU %d Ack\n", CPU());
208 return 0;
209}
Here is the caller graph for this function:

◆ REGISTER_DBGCMD() [1/3]

REGISTER_DBGCMD ( cpu  ,
"Current CPU number"  ,
Debug_CPU   
)

◆ REGISTER_DBGCMD() [2/3]

REGISTER_DBGCMD ( cpus  ,
"Show MP information"  ,
Debug_CPUS   
)

◆ REGISTER_DBGCMD() [3/3]

REGISTER_DBGCMD ( crosscall  ,
"Ping crosscall"  ,
Debug_CrossCall   
)

Variable Documentation

◆ booted

volatile bool booted
static

Definition at line 47 of file mp.c.

◆ cpus

volatile CPUState cpus[MAX_CPUS]
static

Definition at line 49 of file mp.c.

◆ CPUStateToString

const char* CPUStateToString[]
Initial value:
= {
"NOT PRESENT",
"BOOTED",
"HALTED",
}

Definition at line 35 of file mp.c.

◆ lastCPU

volatile int lastCPU
static

Definition at line 48 of file mp.c.

◆ mpstart_begin

uint8_t mpstart_begin[]
extern

◆ mpstart_end

uint8_t mpstart_end[]
extern

◆ systemAS

AS systemAS
extern

Definition at line 15 of file pmap.c.