title: How come Linux kernel interferes the execution of RISC-V custom0 instruction on Zedboard?
body: <p>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.</p>
  
  <p>I once setup dummy_rocc on Spike ISA simulator, the dummy_rocc_test worked well either on pk or on Linux.</p>
  
  <p>Now I replace Spike with Rocket-FPGA on Zedboard. While the execution on pk succeeds:</p>
  
  <pre><code>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!
  </code></pre>
  
  <p>the execution on Linux fails:</p>
  
  <pre><code>./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
  </code></pre>
  
  <p>A screenshot shows that the "signal 4" is caused by a custom0 instruction. 
  <a href="http://i.stack.imgur.com/lRidu.png" rel="nofollow">readelf screenshot of dummy_rocc_test</a></p>
  
  <p>So my problem is <strong>"How come Linux kernel interferes the execution of RISC-V custom0 instruction on Zedboard? "</strong> </p>
  
  <p>The source code of dummy_rocc_test is provided as reference:</p>
  
  <pre><code>// 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 &lt;assert.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdint.h&gt;
  
  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"(&amp;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");
  }
  </code></pre>