Dio 4: Ipak pokrećemo Linux na RocketChip RISC-V

Dio 4: Ipak pokrećemo Linux na RocketChip RISC-V Na slici Linux kernel vam maše putem GPIO-a.

U ovom dijelu priče o portiranju RISC-V RocketChip na kinesku ploču sa Cyclone IV napokon ćemo pokrenuti Linux, naučit ćemo i sami konfigurirati IP Core kontroler memorije te malo urediti dts-opis hardvera. Ovaj članak je nastavak trećeg dijela, ali, za razliku od poprilično dugog prethodnog, bit će prilično kratak.

… Budući da setup_smp se poziva samo ako je kernel konfiguriran s podrškom za SMP, možemo pokušati isključiti višekernelstvo. Bilo bi neugodno ako bih također trebao implementirati podršku za atomarnost u memorijskom modulu (mislio sam da se s tim keš sam nosi), ali u jednomjezgrenoj situaciji to nam ne bi trebalo smetati.

I dalje nije uspjelo…

[    0.000000] OF: fdt: Ignoriranje memorijskog raspona 0x80000000 - 0x80200000
[    0.000000] Linux verzija 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc verzija 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 Čet Jul 4 18:38:10 MSK 2019
[    0.000000] bootconsole [early0] omogućeno
[    0.000000] Početni ramdisk na: 0x(____ptrval____) (16777216 bajta)
[    0.000000] Zone rasponi:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Početak pokretne zone za svaki čvor
[    0.000000] Rane memorijske zone čvorova
[    0.000000]   čvor   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Initmem postavka čvora 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] softverski IO TLB: mapirano [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] Nije moguće pronaći "cpu" ulaz u stablu uređaja
[    0.000000] Izgrađeno 1 zonelista, mobilno grupiranje uključeno.  Ukupno stranica: 258055
[    0.000000] Kernel naredbeni red: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Dentry cache hash tablica unosa: 131072 (redoslijed: 8, 1048576 bajta)
[    0.000000] Inode-cache hash tablica unosa: 65536 (redoslijed: 7, 524288 bajta)
[    0.000000] Sortiranje __ex_table...
[    0.000000] BUG: Loše stanje stranice u procesu swapper  pfn:80bf7
[    0.000000] stranica:ffffffe03f029e08 broj:0 mapcount:-65280 mapiranje:0000000000000000 indeks:0x1
[    0.000000] zastavice: 0x0()
[    0.000000] sirovi: 0000000000000000 0000000000000100 0000000000000200 0000000000000000
[    0.000000] sirovi: 0000000000000001 0000000000000000 00000000ffff00ff
[    0.000000] stranica ispumpana jer: ne-nula mapcount
[    0.000000] Povezani moduli:
[    0.000000] CPU: 0 PID: 0 Ime: swapper Nije zagađeno 4.19.0-sifive-1+ #1
[    0.000000] Pozivni trag:
[    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] Isključivanje debugiranja zaključavanja zbog zagađenja jezgre
[    0.000000] BUG: Loše stanje stranice u procesu swapper  pfn:80bf9
[    0.000000] stranica:ffffffe03f029e78 broj:0 mapcount:-65280 mapiranje:0000000000000000 indeks:0x0
[    0.000000] zastavice: 0x0()
[    0.000000] sirovi: 0000000000000000 ffffffe03f020080 ffffffe03f020080 0000000000000000
[    0.000000] sirovi: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] stranica ispumpana jer: ne-nula mapcount
[    0.000000] Povezani moduli:
[    0.000000] CPU: 0 PID: 0 Ime: swapper Zagađeno: G    B             4.19.0-sifive-1+ #1
[    0.000000] Pozivni trag:
[    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: Loše stanje stranice u procesu swapper  pfn:80bfa
[    0.000000] stranica:ffffffe03f029eb0 broj:0 mapcount:-65280 mapiranje:0000000000000000 indeks:0x0
[    0.000000] zastavice: 0x0()
[    0.000000] sirovi: 0000000000000000 ffffffe03f0200b8 ffffffe03f0200b8 0000000000000000
[    0.000000] sirovi: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] stranica ispumpana jer: ne-nula mapcount
[    0.000000] Povezani moduli:
[    0.000000] CPU: 0 PID: 0 Ime: swapper Zagađeno: G    B             4.19.0-sifive-1+ #1
[    0.000000] Pozivni trag:
[    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: Loše stanje stranice u procesu swapper  pfn:80bfc
[    0.000000] stranica:ffffffe03f029f20 broj:0 mapcount:-65280 mapiranje:0000000000000000 indeks:0x0
[    0.000000] zastavice: 0x0()
[    0.000000] sirovi: 0000000000000000 ffffffe03f020028 ffffffe03f020028 0000000000000000
[    0.000000] sirovi: 0000000000000000 0000000000000000 00000000ffff00ff
...

Zanimljivo je da sam nakon cijele ispravke odlučio vidjeti kako bi trebao izgledati "referentni" izlaz jezgre, rekao make qemu, i vidio sličnu grešku.

Nažalost, sljedeća razina (Linux kernel) je složenija: GDB, povezan putem JTAG-a na RocketChip, očigledno radi s fizičkim adresama bez obzira na to kako je MMU postavljen, a jezgra je u trenutku koji nas zanima već postavila mapiranje adresa, pa jednostavno reći display/10i $pc neće uspjeti — vidjet ćemo samo mnogo unimp. No, ako smo već otkrili pomak (čini se da je 0x80200000 -> 0xffffffe000000000), možemo se poslužiti prevarom:

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)

Breakpointi se postavljaju na sličan način:

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

Program je primio signal SIGTRAP, trap za trag/prekid.
setup_smp () u /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 () u /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
#1  0xffffffe0000022a2 u setup_arch () u /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/setup.c:253
#2  0x0000000000000000 u ?? ()
Backtrace je zaustavljen: okvir nije sačuvao PC

Samo što ih je potrebno ručno ukloniti da bismo nastavili dalje — za GDB je to potpuno nerazumljiv trap. Ah da, ako slučajno kažete s ili n umjesto si, gdb pokušava umetnuti nevidljivi breakpoint, koji se iz razumljivih razloga neće koristiti, ali ni GDB-a već ne možemo odvratiti. No, ne žurite s ponovnim pokretanjem placa — prema mojim zapažanjima, dovoljno je ponovno pokrenuti samo gdb (imajte na umu da stari breakpointi možda neće nestati).

U stvari, morat ćemo se pozabaviti izvorni problem: postavljanje debuggerskih printk u funkciju of_find_node_by_type, kori se kod pretraživanja pokretnog procesorskog jezgra, pokazuje da vidi neku vrstu smeća umjesto naziva tipova uređaja. Na primjer, uzima redak "Serijski port", iako to očito ne postoji u dtb-u na polju device_type. Pretražujući te bajtove u slikama jezgra, pronašao sam ih, pogledao pomak i shvatio očito: veličina jezgra u parametrima pokretanja očito je podcijenjena: dodijeljeno mu je 8Mb, a zapravo zauzima više od deset. Dodijelio sam 16Mb, ali čudnosti nisu prestale. Nakon pokušaja čitanja FDT s raznih adresa (normalno, adresa se predaje jezgru u registru a1), konačno sam odlučio pratiti što se sada parses. Na sreću, umjesto da se bavim debagerom (sjetimo se, postoje nijanse s translacijom adresa koje treba nekako riješiti), jednostavno i na brzinu u datoteci drivers/of/fdt.c navesti #define pr_debug printk. Na kraju, to je ispalo:

dodavanje debag izlaza

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);

Izlaz na hardveru

                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]

Izlaz u 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 [] | [cpu]
[    0.050000] 0 ffffffe03effca78 [] | [cpu]
[    0.050000] 0 ffffffe03effcd98 [] | [cpu]
[    0.050000] 0 ffffffe03effd068 [] | [cpu]
[    0.050000] 0 ffffffe03effd230 [] | [cpu]
[    0.050000] 0 ffffffe03effd4b8 [] | [cpu]
[    0.050000] 0 ffffffe03effd740 [] | [cpu]
[    0.050000] 0 ffffffe03effd9c8 [] | [cpu]
[    0.050000] 0 ffffffe03effdc50 [] | [cpu]
[    0.050000] 0 ffffffe03effded8 [] | [cpu]
[    0.050000] 0 ffffffe03effe160 [] | [cpu]
[    0.050000] 0 ffffffe03effe3e8 [] | [cpu]
[    0.050000] 0 ffffffe03effe670 [] | [cpu]
[    0.050000] 0 ffffffe03effe888 [cpu] | [cpu]
[    0.050000] random: get_random_u32 called from bucket_table_alloc+0x76/0x17a with crng_init=0
[    0.050000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.050000] futex hash table entries: 256 (order: 2, 16384 bytes)
[    0.060000] NET: Registered protocol family 16
[    0.090000] vgaarb: loaded
[    0.090000] SCSI subsystem initialized
[    0.090000] usbcore: registered new interface driver usbfs
[    0.090000] usbcore: registered new interface driver hub
[    0.090000] usbcore: registered new device driver usb
[    0.090000] pps_core: LinuxPPS API ver. 1 registered
[    0.090000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    0.090000] PTP clock support registered
[    0.100000] Advanced Linux Sound Architecture Driver Initialized.
[    0.100000] clocksource: Switched to clocksource riscv_clocksource
[    0.110000] NET: Registered protocol family 2
[    0.110000] tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes)
[    0.110000] TCP established hash table entries: 8192 (order: 4, 65536 bytes)
[    0.110000] TCP bind hash table entries: 8192 (order: 5, 131072 bytes)
[    0.110000] TCP: Hash tables configured (established 8192 bind 8192)
[    0.110000] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    0.110000] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    0.110000] NET: Registered protocol family 1
[    0.120000] Unpacking initramfs...
[    0.590000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[    0.620000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
[    0.620000] io scheduler noop registered
[    0.620000] io scheduler deadline registered
[    0.620000] io scheduler cfq registered (default)
[    0.620000] io scheduler mq-deadline registered
[    0.620000] io scheduler kyber registered
[    0.620000] shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
[    0.690000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.690000] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 10, base_baud = 230400) is a 16550A
[    0.720000] console [ttyS0] enabled
[    0.720000] [drm] radeon kernel modesetting enabled.
[    0.720000] [drm] amdgpu kernel modesetting enabled.
[    0.730000] loop: module loaded
[    0.730000] libphy: Fixed MDIO Bus: probed
[    0.740000] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.740000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.740000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.740000] ehci-pci: EHCI PCI platform driver
[    0.740000] ehci-platform: EHCI generic platform driver
[    0.740000] mousedev: PS/2 mouse device common for all mice
[    0.740000] usbcore: registered new interface driver usbhid
[    0.740000] usbhid: USB HID core driver
[    0.740000] usbcore: registered new interface driver snd-usb-audio
[    0.740000] NET: Registered protocol family 10
[    0.750000] Segment Routing with IPv6
[    0.750000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.750000] NET: Registered protocol family 17
[    0.750000] Key type dns_resolver registered
[    0.760000] ALSA device list:
[    0.760000]   No soundcards found.
[    0.770000] Freeing unused kernel memory: 208K
[    0.770000] This architecture does not have kernel memory protection.
[    0.770000] Run /init as init process

(«Timestamped» lines are output by the core, in front of them the tree displays the BBL) On one hand, the FDT is read successfully, on the other hand — it turns into some nonsense in the parsed "object" tree.

During debugging, I realized that the BBL couldn't read the "double" address not because there was an error in the config, but simply because the root node had been set. #address-cells = <1>; #size-cells = <1>;.

By expanding the debug output, I saw that the pointers to type i ime "collided" in a rather strange way: their first byte (starting from zero) was nulled out, something like 0xabcdef -> 0xab00ef. I had to use the familiar tactic: knowing the addresses where the corrupted memory is, to add printing of these data in printk the function. And to distribute the calls themselves printk where they were few. Unfortunately, it didn't become much clearer. Then I started to compare with the disassembled objdump version, manually setting breakpoints and walking through the problematic part of the code step by step. And here I discovered a mysterious and unpleasant thing: if you immediately set a breakpoint somewhere far from the known good state, then, stopping there, I will already see corrupted memory. But if you try to quietly creep up to it step by step, the error manages to hide! This smells of a faulty memory controller and a cache hiding the error if the needed value is requested constantly. And what if…

Replacing memory

Grabbing onto the chance to solve the problem not on my side, I suggested that maybe I just got a faulty memory stick. Then I remembered that a decade-old netbook is not only a portable computer but also a valuable source of DDR2 SO-DIMM. As a bonus, I can insert the memory removed from the board and get almost instant Memtest hang (Linux, by the way, booted up almost to the graphical shell at this point). But it's better not to repeat such an experiment if you care about the information on the mounted disks…). On one hand, one might assume that the memory simply didn't fit this particular netbook. On the other hand, it managed to boot up! There was hope that the memory was simply "faulty", and the problem wasn't with my wrapper.

Znači, trebamo privremeno pokrenuti s netbook memorijom. Nažalost, Quartus 18 ne može nadograditi ovaj IP Core tako da ga možemo uređivati. Došlo je do vremena da naučim kako stvoriti nove instance. Sve se pokazalo prilično jednostavno: tražimo u IP katalogu stavku DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP i dobivamo blok s istim sučeljem kao i ranije. Jedini problem je pravilno postavljanje postavki memorije.

Dobivamo parametre modula memorije

Postoji relativno očit način postavljanja modula: pročitati parametre iz SPD. Doista, ako običan računar očitava SPD podatke i postavlja kontroler prema njima, onda hajde da očitamo te podatke na postojećem netbooku i unesemo ih u tablicu.

Na Ubuntuu se to radi prilično jednostavno: potrebno je instalirati paket i2c-tools, učitati module eeprom i i2c-i801 (nisam siguran, da li će drugi drajver raditi svuda), a zatim pokrenuti decode-dimms:

Izlaz 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

Problem je u tome što neki od tajminga ovdje nisu navedeni, pa ćemo ići drugim putem.

Što piše na modulima:

Dio 4: Ipak pokrećemo Linux na RocketChip RISC-VDio 4: Ipak pokrećemo Linux na RocketChip RISC-V

U ovom slučaju zanimljivija je oznaka na samim čipovima memorije: K4T1G164QQ-HCF7. Unoseći ovu liniju u Google, dobivamo datasheet od nekoliko desetaka stranica sa svim potrebnim parametrima koje možemo pažljivo unijeti u svojstva IP Core-a. Samo obratite pažnju na mjerne jedinice: negdje ns, negdje — ps, a ponekad čak i dijelovi tCK. Neću vas učiti na što treba obratiti pozornost, ja sam mnogo toga postavljao metodom pokušaja i pogrešaka (ne mogu jamčiti da se na taj način ne može „pregorjeti“ memorija ili FPGA). Obratit ću samo pažnju na ovo: jako dugo nisam mogao natjerati kontroler da radi, i posljednji korak je bio shvaćanje da treba provjeriti širinu svih sučelja za memoriju na usklađenost sa generiranim kodom u Verilogu: jer kada je u MemIfBundle navedeno val mem_ba = IO(Output(UInt(2.W))), a banki 8 (tj. adresna širina od 3 bita), onda sve što imamo — slobodni output iz kontrolera memorije — problem, ali ne kritičan, tako da se sve sintetizira, ali ne radi.

Možda bi sve proradilo i sa starim modulom, ako se kontroler ažurira, ali trenutno mi se ne da baviti potencijalnim plivajućim greškama: i ovih svojih ima dovoljno.

Dakle, nakon premještanja timebase-frequency u DTS s razine konkretnog CPU-a na razinu čvora cpus (na sasvim jasno izrečenu molbu jezgre), dobivamo:

Sakriveni tekst

[    0.000000] OF: fdt: Ignoriranje memorijskog raspona 0x80000000 - 0x80200000
[    0.000000] Linux verzija 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc verzija 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Uto Jul 9 22:42:36 MSK 2019
[    0.000000] bootconsole [early0] omogućeno
[    0.000000] Inicijalna ramdisk na: 0x(____ptrval____) (16777216 bajtova)
[    0.000000] Rasponi zona:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normal   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Početna zona za svaki čvor
[    0.000000] Rane memorijske zone
[    0.000000]   čvor   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Postavke početne memorije čvora 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] softverski IO TLB: mapirano [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] elf_hwcap je 0x112d
[    0.000000] percpu: Ugrađeno 17 stranica/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Izgrađene 1 zoneliste, mobilnost grupiranja uključena.  Ukupno stranica: 258055
[    0.000000] Kernel naredbeni red: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Dentry cache hash tablica unosa: 131072 (narudžba: 8, 1048576 bajtova)
[    0.000000] Inode-cache hash tablica unosa: 65536 (narudžba: 7, 524288 bajtova)
[    0.000000] Sortiranje __ex_table...
[    0.000000] Memorija: 937696K\/1046528K dostupna (6565K kernel koda, 343K rwdata, 2564K rodata, 208K init, 832K bss, 108832K rezervirano, 0K cma-rezervirano)
[    0.000000] SLUB: HWalign=64, Narudžba=0-3, MinObjects=0, CPUs=1, Čvorovi=1
[    0.000000] rcu: Hijerarhijska RCU implementacija.
[    0.000000] rcu:     RCU praćenje događaja je omogućeno.
[    0.000000] rcu:     RCU ograničava CPU od NR_CPUS=8 do nr_cpu_ids=1.
[    0.000000] rcu: Podešavanje geometrije za rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, unaprijed dodijeljeni irqs: 0
[    0.000000] plic: mapirano 8 prekida na 1 (od 2) upravljača.
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000000] Konsole: boja dummy uređaj 80x25
[    0.000000] Kalibriranje petlje odgode (preskočeno), vrijednost izračunata korištenjem učestalosti timera.. 2.00 BogoMIPS (lpj=10000)
[    0.020000] pid_max: zadano: 32768 minimalno: 301
[    0.030000] Mount-cache hash tablica unosa: 2048 (narudžba: 2, 16384 bajtova)
[    0.040000] Mountpoint-cache hash tablica unosa: 2048 (narudžba: 2, 16384 bajtova)
[    0.140000] rcu: Hijerarhijska SRCU implementacija.
[    0.190000] smp: Pokretanje sekundarnih CPU-a ...
[    0.190000] smp: Pokrenut 1 čvor, 1 CPU
[    0.220000] devtmpfs: inicijalizirano
[    0.300000] random: get_random_u32 pozvan iz bucket_table_alloc+0x76\/0x17a s crng_init=0
[    0.330000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.340000] futex hash tablica unosa: 256 (narudžba: 2, 16384 bajtova)
[    0.380000] NET: Registrirana obitelj protokola 16
[    1.850000] vgaarb: učitano
[    1.870000] SCSI podskupina inicijalizirana
[    1.900000] usbcore: registriran novi upravljački program sučelja usbfs
[    1.910000] usbcore: registriran novi upravljački program sučelja hub
[    1.920000] usbcore: registriran novi upravljački program uređaja usb
[    1.930000] pps_core: LinuxPPS API ver. 1 registrirana
[    1.940000] pps_core: Softverska ver. 5.3.6 - Autorska prava 2005-2007 Rodolfo Giometti 
[    1.950000] PTP podrška za sat registrirana
[    1.970000] Napredna Linux zvučna arhitektura upravljački program inicijaliziran.
[    2.010000] clocksource: Prebačeno na clocksource riscv_clocksource
[    2.600000] NET: Registrirana obitelj protokola 2
[    2.640000] tcp_listen_portaddr_hash hash tablica unosa: 512 (narudžba: 1, 8192 bajtova)
[    2.650000] TCP uspostavljena hash tablica unosa: 8192 (narudžba: 4, 65536 bajtova)
[    2.670000] TCP bind hash tablica unosa: 8192 (narudžba: 5, 131072 bajtova)
[    2.700000] TCP: Hash tablice konfigurirane (uspostavljene 8192 bind 8192)
[    2.720000] UDP hash tablica unosa: 512 (narudžba: 2, 16384 bajtova)
[    2.730000] UDP-Lite hash tablica unosa: 512 (narudžba: 2, 16384 bajtova)
[    2.750000] NET: Registrirana obitelj protokola 1
[    2.770000] Raspakiranje initramfs...
[   23.980000] Raspakiranje initramfs nije uspjelo: smeće u kompresiranoj arhivi
[   24.030000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[   25.020000] Blok sloj SCSI generički (bsg) upravljački program verzija 0.4 učitan (glavni 251)
[   25.030000] io rasporednik noop registriran
[   25.040000] io rasporednik deadline registriran
[   25.050000] io rasporednik cfq registriran (zadano)
[   25.060000] io rasporednik mq-deadline registriran
[   25.060000] io rasporednik kyber registriran
[   25.120000] sifive_gpio 64002000.gpio: SiFive GPIO čip registriran 6 GPIO-a
[   25.150000] shpchp: Standardni upravljački program PCI kontrolera za vruće upletanje verzija: 0.4
[   28.870000] Serijski: 8250\/16550 upravljački program, 4 porta, dijeljenje IRQ-a onemogućeno
[   28.940000] sifive-serial 64000000.serial: nije moguće pronaći upravljački sat
[   28.950000] sifive-serial: ispitivanje 64000000.serial nije uspjelo s pogreškom -2
[   28.980000] [drm] radeon kernel modesetting omogućeno.
[   28.990000] [drm] amdgpu kernel modesetting omogućeno.
[   29.500000] loop: modul učitan
[   29.610000] sifive_spi 64001000.spi: Nije moguće pronaći sat sabirnice
[   29.620000] sifive_spi: ispitivanje 64001000.spi nije uspjelo s pogreškom -2
[   29.640000] libphy: Fiksni MDIO Bus: ispitan
[   29.680000] e1000e: Intel(R) PRO\/1000 mrežni upravljački program - 3.2.6-k
[   29.690000] e1000e: Autorska prava(c) 1999 - 2015 Intel Corporation.
[   29.700000] ehci_hcd: USB 2.0 'Poboljšani' Host Kontroler (EHCI) upravljački program
[   29.710000] ehci-pci: EHCI PCI platforma upravljački program
[   29.720000] ehci-platform: EHCI generički platforma upravljački program
[   29.750000] mousedev: PS\/2 uređaj miša zajednički za sve miševe
[   29.790000] usbcore: registriran novi upravljački program sučelja usbhid
[   29.800000] usbhid: USB HID osnovni upravljački program
[   29.820000] usbcore: registriran novi upravljački program sučelja snd-usb-audio
[   29.900000] NET: Registrirana obitelj protokola 10
[   29.960000] Segmentno usmjeravanje s IPv6
[   29.960000] sit: IPv6, IPv4 i MPLS preko IPv4 tuneliranje upravljački program
[   30.020000] NET: Registrirana obitelj protokola 17
[   30.020000] Tip ključa dns_resolver registriran
[   30.070000] bootconsole [early0] koristi inicijalnu memoriju i mora biti onemogućen čak i prije nego što je stvarna spremna
[   30.080000] bootconsole [early0] onemogućeno

Nakon toga ne događa se ništa vidljivo.

Sada možemo pokušati riješiti tri problema:

[   23.980000] Neuspjeh raspakiranja initramfs: smeće u komprimiranom arhivu
...
[   28.940000] sifive-serial 64000000.serial: nije moguće pronaći kontrolni sat
...
[   29.610000] sifive_spi 64001000.spi: nije moguće pronaći bus sat

… kao i s prekidom ispisa na konzolu.

S dva problema s frekvencijama nije teško boriti se: potrebno je dodati stavke clocks u podstablima potrebnih uređaja, radi lakšeg snalaženja davati razumljiv naziv oznake za čvor 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 = <&L0>;
+                        clocks = <&tlclk>;
                         interrupts = <>;
                         reg = <0x64000000 0x1000>;
                         reg-names = "control";
@@ -107,6 +109,7 @@
                         interrupt-parent = <&L0>;
                         interrupts = <>;
                         reg = <0x64001000 0x1000>;
+                        clocks = <&tlclk>;
                         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";

Dodajući redak #define pr_debug printk na početak datoteke init/initramfs.c, poruka o smeću umjesto initramfs daje nešto detaljniju poruku:

[    2.760000] Raspakiravanje initramfs...
[    2.770000] Otklonjen gzip kompresirani podaci
[   23.940000] Otklonjen (null) kompresirani podaci
[   23.970000] Neuspjeh raspakiranja initramfs: smeće u komprimiranom arhivu

Dakle, možda smeće nije umjesto initramfs, već zajedno.

U redu, nešto je pronašao, možda je to dovoljno. A gdje je otišla konzola? Pretraživanje daje poveznicu na problem na GitHubu: linux failed to bringup on vc707 board — ispostavilo se da jedan UART ne vrijedi razgovora prema mišljenju upravljačkog programa. Ali ispravka datirano 11. srpnja 2018. — godinu dana unazad. Ispostavilo se da ovaj commit nije došao u granu iz koje se moj kernel sastavlja. Ručno primjenjujući ovu zakrpu, dobio sam radni Linux! Ispravno je, problem je s initramfs bio, doista, nekritičan.

Prijavivši se kao user=root, password=sifive, mogao sam bez velikih problema (osim što sam morao shvatiti da broj GPIO ima bazu od koje se sve računa, i koju samo treba pročitati iz odgovarajuće pseudo-datoteke) putem sysfs upaliti LED svjetlo na ploči.

Kao i prošli put, prilažem video sa pokretanjem Linuxa. Pri prebacivanju konzole s earlyprintk na standardnu, dolazi do nekakvog šuma koji podsjeća na izlaz pri pogrešno postavljenoj brzini UART-a. Zanimljivo je da je player uspješno obradio ovu 'kašu'.

Dio 4: Ipak pokrećemo Linux na RocketChip RISC-V

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster