[Cbe-oss-dev] [PATCH] spufs: Avoid restarting MFC in context saving
Kazunori Asayama
asayama at sm.sony.co.jp
Wed Jul 4 17:41:01 EST 2007
Kazunori Asayama <asayama at sm.sony.co.jp> wrote:
> Jeremy Kerr <jk at ozlabs.org> wrote:
> > Do you have a testcase that I can use to confirm the fix?
>
> Yes, I have. I'll submit it to this ML later.
Attached is the test. Run it as following:
gcc dma_context_save_test.c -o dma_context_save_test.elf -lspe2
spu-gcc spu_dma_stop.c -o spu_dma_stop.elf
./dma_context_save_test.elf
It will take several seconds on Cell Blade to complete the test, and
more on PS3 (it depends on # of available SPEs). The test silently
returns zero as its exit code if passed, otherwise it returns non-zero
value, crashes or hangs.
--
(ASAYAMA Kazunori
(asayama at sm.sony.co.jp))
t
-------------- next part --------------
/*
* dma_context_save_test - A testcase for SPUFS
*
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* Copyright 2007 Sony Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <libspe2.h>
#define NUM_SPES 17
#define COUNT 10000
#define DMA_SIZE 0x4000
#define MFC_COMMAND_QUEUE_DEPTH 16
#define BUFFER_SIZE (DMA_SIZE * MFC_COMMAND_QUEUE_DEPTH)
#define SPE_ELF "spu_dma_stop.elf"
static char dma_data[BUFFER_SIZE] __attribute__((aligned(16)));
spe_program_handle_t *spe_prog;
static void *spu_thread_proc(void *arg)
{
spe_context_ptr_t spe = (spe_context_ptr_t)arg;
unsigned int entry = SPE_DEFAULT_ENTRY;
int ret;
spe_stop_info_t stop_info;
if (spe_program_load(spe, spe_prog)) {
perror("spe_program_load");
exit(1);
}
for ( ; ; ) {
ret = spe_context_run(spe, &entry, 0, (void*)COUNT, dma_data, &stop_info);
if (ret == 0) {
/* Normal exit */
if (stop_info.result.spe_exit_code) {
fprintf(stderr, "DMA data mismatch.\n");
exit(1);
}
break;
}
else if (ret == 1) {
/* Do nothing here. */
}
else if (ret > 0) {
fprintf(stderr, "Unexpected stop and signal (0x%x).\n", ret);
exit(1);
}
else {
perror("spe_context_run");
exit(1);
}
}
return NULL;
}
static void data_generate(void *data, size_t size)
{
unsigned char *ptr = data;
unsigned char *end = ptr + size;
unsigned char value = 0;
while (ptr < end) {
*ptr++ = value++;
}
}
int main(int argc, char **argv)
{
int i;
int ret;
spe_context_ptr_t spe[NUM_SPES];
pthread_t tid[NUM_SPES];
data_generate(dma_data, BUFFER_SIZE);
spe_prog = spe_image_open(SPE_ELF);
if (!spe_prog) {
perror("spe_image_open");
return 1;
}
for (i = 0; i < NUM_SPES; i++) {
spe[i] = spe_context_create(0, 0);
if (!spe[i]) {
perror("spe_context_create");
return 1;
}
if (pthread_create(&tid[i], NULL, spu_thread_proc, spe[i])) {
perror("pthread_create");
return 1;
}
}
for (i = 0; i < NUM_SPES; i++) {
pthread_join(tid[i], NULL);
ret = spe_context_destroy(spe[i]);
if (ret) {
perror("spe_context_destroy");
return 1;
}
}
spe_image_close(spe_prog);
return 0;
}
-------------- next part --------------
/*
* dma_context_save_test - A testcase for SPUFS
*
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* Copyright 2007 Sony Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <spu_mfcio.h>
#include <string.h>
#define DMA_SIZE 0x4000
#define MFC_COMMAND_QUEUE_DEPTH 16
#define TAG 1
static unsigned char buf[DMA_SIZE] __attribute__((aligned(16)));
static inline int data_check(unsigned char *p, int size)
{
vector unsigned char *pv = (vector unsigned char *)p;
vector unsigned char *pv_end = pv + (size >> 4);
vector unsigned char v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, };
while (pv < pv_end) {
if (spu_extract(spu_gather(spu_cmpeq(v1, *pv)), 0) != 0xffff) {
return 0;
}
v1 += spu_splats((unsigned char)16);
pv++;
}
return 1;
}
int main(unsigned long long spe,
unsigned long long argp /* loop */,
unsigned long long envp /* EA */ )
{
unsigned long long i;
for (i = 0; i < argp; i++) {
unsigned long long ea = envp;
int j;
/* issue DMA */
for (j = 0; j < MFC_COMMAND_QUEUE_DEPTH; j++) {
spu_mfcdma64(buf, mfc_ea2h(ea), mfc_ea2l(ea), DMA_SIZE, TAG, MFC_GETF_CMD);
ea += DMA_SIZE;
}
/* stop here to increase probability of context saving with
outstanding DMAs. */
spu_stop(1);
/* wait for completion */
mfc_write_tag_mask(1 << TAG);
mfc_read_tag_status_all();
/* check the result */
if (!data_check(buf, DMA_SIZE)) {
/* data mismatch */
return 1;
}
memset(buf, 0, sizeof(buf));
}
return 0;
}
More information about the cbe-oss-dev
mailing list