0
votes

dummy_rocc is a naive built-in RoCC accelerator example in RISCV tools, where several custom0 instructions are defined. After setup dummy_rocc (either on Spike ISA simulator or on Rocket-FPGA, differently), we use dummy_rocc_test -- a user program testcase to verify the correctness of the dummy_rocc accelerator. We have two ways to run dummy_rocc_test, either on pk (proxy kernel) or on Linux.

I once setup dummy_rocc on Spike ISA simulator, the dummy_rocc_test worked well either on pk or on Linux.

Now I replace Spike with Rocket-FPGA on Zedboard. While the execution on pk succeeds:

root@zynq:~# ./fesvr-zynq pk /nfs/copy_to_rootfs/work/dummy_rocc_test
begin
after asm code
load x into accumulator 2 (funct=0)
read it back into z (funct=1) to verify it
accumulate 456 into it (funct=3)
verify it
do it all again, but initialize acc2 via memory this time (funct=2)
do it all again, but initialize acc2 via memory this time (funct=2)
do it all again, but initialize acc2 via memory this time (funct=2)
success!

the execution on Linux fails:

./fesvr-zynq +disk=/nfs/root.bin bbl /nfs/fpga-zynq/zedboard/fpga-images-zedboard/riscv/vmlinux
..................................Booting RISC-V Linux.........................................
/ # ./work/dummy_rocc_test
begin
after asm code
[    0.400000] dummy_rocc_test[23]: unhandled signal 4 code 0x30001 at 0x0000000000800500 in ]
[    0.400000] CPU: 0 PID: 23 Comm: dummy_rocc_test Not tainted 3.14.33-g043bb5d #1
[    0.400000] task: ffffffff8fa3f500 ti: ffffffff8fb76000 task.ti: ffffffff8fb76000
[    0.400000] sepc: 0000000000800500 ra : 00000000008004fc sp : 0000003fff943c70
[    0.400000]  gp : 0000000000882198 tp : 0000000000884700 t0 : 0000000000000000
[    0.400000]  t1 : 000000000080adc8 t2 : 8101010101010100 s0 : 0000003fff943ca0
[    0.400000]  s1 : 0000000000800d5c a0 : 000000000000000f a1 : 0000002000002000
[    0.400000]  a2 : 000000000000000f a3 : 000000000085cee8 a4 : 0000000000000001
[    0.400000]  a5 : 000000000000007b a6 : 0000000000000008 a7 : 0000000000000040
[    0.400000]  s2 : 0000000000000000 s3 : 00000000008a2668 s4 : 00000000008d8d98
[    0.400000]  s5 : 00000000008d7770 s6 : 0000000000000008 s7 : 00000000008d6000
[    0.400000]  s8 : 00000000008d8d60 s9 : 0000000000000000 s10: 00000000008a32b8
[    0.400000]  s11: ffffffffffffffff t3 : 000000000000000b t4 : 000000006ffffdff
[    0.400000]  t5 : 000000000000000a t6 : 000000006ffffeff
[    0.400000] sstatus: 8000000000003008 sbadaddr: 0000000000800500 scause: 0000000000000002
Illegal instruction

A screenshot shows that the "signal 4" is caused by a custom0 instruction. readelf screenshot of dummy_rocc_test

So my problem is "How come Linux kernel interferes the execution of RISC-V custom0 instruction on Zedboard? "

The source code of dummy_rocc_test is provided as reference:

// The following is a RISC-V program to test the functionality of the
// dummy RoCC accelerator.
// Compile with riscv64-unknown-elf-gcc dummy_rocc_test.c
// Run with spike --extension=dummy_rocc pk a.out

#include <assert.h>
#include <stdio.h>
#include <stdint.h>

int main() {
  printf("begin\n");
  uint64_t x = 123, y = 456, z = 0;
  // load x into accumulator 2 (funct=0)
// asm  code
   asm volatile ("addi a1, a1, 2");

/// printf again
  printf("after asm code\n");
  asm volatile ("custom0 x0, %0, 2, 0" : : "r"(x));
  printf("load x into accumulator 2 (funct=0)\n");
  // read it back into z (funct=1) to verify it
  asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z));
  printf("read it back into z (funct=1) to verify it\n");
  assert(z == x);
  // accumulate 456 into it (funct=3)
  asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y));
  printf("accumulate 456 into it (funct=3)\n");
  // verify it
  asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z));
  printf("verify it\n");
  assert(z == x+y);
  // do it all again, but initialize acc2 via memory this time (funct=2)
  asm volatile ("custom0 x0, %0, 2, 2" : : "r"(&x));
  printf("do it all again, but initialize acc2 via memory this time (funct=2)\n");
  asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y));
  printf("do it all again, but initialize acc2 via memory this time (funct=2)\n");
  asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z));
  printf("do it all again, but initialize acc2 via memory this time (funct=2)\n");
  assert(z == x+y);

  printf("success!\n");
}
1

1 Answers

0
votes

"Illegal instruction" means your processor threw an illegal instruction exception.

Since custom0 is not going to be something Linux will know how to execute in software (since it's something that's customizable!), Linux will panic and throw the error that you saw.

The question I have for you is "Did you implement the custom0 instruction in the processor? Is it enabled? Did the program execute your custom0 instruction properly and return the correct answer when you used the proxy-kernel?"