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