/[dynamips]/upstream/dynamips-0.2.6-RC5/cpu.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.6-RC5/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations)
Sat Oct 6 16:09:07 2007 UTC (14 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 5787 byte(s)
dynamips-0.2.6-RC5

1 /*
2 * Cisco 7200 (Predator) simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Management of CPU groups (for MP systems).
6 */
7
8 #define _GNU_SOURCE
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include <pthread.h>
19
20 #include "mips64.h"
21 #include "dynamips.h"
22 #include "cpu.h"
23 #include "memory.h"
24 #include "device.h"
25 #include "cp0.h"
26 #include "mips64_exec.h"
27 #include "vm.h"
28
29 /* Find a CPU in a group given its ID */
30 cpu_mips_t *cpu_group_find_id(cpu_group_t *group,u_int id)
31 {
32 cpu_mips_t *cpu;
33
34 if (!group)
35 return NULL;
36
37 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
38 if (cpu->id == id)
39 return cpu;
40
41 return NULL;
42 }
43
44 /* Find the highest CPU ID in a CPU group */
45 int cpu_group_find_highest_id(cpu_group_t *group,u_int *highest_id)
46 {
47 cpu_mips_t *cpu;
48 u_int max_id = 0;
49
50 if (!group || group->cpu_list)
51 return(-1);
52
53 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
54 if (cpu->id >= max_id)
55 max_id = cpu->id;
56
57 *highest_id = max_id;
58 return(0);
59 }
60
61 /* Add a CPU in a CPU group */
62 int cpu_group_add(cpu_group_t *group,cpu_mips_t *cpu)
63 {
64 if (!group)
65 return(-1);
66
67 /* check that we don't already have a CPU with this id */
68 if (cpu_group_find_id(group,cpu->id) != NULL) {
69 fprintf(stderr,"cpu_group_add: CPU%u already present in group.\n",
70 cpu->id);
71 return(-1);
72 }
73
74 cpu->next = group->cpu_list;
75 group->cpu_list = cpu;
76 return(0);
77 }
78
79 /* Create a new CPU group */
80 cpu_group_t *cpu_group_create(char *name)
81 {
82 cpu_group_t *group;
83
84 if (!(group = malloc(sizeof(*group))))
85 return NULL;
86
87 group->name = name;
88 group->cpu_list = NULL;
89 return group;
90 }
91
92 /* Delete a CPU group */
93 void cpu_group_delete(cpu_group_t *group)
94 {
95 cpu_mips_t *cpu,*next;
96
97 if (group != NULL) {
98 for(cpu=group->cpu_list;cpu;cpu=next) {
99 next = cpu->next;
100 cpu_delete(cpu);
101 }
102
103 free(group);
104 }
105 }
106
107 /* Rebuild the MTS subsystem for a CPU group */
108 int cpu_group_rebuild_mts(cpu_group_t *group)
109 {
110 cpu_mips_t *cpu;
111
112 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
113 cpu->mts_rebuild(cpu);
114
115 return(0);
116 }
117
118 /* Log a message for a CPU */
119 void cpu_log(cpu_mips_t *cpu,char *module,char *format,...)
120 {
121 char buffer[256];
122 va_list ap;
123
124 va_start(ap,format);
125 snprintf(buffer,sizeof(buffer),"CPU%u: %s",cpu->id,module);
126 vm_flog(cpu->vm,buffer,format,ap);
127 va_end(ap);
128 }
129
130 /* Create a new CPU */
131 cpu_mips_t *cpu_create(vm_instance_t *vm,u_int id)
132 {
133 void *(*cpu_run_fn)(void *);
134 cpu_mips_t *cpu;
135
136 if (!(cpu = malloc(sizeof(*cpu))))
137 return NULL;
138
139 memset(cpu,0,sizeof(*cpu));
140 cpu->vm = vm;
141
142 /* by default, use a standard initialization (CPU exec is suspended) */
143 mips64_init(cpu);
144 cpu->id = id;
145 cpu->state = MIPS_CPU_SUSPENDED;
146
147 cpu_run_fn = (void *)insn_block_execute;
148 #if __GNUC__ > 2
149 if (!cpu->vm->jit_use) {
150 cpu_run_fn = (void *)mips64_exec_run_cpu;
151 } else {
152 mips64_jit_init(cpu);
153 }
154 #endif
155
156 /* create the CPU thread execution */
157 if (pthread_create(&cpu->cpu_thread,NULL,cpu_run_fn,cpu) != 0) {
158 fprintf(stderr,"cpu_create: unable to create thread for CPU%u\n",id);
159 free(cpu);
160 return NULL;
161 }
162
163 return cpu;
164 }
165
166 /* Delete a CPU */
167 void cpu_delete(cpu_mips_t *cpu)
168 {
169 if (cpu) {
170 /* Stop activity of this CPU */
171 cpu_stop(cpu);
172 pthread_join(cpu->cpu_thread,NULL);
173
174 /* Free resources */
175 mips64_delete(cpu);
176 }
177 }
178
179 /* Start a CPU */
180 void cpu_start(cpu_mips_t *cpu)
181 {
182 if (cpu) {
183 cpu_log(cpu,"CPU_STATE","Starting CPU (old state=%u)...\n",cpu->state);
184 cpu->state = MIPS_CPU_RUNNING;
185 }
186 }
187
188 /* Stop a CPU */
189 void cpu_stop(cpu_mips_t *cpu)
190 {
191 if (cpu) {
192 cpu_log(cpu,"CPU_STATE","Halting CPU (old state=%u)...\n",cpu->state);
193 cpu->state = MIPS_CPU_HALTED;
194 }
195 }
196
197 /* Start all CPUs of a CPU group */
198 void cpu_group_start_all_cpu(cpu_group_t *group)
199 {
200 cpu_mips_t *cpu;
201
202 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
203 cpu_start(cpu);
204 }
205
206 /* Stop all CPUs of a CPU group */
207 void cpu_group_stop_all_cpu(cpu_group_t *group)
208 {
209 cpu_mips_t *cpu;
210
211 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
212 cpu_stop(cpu);
213 }
214
215 /* Set a state of all CPUs of a CPU group */
216 void cpu_group_set_state(cpu_group_t *group,u_int state)
217 {
218 cpu_mips_t *cpu;
219
220 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
221 cpu->state = state;
222 }
223
224 /* Returns TRUE if all CPUs in a CPU group are inactive */
225 static int cpu_group_check_activity(cpu_group_t *group)
226 {
227 cpu_mips_t *cpu;
228
229 for(cpu=group->cpu_list;cpu;cpu=cpu->next) {
230 if (!cpu->cpu_thread_running)
231 continue;
232
233 if ((cpu->state == MIPS_CPU_RUNNING) || !cpu->seq_state)
234 return(FALSE);
235 }
236
237 return(TRUE);
238 }
239
240 /* Synchronize on CPUs (all CPUs must be inactive) */
241 int cpu_group_sync_state(cpu_group_t *group)
242 {
243 cpu_mips_t *cpu;
244 m_tmcnt_t t1,t2;
245
246 /* Check that CPU activity is really suspended */
247 t1 = m_gettime();
248
249 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
250 cpu->seq_state = 0;
251
252 while(!cpu_group_check_activity(group)) {
253 t2 = m_gettime();
254
255 if (t2 > (t1 + 10000))
256 return(-1);
257
258 usleep(50000);
259 }
260
261 return(0);
262 }
263
264 /* Save state of all CPUs */
265 int cpu_group_save_state(cpu_group_t *group)
266 {
267 cpu_mips_t *cpu;
268
269 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
270 cpu->prev_state = cpu->state;
271
272 return(TRUE);
273 }
274
275 /* Restore state of all CPUs */
276 int cpu_group_restore_state(cpu_group_t *group)
277 {
278 cpu_mips_t *cpu;
279
280 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
281 cpu->state = cpu->prev_state;
282
283 return(TRUE);
284 }

  ViewVC Help
Powered by ViewVC 1.1.26