235 lines
5.9 KiB
C
235 lines
5.9 KiB
C
/* Copyright 2007-2014 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;
|
|
}
|
|
|