/[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 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# 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.30 2005/11/13 00:14:09 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   */   */
# Line 63  int dev_mp_access(struct cpu *cpu, struc Line 70  int dev_mp_access(struct cpu *cpu, struc
70          int i, which_cpu;          int i, which_cpu;
71          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
72    
73          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
74                    idata = memory_readmax64(cpu, data, len);
75    
76          /*          /*
77           *  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 153  int dev_mp_access(struct cpu *cpu, struc Line 161  int dev_mp_access(struct cpu *cpu, struc
161                  odata = cpu->machine->physical_ram_in_mb * 1048576;                  odata = cpu->machine->physical_ram_in_mb * 1048576;
162                  break;                  break;
163    
164            case DEV_MP_IPI_ONE:
165            case DEV_MP_IPI_MANY:
166                    /*
167                     *  idata should be of the form:
168                     *
169                     *              (IPI_nr << 16) | cpu_id
170                     *
171                     *  This will send an Inter-processor interrupt to a specific
172                     *  CPU. (DEV_MP_IPI_MANY sends to all _except_ the specific
173                     *  CPU.)
174                     *
175                     *  Sending an IPI means adding the IPI last in the list of
176                     *  pending IPIs, and asserting the IPI "pin".
177                     */
178                    which_cpu = (idata & 0xffff);
179                    for (i=0; i<cpu->machine->ncpus; i++) {
180                            int send_it = 0;
181                            if (relative_addr == DEV_MP_IPI_ONE && i == which_cpu)
182                                    send_it = 1;
183                            if (relative_addr == DEV_MP_IPI_MANY && i != which_cpu)
184                                    send_it = 1;
185                            if (send_it) {
186                                    d->n_pending_ipis[i] ++;
187                                    d->ipi[i] = realloc(d->ipi[i],
188                                        d->n_pending_ipis[i] * sizeof(int));
189                                    if (d->ipi[i] == NULL) {
190                                            fprintf(stderr, "out of memory\n");
191                                            exit(1);
192                                    }
193                                    /*  Add the IPI last in the array:  */
194                                    d->ipi[i][d->n_pending_ipis[i] - 1] =
195                                        idata >> 16;
196                                    cpu_interrupt(d->cpus[i], MIPS_IPI_INT);
197                            }
198                    }
199                    break;
200    
201            case DEV_MP_IPI_READ:
202                    /*
203                     *  If the current CPU has any IPIs pending, accessing this
204                     *  address reads the IPI value. (Writing to this address
205                     *  discards _all_ pending IPIs.)  If there is no pending
206                     *  IPI, then 0 is returned. Usage of the value 0 for real
207                     *  IPIs should thus be avoided.
208                     */
209                    if (writeflag == MEM_WRITE) {
210                            d->n_pending_ipis[cpu->cpu_id] = 0;
211                    }
212                    odata = 0;
213                    if (d->n_pending_ipis[cpu->cpu_id] > 0) {
214                            odata = d->ipi[cpu->cpu_id][0];
215                            if (d->n_pending_ipis[cpu->cpu_id]-- > 1)
216                                    memmove(&d->ipi[cpu->cpu_id][0],
217                                        &d->ipi[cpu->cpu_id][1],
218                                        d->n_pending_ipis[cpu->cpu_id]);
219                    }
220                    /*  Deassert the interrupt, if there are no pending IPIs:  */
221                    if (d->n_pending_ipis[cpu->cpu_id] == 0)
222                            cpu_interrupt_ack(d->cpus[cpu->cpu_id], MIPS_IPI_INT);
223                    break;
224    
225            case DEV_MP_NCYCLES:
226                    /*
227                     *  Return approximately the number of cycles executed
228                     *  in this machine.  (This value is not updated for each
229                     *  instruction.)
230                     */
231                    odata = cpu->machine->ncycles;
232                    break;
233    
234          default:          default:
235                  fatal("[ dev_mp: unimplemented relative addr 0x%x ]\n",                  fatal("[ dev_mp: unimplemented relative addr 0x%x ]\n",
236                      relative_addr);                      relative_addr);
# Line 171  int dev_mp_access(struct cpu *cpu, struc Line 249  int dev_mp_access(struct cpu *cpu, struc
249  int devinit_mp(struct devinit *devinit)  int devinit_mp(struct devinit *devinit)
250  {  {
251          struct mp_data *d;          struct mp_data *d;
252            int n;
253    
254          d = malloc(sizeof(struct mp_data));          d = malloc(sizeof(struct mp_data));
255          if (d == NULL) {          if (d == NULL) {
256                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
# Line 181  int devinit_mp(struct devinit *devinit) Line 261  int devinit_mp(struct devinit *devinit)
261          d->startup_addr = INITIAL_PC;          d->startup_addr = INITIAL_PC;
262          d->stack_addr = INITIAL_STACK_POINTER;          d->stack_addr = INITIAL_STACK_POINTER;
263    
264          memory_device_register(devinit->machine->memory,          n = devinit->machine->ncpus;
265              devinit->name, devinit->addr, DEV_MP_LENGTH,          d->n_pending_ipis = malloc(n * sizeof(int));
266              dev_mp_access, d, MEM_DEFAULT, NULL);          d->ipi = malloc(n * sizeof(int *));
267            if (d->ipi == NULL || d->n_pending_ipis == NULL) {
268                    fprintf(stderr, "out of memory\n");
269                    exit(1);
270            }
271            memset(d->n_pending_ipis, 0, sizeof(int) * n);
272            memset(d->ipi, 0, sizeof(int *) * n);
273    
274            memory_device_register(devinit->machine->memory, devinit->name,
275                devinit->addr, DEV_MP_LENGTH, dev_mp_access, d, DM_DEFAULT, NULL);
276    
277          return 1;          return 1;
278  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26