Update copyright year range in all GDB files.
[external/binutils.git] / gdb / testsuite / gdb.arch / spu-info.c
1 /* Copyright 2007-2019 Free Software Foundation, Inc.
2
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 3 of the License, or
6    (at your option) any later version.
7
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16    This file is part of the gdb testsuite.
17
18    Contributed by Markus Deuling <deuling@de.ibm.com>.
19    Tests for 'info spu' commands.  */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <spu_mfcio.h>
28
29
30 /* PPE-assisted call interface.  */
31 void
32 send_to_ppe (unsigned int signalcode, unsigned int opcode, void *data)
33 {
34   __vector unsigned int stopfunc =
35     {
36       signalcode,     /* stop */
37       (opcode << 24) | (unsigned int) data,
38       0x4020007f,     /* nop */
39       0x35000000      /* bi $0 */
40     };
41
42   void (*f) (void) = (void *) &stopfunc;
43   asm ("sync");
44   f ();
45 }
46
47 /* PPE-assisted call to mmap from SPU.  */
48 unsigned long long
49 mmap_ea (unsigned long long start, size_t length,
50          int prot, int flags, int fd, off_t offset)
51 {
52   struct mmap_args
53     {
54       unsigned long long start __attribute__ ((aligned (16)));
55       size_t length __attribute__ ((aligned (16)));
56       int prot __attribute__ ((aligned (16)));
57       int flags __attribute__ ((aligned (16)));
58       int fd __attribute__ ((aligned (16)));
59       off_t offset __attribute__ ((aligned (16)));
60     } args;
61
62   args.start = start;
63   args.length = length;
64   args.prot = prot;
65   args.flags = flags;
66   args.fd = fd;
67   args.offset = offset;
68
69   send_to_ppe (0x2101, 11, &args);
70   return args.start;
71 }
72
73 /* This works only in a Linux environment with <= 1024 open
74    file descriptors for one process. Result is the file
75    descriptor for the current context if available.  */
76 int
77 find_context_fd (void)
78 {
79   int dir_fd = -1;
80   int i;
81
82   for (i = 0; i < 1024; i++)
83     {
84       struct stat stat;
85
86       if (fstat (i, &stat) < 0)
87         break;
88       if (S_ISDIR (stat.st_mode))
89         dir_fd = dir_fd == -1 ? i : -2;
90     }
91   return dir_fd < 0 ? -1 : dir_fd;
92 }
93
94 /* Open the context file and return the file handler.  */
95 int
96 open_context_file (int context_fd, char *name, int flags)
97 {
98   char buf[128];
99
100   if (context_fd < 0)
101     return -1;
102
103   sprintf (buf, "/proc/self/fd/%d/%s", context_fd, name);
104   return open (buf, flags);
105 }
106
107
108 int
109 do_event_test ()
110 {
111   spu_write_event_mask (MFC_MULTI_SRC_SYNC_EVENT); /* 0x1000 */  /* Marker Event */
112   spu_write_event_mask (MFC_PRIV_ATTN_EVENT); /* 0x0800 */
113   spu_write_event_mask (MFC_LLR_LOST_EVENT); /* 0x0400 */
114   spu_write_event_mask (MFC_SIGNAL_NOTIFY_1_EVENT); /* 0x0200 */
115   spu_write_event_mask (MFC_SIGNAL_NOTIFY_2_EVENT); /* 0x0100 */
116   spu_write_event_mask (MFC_OUT_MBOX_AVAILABLE_EVENT); /* 0x0080 */
117   spu_write_event_mask (MFC_OUT_INTR_MBOX_AVAILABLE_EVENT); /* 0x0040 */
118   spu_write_event_mask (MFC_DECREMENTER_EVENT); /* 0x0020 */
119   spu_write_event_mask (MFC_IN_MBOX_AVAILABLE_EVENT); /* 0x0010 */
120   spu_write_event_mask (MFC_COMMAND_QUEUE_AVAILABLE_EVENT); /* 0x0008 */
121   spu_write_event_mask (MFC_LIST_STALL_NOTIFY_EVENT); /* 0x0002 */
122   spu_write_event_mask (MFC_TAG_STATUS_UPDATE_EVENT); /* 0x0001 */
123
124   return 0;
125 }
126
127 int
128 do_dma_test ()
129 {
130   #define MAP_FAILED      (-1ULL)
131   #define PROT_READ       0x1
132   #define MAP_PRIVATE     0x002
133   #define BSIZE 128
134   static char buf[BSIZE] __attribute__ ((aligned (128)));
135   char *file = "/var/tmp/tmp_buf";
136   struct stat fdstat;
137   int fd, cnt;
138   unsigned long long src;
139
140   /* Create a file and fill it with some bytes.  */
141   fd = open (file, O_CREAT | O_RDWR | O_TRUNC, 0777);
142   if (fd == -1)
143     return -1;
144   memset ((void *)buf, '1', BSIZE);
145   write (fd, buf, BSIZE);
146   write (fd, buf, BSIZE);
147   memset ((void *)buf, 0, BSIZE);
148
149   if (fstat (fd, &fdstat) != 0
150       || !fdstat.st_size)
151     return -2;
152
153   src = mmap_ea(0ULL, fdstat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
154   if (src == MAP_FAILED)
155     return -3;
156
157   /* Copy some data via DMA.  */
158   mfc_get (&buf, src, BSIZE, 5, 0, 0);   /* Marker DMA */
159   mfc_write_tag_mask (1<<5);   /* Marker DMAWait */
160   spu_mfcstat (MFC_TAG_UPDATE_ALL);
161
162   /* Close the file.  */
163   close (fd);
164
165   return cnt;
166 }
167
168 int
169 do_mailbox_test ()
170 {
171   /* Write to SPU Outbound Mailbox.  */
172   if (spu_stat_out_mbox ())            /* Marker Mbox */
173     spu_write_out_mbox (0x12345678);
174
175   /* Write to SPU Outbound Interrupt Mailbox.  */
176   if (spu_stat_out_intr_mbox ())
177     spu_write_out_intr_mbox (0x12345678);
178
179   return 0;       /* Marker MboxEnd */
180 }
181
182 int
183 do_signal_test ()
184 {
185   struct stat fdstat;
186   int context_fd = find_context_fd ();
187   int ret, buf, fd;
188
189   buf = 23;    /* Marker Signal */
190   /* Write to signal1.  */
191   fd = open_context_file (context_fd, "signal1", O_RDWR);
192   if (fstat (fd, &fdstat) != 0)
193     return -1;
194   ret = write (fd, &buf, sizeof (int));
195   close (fd);  /* Marker Signal1 */
196
197   /* Write to signal2.  */
198   fd = open_context_file (context_fd, "signal2", O_RDWR);
199   if (fstat (fd, &fdstat) != 0)
200     return -1;
201   ret = write (fd, &buf, sizeof (int));
202   close (fd);  /* Marker Signal2 */
203
204   /* Read signal1.  */
205   if (spu_stat_signal1 ())
206     ret = spu_read_signal1 ();
207
208   /* Read signal2.  */
209   if (spu_stat_signal2 ())
210     ret = spu_read_signal2 ();   /* Marker SignalRead */
211
212   return 0;
213 }
214
215 int
216 main (unsigned long long speid, unsigned long long argp, 
217       unsigned long long envp)
218 {
219   int res;
220
221   /* info spu event  */
222   res = do_event_test ();
223
224   /* info spu dma  */
225   res = do_dma_test ();
226
227   /* info spu mailbox  */
228   res = do_mailbox_test ();
229
230   /* info spu signal  */
231   res = do_signal_test ();
232
233   return 0;
234 }
235