/[dynamips]/trunk/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

Annotation of /trunk/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Sat Oct 6 16:45:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 7315 byte(s)
make working copy

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * 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 "cpu.h"
21     #include "memory.h"
22     #include "device.h"
23 dpavlin 7 #include "mips64.h"
24     #include "mips64_cp0.h"
25 dpavlin 1 #include "mips64_exec.h"
26 dpavlin 7 #include "mips64_jit.h"
27     #include "ppc32.h"
28     #include "ppc32_exec.h"
29     #include "ppc32_jit.h"
30     #include "dynamips.h"
31 dpavlin 1 #include "vm.h"
32    
33     /* Find a CPU in a group given its ID */
34 dpavlin 7 cpu_gen_t *cpu_group_find_id(cpu_group_t *group,u_int id)
35 dpavlin 1 {
36 dpavlin 7 cpu_gen_t *cpu;
37 dpavlin 1
38 dpavlin 6 if (!group)
39     return NULL;
40    
41 dpavlin 1 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
42     if (cpu->id == id)
43     return cpu;
44    
45     return NULL;
46     }
47    
48     /* Find the highest CPU ID in a CPU group */
49     int cpu_group_find_highest_id(cpu_group_t *group,u_int *highest_id)
50     {
51 dpavlin 7 cpu_gen_t *cpu;
52 dpavlin 1 u_int max_id = 0;
53    
54     if (!group || group->cpu_list)
55     return(-1);
56    
57     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
58     if (cpu->id >= max_id)
59     max_id = cpu->id;
60    
61     *highest_id = max_id;
62     return(0);
63     }
64    
65     /* Add a CPU in a CPU group */
66 dpavlin 7 int cpu_group_add(cpu_group_t *group,cpu_gen_t *cpu)
67 dpavlin 1 {
68 dpavlin 6 if (!group)
69     return(-1);
70    
71 dpavlin 1 /* check that we don't already have a CPU with this id */
72     if (cpu_group_find_id(group,cpu->id) != NULL) {
73     fprintf(stderr,"cpu_group_add: CPU%u already present in group.\n",
74     cpu->id);
75     return(-1);
76     }
77    
78     cpu->next = group->cpu_list;
79     group->cpu_list = cpu;
80     return(0);
81     }
82    
83     /* Create a new CPU group */
84     cpu_group_t *cpu_group_create(char *name)
85     {
86     cpu_group_t *group;
87    
88     if (!(group = malloc(sizeof(*group))))
89     return NULL;
90    
91     group->name = name;
92     group->cpu_list = NULL;
93     return group;
94     }
95    
96     /* Delete a CPU group */
97     void cpu_group_delete(cpu_group_t *group)
98     {
99 dpavlin 7 cpu_gen_t *cpu,*next;
100 dpavlin 1
101     if (group != NULL) {
102     for(cpu=group->cpu_list;cpu;cpu=next) {
103     next = cpu->next;
104     cpu_delete(cpu);
105     }
106    
107     free(group);
108     }
109     }
110    
111     /* Rebuild the MTS subsystem for a CPU group */
112     int cpu_group_rebuild_mts(cpu_group_t *group)
113     {
114 dpavlin 7 cpu_gen_t *cpu;
115 dpavlin 1
116     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
117     cpu->mts_rebuild(cpu);
118    
119     return(0);
120     }
121    
122     /* Log a message for a CPU */
123 dpavlin 7 void cpu_log(cpu_gen_t *cpu,char *module,char *format,...)
124 dpavlin 1 {
125     char buffer[256];
126     va_list ap;
127    
128     va_start(ap,format);
129     snprintf(buffer,sizeof(buffer),"CPU%u: %s",cpu->id,module);
130     vm_flog(cpu->vm,buffer,format,ap);
131     va_end(ap);
132     }
133    
134     /* Create a new CPU */
135 dpavlin 7 cpu_gen_t *cpu_create(vm_instance_t *vm,u_int type,u_int id)
136 dpavlin 1 {
137     void *(*cpu_run_fn)(void *);
138 dpavlin 7 cpu_gen_t *cpu;
139 dpavlin 1
140     if (!(cpu = malloc(sizeof(*cpu))))
141     return NULL;
142    
143     memset(cpu,0,sizeof(*cpu));
144     cpu->vm = vm;
145     cpu->id = id;
146 dpavlin 7 cpu->type = type;
147     cpu->state = CPU_STATE_SUSPENDED;
148 dpavlin 1
149 dpavlin 7 switch(cpu->type) {
150     case CPU_TYPE_MIPS64:
151 dpavlin 9 cpu->jit_op_array_size = MIPS_INSN_PER_PAGE;
152 dpavlin 7 CPU_MIPS64(cpu)->vm = vm;
153     CPU_MIPS64(cpu)->gen = cpu;
154     mips64_init(CPU_MIPS64(cpu));
155    
156     cpu_run_fn = (void *)mips64_jit_run_cpu;
157    
158     if (!cpu->vm->jit_use)
159     cpu_run_fn = (void *)mips64_exec_run_cpu;
160     else
161     mips64_jit_init(CPU_MIPS64(cpu));
162     break;
163    
164     case CPU_TYPE_PPC32:
165 dpavlin 9 cpu->jit_op_array_size = PPC32_INSN_PER_PAGE;
166 dpavlin 7 CPU_PPC32(cpu)->vm = vm;
167     CPU_PPC32(cpu)->gen = cpu;
168     ppc32_init(CPU_PPC32(cpu));
169    
170     cpu_run_fn = (void *)ppc32_jit_run_cpu;
171    
172     if (!cpu->vm->jit_use)
173     cpu_run_fn = (void *)ppc32_exec_run_cpu;
174     else
175     ppc32_jit_init(CPU_PPC32(cpu));
176     break;
177    
178     default:
179     fprintf(stderr,"CPU type %u is not supported yet\n",cpu->type);
180     abort();
181     break;
182 dpavlin 1 }
183    
184     /* create the CPU thread execution */
185     if (pthread_create(&cpu->cpu_thread,NULL,cpu_run_fn,cpu) != 0) {
186     fprintf(stderr,"cpu_create: unable to create thread for CPU%u\n",id);
187     free(cpu);
188     return NULL;
189     }
190    
191     return cpu;
192     }
193    
194     /* Delete a CPU */
195 dpavlin 7 void cpu_delete(cpu_gen_t *cpu)
196 dpavlin 1 {
197     if (cpu) {
198     /* Stop activity of this CPU */
199     cpu_stop(cpu);
200     pthread_join(cpu->cpu_thread,NULL);
201    
202     /* Free resources */
203 dpavlin 7 switch(cpu->type) {
204     case CPU_TYPE_MIPS64:
205     mips64_delete(CPU_MIPS64(cpu));
206     break;
207    
208     case CPU_TYPE_PPC32:
209     ppc32_delete(CPU_PPC32(cpu));
210     break;
211     }
212    
213     free(cpu);
214 dpavlin 1 }
215     }
216    
217     /* Start a CPU */
218 dpavlin 7 void cpu_start(cpu_gen_t *cpu)
219 dpavlin 1 {
220     if (cpu) {
221     cpu_log(cpu,"CPU_STATE","Starting CPU (old state=%u)...\n",cpu->state);
222 dpavlin 7 cpu->state = CPU_STATE_RUNNING;
223 dpavlin 1 }
224     }
225    
226     /* Stop a CPU */
227 dpavlin 7 void cpu_stop(cpu_gen_t *cpu)
228 dpavlin 1 {
229     if (cpu) {
230     cpu_log(cpu,"CPU_STATE","Halting CPU (old state=%u)...\n",cpu->state);
231 dpavlin 7 cpu->state = CPU_STATE_HALTED;
232 dpavlin 1 }
233     }
234    
235     /* Start all CPUs of a CPU group */
236     void cpu_group_start_all_cpu(cpu_group_t *group)
237     {
238 dpavlin 7 cpu_gen_t *cpu;
239 dpavlin 1
240     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
241     cpu_start(cpu);
242     }
243    
244     /* Stop all CPUs of a CPU group */
245     void cpu_group_stop_all_cpu(cpu_group_t *group)
246     {
247 dpavlin 7 cpu_gen_t *cpu;
248 dpavlin 1
249     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
250     cpu_stop(cpu);
251     }
252    
253     /* Set a state of all CPUs of a CPU group */
254     void cpu_group_set_state(cpu_group_t *group,u_int state)
255     {
256 dpavlin 7 cpu_gen_t *cpu;
257 dpavlin 1
258     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
259     cpu->state = state;
260     }
261    
262     /* Returns TRUE if all CPUs in a CPU group are inactive */
263     static int cpu_group_check_activity(cpu_group_t *group)
264     {
265 dpavlin 7 cpu_gen_t *cpu;
266 dpavlin 1
267     for(cpu=group->cpu_list;cpu;cpu=cpu->next) {
268     if (!cpu->cpu_thread_running)
269     continue;
270    
271 dpavlin 7 if ((cpu->state == CPU_STATE_RUNNING) || !cpu->seq_state)
272 dpavlin 1 return(FALSE);
273     }
274    
275     return(TRUE);
276     }
277    
278     /* Synchronize on CPUs (all CPUs must be inactive) */
279     int cpu_group_sync_state(cpu_group_t *group)
280     {
281 dpavlin 7 cpu_gen_t *cpu;
282 dpavlin 1 m_tmcnt_t t1,t2;
283    
284     /* Check that CPU activity is really suspended */
285     t1 = m_gettime();
286    
287     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
288     cpu->seq_state = 0;
289    
290     while(!cpu_group_check_activity(group)) {
291     t2 = m_gettime();
292    
293     if (t2 > (t1 + 10000))
294     return(-1);
295    
296     usleep(50000);
297     }
298    
299     return(0);
300     }
301    
302     /* Save state of all CPUs */
303     int cpu_group_save_state(cpu_group_t *group)
304     {
305 dpavlin 7 cpu_gen_t *cpu;
306 dpavlin 1
307     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
308     cpu->prev_state = cpu->state;
309    
310     return(TRUE);
311     }
312    
313     /* Restore state of all CPUs */
314     int cpu_group_restore_state(cpu_group_t *group)
315     {
316 dpavlin 7 cpu_gen_t *cpu;
317 dpavlin 1
318     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
319     cpu->state = cpu->prev_state;
320    
321     return(TRUE);
322     }
323 dpavlin 7
324     /* Virtual idle loop */
325     void cpu_idle_loop(cpu_gen_t *cpu)
326     {
327     struct timespec t_spc;
328     m_tmcnt_t expire;
329    
330     expire = m_gettime_usec() + cpu->idle_sleep_time;
331    
332     pthread_mutex_lock(&cpu->idle_mutex);
333     t_spc.tv_sec = expire / 1000000;
334     t_spc.tv_nsec = (expire % 1000000) * 1000;
335     pthread_cond_timedwait(&cpu->idle_cond,&cpu->idle_mutex,&t_spc);
336     pthread_mutex_unlock(&cpu->idle_mutex);
337     }
338    
339     /* Break idle wait state */
340     void cpu_idle_break_wait(cpu_gen_t *cpu)
341     {
342     pthread_cond_signal(&cpu->idle_cond);
343     cpu->idle_count = 0;
344     }

  ViewVC Help
Powered by ViewVC 1.1.26