/[dynamips]/upstream/dynamips-0.2.5/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.5/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (12 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 5718 byte(s)
import 0.2.5 from upstream

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

  ViewVC Help
Powered by ViewVC 1.1.26