Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ept-devel/vmm/core/smp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (show annotations) (download) (as text)
Fri May 4 15:02:17 2012 UTC (12 months, 2 weeks ago) by yuichi_xy
File MIME type: text/x-csrc
File size: 5651 byte(s)
BIOS が設定した MTTR の値から物理メモリアドレス領域のキャッシュ属性を取得し、EPT に反映するようにした。不要な関数テーブルである struct cpuid_func と struct msr_func を削除した。
1 /*
2 * Copyright (c) 2007, 2008 University of Tsukuba
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. Neither the name of the University of Tsukuba nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*
30 * Copyright (c) 2010-2012 Yuichi Watanabe
31 */
32
33 #include <core/assert.h>
34 #include <core/linkage.h>
35 #include <core/spinlock.h>
36 #include <core/string.h>
37 #include <core/cpu.h>
38 #include <core/time.h>
39 #include "apic.h"
40 #include "constants.h"
41 #include "entry.h"
42 #include "int.h"
43 #include "mm.h"
44 #include "panic.h"
45 #include "seg.h"
46 #include "smp.h"
47
48 #define APINIT_ADDR ((APINIT_SEGMENT << 4) + APINIT_OFFSET)
49 #define APINIT_SIZE (cpuinit_end - cpuinit_start)
50 #define APINIT_POINTER(n) ((void *)(apinit + ((u8 *)&n - cpuinit_start)))
51
52 static void ap_start (void);
53
54 static int num_of_processors = 1;
55 static spinlock_t num_of_processors_lock;
56 static void (*bsp_main) (void), (*ap_main) (void);
57 static void *newstack_tmp;
58 static spinlock_t sync_lock;
59 volatile static u32 sync_id;
60 volatile static volatile u32 sync_count;
61 static spinlock_t *apinitlock;
62 volatile static bool all_cpu_started = false;
63
64 /* this function is called after starting AP and switching a stack */
65 /* unlock the spinlock because the stack is switched */
66 static asmlinkage void
67 apinitproc1 (void)
68 {
69 void *newstack;
70
71 newstack = newstack_tmp;
72 spinlock_unlock (apinitlock);
73 spinlock_lock (&num_of_processors_lock);
74 num_of_processors++;
75 spinlock_unlock (&num_of_processors_lock);
76 segment_init_ap();
77 currentcpu->stackaddr = newstack;
78 int_init_ap ();
79 for (;;) {
80 if (all_cpu_started) {
81 break;
82 }
83 cpu_relax();
84 }
85 ap_main ();
86 }
87
88 static asmlinkage void
89 bspinitproc1 (void)
90 {
91 ap_start ();
92 bsp_main ();
93 panic ("bspinitproc1");
94 }
95
96 /* this function is called on AP by entry.s */
97 /* other APs are waiting for spinlock */
98 /* the stack is cpuinit_tmpstack defined in entry.s */
99 /* this function allocates a stack and calls apinitproc1 with the new stack */
100 asmlinkage void
101 apinitproc0 (void)
102 {
103 void *newstack;
104 vmmerr_t err;
105
106 err = alloc_pages (&newstack, NULL, VMM_STACKSIZE / PAGESIZE);
107 if (err) {
108 panic("Failed to allocate pages for stack.");
109 }
110 newstack_tmp = newstack;
111 asm_wrrsp_and_jmp ((ulong)newstack + VMM_STACKSIZE, apinitproc1);
112 }
113
114 static void
115 ap_start (void)
116 {
117 volatile u32 *num;
118 u8 *apinit;
119
120 spinlock_init (&num_of_processors_lock);
121 spinlock_init (&sync_lock);
122 sync_id = 0;
123 sync_count = 0;
124
125 apinit = mapmem (MAPMEM_HPHYS | MAPMEM_WRITE, APINIT_ADDR,
126 APINIT_SIZE);
127 if (apinit == NULL) {
128 panic("Failed to map apinit area.");
129 }
130 memcpy (apinit, cpuinit_start, APINIT_SIZE);
131 num = (volatile u32 *)APINIT_POINTER (apinit_procs);
132 apinitlock = (spinlock_t *)APINIT_POINTER (apinit_lock);
133 *num = 1;
134 spinlock_init (apinitlock);
135 apic_start_ap(APINIT_ADDR);
136 for (;;) {
137 if (*num == get_number_of_processors ())
138 break;
139 cpu_relax();
140 }
141 all_cpu_started = true;
142 unmapmem ((void *)apinit, APINIT_SIZE);
143 }
144
145 static void
146 bspinitproc0 ()
147 {
148 void *newstack;
149 vmmerr_t err;
150
151 err = alloc_pages (&newstack, NULL, VMM_STACKSIZE / PAGESIZE);
152 if (err) {
153 panic("Failed to allocate pages for stack.");
154 }
155 currentcpu->stackaddr = newstack;
156 asm_wrrsp_and_jmp ((ulong)newstack + VMM_STACKSIZE, bspinitproc1);
157 }
158
159 void
160 panic_wakeup_all (void)
161 {
162 apic_broadcast_nmi();
163 }
164
165 void
166 sync_all_processors (void)
167 {
168 u32 saved_id;
169 bool ret = false;
170 int num;
171 u64 timeout = 0;
172 bool detect_lockup = time_initialized ();
173
174 num = get_number_of_processors ();
175
176 spinlock_lock (&sync_lock);
177 saved_id = sync_id;
178 sync_count++;
179 if (sync_count == num) {
180 sync_count = 0;
181 sync_id++;
182 ret = true;
183 }
184 spinlock_unlock (&sync_lock);
185
186 if (detect_lockup) {
187 timeout = get_cpu_time() + 30 * 1000 * 1000; /* 30 sec */
188 }
189 while (!ret) {
190 spinlock_lock (&sync_lock);
191 if (sync_id != saved_id) {
192 ret = true;
193 }
194 spinlock_unlock (&sync_lock);
195 if (detect_lockup) {
196 if (time_after (get_cpu_time (), timeout)) {
197 panic ("Other cpu does not come.");
198 }
199 }
200 cpu_relax();
201 }
202 }
203
204 void
205 start_all_processors (void (*bsp) (void), void (*ap) (void))
206 {
207 bsp_main = bsp;
208 ap_main = ap;
209 bspinitproc0();
210 }
211
212 int
213 get_number_of_processors ()
214 {
215 int num;
216 spinlock_lock (&num_of_processors_lock);
217 num = num_of_processors;
218 spinlock_unlock (&num_of_processors_lock);
219 return num;
220 }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.