/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 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 dpavlin 6 if (!group)
35     return NULL;
36    
37 dpavlin 1 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 dpavlin 6 if (!group)
65     return(-1);
66    
67 dpavlin 1 /* 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