Část 4: Přeci jen spouštíme Linux na RocketChip RISC-V

Část 4: Přeci jen spouštíme Linux na RocketChip RISC-V Na obrázku Linux kernel vám posílá pozdrav přes GPIO.

V této části příběhu o portování RISC-V RocketChip na čínskou desku s Cyclone IV se přece jen spustíme s Linuxem a naučíme se sami konfigurovat IP Core paměťového řadiče a mírně upravíme dts popis hardware. Tento článek je pokračováním třetí části, ale na rozdíl od značně rozšířené předchozí části bude docela krátký.

… Protože setup_smp se volá pouze v případě, že je jádro nakonfigurováno s podporou SMP, můžeme zkusit vypnout vícejádrovost. Bylo by nepříjemné, pokud bych musel také implementovat v paměťovém modulu podporu atomarity (zdálo se mi, že se s tím cache vyrovnává sama), ale v jednojádrovém případě by nám to nemělo překážet.

Stejně to nevyšlo…

[    0.000000] OF: fdt: Ignorování rozsahu paměti 0x80000000 - 0x80200000
[    0.000000] Linux verze 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc verze 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 Čt Čvc 4 18:38:10 MSK 2019
[    0.000000] bootconsole [early0] aktivováno
[    0.000000] Počáteční ramdisk na: 0x(____ptrval____) (16777216 bajtů)
[    0.000000] Rozsahy zón:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normální   [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Spouštěcí zóna začíná pro každý uzel
[    0.000000] Ranges prvotní paměti
[    0.000000]   uzel   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Setup paměti uzlu 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] software IO TLB: mapováno [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] Nelze najít záznam "cpu" v devicetree
[    0.000000] Zkonstruováno 1 zonelists, skupinová mobilita aktivována.  Celkový počet stránek: 258055
[    0.000000] Příkazová řádka jádra: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Hash tabulka cache dentry: 131072 (pořadí: 8, 1048576 bajtů)
[    0.000000] Hash tabulka cache Inode: 65536 (pořadí: 7, 524288 bajtů)
[    0.000000] Třídění __ex_table...
[    0.000000] BUG: Špatný stav stránky v procesu swappu  pfn:80bf7
[    0.000000] stránka:ffffffe03f029e08 count:0 mapcount:-65280 mapping:0000000000000000 index:0x1
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 0000000000000100 0000000000000200 0000000000000000
[    0.000000] raw: 0000000000000001 0000000000000000 00000000ffff00ff
[    0.000000] stránka vyhozena kvůli: nonzero mapcount
[    0.000000] Odkazy modulů:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Nezašpiněný 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] Vypnutí ladění zámků kvůli znečištění jádra
[    0.000000] BUG: Špatný stav stránky v procesu swappu  pfn:80bf9
[    0.000000] stránka:ffffffe03f029e78 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020080 ffffffe03f020080 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] stránka vyhozena kvůli: nonzero mapcount
[    0.000000] Odkazy modulů:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Znečištěno: 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: Špatný stav stránky v procesu swappu  pfn:80bfa
[    0.000000] stránka:ffffffe03f029eb0 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f0200b8 ffffffe03f0200b8 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] stránka vyhozena kvůli: nonzero mapcount
[    0.000000] Odkazy modulů:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Znečištěno: 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: Špatný stav stránky v procesu swappu  pfn:80bfb
[    0.000000] stránka:ffffffe03f029ee8 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f0200f0 ffffffe03f0200f0 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
[    0.000000] stránka vyhozena kvůli: nonzero mapcount
[    0.000000] Odkazy modulů:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Znečištěno: 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: Špatný stav stránky v procesu swappu  pfn:80bfc
[    0.000000] stránka:ffffffe03f029f20 count:0 mapcount:-65280 mapping:0000000000000000 index:0x0
[    0.000000] flags: 0x0()
[    0.000000] raw: 0000000000000000 ffffffe03f020028 ffffffe03f020028 0000000000000000
[    0.000000] raw: 0000000000000000 0000000000000000 00000000ffff00ff
...

Zajímavé, že po celém ladění jsem se rozhodl podívat, jak by měl vypadat "referenční" výstup jádra, řekl make qemu, a viděl jsem podobnou chybu.

Bohužel, další úroveň (Linux kernel) je složitější: GDB připojený přes JTAG k RocketChip pracuje zřejmě s fyzickými adresami bez ohledu na to, jak je MMU nastaveno, a jádro v daném okamžiku už nastavilo mapování adres, takže jen říct display/10i $pc nebude fungovat — uvidíme jen spoustu unimp. Naštěstí, pokud jsme už zjistili offset (vypadá to, že 0x80200000 -> 0xffffffe000000000), tak se můžeme trochu šikovně zachovat:

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)

Breakpointy se nastavují stejně:

(gdb) p setup_smp
$1 = {} 0xffffffe000002436 
(gdb) b *0x80202436
Breakpoint 1 at 0x80202436
(gdb) c
Pokračování.

Program přijal signál SIGTRAP, Trace/breakpoint trap.
setup_smp () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
58              while ((dn = of_find_node_by_type(dn, "cpu"))) {
(gdb) bt
#0  setup_smp () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/smpboot.c:58
#1  0xffffffe0000022a2 in setup_arch () at /home/trosinenko/freedom-u-sdk/linux/arch/riscv/kernel/setup.c:253
#2  0x0000000000000000 in ?? ()
Backtrace stopped: frame did not save the PC

Jedině, že je musíte ručně odstranit, abyste mohli pokračovat — pro GDB je to nějaká zcela nepochopitelná past. Ach ano, pokud náhodou řeknete s nebo n místo si, gdb se pokusí vložit implicitní breakpoint, který se z pochopitelných důvodů nenastaví, ale GDB už to nemůžete rozmluvit. Ale nespěchejte na restartování desky — podle mých pozorování stačí restartovat pouze gdb (mějte na paměti, že staré breakpointy se možná neztratí).

Skutečně se budete muset zabývat původním problémem: nastavením vývojových printk do funkce of_find_node_by_type, používaný kód hledání zaváděcího procesorového jádra, ukazuje, že vidí nějaký odpad místo názvů typů zařízení. Například bere řetězec „Seriový port“, i když ten v dtb jasně není. device_type. Po prohledání těchto bajtů v obraze jádra jsem je našel, podíval jsem se na posun a uvědomil si jasnou věc: velikost jádra v parametrech zavádění je jasně podhodnocena: má přiděleno 8Mb, ale zabírá více než deset. Přidělil jsem 16Mb, ale podivnosti nepřestaly. Po tanci s čtením FDT z různých adres (standardně je adresa předávána jádru v registru a1), jsem se konečně rozhodl trasovat, co se tam parsuje. Naštěstí místo chodení s debuggerem (a pamatujeme si, že existují nuance s překladem adres, které je ještě třeba nějak vyřešit) lze jednoduše a z nouze v souboru teď drivers/of/fdt.c uvést. Výsledkem bylo: #define pr_debug printkpřidání ladicího výstupu

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

Výstup na železe

Výstup na hardwaru

                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]

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

(«Timestempnutými» řádky vypisuje jádro, před nimi strom vypisuje BBL) Z jedné strany se FDT úspěšně čte, z druhé strany vzniká nějaká hloupost v parsovaném „objektovém“ stromě.

Během ladění jsem pochopil, že BBL nemohl přečíst „dvojitou“ adresu ne proto, že by byla v konfiguraci chyba, ale prostě proto, že u kořenového uzlu byla nastavena #address-cells = <1>; #size-cells = <1>;.

Rozšířením ladicího výstupu jsem viděl, že ukazatele na type a name „se srazily“, a to docela zvláštním způsobem: jejich první (počínaje nulou) byt byl nulovaný, něco jako 0xabcdef -> 0xab00ef. Musel jsem použít známou taktiku: vědět, na jakých adresách se nachází poškozená paměť, doplnit do funkce printk výpis těchto dat. No a samotné volání printk rozhodit, kde jich je málo. Bohužel, jasněji to moc nepomohlo. Pak jsem začal, porovnávaje se disasemblerovanou objdump verzí, ručně nastavovat breakpointy a po krocích procházet problémovou část kódu. A tady se objevila záhadná a nepříjemná věc: pokud hned na začátku nastavím bod zastavení někde relativně daleko od známého dobrého stavu, když na něm zastavím, uvidím už poškozenou paměť. Ale pokud se pokusím k ní tiše přiblížit po krocích, chyba se stihne schovat! Situace vypadá na poškozený paměťový řadič a cache, která skrývá chybu, pokud neustále požaduji potřebnou hodnotu. A co kdyby…

vyměníme paměť

Chytaje se možnosti vyřešit problém ne na své straně, předpokládal jsem, že možná mi prostě přišla poškozená paměťová lišta. Tady jsem si vzpomněl, že netbook deset let starý – to není jen přenosný počítač, ale také cenný zdroj DDR2 SO-DIMM. Bonus je, že do něj lze vložit paměť vyjmutou z desky a získat téměř okamžité zavěšení Memtest (Linux se mimochodem nabíjel téměř po grafickou plochu. Ale raději tento experiment neopakujte, pokud vám záleží na informacích na připojených discích…). Z jedné strany lze předpokládat, že paměť prostě nevyhovovala konkrétně tomuto netbooku. Z druhé strany, vždyť se dokázal nabootovat! Objevila se naděje, že paměť je prostě „poškozená“, a problém není v mém obalu.

Takže musíme zkusit dočasně spustit s netbookovou pamětí. Bohužel, Quartus 18 neumí upgradovat tento IP Core tak, aby ho bylo možné upravovat. To znamená, že konečně nastal čas naučit se vytvářet nové instance. Ukázalo se, že vše je docela jednoduché: hledáme v IP Catalogu položku DDR2 SDRAM Controller with ALTMEMPHY Intel FPGA IP a dostaneme blok se stejným rozhraním jako dříve. Jediný problém je nastavit správné parametry paměti.

Získáváme parametry modulu paměti

Existuje relativně zřejmý způsob, jak nastavit modul: přečíst parametry ze SPD. Opravdu, pokud běžný počítač čte data SPD a nastavuje podle nich řadič, stačí tyto údaje přečíst na stávajícím netbooku a zadat je do tabulky.

Na Ubuntu se to dělá poměrně snadno: je potřeba nainstalovat balíček i2c-tools, načíst moduly eeprom a i2c-i801 (nejsem si však jist, že druhý ovladač bude vyhovovat všude), poté spustit decode-dimms:

Výstup 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

Problém je v tom, že některé časování zde není uvedeno, takže se vydáme druhou cestou.

Co máme napsáno na modulech:

Část 4: Přeci jen spouštíme Linux na RocketChip RISC-VČást 4: Přeci jen spouštíme Linux na RocketChip RISC-V

V tomto případě je zajímavější nápis na samotných paměťových čipech: K4T1G164QQ-HCF7. Po zadání tohoto řádku do Googlu dostaneme datasheet o několika desítkách stran se všemi potřebnými parametry, které můžeme pečlivě zapsat do vlastností IP Core. Jen si dejte pozor na jednotky měření: někde ns, jinde — ps, a někdy dokonce i zlomky tCK. Nechci vás učit, na co si dát pozor, sám jsem mnohé nastavoval metodou pokusu a omylu (nemohu však zaručit, že takto nelze "spálit" paměť nebo FPGA). Jen bych rád poukázal na to, že jsem velmi dlouho nemohl přimět řadič k práci, a posledním krokem bylo uvědomění si, že je třeba zkontrolovat šířku všech rozhraní k paměti na shodu se vygenerovaným kódem v Verilogu: vždyť když je v MemIfBundle uvedeno val mem_ba = IO(Output(UInt(2.W))), a bank 8 (tzn. adresní šířka 3 bity), pak všechno, co máme — visící v oblacích výstup z paměťového řadiče — je problém, ale ne kritický, takže se všechno syntetizuje, ale nefunguje.

Možná by se to všechno rozběhlo i se starým modulem, pokud by se aktualizoval řadič, ale prozatím se mi nechce zabývat potenciálními plovoucími chybami: vlastních je dost.

Takže po přesunu timebase-frequency do DTS z úrovně konkrétního procesoru na úroveň uzlu cpus (na zcela jasně formulovanou žádost jádra) dostáváme:

Skrytý text

[    0.000000] OF: fdt: Ignorování oblasti paměti 0x80000000 - 0x80200000
[    0.000000] Linux verze 4.19.0-sifive-1+ (trosinenko@trosinenko-pc) (gcc verze 8.3.0 (Buildroot 2019.02-07449-g4eddd28f99)) #1 SMP Út 9. července 22:42:36 MSK 2019
[    0.000000] bootconsole [early0] povoleno
[    0.000000] Počáteční ramdisk na: 0x(____ptrval____) (16777216 bajtů)
[    0.000000] Oblasti zón:
[    0.000000]   DMA32    [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000]   Normální [mem 0x00000000c0000000-0x00000bffffffffff]
[    0.000000] Počáteční oblast pro každý uzel
[    0.000000] Ranges rané paměti
[    0.000000]   uzel   0: [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] Nastavení paměti uzlu 0 [mem 0x0000000080200000-0x00000000bfffffff]
[    0.000000] software IO TLB: mapováno [mem 0xbb1fc000-0xbf1fc000] (64MB)
[    0.000000] elf_hwcap je 0x112d
[    0.000000] percpu: Vloženo 17 stránek/cpu @(____ptrval____) s29400 r8192 d32040 u69632
[    0.000000] Sestaveny 1 zonelisty, mobilita uspořádána.  Celkem stránek: 258055
[    0.000000] Příkazový řádek jádra: debug console=ttySIF0,125200 root=\/dev\/mmcblk0p2 loglevel=7 rootwait
[    0.000000] Dentry cache hash tabulka položek: 131072 (pořadí: 8, 1048576 bajtů)
[    0.000000] Inode-cache hash tabulka položek: 65536 (pořadí: 7, 524288 bajtů)
[    0.000000] Třídění __ex_table...
[    0.000000] Paměť: 937696K\/1046528K dostupná (6565K kód jádra, 343K rwdata, 2564K rodata, 208K init, 832K bss, 108832K rezervováno, 0K cma-rezervováno)
[    0.000000] SLUB: HWalign=64, Pořadí=0-3, MinObjects=0, CPU=1, Uzly=1
[    0.000000] rcu: Hierarchická implementace RCU.
[    0.000000] rcu:     Sledování událostí RCU je povoleno.
[    0.000000] rcu:     RCU omezuje CPU z NR_CPUS=8 na nr_cpu_ids=1.
[    0.000000] rcu: Upravuje geometrii pro rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 0, nr_irqs: 0, předalokované irqs: 0
[    0.000000] plic: mapováno 8 přerušení na 1 (z 2) obsluhovačů.
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000000] Konzole: barevné dummy zařízení 80x25
[    0.000000] Kalibrace zpoždění (přeskočeno), hodnota vypočtena pomocí frekvence časovače.. 2.00 BogoMIPS (lpj=10000)
[    0.020000] pid_max: výchozí: 32768 minimální: 301
[    0.030000] Mount-cache hash tabulka položek: 2048 (pořadí: 2, 16384 bajtů)
[    0.040000] Mountpoint-cache hash tabulka položek: 2048 (pořadí: 2, 16384 bajtů)
[    0.140000] rcu: Hierarchická implementace SRCU.
[    0.190000] smp: Nastavení sekundárních CPU ...
[    0.190000] smp: 1 uzel, 1 CPU zapnuté
[    0.220000] devtmpfs: inicializováno
[    0.300000] náhodné: get_random_u32 voláno z 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 tabulka položek: 256 (pořadí: 2, 16384 bajtů)
[    0.380000] NET: Registrována rodina protokolů 16
[    1.850000] vgaarb: načteno
[    1.870000] SCSI subsystém inicializován
[    1.900000] usbcore: registrován nový ovladač rozhraní usbfs
[    1.910000] usbcore: registrován nový ovladač rozhraní hub
[    1.920000] usbcore: registrován nový ovladač zařízení usb
[    1.930000] pps_core: LinuxPPS API verze 1 registrována
[    1.940000] pps_core: Software verze 5.3.6 - Copyright 2005-2007 Rodolfo Giometti 
[    1.950000] PTP podpora hodinek registrována
[    1.970000] Pokročilá architektura zvuku Linuxu Ovladač inicializován.
[    2.010000] clocksource: Přepnuto na clocksource riscv_clocksource
[    2.600000] NET: Registrována rodina protokolů 2
[    2.640000] tcp_listen_portaddr_hash hash tabulka položek: 512 (pořadí: 1, 8192 bajtů)
[    2.650000] TCP ustanovená hash tabulka položek: 8192 (pořadí: 4, 65536 bajtů)
[    2.670000] TCP bind hash tabulka položek: 8192 (pořadí: 5, 131072 bajtů)
[    2.700000] TCP: Hash tabulky nakonfigurovány (ustanovené 8192 bind 8192)
[    2.720000] UDP hash tabulka položek: 512 (pořadí: 2, 16384 bajtů)
[    2.730000] UDP-Lite hash tabulka položek: 512 (pořadí: 2, 16384 bajtů)
[    2.750000] NET: Registrována rodina protokolů 1
[    2.770000] Rozbalování initramfs...
[   23.980000] Rozbalení initramfs selhalo: odpad v komprimovaném archivu
[   24.030000] workingset: timestamp_bits=62 max_order=18 bucket_order=0
[   25.020000] Bloková vrstva SCSI generický (bsg) ovladač verze 0.4 načtena (major 251)
[   25.030000] io plánovač noop registrován
[   25.040000] io plánovač deadline registrován
[   25.050000] io plánovač cfq registrován (výchozí)
[   25.060000] io plánovač mq-deadline registrován
[   25.060000] io plánovač kyber zaregistrován
[   25.120000] sifive_gpio 64002000.gpio: SiFive GPIO čip registrován 6 GPIOs
[   25.150000] shpchp: Ovladač standardního hotplug PCI Controller verze: 0.4
[   28.870000] Serial: 8250\/16550 ovladač, 4 porty, IRQ sdílení zakázáno
[   28.940000] sifive-serial 64000000.serial: není možné najít obvodový hodin
[   28.950000] sifive-serial: zkouška 64000000.serial selhala s chybou -2
[   28.980000] [drm] radeon kernel modesetting povoleno.
[   28.990000] [drm] amdgpu kernel modesetting povoleno.
[   29.500000] loop: modul načten
[   29.610000] sifive_spi 64001000.spi: Není možné najít hodinovou sběrnici
[   29.620000] sifive_spi: zkouška 64001000.spi selhala s chybou -2
[   29.640000] libphy: Opravený MDIO Bus: probuzen
[   29.680000] e1000e: Intel(R) PRO\/1000 Ovladač sítě - 3.2.6-k
[   29.690000] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[   29.700000] ehci_hcd: Ovladač USB 2.0 'Enhanced' Host Controller
[   29.710000] ehci-pci: EHCI PCI platform ovladač
[   29.720000] ehci-platform: EHCI obecný platformový ovladač
[   29.750000] mousedev: PS\/2 zařízení pro myš společné pro všechny myši
[   29.790000] usbcore: registrován nový ovladač rozhraní usbhid
[   29.800000] usbhid: jádro ovladače USB HID
[   29.820000] usbcore: registrován nový ovladač rozhraní snd-usb-audio
[   29.900000] NET: Registrována rodina protokolů 10
[   29.960000] Segmentové směrování s IPv6
[   29.960000] sit: IPv6, IPv4 a MPLS přes IPv4 tunelovací ovladač
[   30.020000] NET: Registrována rodina protokolů 17
[   30.020000] Typ klíče dns_resolver registrován
[   30.070000] bootconsole [early0] používá počáteční paměť a musí být deaktivována ještě před tím, než je ta skutečná připravena
[   30.080000] bootconsole [early0] deaktivováno

Po této události se nic viditelného neděje.

Nyní se můžeme pokusit vyřešit tři problémy:

[   23.980000] Chyba rozbalení initramfs: odpadky v komprimovaném archivu
...
[   28.940000] sifive-serial 64000000.serial: nebylo možné najít řídící hodinový signál
...
[   29.610000] sifive_spi 64001000.spi: Není možné najít sběrnicový hodinový signál

… a také s ukončením výstupu na konzoli.

Se dvěma problémy s frekvencemi se bojuje velmi snadno: je potřeba přidat body clocks do podstromů požadovaných zařízení, pro usnadnění srozumitelné objekty názvu uzlu 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 = <2>;
                         reg = <64000000 0x1000>;
                         reg-names = "control";
@@ -107,6 +109,7 @@
                         interrupt-parent = <&L0>;
                         interrupts = <1>;
                         reg = <0x64001000 0x1000>;
+                        clocks = <&tlclk>;
                         reg-names = "control";
                         L12: mmc@0 {
                                 compatible = "mmc-spi-slot";
@@ -116,7 +119,7 @@
                                 voltage-ranges = <3300 3300>;
                         };
                 };
-                L11: tlclk {
+                tlclk: tlclk {
                         #clock-cells = <0>;
                         clock-frequency = <25000000>;
                         clock-output-names = "tlclk";

Přidáním řádku #define pr_debug printk na začátek souboru init/initramfs.c, výstupující zpráva o odpadu místo initramfs dostáváme o něco podrobnější zprávu:

[    2.760000] Rozbalení initramfs...
[    2.770000] Detekována gzip komprimovaná data
[   23.940000] Detekována (null) komprimovaná data
[   23.970000] Chyba rozbalení initramfs: odpadky v komprimovaném archivu

To znamená, že odpadky nejsou místo initramfs, ale společně.

Ok, něco našel, možná je to dostatečné. A kde zůstala konzole? Vyhledávání dává odkaz na problém na GitHubu: linux failed to bringup on vc707 board — ukazuje se, že jeden UART podle názoru ovladače není ani hodna diskuze. Ale oprava je datována 11. července 2018 – před rokem. Ukázalo se, že tento commit se do stromu, ze kterého jsem sestavoval jádro, nedostal. Po ruční aplikaci tohoto patchu jsem získal funkční Linux! Oprava initramfs byla opravdu nezávažná.

Po přihlášení jako user=root, password=sifive jsem mohl bez větších problémů (kromě porozumění tomu, že číslo GPIO má základnu, od které se vše počítá, a kterou je potřeba přečíst z příslušného pseudo-souboru) prostřednictvím sysfs rozsvítit LED na desce.

Jak už minule, přikládám textové video spuštění Linuxu. Při přepínání konzole z earlyprintk na standardní se objevuje nějaký odpad, který vypadá jako výstup při nesprávně nastavené rychlosti UART. Co je zajímavé, přehrávač to zvládl vyřešit.

Část 4: Přeci jen spouštíme Linux na RocketChip RISC-V

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster