Skip to content

c-sky/zero_stage_boot

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introduction

The zero stage boot is the XuanTie processor init code before opensbi. Before zero_stage_boot, SoC vendors must prepare ddr_init and CPU reset procedures. All harts would get into zero_stage_boot together, and the first one would duty to relocate GOT & offset variable, and others wait. Every hart would init its CSRs by their CPUID versions separately, allowing different harts to work together, e.g., 4*c908 + 2*c910. You could compile standard opensbi and Linux kernel binaries from open-source repositories, all compatible with XuanTie processors. Here is the simple boot flow:

[Jtag gdbinit] -> [zero_stage_boot] -> [opensbi] -> [Linux]

opensbi: https://github.com/riscv-software-src/opensbi
Linux:   https://kernel.org/

Compiling zero_stage_boot is very straightforward, requiring only a standard RISC-V GCC compiler:

CROSS_COMPILE=riscv64-unknown-linux-gnu- make

However, we strongly recommend using the released binaries for the FPGA bringup. Click the Releases button on the right to obtain pre-compiled binaries for zsb, OpenSBI, and Image (Linux). These binary files have undergone comprehensive testing prior to release and contain detailed and precise version information.

  • 64lp64 means running lp64 ABI on 64-bit Hardware.

  • 32ilp32 means running ilp32 ABI on 32-bit Hardware.

  • 64ilp32 means running ilp32 ABI on 64-bit Hardware.

  • zsb means zero_stage_boot.

  • Linux-5.10 + opensbi-0.9 is for early customers.

  • Linux-6.6 + opensbi-1.3 is for current.

  • zsb-64lp64-xt is simply recompiled with a custom compiler; functionally, it is identical to zsb-64lp64.

For a rv64 processor, you can download zsb-64lp64.tar.gz + opensbi-1.3-64lp64.tar.gz + linux-6.6-64lp64.tar.gz and prepare your own DTS + gdbinit.

Then, you can use Jtag to run FPGA Platform.

linux-6.6 opensbi-1.3 DTS Example

The XuanTie C9xx DTB provided to OpenSBI generic firmware will usually have "thead,c900-clint", "thead,c900-plic", compatible strings.

/dts-v1/;
/ {
	model = "Test Sample";
	compatible = "test,sample";
	#address-cells = <2>;
	#size-cells = <2>;

	memory@60000000 {
		device_type = "memory";
                Caution: Determine your own address here
		reg = <0x0 0x60000000 0x0 0x40000000>;
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;
		timebase-frequency = <25000000>;
		cpu@0 {
			device_type = "cpu";
			reg = <0>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64imafdc_zicbom_svpbmt_sstc_sscofpmf";
			riscv,cbom-block-size = <64>;
			mmu-type = "riscv,sv57";
			cpu0_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
		cpu@1 {
			device_type = "cpu";
			reg = <1>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64imafdc_zicbom_svpbmt_sstc_sscofpmf";
			riscv,cbom-block-size = <64>;
			mmu-type = "riscv,sv57";
			cpu1_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
		cpu@2 {
			device_type = "cpu";
			reg = <2>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64imafdc_zicbom_svpbmt_sstc_sscofpmf";
			riscv,cbom-block-size = <64>;
			mmu-type = "riscv,sv57";
			cpu2_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
		cpu@3 {
			device_type = "cpu";
			reg = <3>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64imafdc_zicbom_svpbmt_sstc_sscofpmf";
			riscv,cbom-block-size = <64>;
			mmu-type = "riscv,sv57";
			cpu3_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
	};


	soc {
		#address-cells = <2>;
		#size-cells = <2>;
		compatible = "simple-bus";
		dma-noncoherent;
		ranges;

		clint0: clint@c000000 {
			compatible = "thead,c900-clint";
			interrupts-extended = <
				&cpu0_intc  3 &cpu0_intc  7
				&cpu1_intc  3 &cpu1_intc  7
				&cpu2_intc  3 &cpu2_intc  7
				&cpu3_intc  3 &cpu3_intc  7
				>;
			reg = <0x0 0x0c000000 0x0 0x04000000>;
                Caution: Determine your own address here
			clint,has-no-64bit-mmio;
		};

		intc: interrupt-controller@8000000 {
			#address-cells = <0>;
			#interrupt-cells = <2>;
			compatible = "thead,c900-plic";
			reg = <0x0 0x08000000 0x0 0x04000000>;
                Caution: Determine your own address here
			riscv,ndev = <64>;
			interrupt-controller;
			interrupts-extended = <
				&cpu0_intc  0xffffffff &cpu0_intc  9
				&cpu1_intc  0xffffffff &cpu1_intc  9
				&cpu2_intc  0xffffffff &cpu2_intc  9
				&cpu3_intc  0xffffffff &cpu3_intc  9
				>;
		};
	};
};

linux-5.10 opensbi-0.9 DTS Example

The XuanTie C9xx DTB provided to OpenSBI generic firmware will usually have "riscv,clint0", "riscv,plic0", compatible strings.

/dts-v1/;
/ {
	model = "Test Sample";
	compatible = "test,sample";
	#address-cells = <2>;
	#size-cells = <2>;

	memory@60000000 {
		device_type = "memory";
                Caution: Determine your own address here
		reg = <0x0 0x60000000 0x0 0x40000000>;
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;
		timebase-frequency = <25000000>;
		cpu@0 {
			device_type = "cpu";
			reg = <0>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64ima";
			mmu-type = "riscv,sv39";
			cpu0_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
		cpu@1 {
			device_type = "cpu";
			reg = <1>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64ima";
			mmu-type = "riscv,sv39";
			cpu1_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
		cpu@2 {
			device_type = "cpu";
			reg = <2>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64ima";
			mmu-type = "riscv,sv39";
			cpu2_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
		cpu@3 {
			device_type = "cpu";
			reg = <3>;
			status = "okay";
			compatible = "riscv";
			riscv,isa = "rv64ima";
			mmu-type = "riscv,sv39";
			cpu3_intc: interrupt-controller {
				#address-cells = <0>;
				#interrupt-cells = <1>;
				compatible = "riscv,cpu-intc";
				interrupt-controller;
			};
		};
	};


	soc {
		#address-cells = <2>;
		#size-cells = <2>;
		compatible = "simple-bus";
		ranges;

		clint0: clint@c000000 {
			compatible = "riscv,clint0";
			interrupts-extended = <
				&cpu0_intc  3 &cpu0_intc  7
				&cpu1_intc  3 &cpu1_intc  7
				&cpu2_intc  3 &cpu2_intc  7
				&cpu3_intc  3 &cpu3_intc  7
				>;
			reg = <0x0 0x0c000000 0x0 0x04000000>;
                Caution: Determine your own address here
			clint,has-no-64bit-mmio;
		};

		intc: interrupt-controller@8000000 {
			#address-cells = <0>;
			#interrupt-cells = <1>;
			compatible = "riscv,plic0";
			reg = <0x0 0x08000000 0x0 0x04000000>;
                Caution: Determine your own address here
			riscv,ndev = <64>;
			interrupt-controller;
			interrupts-extended = <
				&cpu0_intc  0xffffffff &cpu0_intc  9
				&cpu1_intc  0xffffffff &cpu1_intc  9
				&cpu2_intc  0xffffffff &cpu2_intc  9
				&cpu3_intc  0xffffffff &cpu3_intc  9
				>;
		};
	};
};

CPU gdbinit script

# Set gdb environment
set confirm off
set height  0
monitor set resume-bkpt-exception on

# memory layout
set $opensbi_addr = 0x60000000
set $vmlinux_addr = $opensbi_addr + 0x00400000
set $rootfs_addr  = $opensbi_addr + 0x04000000
set $dtb_addr     = $rootfs_addr  - 0x00100000
set $zsb_addr     = $rootfs_addr  - 0x00008000
set $dyninfo_addr = $rootfs_addr  - 0x40
set $flag_addr    = $rootfs_addr  - 0x100

# Load kernel
restore zero_stage_boot.bin binary          $zsb_addr
restore <preceding dts example>.dtb binary  $dtb_addr
restore fw_dynamic.bin binary               $opensbi_addr
restore Image binary                        $vmlinux_addr

# Set opensbi dynamic info param
set *(unsigned long *)($dyninfo_addr)      = 0x4942534f
set *(unsigned long *)($dyninfo_addr + 8)  = 2
set *(unsigned long *)($dyninfo_addr + 16) = $vmlinux_addr
set *(unsigned long *)($dyninfo_addr + 24) = 1
set *(unsigned long *)($dyninfo_addr + 32) = 0
set *(unsigned long *)($dyninfo_addr + 40) = -1

# Set boot flag for CPU functional setting
# This flag.BIT[0] makes zsb enable RV64XT32 by setting mxstatus.[63]=1
# set *(unsigned int *)$flag_addr = 0x1
set *(unsigned int *)$flag_addr = 0x0

# PLIC delegate (Only opensbi-0.9 & Linux-5.10 need it)
set *0x081ffffc=1

# Set all harts reset address
set *0x18030010 = $zsb_addr
set *0x18030018 = $zsb_addr
set *0x18030020 = $zsb_addr
set *0x18030028 = $zsb_addr
set *0x18030030 = $zsb_addr
set $pc         = $zsb_addr

# Release all harts from reset
set *0x18030000 = 0x7f

# If you don't have a reset controller in SoC, and harts reset into bootrom's loop code.
# Then, Use below method:
# thread 1
# set $pc = $zsb_addr
# thread 2
# set $pc = $zsb_addr
# thread 3
# set $pc = $zsb_addr
# thread 4
# set $pc = $zsb_addr
# thread 5
# set $pc = $zsb_addr
# -ex "c" would let all harts jump to $zsb_addr.

Run

Start Jtag Server.

DebugServerConsole -prereset

Then use gdb connect the Jtag Server.

riscv64-elf-gdb -ex "tar remote <Jtag Server ip:port>" -x <your soc gdbinit> -x <preceding cpu gdbinit> -ex "c"

Use ctrl+c to get into the gdb shell.

file vmlinux
source gdbmarcos.txt
dmesg

gdbmacros.txt:

vmlinux: The Linux kernel ELF file

Appendix A - PMU in DTS

The configuration of PMU can be referred to OpenSBI SBI PMU extension

The following is an example of PMU configuration for the Xuantie C-series CPU, which may need to be modified according to the datasheet during actual use.

pmu {
	compatible = "riscv,pmu";
	riscv,event-to-mhpmevent =
		/* PMU_HW_CACHE_REFERENCES -> ll_cache_read_access */
		<0x00003 0x00000000 0x00000010>,
		/* PMU_HW_CACHE_MISSES -> ll_cache_read_miss */
		<0x00004 0x00000000 0x00000011>,
		/* PMU_HW_BRANCH_INSTRUCTIONS -> inst_branch */
		<0x00005 0x00000000 0x00000007>,
		/* PMU_HW_BRANCH_MISSES -> inst_branch_mispredict */
		<0x00006 0x00000000 0x00000006>,
		/* PMU_HW_STALLED_CYCLES_FRONTEND -> ifu_stalled_cycle */
		<0x00008 0x00000000 0x00000027>,
		/* PMU_HW_STALLED_CYCLES_BACKEND -> idu_stalled_cycle */
		<0x00009 0x00000000 0x00000028>,
		/* L1D_READ_ACCESS -> l1_dcache_read_access */
		<0x10000 0x00000000 0x0000000c>,
		/* L1D_READ_MISS -> l1_dcache_read_miss */
		<0x10001 0x00000000 0x0000000d>,
		/* L1D_WRITE_ACCESS -> l1_dcache_write_access */
		<0x10002 0x00000000 0x0000000e>,
		/* L1D_WRITE_MISS -> l1_dcache_write_miss */
		<0x10003 0x00000000 0x0000000f>,
		/* L1I_READ_ACCESS -> l1_icache_access */
		<0x10008 0x00000000 0x00000001>,
		/* L1I_READ_MISS -> l1_icache_miss */
		<0x10009 0x00000000 0x00000002>,
		/* LL_READ_ACCESS -> ll_cache_read_access */
		<0x10010 0x00000000 0x00000010>,
		/* LL_READ_MISS -> ll_cache_read_miss */
		<0x10011 0x00000000 0x00000011>,
		/* LL_WRITE_ACCESS -> ll_cache_write_access */
		<0x10012 0x00000000 0x00000012>,
		/* LL_WRITE_MISS -> ll_cache_write_miss */
		<0x10013 0x00000000 0x00000013>,
		/* DTLB_READ_MISS -> dtlb_miss */
		<0x10019 0x00000000 0x00000004>,
		/* ITLB_READ_MISS -> itlb_miss */
		<0x10021 0x00000000 0x00000003>,
		/* BPU_READ_ACCESS -> branch_direction_prediction */
		<0x10030 0x00000000 0x0000001c>,
		/* BPU_READ_MISS -> branch_direction_misprediction */
		<0x10031 0x00000000 0x0000001b>;
	riscv,event-to-mhpmcounters =
		<0x00003 0x00003 0xfffffff8>,
		<0x00004 0x00004 0xfffffff8>,
		<0x00005 0x00005 0xfffffff8>,
		<0x00006 0x00006 0xfffffff8>,
		<0x00007 0x00007 0xfffffff8>,
		<0x00008 0x00008 0xfffffff8>,
		<0x00009 0x00009 0xfffffff8>,
		<0x0000a 0x0000a 0xfffffff8>,
		<0x10000 0x10000 0xfffffff8>,
		<0x10001 0x10001 0xfffffff8>,
		<0x10002 0x10002 0xfffffff8>,
		<0x10003 0x10003 0xfffffff8>,
		<0x10008 0x10008 0xfffffff8>,
		<0x10009 0x10009 0xfffffff8>,
		<0x10010 0x10010 0xfffffff8>,
		<0x10011 0x10011 0xfffffff8>,
		<0x10012 0x10012 0xfffffff8>,
		<0x10013 0x10013 0xfffffff8>,
		<0x10019 0x10019 0xfffffff8>,
		<0x10021 0x10021 0xfffffff8>,
		<0x10030 0x10030 0xfffffff8>,
		<0x10031 0x10031 0xfffffff8>;
	riscv,raw-event-to-mhpmcounters =
		<0x00000000 0x00000001 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000002 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000003 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000004 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000005 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000006 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000007 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000008 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000009 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000000a 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000000b 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000000c 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000000d 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000000e 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000000f 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000010 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000011 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000012 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000013 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000014 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000015 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000016 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000017 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000018 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000019 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000001a 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000001b 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000001c 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000001d 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000001e 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000001f 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000020 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000021 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000022 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000023 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000024 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000025 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000026 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000027 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000028 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x00000029 0xffffffff 0xffffffff 0xfffffff8>,
		<0x00000000 0x0000002a 0xffffffff 0xffffffff 0xfffffff8>;
};

For example, using perf stat & perf record:

# perf stat ls

 Performance counter stats for 'ls':

             74.05 msec task-clock                       #    0.747 CPUs utilized
                 0      context-switches                 #    0.000 /sec
                 0      cpu-migrations                   #    0.000 /sec
                58      page-faults                      #  783.256 /sec
           3689065      cycles                           #    0.050 GHz
           1336494      instructions                     #    0.36  insn per cycle
            162119      branches                         #    2.189 M/sec
             28716      branch-misses                    #   17.71% of all branches

       0.099143960 seconds time elapsed

       0.016153000 seconds user
       0.092880000 seconds sys
# echo 1000 > /proc/sys/kernel/perf_event_max_sample_rate
# perf record -g ls
perf.data
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.006 MB perf.data (9 samples) ]

Appendix B - How to compile perf

We can use buildroot to compile rootfs with perf tool.

# git clone https://github.com/buildroot/buildroot.git
# cd buildroot/
# make qemu_riscv64_virt_defconfig
# make menuconfig

Enable the following PACKAGE config in menuconfig.

BR2_PACKAGE_LINUX_TOOLS=y
BR2_PACKAGE_LINUX_TOOLS_PERF=y
BR2_PACKAGE_ELFUTILS=y

Appendix C - Additional DTS

Additional DTS examples(serial, bootargs with initrd):

serial@1900d000 {
	compatible = "snps,dw-apb-uart";
	reg = <0x0 0x1900d000 0x0 0x400>;
	interrupt-parent = <&intc>;
	interrupts = <20 4>;
	clock-frequency = <36000000>;
	clock-names = "baudclk";
	reg-shift = <2>;
	reg-io-width = <4>;
};

chosen {
	bootargs = "console=ttyS0,115200 norandmaps loglevel=7";
	linux,initrd-start = <0x0 0x64000000>;
	linux,initrd-end = <0x0 0x66000000>;
	stdout-path = "/soc/serial@1900d000:115200";
};

The 'serial' needs to be configured based on the actual configuration of 'reg', 'interrupts', 'clock-frequency', while the 'chosen' needs to be configured based on the actual configuration of 'linux,initrd-start', 'linux,initrd-end'.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 93.4%
  • Assembly 4.8%
  • Makefile 1.8%