/[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 8 by dpavlin, Mon Oct 8 16:18:19 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  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.27 2005/06/11 20:51:41 debug Exp $   *  $Id: dev_mp.c,v 1.40 2007/01/28 13:45:46 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
32   *  multiprocessor controller used in any real machine.   *  multiprocessor controller used in any real machine.
33     *
34     *  NOTE: The devinit irq string should be the part _after_ "cpu[%i].".
35     *        For MIPS, it will be MIPS_IPI_INT.
36   */   */
37    
38  #include <stdio.h>  #include <stdio.h>
# Line 37  Line 40 
40  #include <string.h>  #include <string.h>
41    
42  #include "cpu.h"  #include "cpu.h"
 #include "cpu_mips.h"  
43  #include "device.h"  #include "device.h"
44  #include "machine.h"  #include "machine.h"
45    #include "interrupt.h"
46  #include "memory.h"  #include "memory.h"
47  #include "misc.h"  #include "misc.h"
48  #include "mp.h"  
49    #include "testmachine/dev_mp.h"
50    
51    
52  struct mp_data {  struct mp_data {
# Line 54  struct mp_data { Line 58  struct mp_data {
58          /*  Each CPU has an array of pending ipis.  */          /*  Each CPU has an array of pending ipis.  */
59          int             *n_pending_ipis;          int             *n_pending_ipis;
60          int             **ipi;          int             **ipi;
61    
62            /*  Connections to all CPUs' IPI pins:  */
63            struct interrupt *ipi_irq;
64  };  };
65    
66    
67  extern int single_step;  extern int single_step;
68    
69    
70  /*  DEVICE_ACCESS(mp)
  *  dev_mp_access():  
  */  
 int dev_mp_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,  
         unsigned char *data, size_t len, int writeflag, void *extra)  
71  {  {
72          struct mp_data *d = extra;          struct mp_data *d = extra;
73          int i, which_cpu;          int i, which_cpu;
74          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
75    
76          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
77                    idata = memory_readmax64(cpu, data, len);
78    
79          /*          /*
80           *  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 120  int dev_mp_access(struct cpu *cpu, struc Line 124  int dev_mp_access(struct cpu *cpu, struc
124                  break;                  break;
125    
126          case DEV_MP_PAUSE_CPU:          case DEV_MP_PAUSE_CPU:
127                  /*  Pause all cpus except our selves:  */                  /*  Pause all cpus except a specific CPU:  */
128                  which_cpu = idata;                  which_cpu = idata;
129    
130                  for (i=0; i<cpu->machine->ncpus; i++)                  for (i=0; i<cpu->machine->ncpus; i++)
131                          if (i!=which_cpu)                          if (i != which_cpu)
132                                  d->cpus[i]->running = 0;                                  d->cpus[i]->running = 0;
133                  break;                  break;
134    
135          case DEV_MP_UNPAUSE_CPU:          case DEV_MP_UNPAUSE_CPU:
136                  /*  Unpause all cpus except our selves:  */                  /*  Unpause a specific CPU:  */
137                  which_cpu = idata;                  which_cpu = idata;
138                  for (i=0; i<cpu->machine->ncpus; i++)  
139                          if (i!=which_cpu)                  if (which_cpu >= 0 && which_cpu <cpu->machine->ncpus)
140                                  d->cpus[i]->running = 1;                          d->cpus[which_cpu]->running = 1;
141                  break;                  break;
142    
143          case DEV_MP_STARTUPSTACK:          case DEV_MP_STARTUPSTACK:
# Line 143  int dev_mp_access(struct cpu *cpu, struc Line 147  int dev_mp_access(struct cpu *cpu, struc
147                  break;                  break;
148    
149          case DEV_MP_HARDWARE_RANDOM:          case DEV_MP_HARDWARE_RANDOM:
150                  /*  Return (up to) 64 bits of "hardware random":  */                  /*
151                     *  Return (up to) 64 bits of "hardware random":
152                     *
153                     *  NOTE: Remember that random() is (usually) 31 bits of
154                     *        random data, _NOT_ 32, hence this construction.
155                     */
156                  odata = random();                  odata = random();
157                  odata = (odata << 31) ^ random();                  odata = (odata << 31) ^ random();
158                  odata = (odata << 31) ^ random();                  odata = (odata << 31) ^ random();
# Line 189  int dev_mp_access(struct cpu *cpu, struc Line 198  int dev_mp_access(struct cpu *cpu, struc
198                                          fprintf(stderr, "out of memory\n");                                          fprintf(stderr, "out of memory\n");
199                                          exit(1);                                          exit(1);
200                                  }                                  }
201    
202                                  /*  Add the IPI last in the array:  */                                  /*  Add the IPI last in the array:  */
203                                  d->ipi[i][d->n_pending_ipis[i] - 1] =                                  d->ipi[i][d->n_pending_ipis[i] - 1] =
204                                      idata >> 16;                                      idata >> 16;
205                                  cpu_interrupt(d->cpus[i], MIPS_IPI_INT);  
206                                    INTERRUPT_ASSERT(d->ipi_irq[i]);
207                          }                          }
208                  }                  }
209                  break;                  break;
# Line 216  int dev_mp_access(struct cpu *cpu, struc Line 227  int dev_mp_access(struct cpu *cpu, struc
227                                      &d->ipi[cpu->cpu_id][1],                                      &d->ipi[cpu->cpu_id][1],
228                                      d->n_pending_ipis[cpu->cpu_id]);                                      d->n_pending_ipis[cpu->cpu_id]);
229                  }                  }
230    
231                  /*  Deassert the interrupt, if there are no pending IPIs:  */                  /*  Deassert the interrupt, if there are no pending IPIs:  */
232                  if (d->n_pending_ipis[cpu->cpu_id] == 0)                  if (d->n_pending_ipis[cpu->cpu_id] == 0)
233                          cpu_interrupt_ack(d->cpus[cpu->cpu_id], MIPS_IPI_INT);                          INTERRUPT_DEASSERT(d->ipi_irq[cpu->cpu_id]);
234                    break;
235    
236            case DEV_MP_NCYCLES:
237                    /*
238                     *  Return _approximately_ the number of cycles executed
239                     *  in this machine.
240                     *
241                     *  Note: At the moment, this is actually the number of
242                     *  instructions executed on CPU 0.
243                     *
244                     *  (This value is not updated for each instruction.)
245                     */
246                    odata = cpu->machine->ninstrs;
247                  break;                  break;
248    
249          default:          default:
# Line 233  int dev_mp_access(struct cpu *cpu, struc Line 258  int dev_mp_access(struct cpu *cpu, struc
258  }  }
259    
260    
261  /*  DEVINIT(mp)
  *  devinit_mp():  
  */  
 int devinit_mp(struct devinit *devinit)  
262  {  {
263          struct mp_data *d;          struct mp_data *d;
264          int n;          int n, i;
265    
266          d = malloc(sizeof(struct mp_data));          d = malloc(sizeof(struct mp_data));
267          if (d == NULL) {          if (d == NULL) {
# Line 252  int devinit_mp(struct devinit *devinit) Line 274  int devinit_mp(struct devinit *devinit)
274          d->stack_addr = INITIAL_STACK_POINTER;          d->stack_addr = INITIAL_STACK_POINTER;
275    
276          n = devinit->machine->ncpus;          n = devinit->machine->ncpus;
277    
278            /*  Connect to all CPUs' IPI pins:  */
279            d->ipi_irq = malloc(n * sizeof(struct interrupt));
280            if (d->ipi_irq == NULL) {
281                    fprintf(stderr, "out of memory\n");
282                    exit(1);
283            }
284            for (i=0; i<n; i++) {
285                    char tmpstr[200];
286                    snprintf(tmpstr, sizeof(tmpstr), "%s.cpu[%i].%s",
287                        devinit->machine->path, i, devinit->interrupt_path);
288                    INTERRUPT_CONNECT(tmpstr, d->ipi_irq[i]);
289            }
290    
291          d->n_pending_ipis = malloc(n * sizeof(int));          d->n_pending_ipis = malloc(n * sizeof(int));
292          d->ipi = malloc(n * sizeof(int *));          d->ipi = malloc(n * sizeof(int *));
293          if (d->ipi == NULL || d->n_pending_ipis == NULL) {          if (d->ipi == NULL || d->n_pending_ipis == NULL) {
# Line 262  int devinit_mp(struct devinit *devinit) Line 298  int devinit_mp(struct devinit *devinit)
298          memset(d->ipi, 0, sizeof(int *) * n);          memset(d->ipi, 0, sizeof(int *) * n);
299    
300          memory_device_register(devinit->machine->memory, devinit->name,          memory_device_register(devinit->machine->memory, devinit->name,
301              devinit->addr, DEV_MP_LENGTH, dev_mp_access, d, MEM_DEFAULT, NULL);              devinit->addr, DEV_MP_LENGTH, dev_mp_access, d, DM_DEFAULT, NULL);
302    
303          return 1;          return 1;
304  }  }

Legend:
Removed from v.8  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26