Parte 4: Finalmente avviamo Linux su RocketChip RISC-V

Parte 4: Finalmente avviamo Linux su RocketChip RISC-V Nell'immagine, il kernel Linux vi manda un saluto tramite GPIO.

In questa parte della storia del porting di RISC-V RocketChip su una scheda cinese con Cyclone IV, faremo finalmente partire Linux e impareremo a configurare il controllo dell'IP Core della memoria, oltre a modificare leggermente la descrizione DTS dell'hardware. Questo articolo è una continuazione del terzo articolo, ma, a differenza della precedente che si era allungata considerevolmente, sarà piuttosto breve.

… Poiché setup_smp viene chiamato solo se il kernel è configurato con supporto SMP, si può provare a disabilitare il multi-core. Sarebbe sgradevole dover implementare nel modulo di memoria anche il supporto per l'atomicità (pensavo che fosse gestito autonomamente dalla cache), ma in un caso a singolo core non dovrebbe darci problemi.

Non è comunque decollato…

[    0.000000] OF: fdt: Ignorando la gamma di memoria 0x80000000 - 0x80200000
[    0.000000] Versione Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 Gio Lug 4 18:38:10 MSK 2019
[    0.000000] bootconsole [early0] abilitato
[    0.000000] Ramdisk iniziale a: 0x(____ptrval____) (16777216 byte)
[    0.000000] Gamma di 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 di nodi di memoria iniziale
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configurazione della memoria iniziale nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] software IO TLB: mappato [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] Impossibile trovare l'entrata "cpu" nel devicetree
[    0.000000] Costruiti 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 hash della cache Dentry: 131072 (ordine: 8, 1048576 byte)
[    0.000000] Voci della tabella hash della cache Inode: 65536 (ordine: 7, 524288 byte)
[    0.000000] Ordinamento __ex_table...
[    0.000000] BUG: Stato della pagina non valido nel processo swapper  pfn:80bf7
[    0.000000] pagina:ffffffe03f029e08 conteggio:0 mapcount:-65280 mappatura:0000000000000000 indice:0x1
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 0000000000000100 0000000000000200 0000000000000000
[    0.000000] raw: 0000000000000001 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpata perché: mapcount diverso da zero
[    0.000000] Moduli collegati:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Non contaminato 4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    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] Disabilitando il debug del lock a causa della contaminazione del kernel
[    0.000000] BUG: Stato della pagina non valido nel processo swapper  pfn:80bf9
[    0.000000] pagina:ffffffe03f029e78 conteggio:0 mapcount:-65280 mappatura:0000000000000000 indice:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020080 ffffffe03f020080 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpata perché: mapcount diverso da zero
[    0.000000] Moduli collegati:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminato: G    B             4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    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 non valido nel processo swapper  pfn:80bfa
[    0.000000] pagina:ffffffe03f029eb0 conteggio:0 mapcount:-65280 mappatura:0000000000000000 indice:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f0200b8 ffffffe03f0200b8 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] pagina dumpata perché: mapcount diverso da zero
[    0.000000] Moduli collegati:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Contaminato: G    B             4.19.0-sifive-1+ #1
[    0.000000] Call Trace:
[    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 non valido nel processo swapper  pfn:80bfc
[    0.000000] pagina:ffffffe03f029f20 conteggio:0 mapcount:-65280 mappatura:0000000000000000 indice:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020028 ffffffe03f020028 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
...

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

Purtroppo, il livello successivo (il kernel Linux) è più complesso: GDB, connesso tramite JTAG a RocketChip, sembra funzionare con indirizzi fisici indipendentemente da come è configurato l'MMU, e il kernel nel momento che ci interessa ha già configurato la mappatura degli indirizzi, quindi semplicemente dire display/10i $pc non funzionerà — vedremo solo molti unimp. Tuttavia, se abbiamo già trovato il dislocamento (sembra che 0x80200000 -> 0xffffffe000000000), possiamo ingannare:

1: x/10i $pc
=> 0xffffffe000002436 <setup_smp>:      unimp
   0xffffffe000002438 <setup_smp+2>:    unimp
   0xffffffe00000243a <setup_smp+4>:    unimp
   0xffffffe00000243c <setup_smp+6>:    unimp
   0xffffffe00000243e <setup_smp+8>:    unimp
   0xffffffe000002440 <setup_smp+10>:   unimp
   0xffffffe000002442 <setup_smp+12>:   unimp
   0xffffffe000002444 <setup_smp+14>:   unimp
   0xffffffe000002446 <setup_smp+16>:   unimp
   0xffffffe000002448 <setup_smp+18>:   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 analogo:

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

Programma ricevuto segnale SIGTRAP, trap di tracciamento/ breakpoint.
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 devono essere rimossi manualmente per andare avanti — per GDB è una trappola completamente incomprensibile. Ah già, se per caso dici s o n invece di si, gdb cercherà di inserire un breakpoint implicito, che per ovvie ragioni non verrà impostato, ma non c'è modo di dissuadere GDB. Ma non affrettarti a riavviare la scheda — dalle mie osservazioni, è sufficiente riavviare solo gdb (tieni presente che i vecchi breakpoint potrebbero non scomparire).

In effetti, dovremo affrontare il problema originale: la posizione dei punti di debug printk nella funzione of_find_node_by_type, utilizzata dal codice di ricerca del kernel del processore per l'avvio, mostra che vede qualcosa di irrilevante invece dei nomi dei tipi di dispositivo. Ad esempio, riporta da qualche parte la riga «Serial port», anche se non c'è nulla di simile nel dtb nel campo device_type. Cercando 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: ha 8Mb riservati, ma ne occupa più di dieci. Ho allocato 16Mb, ma le anomalie non sono cessate. Dopo vari tentativi di lettura del FDT da diversi indirizzi (normalmente l'indirizzo viene passato al kernel nel registro a1), ho infine deciso di tracciare cosa viene ora analizzato. Fortunatamente, invece di destreggiarmi con il debugger (e ricordiamo che ci sono aspetti legati alla traduzione degli indirizzi che devono essere risolti in un modo o nell'altro), posso semplicemente e maldestramente nel file drivers/of/fdt.c specificare #define pr_debug printk. In definitiva, è venuto fuori:

l'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 = %lx\n", 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: %lx\n", initial_boot_params);
        __unflatten_device_tree(initial_boot_params, NULL, &of_root,
                                early_init_dt_alloc_memory_arch, false);

Output on 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

           Core IP RISC-V di SiFive
 {
  #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] ricerca "chosen", profondità: 0, uname:
[    0.000000] ricerca "chosen", profondità: 1, uname: chosen
[    0.000000] Cercando le proprietà initrd...
[    0.000000] La riga di comando è: 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] scansione della memoria nodo ram@80000000, dimensione reg 8,
[    0.000000]  - 80000000 ,  40000000
[    0.000000] OF: fdt: Ignorando il range 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 6 Lug 12:14:41 MSK 2019
[    0.000000] bootconsole [early0] abilitato
[    0.000000] initrd non trovato o vuoto - disabilitando initrd
[    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 del nodo di memoria precoci
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Inizializzazione della memoria nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] INIZIALE: ffffffe001000000
[    0.000000]  -> unflatten_device_tree()
[    0.000000] Smontaggio dell'albero dei dispositivi:
[    0.000000] magic: d00dfeed
[    0.000000] size: 00001000
[    0.000000]   la dimensione è 13512, allocando...
[    0.000000]   smontaggio (____ptrval____)...
[    0.000000] nome fisso per  ->
[    0.000000] nome fisso per chosen -> chosen
[    0.000000] nome fisso per firmware -> firmware
[    0.000000] nome fisso per aliases -> aliases
[    0.000000] nome fisso per cpus -> cpus
[    0.000000] nome fisso per cpu@0 -> cpu
[    0.000000] nome fisso per interrupt-controller -> interrupt-controller
[    0.000000] nome fisso per ram@80000000 -> ram
[    0.000000] nome fisso per soc -> soc
[    0.000000] nome fisso per clint@2000000 -> clint
[    0.000000] nome fisso per debug-controller@0 -> debug-controller
[    0.000000] nome fisso per gpio@64002000 -> gpio
[    0.000000] nome fisso per interrupt-controller@c000000 -> interrupt-controller
[    0.000000] nome fisso per rom@10000 -> rom
[    0.000000] nome fisso per serial@64000000 -> serial
[    0.000000] nome fisso per spi@64001000 -> spi
[    0.000000] nome fisso per mmc@0 -> mmc
[    0.000000] nome fisso per tlclk -> tlclk
[    0.000000]  <- unflatten_device_tree()
[    0.000000] mappatura TLB IO software: mappato [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] 0 ffffffe03effcab0 [attach() failed for %s with error %d
[    0.000000] ] | [cpu]
[    0.000000] 0 ffffffe03eff0020 [(null)] | [cpu]

Uscita 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] 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 <giometti@linux.it>
[    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

(«Тimestampted» righe visualizzate dal core, davanti ad esse l'albero visualizza BBL) Da un lato, FDT viene letto con successo, dall'altro — appare una stramberia nell'albero «oggettivo» analizato.

Durante il processo di debug ho capito che BBL non riusciva a leggere l'indirizzo «doppio» non perché ci fosse un errore nella configurazione, 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 «rotti», in modo piuttosto strano: il primo byte (a partire da zero) si era azzerato, qualcosa di simile a 0xabcdef -> 0xab00ef. Ho dovuto utilizzare una tattica conosciuta: conoscendo gli indirizzi in cui si trova la memoria danneggiata, aggiungere nella funzione printk la stampa di questi dati. E i vari chiamate printk distribuirle dove ce ne sono poche. Purtroppo, non è diventato molto più chiaro. Allora ho iniziato, confrontandomi con il disassemblato objdump con la versione, impostando manualmente i breakpoint e procedendo passo per passo attraverso la parte problematica del codice. Qui è emerso qualcosa di misterioso e sgradevole: se metto subito un breakpoint lontano da uno stato 'known-good', fermandomi su di esso vedo già memoria corrotta. Ma se provo ad avvicinarmi silenziosamente a quel punto passo dopo passo, l'errore riesce a nascondersi! Sembra che ci sia un controller di memoria danneggiato e una cache che nasconde l'errore, se si richiede continuamente il valore corretto. E se…

Sostituzione della memoria

Aggrappandomi alla possibilità di risolvere il problema non dalla mia parte, ho supposto che potesse essere semplicemente arrivata una scheda di memoria danneggiata. Ho ricordato che il netbook di dieci anni fa non è solo un computer portatile, ma anche una preziosa fonte di DDR2 SO-DIMM. Come bonus, posso inserire la memoria estratta dalla scheda e ottengo quasi immediatamente un blocco di Memtest (Linux, tra l'altro, si avviava quasi fino all'interfaccia grafica. Ma è meglio non ripetere un esperimento del genere se i dati sui dischi montati ti stanno a cuore…). Da un lato, si potrebbe supporre che la memoria non fosse compatibile con questo netbook. Dall'altro lato, è riuscito ad avviarsi! È nata la speranza che la memoria sia semplicemente 'danneggiata' e che il problema non riguardi il mio involucro.

Quindi, dobbiamo provare a lanciare temporaneamente con la memoria del netbook. Sfortunatamente, Quartus 18 non è in grado di aggiornare questo IP Core in modo da poterlo modificare. È dunque giunto il momento di imparare a creare nuove istanze. Tutto si è rivelato piuttosto semplice: cerchiamo nel Catalogo IP il punto DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP e otteniamo un modulo con la stessa interfaccia di prima. L'unico problema è impostare le configurazioni corrette della memoria.

Otteniamo i parametri del modulo di memoria

C'è un modo relativamente ovvio per configurare il modulo: leggere i parametri dallo SPD. Infatti, se un normale computer legge i dati SPD e configura il controller in base a quelli, facciamo la stessa cosa con il netbook in nostro possesso e inseriamo questi dati in un foglio.

Su Ubuntu questo si fa in modo piuttosto semplice: è necessario installare il pacchetto i2c-tools, caricare i moduli eeprom e i2c-i801 non sono sicuro, però, che il secondo driver funzioni ovunque), dopo di che lanciare decode-dimms:

Decodifica 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 dei timing non sono specificati qui, quindi procederemo per il secondo percorso.

Cosa abbiamo scritto sui moduli:

Parte 4: Finalmente avviamo Linux su RocketChip RISC-VParte 4: Finalmente avviamo Linux su RocketChip RISC-V

In questo caso, è interessante l'iscrizione sui chip di memoria stessi: K4T1G164QQ-HCF7. Inserendo questa stringa su Google, otteniamo un datasheet di diverse decine di pagine con tutti i parametri necessari, che possiamo inserire con attenzione nelle proprietà di IP Core. Fate attenzione alle unità di misura: da qualche parte ns, in altre parti — ps, e a volte anche frazioni di tCK. Non vi insegnerò a cosa prestare attenzione; ho configurato molto tramite tentativi ed errori (non posso garantire che in questo modo non si «brucerà» la memoria o la FPGA). Vorrei solo farvi notare quanto segue: ho impiegato molto tempo per far funzionare il controller e l'ultimo passo è stata la realizzazione che dovevo controllare la larghezza di tutte le interfacce di memoria per verificarne la corrispondenza con il codice generato in Verilog: infatti, quando in MemIfBundle specificato val mem_ba = IO(Output(UInt(2.W))), e ci sono 8 banchi (cioè un indirizzo largo 3 bit), allora tutto ciò che abbiamo — una output appesa dell'attuatore di memoria — è un problema, ma non critico, quindi tutto viene sintetizzato, ma non funziona.

Forse tutto funzionerebbe anche con il vecchio modulo, se aggiornassi il controller, ma per ora non mi va di affrontare possibili bug intermittenti: ne ho già abbastanza dei miei.

Quindi, dopo aver spostato timebase-frequency da DTS dal livello di un singolo CPU a quello del nodo cpus (su una richiesta chiaramente espressa del kernel), otteniamo:

Testo nascosto

[    0.000000] OF: fdt: Ignorando il range di memoria 0x80000000 - 0x80200000
[    0.000000] Versione di Linux 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc version 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Mar 9 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 ciascun nodo
[    0.000000] Intervalli di nodi di memoria iniziale
[    0.000000]   nodo   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Configurazione della memoria iniziale nodo 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] software IO TLB: mappato [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] elf_hwcap è 0x112d
[    0.000000] percpu: 17 pagine integrate/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Creato 1 zonelists, raggruppamento mobilità attivo.  Pagine totali: 258055
[    0.000000] Linea di comando del kernel: debug console=ttySIF0,125200 root=/dev/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Dentry cache ha voci nella tabella hash: 131072 (ordine: 8, 1048576 bytes)
[    0.000000] Inode-cache ha voci nella tabella hash: 65536 (ordine: 7, 524288 bytes)
[    0.000000] Ordinamento __ex_table...
[    0.000000] Memoria: 937696K/1046528K disponibile (6565K codice kernel, 343K rwdata, 2564K rodata, 208K init, 832K bss, 108832K riservato, 0K cma-riservato)
[    0.000000] SLUB: HWalign=64, Ordine=0-3, MinObjects=0, CPU=1, Nodi=1
[    0.000000] rcu: Implementazione RCU gerarchica.
[    0.000000] rcu:     Tracciamento eventi RCU è abilitato.
[    0.000000] rcu:     RCU restringe le CPU da NR_CPUS=8 a nr_cpu_ids=1.
[    0.000000] rcu: Regolando la geometria per rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, irqs preallocati: 0
[    0.000000] plic: 8 interruttori mappati a 1 (su 2) gestori.
[    0.000000] clocksource: riscv_clocksource: maschera: 0xffffffffffffffff cicli massimi: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000000] Console: dispositivo dummy colorato 80x25
[    0.000000] Calibrando il ciclo di attesa (saltato), valore calcolato usando la frequenza del timer.. 2.00 BogoMIPS (lpj=10000)
[    0.020000] pid_max: default: 32768 minimo: 301
[    0.030000] Voci nella tabella hash della cache di montaggio: 2048 (ordine: 2, 16384 bytes)
[    0.040000] Voci nella tabella hash del punto di montaggio: 2048 (ordine: 2, 16384 bytes)
[    0.140000] rcu: Implementazione SRCU gerarchica.
[    0.190000] smp: Attivando le CPU secondarie ...
[    0.190000] smp: 1 nodo, 1 CPU è stato avviato
[    0.220000] devtmpfs: inizializzato
[    0.300000] random: get_random_u32 chiamato da bucket_table_alloc+0x76/0x17a con crng_init=0
[    0.330000] clocksource: jiffies: maschera: 0xffffffff cicli massimi: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.340000] voci nella tabella hash futex: 256 (ordine: 2, 16384 bytes)
[    0.380000] NET: Protocollo di famiglia registrato 16
[    1.850000] vgaarb: caricato
[    1.870000] sottosistema SCSI inizializzato
[    1.900000] usbcore: registrato nuovo driver interfaccia usbfs
[    1.910000] usbcore: registrato nuovo driver interfaccia hub
[    1.920000] usbcore: registrato nuovo driver di dispositivi usb
[    1.930000] pps_core: API LinuxPPS ver. 1 registrata
[    1.940000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    1.950000] Supporto orologio PTP registrato
[    1.970000] Driver Advanced Linux Sound Architecture inizializzato.
[    2.010000] clocksource: Passato a clocksource riscv_clocksource
[    2.600000] NET: Protocollo di famiglia registrato 2
[    2.640000] tcp_listen_portaddr_hash ha voci nella tabella hash: 512 (ordine: 1, 8192 bytes)
[    2.650000] TCP registre voci nella tabella hash stabilita: 8192 (ordine: 4, 65536 bytes)
[    2.670000] TCP bind ha voci nella tabella hash: 8192 (ordine: 5, 131072 bytes)
[    2.700000] TCP: Tabelle hash configurate (stabilite 8192 bind 8192)
[    2.720000] UDP ha voci nella tabella hash: 512 (ordine: 2, 16384 bytes)
[    2.730000] UDP-Lite ha voci nella tabella hash: 512 (ordine: 2, 16384 bytes)
[    2.750000] NET: Protocollo di famiglia registrato 1
[    2.770000] Decomprimendo initramfs...
[   23.980000] Decompressione initramfs fallita: spazzatura nell'archivio compresso
[   24.030000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[   25.020000] Driver SCSI generico di blocco (bsg) versione 0.4 caricata (maggiore 251)
[   25.030000] io scheduler noop registrato
[   25.040000] io scheduler deadline registrato
[   25.050000] io scheduler cfq registrato (predefinito)
[   25.060000] io scheduler mq-deadline registrato
[   25.060000] io scheduler kyber registrato
[   25.120000] sifive_gpio 64002000.gpio: Chip GPIO SiFive registrato 6 GPIOs
[   25.150000] shpchp: Driver standard per controller PCI Hot Plug versione: 0.4
[   28.870000] Serial: driver 8250/16550, 4 porte, IRQ condivisi disabilitati
[   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] abilitato il kernel modesetting radeon.
[   28.990000] [drm] abilitato il kernel modesetting amdgpu.
[   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: MDIO fisso: individuato
[   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: Driver del controller host USB 2.0 'Enhanced' (EHCI)
[   29.710000] ehci-pci: Driver PCI EHCI
[   29.720000] ehci-platform: Driver generico EHCI per piattaforma
[   29.750000] mousedev: dispositivo mouse PS/2 comune a tutti i mouse
[   29.790000] usbcore: registrato nuovo driver interfaccia usbhid
[   29.800000] usbhid: driver core USB HID
[   29.820000] usbcore: registrato nuovo driver interfaccia snd-usb-audio
[   29.900000] NET: Protocollo di famiglia registrato 10
[   29.960000] Segment Routing con IPv6
[   29.960000] sit: driver di tunneling IPv6, IPv4 e MPLS su IPv4
[   30.020000] NET: Protocollo di famiglia registrato 17
[   30.020000] Tipo chiave dns_resolver registrato
[   30.070000] bootconsole [early0] utilizza memoria iniziale e deve essere disabilitato anche prima che quello reale sia pronto
[   30.080000] bootconsole [early0] disabilitato

Dopo di che non succede nulla di visibile.

Ora possiamo provare a combattere tre problemi:

[   23.980000] Il decompressione di Initramfs non è riuscita: spazzatura nell'archivio compresso
...
[   28.940000] sifive-serial 64000000.serial: impossibile trovare l'orologio del controller
...
[   29.610000] sifive_spi 64001000.spi: impossibile trovare l'orologio del bus

… e anche con l'interruzione dell'uscita sulla console.

Affrontare due problemi con le frequenze è piuttosto semplice: è necessario aggiungere voci clocks negli alberi dei dispositivi richiesti, usando un nome significativo per il nodo per comodità 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 la riga #define pr_debug printk all'inizio del file init/initramfs.c, otteniamo un messaggio leggermente più dettagliato che informa di spazzatura invece di initramfs:

[    2.760000] Decompattamento initramfs...
[    2.770000] Dati compressi gzip rilevati
[   23.940000] Dati compressi (null) rilevati
[   23.970000] Decompattamento initramfs non riuscito: spazzatura nell'archivio compresso

Quindi, forse, la spazzatura non è invece di initramfs, ma insieme.

Ok, ha trovato qualcosa, forse basta così. Ma dov'è andata a finire la console? La ricerca dà un link a un issue su GitHub: linux non è riuscito a partire sulla scheda vc707 — si scopre che un UART, per il driver, non vale nemmeno una discussione. Ma la correzione è datato 11 luglio 2018 — un anno fa. Si è scoperto che questo commit non è mai finito nell'albero da cui stavo costruendo il kernel. Applicando manualmente questa patch, ho ottenuto un Linux funzionante! Si è rivelato che il problema con initramfs non era, in effetti, critico.

Accedendo come user=root, password=sifive, sono riuscito senza particolari problemi (tranne per capire che il numero GPIO ha un base da cui tutto viene calcolato, e che deve semplicemente essere letto dal corrispondente pseudo-file) tramite sysfs accendere il LED sulla scheda.

Come la volta scorsa, allego un video testuale dell'avvio di Linux. Nel momento in cui la console passa da earlyprintk a quella standard, appare un qualche tipo di rumore, simile all'output di una velocità UART impostata in modo errato. Interessante è che il lettore ha gestito con successo questa 'pasta'.

Parte 4: Finalmente avviamo Linux su RocketChip RISC-V

Fonte: habr.com

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