Parte 4: Finalmente lanzamos Linux en RocketChip RISC-V

Parte 4: Finalmente lanzamos Linux en RocketChip RISC-V En la imagen, el núcleo de Linux te envía un saludo a través de GPIO.

En esta parte de la historia sobre la portabilidad del RISC-V RocketChip a una placa china con Cyclone IV, finalmente ejecutaremos Linux y también aprenderemos a configurar el IP Core del controlador de memoria y editaremos un poco la descripción dts del hardware. Este artículo es la continuación de la tercera parte, pero, a diferencia de la anterior que se expandió considerablemente, será bastante corta.

… Dado que setup_smp se invoca solo si el núcleo está configurado con soporte SMP, se puede intentar desactivar la multiprocesamiento. Sería molesto si también tuviera que implementar el soporte de atomicidad en el módulo de memoria (me parecía que este problema lo maneja la caché por sí misma), pero en el caso de un solo núcleo no debería interferir.

De todas formas, no funcionó…

[    0.000000] OF: fdt: Ignorando el rango de memoria 0x80000000 - 0x80200000
[    0.000000] Versión de Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 Jue Jul 4 18:38:10 MSK 2019
[    0.000000] bootconsole [early0] habilitado
[    0.000000] Ramdisk inicial en: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Rangos de zona:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Punto de inicio de la zona móvil para cada nodo
[    0.000000] Rangos de nodo de memoria temprana
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configuración de mem inicial nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] TLB de entrada/salida de software: mapeado [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] No se pudo encontrar la entrada del dispositivo "cpu" en el árbol de dispositivos
[    0.000000] Se construyeron 1 listas de zonas, agrupamiento de movilidad activado.  Páginas totales: 258055
[    0.000000] Línea de comando del kernel: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Entradas de tabla de hash de caché de directorios: 131072 (orden: 8, 1048576 bytes)
[    0.000000] Entradas de tabla de hash de caché de inodos: 65536 (orden: 7, 524288 bytes)
[    0.000000] Ordenando __ex_table...
[    0.000000] BUG: Estado de página malo en el proceso swapper  pfn:80bf7
[    0.000000] página:ffffffe03f029e08 count:0 mapcount:-65280 mapping:0000000000000000 index:0x1
[    0.000000] flags: 0x0()
[    0.000000] crudo: 0000000000000000 0000000000000100 0000000000000200 0000000000000000
[    0.000000] crudo: 0000000000000001 0000000000000000 00000000ffff00ff
[    0.000000] página volcada porque: mapcount distinto de cero
[    0.000000] Módulos vinculados:
[    0.000000] CPU: 0 PID: 0 Comm: swapper No contaminado 4.19.0-sifive-1+ #1
[    0.000000] Traza de llamadas:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe000094bb0>] free_pcppages_bulk+0x106\/0x36c
[    0.000000] [<ffffffe0000957be>] free_unref_page_commit.isra.23+0x86\/0x8e
[    0.000000] [<ffffffe0000960bc>] free_unref_page+0x44\/0x58
[    0.000000] [<ffffffe0000960de>] __free_pages.part.28+0xe\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c
[    0.000000] Deshabilitando la depuración de bloqueo debido a la contaminación del kernel
[    0.000000] BUG: Estado de página malo en el proceso swapper  pfn:80bf9
[    0.000000] página:ffffffe03f029e78 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] crudo: 0000000000000000 ffffffe03f020080 ffffffe03f020080 0000000000000000
[    0.000000] crudo: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] página volcada porque: mapcount distinto de cero
[    0.000000] Módulos vinculados:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminado: G    B             4.19.0-sifive-1+ #1
[    0.000000] Traza de llamadas:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe0000955c6>] __free_pages_ok+0x3fe\/0x430
[    0.000000] [<ffffffe0000960ea>] __free_pages.part.28+0x1a\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c
[    0.000000] BUG: Estado de página malo en el proceso swapper  pfn:80bfa
[    0.000000] página:ffffffe03f029eb0 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] crudo: 0000000000000000 ffffffe03f0200b8 ffffffe03f0200b8 0000000000000000
[    0.000000] crudo: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] página volcada porque: mapcount distinto de cero
[    0.000000] Módulos vinculados:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminado: G    B             4.19.0-sifive-1+ #1
[    0.000000] Traza de llamadas:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe0000955c6>] __free_pages_ok+0x3fe\/0x430
[    0.000000] [<ffffffe0000960ea>] __free_pages.part.28+0x1a\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c
[    0.000000] BUG: Estado de página malo en el proceso swapper  pfn:80bfb
[    0.000000] página:ffffffe03f029ee8 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] crudo: 0000000000000000 ffffffe03f0200f0 ffffffe03f0200f0 0000000000000000
[    0.000000] crudo: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] página volcada porque: mapcount distinto de cero
[    0.000000] Módulos vinculados:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminado: G    B             4.19.0-sifive-1+ #1
[    0.000000] Traza de llamadas:
[    0.000000] [<ffffffe00002cfde>] walk_stackframe+0x0\/0xa0
[    0.000000] [<ffffffe00002d1da>] show_stack+0x2a\/0x34
[    0.000000] [<ffffffe00063c898>] chachachllachachachTradeonachachach_inachachipachachachachllachachachTradeonachachachdevachachachypachachachllachachachTradeona+0x20\/0x28
[    0.000000] [<ffffffe00009499c>] bad_page+0xe4\/0x102
[    0.000000] [<ffffffe0000949f2>] free_pages_check_bad+0x38\/0x7a
[    0.000000] [<ffffffe0000955c6>] __free_pages_ok+0x3fe\/0x430
[    0.000000] [<ffffffe0000960ea>] __free_pages.part.28+0x1a\/0x22
[    0.000000] [<ffffffe0000056da>] __free_pages_bootmem+0x86\/0x90
[    0.000000] [<ffffffe000007c46>] free_all_bootmem+0x156\/0x1ba
[    0.000000] [<ffffffe0000023f8>] mem_init+0x36\/0x44
[    0.000000] [<ffffffe0000007a0>] start_kernel+0x1aa\/0x328
[    0.000000] [<ffffffe000000058>] _sinittext+0x58\/0x5c

Es interesante que después de toda la depuración decidí ver cómo debería ser la salida "referencial" del núcleo, dijo make qemu, y vi un error similar.

Lamentablemente, el siguiente nivel (núcleo de Linux) es más complicado: GDB, conectado a RocketChip a través de JTAG, parece trabajar con direcciones físicas sin importar cómo esté configurado el MMU, y el núcleo en el momento que nos interesa ya ha configurado el mapeo de direcciones, así que simplemente decir display/10i $pc no funcionará — solo veremos muchos unimp. Sin embargo, si ya hemos determinado el desplazamiento (parece que 0x80200000 -> 0xffffffe000000000), podemos ser astutos:

1: x/10i $pc
=> 0xffffffe000002436 :      unimp
   0xffffffe000002438 :    unimp
   0xffffffe00000243a :    unimp
   0xffffffe00000243c :    unimp
   0xffffffe00000243e :    unimp
   0xffffffe000002440 :   unimp
   0xffffffe000002442 :   unimp
   0xffffffe000002444 :   unimp
   0xffffffe000002446 :   unimp
   0xffffffe000002448 :   unimp
(gdb) undisplay 1
(gdb) display/10i ($pc - 0xffffffe000002436 + 0x80202436)
2: x/10i ($pc - 0xffffffe000002436 + 0x80202436)
   0x80202436:  addi    sp,sp,-96
   0x80202438:  sd      s0,80(sp)
   0x8020243a:  sd      s1,72(sp)
   0x8020243c:  sd      s2,64(sp)
   0x8020243e:  sd      s3,56(sp)
   0x80202440:  sd      s4,48(sp)
   0x80202442:  sd      s5,40(sp)
   0x80202444:  sd      s6,32(sp)
   0x80202446:  sd      s7,24(sp)
   0x80202448:  sd      s8,16(sp)

Los puntos de ruptura se establecen de manera similar:

(gdb) p setup_smp
$1 = {} 0xffffffe000002436 
(gdb) b *0x80202436
Breakpoint 1 at 0x80202436
(gdb) c
Continuando.

El programa recibió la señal SIGTRAP, trampa de seguimiento/punto de ruptura.
setup_smp () en /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
58              while ((dn = of_find_node_by_type(dn, "cpu"))) {
(gdb) bt
#0  setup_smp () en /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
#1  0xffffffe0000022a2 en setup_arch () en /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/setup.c:253
#2  0x0000000000000000 en ?? ()
La traza se detuvo: el marco no guardó el PC.

Solo que hay que quitarlos manualmente para continuar — para GDB es una trampa completamente incomprensible. Ah, sí, si accidentalmente dices s o n en lugar de si, gdb intentará insertar un punto de ruptura implícito, que por razones obvias no se establecerá, pero ya no hay forma de disuadir a GDB. Pero no te apresures a reiniciar la placa — según mis observaciones, basta con reiniciar solo gdb (ten en cuenta que los puntos de ruptura antiguos pueden no desaparecer).

De hecho, tendremos que lidiar con el problema original: colocar los puntos de depuración printk en la función of_find_node_by_type, que utiliza el código de búsqueda del núcleo del procesador de arranque, muestra que ve algún tipo de basura en lugar de los nombres de los tipos de dispositivos. Por ejemplo, obtiene de alguna parte la línea "Puerto serial", aunque claramente no existe en el dtb en el campo device_type. Al buscar estos bytes en la imagen del núcleo, los encontré, revisé el desplazamiento y entendí lo obvio: el tamaño del núcleo en los parámetros de arranque está claramente subestimado: se le asignan 8Mb, pero ocupa más de diez. Asigné 16Mb, pero las rarezas no cesaron. Tras varios intentos de leer el FDT desde diferentes direcciones (normalmente la dirección se pasa al núcleo en el registro a1), finalmente decidí rastrear qué está ahora parsiendo. Afortunadamente, en lugar de andar con el depurador (y recordamos que hay matices con la traducción de direcciones que aún necesitan ser solucionados de alguna manera), se puede simplemente y de manera improvisada en el archivo drivers/of/fdt.c especificar #define pr_debug printk. Al final resultó:

añadiendo salida de depuración

diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 3db0d71d128b..fac47df9d1db 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -173,6 +173,7 @@ asmlinkage void __init setup_vm(void)

 void __init parse_dtb(unsigned int hartid, void *dtb)
 {
+       printk("HART = %u DTB = %lxn", hartid, dtb);
        early_init_dt_scan(__va(dtb));
 }

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 74eaedd5b860..c019e4158e1d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -940,10 +940,12 @@ struct device_node *of_find_node_by_type(struct device_node *from,
        unsigned long flags;

        raw_spin_lock_irqsave(&devtree_lock, flags);
-       for_each_of_allnodes_from(from, np)
+       for_each_of_allnodes_from(from, np) {
+               printk("%lx %lx [%s] | [%s]n", from, np, np->type, type);
                if (np->type && (of_node_cmp(np->type, type) == 0)
                    && of_node_get(np))
                        break;
+       }
        of_node_put(from);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 800ad252cf9c..2b45870ebada 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -31,6 +31,8 @@

 #include "of_private.h"

+#define pr_debug printk
+
 /*
  * of_fdt_limit_memory - limita el número de regiones en el nodo /memory
  * @limit: entradas máximas
@@ -1253,6 +1255,7 @@ bool __init early_init_dt_scan(void *params)
  *//
 void __init unflatten_device_tree(void)
 {
+       printk("INICIAL: %lxn", initial_boot_params);
        __unflatten_device_tree(initial_boot_params, NULL, &of_root,
                                early_init_dt_alloc_memory_arch, false);

Salida en hardware

                SIFIVE, INC.

         5555555555555555555555555
        5555                   5555
       5555                     5555
      5555                       5555
     5555       5555555555555555555555
    5555       555555555555555555555555
   5555                             5555
  5555                               5555
 5555                                 5555
5555555555555555555555555555          55555
 55555           555555555           55555
   55555           55555           55555
     55555           5           55555
       55555                   55555
         55555               55555
           55555           55555
             55555       55555
               55555   55555
                 555555555
                   55555
                     5

           SiFive RISC-V Core IP
 {
  #address-cells = ;
  #size-cells = ;
  compatible = "freechips,rocketchip-unknown-dev";
  model = "freechips,rocketchip-unknown";
  chosen {
    linux,initrd-start = ;
    riscv,kernel-end = ;
    riscv,kernel-start = ;
    #address-cells = ;
    #size-cells = ;
    bootargs = ;
  }
  firmware {
    sifive,uboot = "YYYY-MM-DD";
  }
  aliases {
    serial0 = ;
  }
  cpus {
    #address-cells = ;
    #size-cells = ;
    cpu@0 {
      device_type = "cpu";
      clock-frequency = ;
      compatible = "sifive,rocket0", "riscv";
      d-cache-block-size = ;
      d-cache-sets = ;
      d-cache-size = ;
      d-tlb-sets = ;
      d-tlb-size = ;
      i-cache-block-size = ;
      i-cache-sets = ;
      i-cache-size = ;
      i-tlb-sets = ;
      i-tlb-size = ;
      mmu-type = "riscv,sv39";
      next-level-cache = ;
      reg = ;
      riscv,isa = "rv64imafdc";
      status = "okay";
      timebase-frequency = ;
      tlb-split;
      interrupt-controller {
        #interrupt-cells = ;
        compatible = "riscv,cpu-intc";
        interrupt-controller;
        phandle = ;
      }
    }
  }
  ram@80000000 {
    device_type = "memory";
    reg = ;
    reg-names = "mem";
    phandle = ;
  }
  soc {
    #address-cells = ;
    #size-cells = ;
    compatible = "freechips,rocketchip-unknown-soc", "simple-bus";
    ranges;
    clint@2000000 {
      compatible = "riscv,clint0";
      interrupts-extended = ;
      reg = ;
      reg-names = "control";
    }
    debug-controller@0 {
      compatible = "sifive,debug-013", "riscv,debug-013";
      interrupts-extended = ;
      reg = ;
      reg-names = "control";
    }
    gpio@64002000 {
      #gpio-cells = ;
      #interrupt-cells = ;
      compatible = "sifive,gpio0";
      gpio-controller;
      interrupt-controller;
      interrupt-parent = ;
      interrupts = ;
      reg = ;
      reg-names = "control";
    }
    interrupt-controller@c000000 {
      #interrupt-cells = ;
      compatible = "riscv,plic0";
      interrupt-controller;
      interrupts-extended = ;
      reg = ;
      reg-names = "control";
      riscv,max-priority = ;
      riscv,ndev = ;
      phandle = ;
    }
    rom@10000 {
      compatible = "sifive,maskrom0";
      reg = ;
      reg-names = "mem";
    }
    serial@64000000 {
      compatible = "sifive,uart0";
      interrupt-parent = ;
      interrupts = ;
      reg = ;
      reg-names = "control";
    }
    spi@64001000 {
      #address-cells = ;
      #size-cells = ;
      compatible = "sifive,spi0";
      interrupt-parent = ;
      interrupts = ;
      reg = ;
      reg-names = "control";
      mmc@0 {
        compatible = "mmc-spi-slot";
        disable-wp;
        reg = ;
        spi-max-frequency = ;
        voltage-ranges = ;
      }
    }
    tlclk {
      #clock-cells = ;
      clock-frequency = ;
      clock-output-names = "tlclk";
      compatible = "fixed-clock";
    }
  }
}
[    0.000000] HART = 0 DTB = 81200000
[    0.000000] search "chosen", depth: 0, uname:
[    0.000000] search "chosen", depth: 1, uname: chosen
[    0.000000] Looking for initrd properties...
[    0.000000] Command line is: debug console=ttySIF0,125200 root=/dev/mmcblk0p2 loglevel=7 rootwait
[    0.000000] dt_root_size_cells = 1
[    0.000000] dt_root_addr_cells = 1
[    0.000000] memory scan node ram@80000000, reg size 8,
[    0.000000]  - 80000000 ,  40000000
[    0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
[    0.000000] Linux version 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Sat Jul 6 12:14:41 MSK 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] initrd not found or empty - disabling initrd
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] INITIAL: ffffffe001000000
[    0.000000]  -> unflatten_device_tree()
[    0.000000] Unflattening device tree:
[    0.000000] magic: d00dfeed
[    0.000000] size: 00001000
[    0.000000] version: 00000011
[    0.000000]   size is 13512, allocating...
[    0.000000]   unflattening (____ptrval____)...
[    0.000000] fixed up name for  ->
[    0.000000] fixed up name for chosen -> chosen
[    0.000000] fixed up name for firmware -> firmware
[    0.000000] fixed up name for aliases -> aliases
[    0.000000] fixed up name for cpus -> cpus
[    0.000000] fixed up name for cpu@0 -> cpu
[    0.000000] fixed up name for interrupt-controller -> interrupt-controller
[    0.000000] fixed up name for ram@80000000 -> ram
[    0.000000] fixed up name for soc -> soc
[    0.000000] fixed up name for clint@2000000 -> clint
[    0.000000] fixed up name for debug-controller@0 -> debug-controller
[    0.000000] fixed up name for gpio@64002000 -> gpio
[    0.000000] fixed up name for interrupt-controller@c000000 -> interrupt-controller
[    0.000000] fixed up name for rom@10000 -> rom
[    0.000000] fixed up name for serial@64000000 -> serial
[    0.000000] fixed up name for spi@64001000 -> spi
[    0.000000] fixed up name for mmc@0 -> mmc
[    0.000000] fixed up name for tlclk -> tlclk
[    0.000000]  <- unflatten_device_tree()
[    0.000000] software IO TLB: mapped [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] 0 ffffffe03effcab0 [attach() failed for %s with error %d
[    0.000000] ] | [cpu]
[    0.000000] 0 ffffffe03eff0020 [(null)] | [cpu]

Salida en QEMU

                SIFIVE, INC.

         5555555555555555555555555
        5555                   5555
       5555                     5555
      5555                       5555
     5555       5555555555555555555555
    5555       555555555555555555555555
   5555                             5555
  5555                               5555
 5555                                 5555
5555555555555555555555555555          55555
 55555           555555555           55555
   55555           55555           55555
     55555           5           55555
       55555                   55555
         55555               55555
           55555           55555
             55555       55555
               55555   55555
                 555555555
                   55555
                     5

           SiFive RISC-V Core IP
 {
  #address-cells = ;
  #size-cells = ;
  compatible = "riscv-virtio";
  model = "riscv-virtio,qemu";
  chosen {
    linux,initrd-start = ;
    linux,initrd-end = ;
    riscv,kernel-start = ;
    riscv,kernel-end = ;
    bootargs = "";
    stdout-path = ;
  }
  uart@10000000 {
    interrupts = ;
    interrupt-parent = ;
    clock-frequency = ;
    reg = ;
    compatible = "ns16550a";
  }
  test@100000 {
    reg = ;
    compatible = "sifive,test0";
  }
  virtio_mmio@10008000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10007000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10006000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10005000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10004000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10003000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10002000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  virtio_mmio@10001000 {
    interrupts = ;
    interrupt-parent = ;
    reg = ;
    compatible = "virtio,mmio";
  }
  cpus {
    #address-cells = ;
    #size-cells = ;
    timebase-frequency = ;
    cpu@0 {
      device_type = "cpu";
      reg = ;
      status = "okay";
      compatible = "riscv";
      riscv,isa = "rv64imafdcsu";
      mmu-type = "riscv,sv48";
      clock-frequency = ;
      interrupt-controller {
        #interrupt-cells = ;
        interrupt-controller;
        compatible = "riscv,cpu-intc";
        linux,phandle = ;
        phandle = ;
      }
    }
  }
  memory@80000000 {
    device_type = "memory";
    reg = ;
  }
  soc {
    #address-cells = ;
    #size-cells = ;
    compatible = "simple-bus";
    ranges;
    pci@30000000 {
      interrupt-map-mask = ;
      interrupt-map = ;
      ranges = ;
      reg = ;
      dma-coherent;
      bus-range = ;
      linux,pci-domain = ;
      device_type = "pci";
      compatible = "pci-host-ecam-generic";
      #size-cells = ;
      #interrupt-cells = ;
      #address-cells = ;
    }
    interrupt-controller@c000000 {
      linux,phandle = ;
      phandle = ;
      riscv,ndev = ;
      riscv,max-priority = ;
      reg-names = "control";
      reg = ;
      interrupts-extended = ;
      interrupt-controller;
      compatible = "riscv,plic0";
      #interrupt-cells = ;
      #address-cells = ;
    }
    clint@2000000 {
      interrupts-extended = ;
      reg = ;
      compatible = "riscv,clint0";
    }
  }
}
[    0.000000] HART = 0 DTB = 80e00000
[    0.000000] search "chosen", depth: 0, uname:
[    0.000000] search "chosen", depth: 1, uname: chosen
[    0.000000] Looking for initrd properties...
[    0.000000] initrd_start=0x88000000  initrd_end=0x88442b86
[    0.000000] Command line is: earlyprintk
[    0.000000] dt_root_size_cells = 2
[    0.000000] dt_root_addr_cells = 2
[    0.000000] memory scan node memory@80000000, reg size 16,
[    0.000000]  - 80000000 ,  40000000
[    0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000
[    0.000000] Linux version 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Sat Jul 6 12:14:41 MSK 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] Initial ramdisk at: 0x(____ptrval____) (4467590 bytes)
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] INITIAL: ffffffe000c00000
[    0.000000]  -> unflatten_device_tree()
[    0.000000] Unflattening device tree:
[    0.000000] magic: d00dfeed
[    0.000000] size: 00000d56
[    0.000000] version: 00000011
[    0.000000]   size is 14192, allocating...
[    0.000000]   unflattening (____ptrval____)...
[    0.000000] fixed up name for  ->
[    0.000000] fixed up name for chosen -> chosen
[    0.000000] fixed up name for uart@10000000 -> uart
[    0.000000] fixed up name for test@100000 -> test
[    0.000000] fixed up name for virtio_mmio@10008000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10007000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10006000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10005000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10004000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10003000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10002000 -> virtio_mmio
[    0.000000] fixed up name for virtio_mmio@10001000 -> virtio_mmio
[    0.000000] fixed up name for cpus -> cpus
[    0.000000] fixed up name for cpu@0 -> cpu
[    0.000000] fixed up name for interrupt-controller -> interrupt-controller
[    0.000000] fixed up name for memory@80000000 -> memory
[    0.000000] fixed up name for soc -> soc
[    0.000000] fixed up name for pci@30000000 -> pci
[    0.000000] fixed up name for interrupt-controller@c000000 -> interrupt-controller
[    0.000000] fixed up name for clint@2000000 -> clint
[    0.000000]  <- unflatten_device_tree()
[    0.000000] software IO TLB: mapped [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] 0 ffffffe03effc808 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effca78 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effcd98 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd068 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd230 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd4b8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd740 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd9c8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effdc50 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effded8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe160 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe3e8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe670 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03effec00 [<NULL>] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03effeee8 [memory] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efff0b0 [<NULL>] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efff320 [pci] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efff858 [<NULL>] | [cpu]
[    0.000000] ffffffe03effe888 ffffffe03efffd58 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effc808 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effca78 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effcd98 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd068 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd230 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd4b8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd740 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effd9c8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effdc50 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effded8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe160 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe3e8 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe670 [<NULL>] | [cpu]
[    0.000000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.000000] elf_hwcap is 0x112d
[    0.000000] percpu: Embedded 17 pages/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 258055
[    0.000000] Kernel command line: earlyprintk
[    0.000000] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes)
[    0.000000] Sorting __ex_table...
[    0.000000] Memory: 949716K/1046528K available (6565K kernel code, 342K rwdata, 2564K rodata, 208K init, 832K bss, 96812K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu:     RCU event tracing is enabled.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, preallocated irqs: 0
[    0.000000] plic: mapped 53 interrupts to 2 (out of 2) handlers.
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
[    0.000000] Console: colour dummy device 80x25
[    0.000000] console [tty0] enabled
[    0.000000] bootconsole [early0] disabled
[    0.000000] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=100000)
[    0.000000] pid_max: default: 32768 minimum: 301
[    0.000000] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)
[    0.000000] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes)
[    0.020000] rcu: Hierarchical SRCU implementation.
[    0.020000] smp: Bringing up secondary CPUs ...
[    0.020000] smp: Brought up 1 node, 1 CPU
[    0.050000] devtmpfs: initialized
[    0.050000] 0 ffffffe03effc808 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effca78 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effcd98 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd068 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd230 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd4b8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd740 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effd9c8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effdc50 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effded8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe160 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe3e8 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe670 [<NULL>] | [cpu]
[    0.050000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.050000] random: get_random_u32 called from bucket_table_alloc+0x76/0x17a with crng_init=0
[    0.050000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.050000] futex hash table entries: 256 (order: 2, 16384 bytes)
[    0.060000] NET: Registered protocol family 16
[    0.090000] vgaarb: loaded
[    0.090000] SCSI subsystem initialized
[    0.090000] usbcore: registered new interface driver usbfs
[    0.090000] usbcore: registered new interface driver hub
[    0.090000] usbcore: registered new device driver usb
[    0.090000] pps_core: LinuxPPS API ver. 1 registered
[    0.090000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    0.090000] PTP clock support registered
[    0.100000] Advanced Linux Sound Architecture Driver Initialized.
[    0.100000] clocksource: Switched to clocksource riscv_clocksource
[    0.110000] NET: Registered protocol family 2
[    0.110000] tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes)
[    0.110000] TCP established hash table entries: 8192 (order: 4, 65536 bytes)
[    0.110000] TCP bind hash table entries: 8192 (order: 5, 131072 bytes)
[    0.110000] TCP: Hash tables configured (established 8192 bind 8192)
[    0.110000] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    0.110000] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    0.110000] NET: Registered protocol family 1
[    0.120000] Unpacking initramfs...
[    0.590000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[    0.620000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
[    0.620000] io scheduler noop registered
[    0.620000] io scheduler deadline registered
[    0.620000] io scheduler cfq registered (default)
[    0.620000] io scheduler mq-deadline registered
[    0.620000] io scheduler kyber registered
[    0.620000] shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
[    0.690000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.690000] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 10, base_baud = 230400) is a 16550A
[    0.720000] console [ttyS0] enabled
[    0.720000] [drm] radeon kernel modesetting enabled.
[    0.720000] [drm] amdgpu kernel modesetting enabled.
[    0.730000] loop: module loaded
[    0.730000] libphy: Fixed MDIO Bus: probed
[    0.740000] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.740000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.740000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.740000] ehci-pci: EHCI PCI platform driver
[    0.740000] ehci-platform: EHCI generic platform driver
[    0.740000] mousedev: PS/2 mouse device common for all mice
[    0.740000] usbcore: registered new interface driver usbhid
[    0.740000] usbhid: USB HID core driver
[    0.740000] usbcore: registered new interface driver snd-usb-audio
[    0.740000] NET: Registered protocol family 10
[    0.750000] Segment Routing with IPv6
[    0.750000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.750000] NET: Registered protocol family 17
[    0.750000] Key type dns_resolver registered
[    0.760000] ALSA device list:
[    0.760000]   No soundcards found.
[    0.770000] Freeing unused kernel memory: 208K
[    0.770000] This architecture does not have kernel memory protection.
[    0.770000] Run /init as init process

(El núcleo imprime líneas con "timestamp", antes de las cuales el árbol imprime BBL) Por un lado, FDT se lee con éxito, por otro lado, se obtiene una especie de tontería en el árbol "objetual" parseado.

Durante el proceso de depuración, entendí que BBL no podía leer la dirección "doble" no porque hubiera un error en la configuración, sino simplemente porque se había establecido en el nodo raíz #address-cells = <1>; #size-cells = <1>;.

Al ampliar la salida de depuración, vi que los punteros a tipo y name "se rompieron", de una manera bastante extraña: su primer byte (empezando desde cero) se había anulado, algo así como 0xabcdef -> 0xab00ef. Tuve que utilizar una táctica familiar: sabiendo las direcciones donde se encuentra la memoria dañada, añadir en la función printk la impresión de estos datos. Bueno, también distribuidos los llamados printk donde hay pocos. Lamentablemente, no se volvió mucho más claro. Entonces comencé, comparando con el desensamblador objdump la versión, a colocar manualmente los breakpoints y pasar paso a paso por la sección problemática del código. Y aquí se descubrió un misterio desagradable: si inmediatamente se coloca el punto de ruptura en algún lugar relativamente lejos del estado conocido y bueno, al detenerse en él, veré que ya hay memoria dañada. Pero si intento acercarme sigilosamente a ella paso a paso, ¡entonces el error tiene tiempo de esconderse! Este asunto huele a un controlador de memoria dañado y a un caché que oculta el error, si se solicita constantemente el valor correcto. ¿Y si…

Reemplazamos la memoria

Aprovechando la oportunidad de resolver el problema que no está de mi lado, supuse que tal vez simplemente tenía un módulo de memoria dañado. Recordé que el netbook de hace diez años no es solo una computadora portátil, sino también una valiosa fuente de DDR2 SO-DIMM. Además, se puede insertar la memoria retirada de la placa y obtener casi de inmediato un bloqueo de Memtest (Linux, por cierto, se cargó casi hasta la interfaz gráfica). Pero mejor no repitas tal experimento si valoras la información en los discos montados...). Por un lado, se podría suponer que simplemente la memoria no encajaba específicamente en este netbook. Por otro lado, ¡él pudo arrancar! Surgió la esperanza de que simplemente la memoria está "rota" y el problema no está en mi envoltura.

Entonces, necesitamos intentar iniciar temporalmente con memoria de netbook. Desafortunadamente, Quartus 18 no puede actualizar este IP Core para que sea editable. Así que, de hecho, ha llegado el momento de aprender a crear nuevas instancias. Resultó ser bastante simple: buscamos en el IP Catalog el ítem DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP y obtenemos un bloque con la misma interfaz que antes. El único problema es establecer los ajustes de memoria correctos.

Obtenemos los parámetros del módulo de memoria

Hay un método relativamente obvio para configurar el módulo: leer los parámetros del SPD. De hecho, si una computadora normal lee los datos del SPD y configura el controlador con ellos, entonces vamos a leer estos datos en el netbook existente y los introduciremos en una tabla.

En Ubuntu, esto se hace de manera bastante sencilla: necesitamos instalar el paquete i2c-tools, cargar los módulos eeprom y i2c-i801 (no estoy seguro, la verdad, de que el segundo controlador sirva en todos lados), después de lo cual se debe ejecutar decode-dimms:

Salida de decode-dimms

# decode-dimms version 6231 (2014-02-20 10:54:34 +0100)

Memory Serial Presence Detect Decoder
By Philip Edelbrock, Christian Zuckschwerdt, Burkart Lingner,
Jean Delvare, Trent Piepho and others

Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/0-0050
Guessing DIMM is in                             bank 1

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                   OK (0x00)
SPD Revision                                    Invalid
Fundamental Memory type                         Unknown (0x00)

---=== Manufacturing Information ===---
Manufacturer                                    Undefined
Part Number                                     Undefined

Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/4-0050
Guessing DIMM is in                             bank 1

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                   OK (0x00)
SPD Revision                                    Invalid
Fundamental Memory type                         Unknown (0x00)

---=== Manufacturing Information ===---
Manufacturer                                    Undefined
Part Number                                     Undefined

Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/6-0050
Guessing DIMM is in                             bank 1

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                   OK (0x76)
# of bytes written to SDRAM EEPROM              128
Total number of bytes in EEPROM                 256
Fundamental Memory type                         DDR2 SDRAM
SPD Revision                                    1.2

---=== Memory Characteristics ===---
Maximum module speed                            800 MHz (PC2-6400)
Size                                            1024 MB
Banks x Rows x Columns x Bits                   8 x 13 x 10 x 64
Ranks                                           2
SDRAM Device Width                              16 bits
Module Height                                   30.0 mm
Module Type                                     SO-DIMM (67.6 mm)
DRAM Package                                    Planar
Voltage Interface Level                         SSTL 1.8V
Module Configuration Type                       No Parity
Refresh Rate                                    Reduced (7.8 us) - Self Refresh
Supported Burst Lengths                         4, 8
tCL-tRCD-tRP-tRAS                               6-6-6-18
Supported CAS Latencies (tCL)                   6T, 5T, 4T
Minimum Cycle Time                              2.50 ns at CAS 6 (tCK min)
                                                3.00 ns at CAS 5
                                                3.75 ns at CAS 4
Maximum Access Time                             0.40 ns at CAS 6 (tAC)
                                                0.45 ns at CAS 5
                                                0.50 ns at CAS 4
Maximum Cycle Time (tCK max)                    8.00 ns

---=== Timing Parameters ===---
Address/Command Setup Time Before Clock (tIS)   0.17 ns
Address/Command Hold Time After Clock (tIH)     0.25 ns
Data Input Setup Time Before Strobe (tDS)       0.05 ns
Data Input Hold Time After Strobe (tDH)         0.12 ns
Minimum Row Precharge Delay (tRP)               15.00 ns
Minimum Row Active to Row Active Delay (tRRD)   10.00 ns
Minimum RAS# to CAS# Delay (tRCD)               15.00 ns
Minimum RAS# Pulse Width (tRAS)                 45.00 ns
Write Recovery Time (tWR)                       15.00 ns
Minimum Write to Read CMD Delay (tWTR)          7.50 ns
Minimum Read to Pre-charge CMD Delay (tRTP)     7.50 ns
Minimum Active to Auto-refresh Delay (tRC)      60.00 ns
Minimum Recovery Delay (tRFC)                   127.50 ns
Maximum DQS to DQ Skew (tDQSQ)                  0.20 ns
Maximum Read Data Hold Skew (tQHS)              0.30 ns

---=== Manufacturing Information ===---
Manufacturer                                    Samsung
Manufacturing Location Code                     0x02
Part Number                                     M4 70T2864QZ3-CF7
Revision Code                                   0x3351
Manufacturing Date                              2009-W34
Assembly Serial Number                          0x79C64E9A

Number of SDRAM DIMMs detected and decoded: 3

El problema es que algunos tiempos no se indican aquí, así que vamos a optar por el segundo camino.

¿Qué está escrito en los módulos:

Parte 4: Finalmente lanzamos Linux en RocketChip RISC-VParte 4: Finalmente lanzamos Linux en RocketChip RISC-V

En este caso, es más interesante la inscripción en los propios chips de memoria: K4T1G164QQ-HCF7. Al introducir esta línea en Google, obtenemos la hoja de datos de varias decenas de páginas con todos los parámetros necesarios, que se pueden transcribir cuidadosamente en las propiedades del IP Core. Solo asegúrate de prestar atención a las unidades de medida: a veces ns, a veces — ps, y a veces incluso fracciones de tCK. No voy a enseñarte en qué debes prestar atención, ya que yo mismo configuré mucho a prueba y error (no puedo garantizar que no se pueda "quemar" la memoria o el FPGA). Solo haré hincapié en lo siguiente: me costó mucho hacer que el controlador funcionara, y el último paso fue darme cuenta de que necesitaba verificar el ancho de todas las interfaces de memoria para que coincidieran con el código generado en Verilog: sucede que cuando en MemIfBundle especificado val mem_ba = IO(Output(UInt(2.W))), y hay 8 bancos (es decir, dirección de 3 bits de ancho), entonces todo lo que tenemos — una salida flotante del controlador de memoria — es un problema, pero no crítico, así que se sintetiza, pero no funciona.

Quizás todo funcionaría también con el antiguo módulo, si se actualizara el controlador, pero por ahora no tengo ganas de lidiar con los posibles errores intermitentes: ya tengo suficientes de los míos.

Así que, después de mover timebase-frequency en DTS del nivel de CPU específico al nivel del nodo cpus (por una solicitud claramente expresada del núcleo), obtenemos:

Texto oculto

[    0.000000] OF: fdt: Ignorando el rango de memoria 0x80000000 - 0x80200000
[    0.000000] Versión de Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versión 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Tue Jul 9 22:42:36 MSK 2019
[    0.000000] bootconsole [early0] habilitado
[    0.000000] Ramdisk inicial en: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Rangos de zona:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Inicio de zona movible para cada nodo
[    0.000000] Rangos de nodos de memoria temprana
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configuración de memoria inicial del nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] software IO TLB: mapeado [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] elf_hwcap es 0x112d
[    0.000000] percpu: 17 páginas/cpu incrustadas @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Se construyeron 1 listas de zonas, agrupando movilidad.  Total de páginas: 258055
[    0.000000] Línea de comandos del kernel: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Entradas de tabla de hash de caché de Dentry: 131072 (orden: 8, 1048576 bytes)
[    0.000000] Entradas de tabla de hash de caché de inodo: 65536 (orden: 7, 524288 bytes)
[    0.000000] Clasificando __ex_table...
[    0.000000] Memoria: 937696K\/1046528K disponible (6565K código del núcleo, 343K rwdata, 2564K rodata, 208K init, 832K bss, 108832K reservado, 0K cma-reservado)
[    0.000000] SLUB: HWalign=64, Orden=0-3, MinObjects=0, CPUs=1, Nodos=1
[    0.000000] rcu: Implementación jerárquica de RCU.
[    0.000000] rcu:     El trazado de eventos RCU está habilitado.
[    0.000000] rcu:     RCU restringiendo CPUs desde NR_CPUS=8 a nr_cpu_ids=1.
[    0.000000] rcu: Ajustando geometría para rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, IRQS preasignados: 0
[    0.000000] plic: mapeadas 8 interrupciones a 1 (de 2) controladores.
[    0.000000] source de reloj: riscv_clocksource: máscara: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000000] Consola: dispositivo dummy de color 80x25
[    0.000000] Calibrando el bucle de retardo (omitido), valor calculado usando la frecuencia del temporizador.. 2.00 BogoMIPS (lpj=10000)
[    0.020000] pid_max: predeterminado: 32768 mínimo: 301
[    0.030000] Entradas de tabla de hash de caché de montaje: 2048 (orden: 2, 16384 bytes)
[    0.040000] Entradas de tabla de hash de caché de punto de montaje: 2048 (orden: 2, 16384 bytes)
[    0.140000] rcu: Implementación jerárquica de SRCU.
[    0.190000] smp: Activando CPUs secundarias ...
[    0.190000] smp: Se activó 1 nodo, 1 CPU
[    0.220000] devtmpfs: inicializado
[    0.300000] random: get_random_u32 llamado desde bucket_table_alloc+0x76\/0x17a con crng_init=0
[    0.330000] source de reloj: jiffies: máscara: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.340000] entradas de tabla de hash futex: 256 (orden: 2, 16384 bytes)
[    0.380000] NET: Familia de protocolo 16 registrada
[    1.850000] vgaarb: cargado
[    1.870000] subsistema SCSI inicializado
[    1.900000] usbcore: controlador de interfaz nuevo registrado usbfs
[    1.910000] usbcore: controlador de interfaz nuevo registrado hub
[    1.920000] usbcore: nuevo controlador de dispositivo registrado usb
[    1.930000] pps_core: API de LinuxPPS ver. 1 registrada
[    1.940000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    1.950000] Soporte de reloj PTP registrado
[    1.970000] Controlador de Arquitectura de Sonido de Linux Avanzado Inicializado.
[    2.010000] source de reloj: Cambiado a source riscv_clocksource
[    2.600000] NET: Familia de protocolo 2 registrada
[    2.640000] tcp_listen_portaddr_hash entradas de tabla de hash: 512 (orden: 1, 8192 bytes)
[    2.650000] Entradas de tabla de hash de TCP establecidas: 8192 (orden: 4, 65536 bytes)
[    2.670000] Entradas de tabla de hash de TCP bind: 8192 (orden: 5, 131072 bytes)
[    2.700000] TCP: Tablas de hash configuradas (establecidas 8192 bind 8192)
[    2.720000] UDP entradas de tabla de hash: 512 (orden: 2, 16384 bytes)
[    2.730000] UDP-Lite entradas de tabla de hash: 512 (orden: 2, 16384 bytes)
[    2.750000] NET: Familia de protocolo 1 registrada
[    2.770000] Desempaquetando initramfs...
[   23.980000] Desempaquetado de initramfs fallido: basura en el archivo comprimido
[   24.030000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[   25.020000] Controlador genérico SCSI de capa de bloque (bsg) versión 0.4 cargado (mayor 251)
[   25.030000] programador de io noop registrado
[   25.040000] programador de io deadline registrado
[   25.050000] programador de io cfq registrado (predeterminado)
[   25.060000] programador de io mq-deadline registrado
[   25.060000] programador de io kyber registrado
[   25.120000] sifive_gpio 64002000.gpio: Chip GPIO de SiFive registrado 6 GPIOs
[   25.150000] shpchp: Controlador estándar de PCI Hot Plug versión: 0.4
[   28.870000] Serial: controlador 8250\/16550, 4 puertos, compartición de IRQ deshabilitada
[   28.940000] sifive-serial 64000000.serial: no se puede encontrar el reloj del controlador
[   28.950000] sifive-serial: la prueba de 64000000.serial falló con el error -2
[   28.980000] [drm] configuración de modo del kernel de radeon habilitada.
[   28.990000] [drm] configuración de modo del kernel de amdgpu habilitada.
[   29.500000] loop: módulo cargado
[   29.610000] sifive_spi 64001000.spi: No se puede encontrar el reloj de bus
[   29.620000] sifive_spi: la prueba de 64001000.spi falló con el error -2
[   29.640000] libphy: Bus MDIO fijo: probado
[   29.680000] e1000e: Controlador de Red Intel(R) PRO\/1000 - 3.2.6-k
[   29.690000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[   29.700000] ehci_hcd: Controlador del controlador de Host USB 2.0 'Mejorado' (EHCI)
[   29.710000] ehci-pci: Controlador de plataforma EHCI PCI
[   29.720000] ehci-platform: Controlador genérico de plataforma EHCI
[   29.750000] mousedev: dispositivo de mouse PS\/2 común para todos los ratones
[   29.790000] usbcore: nuevo controlador de interfaz registrado usbhid
[   29.800000] usbhid: controlador del núcleo USB HID
[   29.820000] usbcore: nuevo controlador de interfaz registrado snd-usb-audio
[   29.900000] NET: Familia de protocolo 10 registrada
[   29.960000] Segment Routing con IPv6
[   29.960000] sit: controladores de túnel IPv6, IPv4 y MPLS sobre IPv4
[   30.020000] NET: Familia de protocolo 17 registrada
[   30.020000] Tipo de clave dns_resolver registrado
[   30.070000] bootconsole [early0] usa memoria de inicio y debe ser deshabilitado incluso antes de que la real esté lista
[   30.080000] bootconsole [early0] deshabilitado

Después de eso, no ocurre nada visible.

Ahora se puede intentar abordar tres problemas:

[   23.980000] Fallo al descomprimir initramfs: basura en el archivo comprimido
...
[   28.940000] sifive-serial 64000000.serial: incapaz de encontrar el reloj del controlador
...
[   29.610000] sifive_spi 64001000.spi: No se pudo encontrar el reloj del bus

… así como con la interrupción de la salida en la consola.

No es muy difícil abordar dos problemas de frecuencias: se necesita agregar puntos clocks en los subárboles de los dispositivos requeridos, para mayor comodidad, dando un nombre claro a la etiqueta del nodo tlclk:

diff --git a/arch/riscv/dts/zeowaa-1gb.dts b/arch/riscv/dts/zeowaa-1gb.dts
index 4b2cebc..1347e76 100644
--- a/arch/riscv/dts/zeowaa-1gb.dts
+++ b/arch/riscv/dts/zeowaa-1gb.dts
@@ -96,6 +97,7 @@
                 L8: serial@64000000 {
                         compatible = "sifive,uart0";
                         interrupt-parent = ;
+                        clocks = ;
                         interrupts = ;
                         reg = ;
                         reg-names = "control";
@@ -107,6 +109,7 @@
                         interrupt-parent = ;
                         interrupts = ;
                         reg = ;
+                        clocks = ;
                         reg-names = "control";
                         L12: mmc@0 {
                                 compatible = "mmc-spi-slot";
@@ -116,7 +119,7 @@
                                 voltage-ranges = ;
                         };
                 };
-                L11: tlclk {
+                tlclk: tlclk {
                         #clock-cells = ;
                         clock-frequency = ;
                         clock-output-names = "tlclk";

Agregando una línea #define pr_debug printk al principio del archivo init/initramfs.c, la salida que muestra un mensaje sobre basura en lugar de initramfs se convierte en un mensaje un poco más detallado:

[    2.760000] Desempaquetando initramfs...
[    2.770000] Datos comprimidos gzip detectados
[   23.940000] Datos comprimidos (null) detectados
[   23.970000] Fallo al descomprimir initramfs: basura en el archivo comprimido

Es decir, es posible que la basura no sea en lugar de initramfs, sino juntos.

Está bien, encontró algo, tal vez esto sea suficiente. ¿Pero a dónde fue la consola? La búsqueda da un enlace a un problema en GitHub: linux failed to bringup on vc707 board — resulta que un UART, según el controlador, ni siquiera merece la pena discutir. Pero la corrección data del 11 de julio de 2018 — hace un año. Resulta que este commit nunca llegó al árbol desde el cual estoy compilando el núcleo. Al aplicar manualmente este parche, ¡obtuve un Linux funcional! Resultó que el problema con initramfs no era crítico.

Iniciando sesión como user=root, password=sifive, pude sin mayores problemas (exceptuando entender que el número GPIO tiene un base desde el cual se cuenta, y que simplemente se necesita leer de un archivo pseudo correspondiente) a través de sysfs encender un LED en la placa.

Como la última vez, adjunto el video de texto sobre el arranque de Linux. En el momento de cambiar la consola de earlyprintk a la estándar, aparece algún tipo de desorden, similar a la salida cuando la velocidad del UART está incorrectamente configurada. Curiosamente, el reproductor manejó esta "confusión" con éxito.

Parte 4: Finalmente lanzamos Linux en RocketChip RISC-V

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster