Почему ядро ​​Linux мешает выполнению инструкции RISC-V custom0 на Zedboard?

dummy_rocc - это простой пример встроенного ускорителя RoCC в инструментах RISCV, где определены несколько инструкций custom0. После установки dummy_rocc (либо на симуляторе Spike ISA, либо на Rocket-FPGA, по-разному) мы используем dummy_rocc_test - тестовый сценарий пользовательской программы для проверки правильности ускорителя dummy_rocc. У нас есть два способа запустить dummy_rocc_test: на pk (прокси-ядро) или на Linux.

Однажды я установил dummy_rocc на симуляторе Spike ISA, dummy_rocc_test хорошо работал как на pk, так и на Linux.

Сейчас я заменяю Spike на Rocket-FPGA на Zedboard. Пока выполнение на pk завершается успешно:

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!

выполнение в Linux не выполняется:

./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

На скриншоте видно, что "сигнал 4" вызван инструкцией custom0. расширенный снимок экрана dummy_rocc_test

Итак, моя проблема: «Почему ядро ​​Linux мешает выполнению инструкции RISC-V custom0 на Zedboard?»

Исходный код dummy_rocc_test предоставляется в качестве ссылки:

// 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");
}

person Guanglin Xu    schedule 06.10.2015    source источник


Ответы (1)


«Недопустимая инструкция» означает, что ваш процессор выдал исключение из-за недопустимой инструкции.

Поскольку custom0 не будет чем-то, что Linux умеет выполнять в программном обеспечении (поскольку это что-то настраиваемое!), Linux запаникует и выдаст ошибку, которую вы видели.

У меня к вам вопрос: «Реализовали ли вы инструкцию custom0 в процессоре? Включена ли она? Правильно ли программа выполнила вашу инструкцию custom0 и вернула правильный ответ, когда вы использовали прокси-ядро?»

person Chris    schedule 07.10.2015
comment
Да, я реализовал в процессоре инструкцию custom0. Когда я использовал прокси-ядро, выполнение custom0 возвращает правильные ответы (как показано в теле моего вопроса). Вот почему мне интересно, почему выполнение в Linux не выполняется. - person Guanglin Xu; 07.10.2015
comment
Может быть, мне стоит задать этот вопрос по-другому: пробовали ли вы когда-нибудь dummy_acc_test на RISCV Linux на Zybo, Zedboard или ZC706? - person Guanglin Xu; 07.10.2015