/[gxemul]/trunk/src/devices/dev_mp.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

Diff of /trunk/src/devices/dev_mp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_mp.c,v 1.25 2005/02/25 06:27:48 debug Exp $   *  $Id: dev_mp.c,v 1.34 2006/02/09 20:02:59 debug Exp $
29   *   *
30   *  This is a fake multiprocessor (MP) device. It can be useful for   *  This is a fake multiprocessor (MP) device. It can be useful for
31   *  theoretical experiments, but probably bares no resemblance to any   *  theoretical experiments, but probably bares no resemblance to any
# Line 50  struct mp_data { Line 50  struct mp_data {
50          uint64_t        startup_addr;          uint64_t        startup_addr;
51          uint64_t        stack_addr;          uint64_t        stack_addr;
52          uint64_t        pause_addr;          uint64_t        pause_addr;
53    
54            /*  Each CPU has an array of pending ipis.  */
55            int             *n_pending_ipis;
56            int             **ipi;
57  };  };
58    
59    
60    extern int single_step;
61    
62    
63  /*  /*
64   *  dev_mp_access():   *  dev_mp_access():
65   */   */
66  int dev_mp_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,  DEVICE_ACCESS(mp)
         unsigned char *data, size_t len, int writeflag, void *extra)  
67  {  {
68          struct mp_data *d = extra;          struct mp_data *d = extra;
69          int i, which_cpu;          int i, which_cpu;
70          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
71    
72          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
73                    idata = memory_readmax64(cpu, data, len);
74    
75          /*          /*
76           *  NOTE: It is up to the user of this device to read or write           *  NOTE: It is up to the user of this device to read or write
# Line 117  int dev_mp_access(struct cpu *cpu, struc Line 124  int dev_mp_access(struct cpu *cpu, struc
124                  which_cpu = idata;                  which_cpu = idata;
125    
126                  for (i=0; i<cpu->machine->ncpus; i++)                  for (i=0; i<cpu->machine->ncpus; i++)
127                          if (i!=which_cpu)                          if (i != which_cpu)
128                                  d->cpus[i]->running = 0;                                  d->cpus[i]->running = 0;
129                  break;                  break;
130    
131          case DEV_MP_UNPAUSE_CPU:          case DEV_MP_UNPAUSE_CPU:
132                  /*  Unpause all cpus except our selves:  */                  /*  Unpause a specific CPU:  */
133                  which_cpu = idata;                  which_cpu = idata;
134                  for (i=0; i<cpu->machine->ncpus; i++)  
135                          if (i!=which_cpu)                  if (which_cpu >= 0 && which_cpu <cpu->machine->ncpus)
136                                  d->cpus[i]->running = 1;                          d->cpus[which_cpu]->running = 1;
137                  break;                  break;
138    
139          case DEV_MP_STARTUPSTACK:          case DEV_MP_STARTUPSTACK:
# Line 136  int dev_mp_access(struct cpu *cpu, struc Line 143  int dev_mp_access(struct cpu *cpu, struc
143                  break;                  break;
144    
145          case DEV_MP_HARDWARE_RANDOM:          case DEV_MP_HARDWARE_RANDOM:
146                  /*  Return (up to) 64 bits of "hardware random":  */                  /*
147                     *  Return (up to) 64 bits of "hardware random":
148                     *
149                     *  NOTE: Remember that random() is (usually) 31 bits of
150                     *        random data, _NOT_ 32, hence this construction.
151                     */
152                  odata = random();                  odata = random();
153                  odata = (odata << 31) ^ random();                  odata = (odata << 31) ^ random();
154                  odata = (odata << 31) ^ random();                  odata = (odata << 31) ^ random();
# Line 153  int dev_mp_access(struct cpu *cpu, struc Line 165  int dev_mp_access(struct cpu *cpu, struc
165                  odata = cpu->machine->physical_ram_in_mb * 1048576;                  odata = cpu->machine->physical_ram_in_mb * 1048576;
166                  break;                  break;
167    
168            case DEV_MP_IPI_ONE:
169            case DEV_MP_IPI_MANY:
170                    /*
171                     *  idata should be of the form:
172                     *
173                     *              (IPI_nr << 16) | cpu_id
174                     *
175                     *  This will send an Inter-processor interrupt to a specific
176                     *  CPU. (DEV_MP_IPI_MANY sends to all _except_ the specific
177                     *  CPU.)
178                     *
179                     *  Sending an IPI means adding the IPI last in the list of
180                     *  pending IPIs, and asserting the IPI "pin".
181                     */
182                    which_cpu = (idata & 0xffff);
183                    for (i=0; i<cpu->machine->ncpus; i++) {
184                            int send_it = 0;
185                            if (relative_addr == DEV_MP_IPI_ONE && i == which_cpu)
186                                    send_it = 1;
187                            if (relative_addr == DEV_MP_IPI_MANY && i != which_cpu)
188                                    send_it = 1;
189                            if (send_it) {
190                                    d->n_pending_ipis[i] ++;
191                                    d->ipi[i] = realloc(d->ipi[i],
192                                        d->n_pending_ipis[i] * sizeof(int));
193                                    if (d->ipi[i] == NULL) {
194                                            fprintf(stderr, "out of memory\n");
195                                            exit(1);
196                                    }
197                                    /*  Add the IPI last in the array:  */
198                                    d->ipi[i][d->n_pending_ipis[i] - 1] =
199                                        idata >> 16;
200                                    cpu_interrupt(d->cpus[i], MIPS_IPI_INT);
201                            }
202                    }
203                    break;
204    
205            case DEV_MP_IPI_READ:
206                    /*
207                     *  If the current CPU has any IPIs pending, accessing this
208                     *  address reads the IPI value. (Writing to this address
209                     *  discards _all_ pending IPIs.)  If there is no pending
210                     *  IPI, then 0 is returned. Usage of the value 0 for real
211                     *  IPIs should thus be avoided.
212                     */
213                    if (writeflag == MEM_WRITE) {
214                            d->n_pending_ipis[cpu->cpu_id] = 0;
215                    }
216                    odata = 0;
217                    if (d->n_pending_ipis[cpu->cpu_id] > 0) {
218                            odata = d->ipi[cpu->cpu_id][0];
219                            if (d->n_pending_ipis[cpu->cpu_id]-- > 1)
220                                    memmove(&d->ipi[cpu->cpu_id][0],
221                                        &d->ipi[cpu->cpu_id][1],
222                                        d->n_pending_ipis[cpu->cpu_id]);
223                    }
224                    /*  Deassert the interrupt, if there are no pending IPIs:  */
225                    if (d->n_pending_ipis[cpu->cpu_id] == 0)
226                            cpu_interrupt_ack(d->cpus[cpu->cpu_id], MIPS_IPI_INT);
227                    break;
228    
229            case DEV_MP_NCYCLES:
230                    /*
231                     *  Return approximately the number of cycles executed
232                     *  in this machine.  (This value is not updated for each
233                     *  instruction.)
234                     */
235                    odata = cpu->machine->ncycles;
236                    break;
237    
238          default:          default:
239                  fatal("[ dev_mp: unimplemented relative addr 0x%x ]\n",                  fatal("[ dev_mp: unimplemented relative addr 0x%x ]\n",
240                      relative_addr);                      relative_addr);
# Line 165  int dev_mp_access(struct cpu *cpu, struc Line 247  int dev_mp_access(struct cpu *cpu, struc
247  }  }
248    
249    
250  /*  DEVINIT(mp)
  *  devinit_mp():  
  */  
 int devinit_mp(struct devinit *devinit)  
251  {  {
252          struct mp_data *d;          struct mp_data *d;
253            int n;
254    
255          d = malloc(sizeof(struct mp_data));          d = malloc(sizeof(struct mp_data));
256          if (d == NULL) {          if (d == NULL) {
257                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
# Line 181  int devinit_mp(struct devinit *devinit) Line 262  int devinit_mp(struct devinit *devinit)
262          d->startup_addr = INITIAL_PC;          d->startup_addr = INITIAL_PC;
263          d->stack_addr = INITIAL_STACK_POINTER;          d->stack_addr = INITIAL_STACK_POINTER;
264    
265          memory_device_register(devinit->machine->memory,          n = devinit->machine->ncpus;
266              devinit->name, devinit->addr, DEV_MP_LENGTH,          d->n_pending_ipis = malloc(n * sizeof(int));
267              dev_mp_access, d, MEM_DEFAULT, NULL);          d->ipi = malloc(n * sizeof(int *));
268            if (d->ipi == NULL || d->n_pending_ipis == NULL) {
269                    fprintf(stderr, "out of memory\n");
270                    exit(1);
271            }
272            memset(d->n_pending_ipis, 0, sizeof(int) * n);
273            memset(d->ipi, 0, sizeof(int *) * n);
274    
275            memory_device_register(devinit->machine->memory, devinit->name,
276                devinit->addr, DEV_MP_LENGTH, dev_mp_access, d, DM_DEFAULT, NULL);
277    
278          return 1;          return 1;
279  }  }

Legend:
Removed from v.4  
changed lines
  Added in v.22

  ViewVC Help
Powered by ViewVC 1.1.26