Upload Tizen:Base source
[external/gdb.git] / gdb / testsuite / gdb.arch / spu-info.c
1 /* Copyright 2007, 2008, 2009, 2010 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 <spu_mfcio.h>
27
28
29 /* PPE-assisted call interface.  */
30 void
31 send_to_ppe (unsigned int signalcode, unsigned int opcode, void *data)
32 {
33   __vector unsigned int stopfunc =
34     {
35       signalcode,     /* stop */
36       (opcode << 24) | (unsigned int) data,
37       0x4020007f,     /* nop */
38       0x35000000      /* bi $0 */
39     };
40
41   void (*f) (void) = (void *) &stopfunc;
42   asm ("sync");
43   f ();
44 }
45
46 /* PPE-assisted call to mmap from SPU.  */
47 unsigned long long
48 mmap_ea (unsigned long long start, size_t length,
49          int prot, int flags, int fd, off_t offset)
50 {
51   struct mmap_args
52     {
53       unsigned long long start __attribute__ ((aligned (16)));
54       size_t length __attribute__ ((aligned (16)));
55       int prot __attribute__ ((aligned (16)));
56       int flags __attribute__ ((aligned (16)));
57       int fd __attribute__ ((aligned (16)));
58       off_t offset __attribute__ ((aligned (16)));
59     } args;
60
61   args.start = start;
62   args.length = length;
63   args.prot = prot;
64   args.flags = flags;
65   args.fd = fd;
66   args.offset = offset;
67
68   send_to_ppe (0x2101, 11, &args);
69   return args.start;
70 }
71
72 /* This works only in a Linux environment with <= 1024 open
73    file descriptors for one process. Result is the file
74    descriptor for the current context if available.  */
75 int
76 find_context_fd (void)
77 {
78   int dir_fd = -1;
79   int i;
80
81   for (i = 0; i < 1024; i++)
82     {
83       struct stat stat;
84
85       if (fstat (i, &stat) < 0)
86         break;
87       if (S_ISDIR (stat.st_mode))
88         dir_fd = dir_fd == -1 ? i : -2;
89     }
90   return dir_fd < 0 ? -1 : dir_fd;
91 }
92
93 /* Open the context file and return the file handler.  */
94 int
95 open_context_file (int context_fd, char *name, int flags)
96 {
97   char buf[128];
98
99   if (context_fd < 0)
100     return -1;
101
102   sprintf (buf, "/proc/self/fd/%d/%s", context_fd, name);
103   return open (buf, flags);
104 }
105
106
107 int
108 do_event_test ()
109 {
110   spu_write_event_mask (MFC_MULTI_SRC_SYNC_EVENT); /* 0x1000 */  /* Marker Event */
111   spu_write_event_mask (MFC_PRIV_ATTN_EVENT); /* 0x0800 */
112   spu_write_event_mask (MFC_LLR_LOST_EVENT); /* 0x0400 */
113   spu_write_event_mask (MFC_SIGNAL_NOTIFY_1_EVENT); /* 0x0200 */
114   spu_write_event_mask (MFC_SIGNAL_NOTIFY_2_EVENT); /* 0x0100 */
115   spu_write_event_mask (MFC_OUT_MBOX_AVAILABLE_EVENT); /* 0x0080 */
116   spu_write_event_mask (MFC_OUT_INTR_MBOX_AVAILABLE_EVENT); /* 0x0040 */
117   spu_write_event_mask (MFC_DECREMENTER_EVENT); /* 0x0020 */
118   spu_write_event_mask (MFC_IN_MBOX_AVAILABLE_EVENT); /* 0x0010 */
119   spu_write_event_mask (MFC_COMMAND_QUEUE_AVAILABLE_EVENT); /* 0x0008 */
120   spu_write_event_mask (MFC_LIST_STALL_NOTIFY_EVENT); /* 0x0002 */
121   spu_write_event_mask (MFC_TAG_STATUS_UPDATE_EVENT); /* 0x0001 */
122
123   return 0;
124 }
125
126 int
127 do_dma_test ()
128 {
129   #define MAP_FAILED      (-1ULL)
130   #define PROT_READ       0x1
131   #define MAP_PRIVATE     0x002
132   #define BSIZE 128
133   static char buf[BSIZE] __attribute__ ((aligned (128)));
134   char *file = "/var/tmp/tmp_buf";
135   struct stat fdstat;
136   int fd, cnt;
137   unsigned long long src;
138
139   /* Create a file and fill it with some bytes.  */
140   fd = open (file, O_CREAT | O_RDWR | O_TRUNC, 0777);
141   if (fd == -1)
142     return -1;
143   memset ((void *)buf, '1', BSIZE);
144   write (fd, buf, BSIZE);
145   write (fd, buf, BSIZE);
146   memset ((void *)buf, 0, BSIZE);
147
148   if (fstat (fd, &fdstat) != 0
149       || !fdstat.st_size)
150     return -2;
151
152   src = mmap_ea(0ULL, fdstat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
153   if (src == MAP_FAILED)
154     return -3;
155
156   /* Copy some data via DMA.  */
157   mfc_get (&buf, src, BSIZE, 5, 0, 0);   /* Marker DMA */
158   mfc_write_tag_mask (1<<5);   /* Marker DMAWait */
159   spu_mfcstat (MFC_TAG_UPDATE_ALL);
160
161   /* Close the file.  */
162   close (fd);
163
164   return cnt;
165 }
166
167 int
168 do_mailbox_test ()
169 {
170   /* Write to SPU Outbound Mailbox.  */
171   if (spu_stat_out_mbox ())            /* Marker Mbox */
172     spu_write_out_mbox (0x12345678);
173
174   /* Write to SPU Outbound Interrupt Mailbox.  */
175   if (spu_stat_out_intr_mbox ())
176     spu_write_out_intr_mbox (0x12345678);
177
178   return 0;       /* Marker MboxEnd */
179 }
180
181 int
182 do_signal_test ()
183 {
184   struct stat fdstat;
185   int context_fd = find_context_fd ();
186   int ret, buf, fd;
187
188   buf = 23;    /* Marker Signal */
189   /* Write to signal1.  */
190   fd = open_context_file (context_fd, "signal1", O_RDWR);
191   if (fstat (fd, &fdstat) != 0)
192     return -1;
193   ret = write (fd, buf, sizeof (int));
194   close (fd);  /* Marker Signal1 */
195
196   /* Write to signal2.  */
197   fd = open_context_file (context_fd, "signal2", O_RDWR);
198   if (fstat (fd, &fdstat) != 0)
199     return -1;
200   ret = write (fd, buf, sizeof (int));
201   close (fd);  /* Marker Signal2 */
202
203   /* Read signal1.  */
204   if (spu_stat_signal1 ())
205     ret = spu_read_signal1 ();
206
207   /* Read signal2.  */
208   if (spu_stat_signal2 ())
209     ret = spu_read_signal2 ();   /* Marker SignalRead */
210
211   return 0;
212 }
213
214 int
215 main (unsigned long long speid, unsigned long long argp, 
216       unsigned long long envp)
217 {
218   int res;
219
220   /* info spu event  */
221   res = do_event_test ();
222
223   /* info spu dma  */
224   res = do_dma_test ();
225
226   /* info spu mailbox  */
227   res = do_mailbox_test ();
228
229   /* info spu signal  */
230   res = do_signal_test ();
231
232   return 0;
233 }
234