Parte 4: Alla fine avviamo Linux su RocketChip RISC-V

Parte 4: Alla fine avviamo Linux su RocketChip RISC-V Nell'immagine il kernel Linux ti saluta tramite GPIO.

In questa parte della storia del porting di RISC-V RocketChip su una scheda cinese con Cyclone IV, avvieremo Linux e impareremo a configurare il core IP del controller di memoria, apportando alcune modifiche alla descrizione dts dell'hardware. Questo articolo è un seguito della terza parte, ma, a differenza della precedente, piuttosto estesa, sarà piuttosto breve.

… Poiché setup_smp viene chiamato solo se il kernel è configurato con supporto SMP, potremmo provare a disattivare il supporto multi-core. Sarebbe sgradevole dover implementare anche il supporto per l'atomicità nel modulo di memoria (pensavo che il cache se ne occupasse da solo), ma nel caso monocore non dovrebbe crearci problemi.

Tuttavia non ha funzionato…

[    0.000000] OF: fdt: Ignorando la gamma di memoria 0x80000000 - 0x80200000
[    0.000000] Versione Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versione 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 Gio 4 Lug 18:38:10 MSK 2019
[    0.000000] bootconsole [early0] abilitato
[    0.000000] Ramdisk iniziale a: 0x(____ptrval____) (16777216 byte)
[    0.000000] Gamma delle zone:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normale   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Inizio della zona mobile per ogni nodo
[    0.000000] Gamma iniziale della memoria dei nodi
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configurazione dell'inizializzazione della memoria nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] TLB software IO: mappato [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] Impossibile trovare l'entrata del dispositivo "cpu" nel device tree
[    0.000000] Costruito 1 zonelists, raggruppamento di mobilità attivato.  Pagine totali: 258055
[    0.000000] Linea di comando del kernel: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Voci della tabella di hash della cache Dentry: 131072 (ordine: 8, 1048576 byte)
[    0.000000] Voci della tabella di hash della cache Inode: 65536 (ordine: 7, 524288 byte)
[    0.000000] Ordinamento __ex_table...
[    0.000000] BUG: Stato della pagina errato nel processo swapper  pfn:80bf7
[    0.000000] pagina:ffffffe03f029e08 conteggio:0 mappa conteggio:-65280 mapping:0000000000000000 indice:0x1
[    0.000000] flag: 0x0()
[    0.000000] raw: 0000000000000000 0000000000000100 0000000000000200 0000000000000000
[    0.000000] raw: 0000000000000001 0000000000000000 00000000ffff00ff
[    0.000000] pagina scaricata a causa di: mapcount non zero
[    0.000000] Moduli collegati:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Non contaminato 4.19.0-sifive-1+ #1
[    0.000000] Trace della chiamata:
[    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] Disabilitazione del debug del lock a causa di contaminazione del kernel
[    0.000000] BUG: Stato della pagina errato nel processo swapper  pfn:80bf9
[    0.000000] pagina:ffffffe03f029e78 conteggio:0 mappa conteggio:-65280 mapping:0000000000000000 indice:0x0
[    0.000000] flag: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020080 ffffffe03f020080 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina scaricata a causa di: mapcount non zero
[    0.000000] Moduli collegati:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminato: G    B             4.19.0-sifive-1+ #1
[    0.000000] Trace della chiamata:
[    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: Stato della pagina errato nel processo swapper  pfn:80bfa
[    0.000000] pagina:ffffffe03f029eb0 conteggio:0 mappa conteggio:-65280 mapping:0000000000000000 indice:0x0
[    0.000000] flag: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f0200b8 ffffffe03f0200b8 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina scaricata a causa di: mapcount non zero
[    0.000000] Moduli collegati:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminato: G    B             4.19.0-sifive-1+ #1
[    0.000000] Trace della chiamata:
[    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: Stato della pagina errato nel processo swapper  pfn:80bfc
[    0.000000] pagina:ffffffe03f029f20 conteggio:0 mappa conteggio:-65280 mapping:0000000000000000 indice:0x0
[    0.000000] flag: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020028 ffffffe03f020028 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
...

È interessante notare che dopo tutta la debug, ho deciso di controllare come dovrebbe apparire l'output "riferimento" del kernel, ha detto make qemu, e ho visto un errore simile.

Purtroppo, il livello successivo (Linux kernel) è più complesso: GDB, connesso tramite JTAG a RocketChip, sembra lavorare con indirizzi fisici indipendentemente da come è configurato l'MMU, e il kernel in quel momento aveva già impostato la mappatura degli indirizzi, quindi non basta dire display/10i $pc non funziona — vedremo solo molte unimp. Tuttavia, se abbiamo già determinato l'offset (sembra che 0x80200000 -> 0xffffffe000000000), possiamo fare un trucco:

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)

I breakpoint vengono impostati in modo simile:

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

Programma ricevuto segnale SIGTRAP, Trace/breakpoint trap.
setup_smp () at /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 () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
#1  0xffffffe0000022a2 in setup_arch () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/setup.c:253
#2  0x0000000000000000 in ?? ()
Backtrace stopped: frame did not save the PC

Solo che bisogna disattivarli manualmente per proseguire — per GDB è una sorta di trappola completamente incomprensibile. Ah già, se per caso dite s o n anziché si, gdb cercherà di inserire un breakpoint implicito, che per ovvie ragioni non verrà impostato, ma neanche GDB può essere dissuaso. Ma non affrettatevi a riavviare la scheda — dalle mie osservazioni, è sufficiente riavviare solo gdb (tenete presente che i vecchi breakpoint potrebbero non scomparire).

Dobbiamo effettivamente affrontare il problema iniziale: la disposizione dei punti di debug printk nella funzione of_find_node_by_type, utilizzata dal codice per cercare il core del processore di avvio, mostra che vede qualche spazzatura invece dei nomi dei tipi di dispositivo. Ad esempio, prende da qualche parte la stringa "Serial port", sebbene non ci sia affatto nel dtb nel campo tipo_di_dispositivo. Dopo aver cercato questi byte nell'immagine del kernel, li ho trovati, ho guardato l'offset e ho capito l'ovvio: la dimensione del kernel nei parametri di avvio è chiaramente sottovalutata: sono stati allocati 8Mb, ma ne occupa più di dieci. Ho allocato 16Mb, ma le stranezze non sono cessate. Dopo aver danzato con la lettura dell'FDT da diversi indirizzi (di solito l'indirizzo viene passato al kernel nel registro a1), ho finalmente deciso di tracciare cosa viene adesso analizzato. Fortunatamente, invece di girare con il debugger (e ricordiamo che ci sono aspetti da considerare con la traduzione degli indirizzi, che devono comunque essere risolti in un modo o nell'altro), si può semplicemente e in modo approssimativo nel file drivers/of/fdt.c specificare #define pr_debug printk. Alla fine è venuto fuori:

aggiunta di output di debug

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 - limit the number of regions in the /memory node
  * @limit: maximum entries
@@ -1253,6 +1255,7 @@ bool __init early_init_dt_scan(void *params)
  */
 void __init unflatten_device_tree(void)
 {
+       printk("INITIAL: %lxn", initial_boot_params);
        __unflatten_device_tree(initial_boot_params, NULL, &of_root,
                                early_init_dt_alloc_memory_arch, false);

Output su 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]

Output in 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] ricerca "chosen", depth: 0, uname:
[    0.000000] ricerca "chosen", depth: 1, uname: chosen
[    0.000000] Cerco proprietà initrd...
[    0.000000] initrd_start=0x88000000  initrd_end=0x88442b86
[    0.000000] La riga di comando è: earlyprintk
[    0.000000] dt_root_size_cells = 2
[    0.000000] dt_root_addr_cells = 2
[    0.000000] scansione della memoria nodo memory@80000000, dimensione reg 16,
[    0.000000]  - 80000000 ,  40000000
[    0.000000] OF: fdt: Ignorando l'intervallo di memoria 0x80000000 - 0x80200000
[    0.000000] Versione Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versione 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Sab Jul 6 12:14:41 MSK 2019
[    0.000000] bootconsole [early0] abilitato
[    0.000000] Ramdisk iniziale a: 0x(____ptrval____) (4467590 byte)
[    0.000000] Intervalli di zona:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normale   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Inizio della zona mobile per ogni nodo
[    0.000000] Intervalli dei nodi di memoria iniziali
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configurazione della memoria iniziale nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] INIZIALE: ffffffe000c00000
[    0.000000]  -> unflatten_device_tree()
[    0.000000] Disunflattening alberi dispositivi:
[    0.000000] magic: d00dfeed
[    0.000000] size: 00000d56
[    0.000000] versione: 00000011
[    0.000000]   la dimensione è 14192, allocazione in corso...
[    0.000000]   disunflattening (____ptrval____)...
[    0.000000] nome sistemato per  ->
[    0.000000] nome sistemato per scelto -> scelto
[    0.000000] nome sistemato per uart@10000000 -> uart
[    0.000000] nome sistemato per test@100000 -> test
[    0.000000] nome sistemato per virtio_mmio@10008000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10007000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10006000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10005000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10004000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10003000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10002000 -> virtio_mmio
[    0.000000] nome sistemato per virtio_mmio@10001000 -> virtio_mmio
[    0.000000] nome sistemato per cpus -> cpus
[    0.000000] nome sistemato per cpu@0 -> cpu
[    0.000000] nome sistemato per interrupt-controller -> interrupt-controller
[    0.000000] nome sistemato per memory@80000000 -> memory
[    0.000000] nome sistemato per soc -> soc
[    0.000000] nome sistemato per pci@30000000 -> pci
[    0.000000] nome sistemato per interrupt-controller@c000000 -> interrupt-controller
[    0.000000] nome sistemato per clint@2000000 -> clint
[    0.000000]  <- disunflatten_device_tree()
[    0.000000] software IO TLB: mappato [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 è 0x112d
[    0.000000] percpu: Memoria integrata 17 pagine/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Costruito 1 zone list, raggruppamento mobilità attivato.  Totale pagine: 258055
[    0.000000] Riga di comando del kernel: earlyprintk
[    0.000000] Dentry cache hash table entries: 131072 (order: 8, 1048576 byte)
[    0.000000] Inode-cache hash table entries: 65536 (order: 7, 524288 byte)
[    0.000000] Ordinamento __ex_table...
[    0.000000] Memoria: 949716K/1046528K disponibile (6565K codice kernel, 342K rwdata, 2564K rodata, 208K init, 832K bss, 96812K riservato, 0K cma-riservato)
[    0.000000] SLUB: HWalign=64, Ordine=0-3, MinObjects=0, CPUs=1, Nodazioni=1
[    0.000000] rcu: Implementazione RCU gerarchica.
[    0.000000] rcu:     Tracciamento eventi RCU è attivato.
[    0.000000] rcu:     RCU limita le CPU da NR_CPUS=8 a nr_cpu_ids=1.
[    0.000000] rcu: Regolazione della geometria per rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, irq preallocati: 0
[    0.000000] plic: mappati 53 irq a 2 (su 2) handler.
[    0.000000] clocksource: riscv_clocksource: maschera: 0xffffffffffffffff massimi cicli: 0x24e6a1710, massimi_idle_ns: 440795202120 ns
[    0.000000] Console: dispositivo dummy a colori 80x25
[    0.000000] console [tty0] abilitato
[    0.000000] bootconsole [early0] disabilitato
[    0.000000] Calibrando il ciclo di attesa (saltato), valore calcolato usando la frequenza del timer.. 20.00 BogoMIPS (lpj=100000)
[    0.000000] pid_max: predefinito: 32768 minimo: 301
[    0.000000] Mount-cache hash table entries: 2048 (order: 2, 16384 byte)
[    0.000000] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 byte)
[    0.020000] rcu: Implementazione SRCU gerarchica.
[    0.020000] smp: Avvio CPU secondari ...
[    0.020000] smp: Avvio di 1 nodo, 1 CPU
[    0.050000] devtmpfs: inizializzato
[    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] ffffffe03effe888 ffffffe03effec00 [<NULL>] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03effeee8 [memory] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efff0b0 [<NULL>] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efff320 [pci] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efff858 [<NULL>] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efffd58 [<NULL>] | [cpu]
[    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] elf_hwcap è 0x112d
[    0.050000] percpu: Memoria integrata 17 pagine/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.050000] Costruito 1 zone list, raggruppamento mobilità attivato.  Totale pagine: 258055
[    0.050000] Riga di comando del kernel: earlyprintk
[    0.050000] Dentry cache hash table entries: 131072 (order: 8, 1048576 byte)
[    0.050000] Inode-cache hash table entries: 65536 (order: 7, 524288 byte)
[    0.050000] Ordinamento __ex_table...
[    0.050000] Memoria: 949716K/1046528K disponibile (6565K codice kernel, 342K rwdata, 2564K rodata, 208K init, 832K bss, 96812K riservato, 0K cma-riservato)
[    0.050000] SLUB: HWalign=64, Ordine=0-3, MinObjects=0, CPUs=1, Nodazioni=1
[    0.050000] rcu: Implementazione RCU gerarchica.
[    0.050000] rcu:     Tracciamento eventi RCU è attivato.
[    0.050000] rcu:     RCU limita le CPU da NR_CPUS=8 a nr_cpu_ids=1.
[    0.050000] rcu: Regolazione della geometria per rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.050000] NR_IRQS: 0, nr_irqs: 0, irq preallocati: 0
[    0.050000] plic: mappati 53 irq a 2 (su 2) handler.
[    0.050000] clocksource: riscv_clocksource: maschera: 0xffffffffffffffff massimi cicli: 0x24e6a1710, massimi_idle_ns: 440795202120 ns
[    0.050000] Console: dispositivo dummy a colori 80x25
[    0.050000] console [tty0] abilitato
[    0.050000] bootconsole [early0] disabilitato
[    0.050000] Calibrando il ciclo di attesa (saltato), valore calcolato usando la frequenza del timer.. 20.00 BogoMIPS (lpj=100000)
[    0.050000] pid_max: predefinito: 32768 minimo: 301
[    0.050000] Mount-cache hash table entries: 2048 (order: 2, 16384 byte)
[    0.050000] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 byte)
[    0.050000] rcu: Implementazione SRCU gerarchica.
[    0.050000] smp: Avvio CPU secondari ...
[    0.050000] smp: Avvio di 1 nodo, 1 CPU
[    0.050000] devtmpfs: inizializzato
[    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] ffffffe03effe888 ffffffe03effec00 [<NULL>] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03effeee8 [memory] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efff0b0 [<NULL>] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efff320 [pci] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efff858 [<NULL>] | [cpu]
[    0.050000] ffffffe03effe888 ffffffe03efffd58 [<NULL>] | [cpu]
[    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] elf_hwcap è 0x112d
[    0.050000] percpu: Memoria integrata 17 pagine/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.050000] Costruito 1 zone list, raggruppamento mobilità attivato.  Totale pagine: 258055
[    0.050000] Riga di comando del kernel: earlyprintk
[    0.050000] Dentry cache hash table entries: 131072 (order: 8, 1048576 byte)
[    0.050000] Inode-cache hash table entries: 65536 (order: 7, 524288 byte)
[    0.050000] Ordinamento __ex_table...
[    0.050000] Memoria: 949716K/1046528K disponibile (6565K codice kernel, 342K rwdata, 2564K rodata, 208K init, 832K bss, 96812K riservato, 0K cma-riservato)
[    0.050000] SLUB: HWalign=64, Ordine=0-3, MinObjects=0, CPUs=1, Nodazioni=1
[    0.050000] rcu: Implementazione RCU gerarchica.
[    0.050000] rcu:     Tracciamento eventi RCU è attivato.
[    0.050000] rcu:     RCU limita le CPU da NR_CPUS=8 a nr_cpu_ids=1.
[    0.050000] rcu: Regolazione della geometria per rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.050000] NR_IRQS: 0, nr_irqs: 0, irq preallocati: 0
[    0.050000] plic: mappati 53 irq a 2 (su 2) handler.
[    0.050000] clocksource: riscv_clocksource: maschera: 0xffffffffffffffff massimi cicli: 0x24e6a1710, massimi_idle_ns: 440795202120 ns
[    0.050000] Console: dispositivo dummy a colori 80x25
[    0.050000] console [tty0] abilitato
[    0.050000] bootconsole [early0] disabilitato
[    0.050000] Calibrando il ciclo di attesa (saltato), valore calcolato usando la frequenza del timer.. 20.00 BogoMIPS (lpj=100000)
[    0.050000] pid_max: predefinito: 32768 minimo: 301
[    0.050000] Mount-cache hash table entries: 2048 (order: 2, 16384 byte)
[    0.050000] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 byte)
[    0.050000] rcu: Implementazione SRCU gerarchica.
[    0.050000] smp: Avvio CPU secondari ...
[    0.050000] smp: Avvio di 1 nodo, 1 CPU
[    0.050000] devtmpfs: inizializzato

(«Le righe timestamp» viene visualizzata dal kernel, prima di esse l'albero visualizza BBL) Da un lato, FDT viene letto con successo, dall'altro sembra essere una sorta di assurdità nell'albero «oggettivo» analizzato.

Durante il debug ho capito che BBL non riusciva a leggere l'indirizzo «doppio» non perché ci fosse un errore nel config, ma semplicemente perché il nodo radice era impostato #address-cells = <1>; #size-cells = <1>;.

Espandendo l'output di debug, ho visto che i puntatori a type e name si erano «incrociati», e in modo piuttosto strano: il loro primo byte (a partire da zero) era stato azzerato, qualcosa del tipo 0xabcdef -> 0xab00ef. Ho dovuto usare una tattica familiare: conoscendo gli indirizzi in cui si trova la memoria danneggiata, aggiungere nella funzione printk la stampa di questi dati. E anche i... chiamate printk spargerle dove ce ne sono poche. Purtroppo, non è diventato molto più chiaro. Allora ho iniziato, confrontandomi con il disassemblato objdump versione, a posizionare manualmente i breakpoint e procedere passo dopo passo attraverso il segmento di codice problematico. E qui è emerso qualcosa di misterioso e sgradevole: se metto subito un punto di interruzione abbastanza lontano dallo stato known-good, allora, fermandomi su di esso, vedrò già la memoria danneggiata. Ma se cerco di avvicinarmi lentamente a essa passo dopo passo, l'errore riesce a nascondersi! La faccenda profuma di un controller di memoria guasto e di una cache che nasconde l'errore, se continuo a richiedere il valore necessario. E cosa se…

Sostituiamo la memoria

Aggrappandomi alla possibilità di risolvere il problema non dalla mia parte, ho ipotizzato che magari mi fosse semplicemente arrivato un modulo di memoria difettoso. Qui ho ricordato che un netbook di dieci anni fa non è solo un computer portatile, ma anche una preziosa fonte di DDR2 SO-DIMM. In aggiunta, posso inserire la memoria estratta dalla scheda e ottenere un blocco quasi istantaneo di Memtest (Linux, tra l'altro, si caricava quasi fino all'interfaccia grafica. Ma è meglio non ripetere un esperimento simile se ti interessa l'informazione sui dischi montati...). Da un lato, si potrebbe ipotizzare che la memoria non fosse semplicemente compatibile con questo netbook. Dall'altro, però, è riuscito a avviarsi! È emersa la speranza che la memoria fosse semplicemente «difettosa» e che il problema non fosse nella mia interfaccia.

Quindi, dobbiamo provare a lanciare temporaneamente con la memoria non notebook. Sfortunatamente, Quartus 18 non è in grado di aggiornare questo IP Core in modo da poterlo modificare. È giunto il momento di imparare a creare nuove istanze. Tutto si è rivelato piuttosto semplice: cercare nel Catalogo IP la voce DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP e ottenere un blocco con la stessa interfaccia di prima. L'unico problema è impostare correttamente le impostazioni della memoria.

Otteniamo i parametri del modulo di memoria

C'è un modo relativamente ovvio per configurare il modulo: leggere i parametri da SPD. Infatti, se un computer normale legge i dati SPD e configura il controller in base a questi, allora leggiamo questi dati sul notebook disponibile e li inseriamo in una tabella.

Su Ubuntu si fa piuttosto facilmente: è necessario installare il pacchetto i2c-tools, caricare i moduli eeprom e i2c-i801 (non sono sicuro, comunque, che il secondo driver funzioni ovunque), dopo di che si deve avviare decode-dimms:

Uscita di 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

Il problema è che alcuni timing non sono specificati, quindi sceglieremo la seconda strada.

Cosa è scritto sui moduli:

Parte 4: Alla fine avviamo Linux su RocketChip RISC-VParte 4: Alla fine avviamo Linux su RocketChip RISC-V

In questo caso è più interessante l'iscrizione sui chip di memoria stessi: K4T1G164QQ-HCF7. Immettendo questa riga su Google, otteniamo un datasheet di diverse decine di pagine con tutti i parametri necessari, che possono essere inseriti con attenzione nelle proprietà dell'IP Core. Basta prestare attenzione alle unità di misura: in alcuni casi ns, in altri — ps, e a volte anche frazioni di tCK. Non voglio insegnarvi su cosa prestare attenzione: ho impostato molto per tentativi ed errori (non posso garantire che in questo modo non si possa "bruciare" la memoria o la FPGA). Vorrei solo sottolineare una cosa: ho impiegato molto tempo per far funzionare il controller, e l'ultima fase è stata rendersi conto che era necessario controllare la larghezza di tutte le interfacce di memoria in relazione al codice generato in Verilog: infatti quando in MemIfBundle sia indicato val mem_ba = IO(Output(UInt(2.W))), e ci sono 8 banchi (cioè indirizzo largo 3 bit), tutto ciò che abbiamo — un output sospeso dal controller di memoria — è un problema, ma non critico, quindi tutto si sintetizza, ma non funziona.

Forse tutto si sarebbe avviato anche con il vecchio modulo, se si aggiornasse il controller, ma per ora sono un po' pigro per affrontare potenziali bug fluttuanti: ne ho già abbastanza dei miei.

Quindi, dopo aver spostato timebase-frequency in DTS dal livello di una CPU specifica al livello del nodo cpus (su richiesta chiaramente espressa del nucleo), otteniamo:

Testo nascosto

[    0.000000] OF: fdt: Ignorando l'intervallo di memoria 0x80000000 - 0x80200000
[    0.000000] Versione Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc versione 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Martedì 9 Lug 22:42:36 MSK 2019
[    0.000000] bootconsole [early0] abilitato
[    0.000000] Ramdisk iniziale a: 0x(____ptrval____) (16777216 bytes)
[    0.000000] Intervalli di zona:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normale   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Inizio della zona mobile per ogni nodo
[    0.000000] Intervalli di memoria iniziale
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Impostazione della memoria iniziale nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] IO TLB software: mappato [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] elf_hwcap è 0x112d
[    0.000000] percpu: 17 pagine incorporate/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Costruito 1 zonelists, raggruppamento di mobilità attivo.  Pagine totali: 258055
[    0.000000] Linea di comando del kernel: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Cache hash della dentry: 131072 voci (ordine: 8, 1048576 bytes)
[    0.000000] Cache hash dell'Inode: 65536 voci (ordine: 7, 524288 bytes)
[    0.000000] Ordinamento __ex_table...
[    0.000000] Memoria: 937696K\/1046528K disponibile (6565K codice del kernel, 343K rwdata, 2564K rodata, 208K init, 832K bss, 108832K riservato, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Ordine=0-3, MinObjects=0, CPU=1, Nodi=1
[    0.000000] rcu: Implementazione gerarchica RCU.
[    0.000000] rcu:     La tracciatura degli eventi RCU è abilitata.
[    0.000000] rcu:     RCU sta limitando le CPU da NR_CPUS=8 a nr_cpu_ids=1.
[    0.000000] rcu: Regolazione della geometria per rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, irqs preallocati: 0
[    0.000000] plic: mappati 8 interruzioni a 1 (fuori 2) gestori.
[    0.000000] fonte di clock: riscv_clocksource: maschera: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000000] Console: dispositivo dummy a colori 80x25
[    0.000000] Calibrando il ciclo di attesa (saltato), valore calcolato utilizzando la frequenza del timer.. 2.00 BogoMIPS (lpj=10000)
[    0.020000] pid_max: predefinito: 32768 minimo: 301
[    0.030000] Cache hash del mount: 2048 voci (ordine: 2, 16384 bytes)
[    0.040000] Cache hash del mountpoint: 2048 voci (ordine: 2, 16384 bytes)
[    0.140000] rcu: Implementazione SRCU gerarchica.
[    0.190000] smp: Inizializzazione delle CPU secondarie ...
[    0.190000] smp: Inizializzato 1 nodo, 1 CPU
[    0.220000] devtmpfs: inizializzato
[    0.300000] random: get_random_u32 chiamato da bucket_table_alloc+0x76\/0x17a con crng_init=0
[    0.330000] fonte di clock: jiffies: maschera: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.340000] voci della tabella di hash futex: 256 (ordine: 2, 16384 bytes)
[    0.380000] NET: Famiglia di protocolli registrata 16
[    1.850000] vgaarb: caricato
[    1.870000] sottosistema SCSI inizializzato
[    1.900000] usbcore: interfaccia driver usbfs registrata
[    1.910000] usbcore: interfaccia driver hub registrata
[    1.920000] usbcore: nuovo driver di dispositivo usb registrato
[    1.930000] pps_core: API LinuxPPS ver. 1 registrata
[    1.940000] pps_core: Versione software 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    1.950000] Supporto per orologio PTP registrato
[    1.970000] Driver Advanced Linux Sound Architecture Inizializzato.
[    2.010000] fonte di clock: Passato a riscv_clocksource
[    2.600000] NET: Famiglia di protocolli registrata 2
[    2.640000] tcp_listen_portaddr_hash voci della tabella di hash: 512 (ordine: 1, 8192 bytes)
[    2.650000] TCP voci della tabella di hash stabilite: 8192 (ordine: 4, 65536 bytes)
[    2.670000] voci della tabella di hash TCP bind: 8192 (ordine: 5, 131072 bytes)
[    2.700000] TCP: Tabelle di hash configurate (stabilite 8192 bind 8192)
[    2.720000] voci della tabella di hash UDP: 512 (ordine: 2, 16384 bytes)
[    2.730000] voci della tabella di hash UDP-Lite: 512 (ordine: 2, 16384 bytes)
[    2.750000] NET: Famiglia di protocolli registrata 1
[    2.770000] Decomprimendo initramfs...
[   23.980000] Decompressione di initramfs fallita: spazzatura nell'archivio compresso
[   24.030000] working set: timestamp_bits=62 max_order=18 bucket_order=0
[   25.020000] Driver generico SCSI del layer Block (bsg) versione 0.4 caricata (maggiore 251)
[   25.030000] scheduler di io noop registrato
[   25.040000] scheduler di io deadline registrato
[   25.050000] scheduler di io cfq registrato (predefinito)
[   25.060000] scheduler di io mq-deadline registrato
[   25.060000] scheduler di io kyber registrato
[   25.120000] sifive_gpio 64002000.gpio: Chip GPIO SiFive registrato 6 GPIO
[   25.150000] shpchp: Driver standard Hot Plug PCI Controller versione: 0.4
[   28.870000] Serial: driver 8250\/16550, 4 porte, condivisione IRQ disabilitata
[   28.940000] sifive-serial 64000000.serial: impossibile trovare l'orologio del controller
[   28.950000] sifive-serial: il probe di 64000000.serial è fallito con errore -2
[   28.980000] [drm] radeon kernel modesetting attivato.
[   28.990000] [drm] amdgpu kernel modesetting attivato.
[   29.500000] loop: modulo caricato
[   29.610000] sifive_spi 64001000.spi: Impossibile trovare l'orologio del bus
[   29.620000] sifive_spi: il probe di 64001000.spi è fallito con errore -2
[   29.640000] libphy: Bus MDIO fisso: analizzato
[   29.680000] e1000e: Driver di rete Intel(R) PRO\/1000 - 3.2.6-k
[   29.690000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[   29.700000] ehci_hcd: Controller host USB 2.0 'Enhanced' (EHCI) Driver
[   29.710000] ehci-pci: Driver piattaforma EHCI PCI
[   29.720000] ehci-platform: Driver piattaforma EHCI generico
[   29.750000] mousedev: Dispositivo comune per mouse PS\/2 per tutti i topi
[   29.790000] usbcore: registrato nuovo driver di interfaccia usbhid
[   29.800000] usbhid: driver di core USB HID
[   29.820000] usbcore: registrato nuovo driver di interfaccia snd-usb-audio
[   29.900000] NET: Famiglia di protocolli registrata 10
[   29.960000] Segment Routing con IPv6
[   29.960000] sit: driver di tunneling IPv6, IPv4 e MPLS su IPv4
[   30.020000] NET: Famiglia di protocolli registrata 17
[   30.020000] Tipo di chiave dns_resolver registrato
[   30.070000] bootconsole [early0] utilizza la memoria init e deve essere disabilitato anche prima che quella reale sia pronta
[   30.080000] bootconsole [early0] disabilitato

Dopo di che non succede nulla di visibile.

Ora possiamo provare a combattere tre problemi:

[   23.980000] Fallimento del decompressione dell'initramfs: spazzatura nell'archivio compresso
...
[   28.940000] sifive-serial 64000000.serial: impossibile trovare il clock del controller
...
[   29.610000] sifive_spi 64001000.spi: impossibile trovare il clock del bus

… e anche con l'interruzione dell'output nella console.

Affrontare due problemi di frequenze non è affatto difficile: è necessario aggiungere voci clocks negli alberi dei dispositivi richiesti, per comodità dando un nome significativo al 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";

Aggiungendo questa riga #define pr_debug printk all'inizio del file init/initramfs.c, l'output di un messaggio sulla spazzatura invece di initramfs diventa un messaggio leggermente più dettagliato:

[    2.760000] Decompressione initramfs...
[    2.770000] Dati compressi gzip rilevati
[   23.940000] Dati compressi (null) rilevati
[   23.970000] Fallimento della decompressione dell'initramfs: spazzatura nell'archivio compresso

Cioè, potrebbe essere che la spazzatura non sia anziché initramfs, ma insieme.

Ok, ha trovato qualcosa, forse è sufficiente. E dove è finita la console? La ricerca fornisce un collegamento a un'issue su GitHub: linux failed to bringup on vc707 board — risulta che un UART, secondo il driver, non merita nemmeno di essere discusso. Ma una correzione datato 11 luglio 2018 — un anno fa. Si è scoperto che questo commit non è mai finito nell'albero da cui compilo il kernel. Applicando manualmente questa patch, ho ottenuto un Linux funzionante! Si è rivelato che il problema con initramfs non era affatto critico.

Accedendo come user=root, password=sifive, sono riuscito senza particolari problemi (a parte capire che il numero GPIO ha un base da cui si parte, e che deve semplicemente essere letto dal file pseudo-corretto) attraverso sysfs ad accendere il LED sulla scheda.

Come l'ultima volta, allego il video testuale di avvio di Linux. Nel momento in cui si passa dalla console con earlyprintk a quella standard, appare qualche spazzatura, simile all'output di una velocità UART mal impostata. È interessante notare che il lettore ha gestito correttamente questo "pastrocchio".

Parte 4: Alla fine avviamo Linux su RocketChip RISC-V

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster