Linux移植日记 day1

大城市里の小女人 提交于 2020-03-11 10:04:54

基础条件回顾:
完成了一个带有段寄存器的基于MIPS的多周期CPU,现有u-boot代码以及差分测试框架,以成功运行u-boot为目标

实用工具积累:
2020-3-6:

mips-linux-gnu-objdump -d u-boot | less

——定位u-boot运行结果出错的pc、instr

交叉编译的话需要用对应的编译器,比如:aarch64-linux-gnu-objdump -d build/kernel8.elf

因为本机使用的是mips和linux-gnu的交叉编译器,所以需要使用这样的命令才能反汇编。

-d 参数表示反汇编需要执行指令的section(-D 表示反汇编全部section)

| 在linux中称为管道,可以把上一条命令的结果作为下一条命令的参数,在此处就是将反汇编的文件作为了less的参数

less 命令可以随意浏览文件, 在查看之前不会加载整个文件,进入文件后可以/something 搜索指定内容somthing

& 表示任务在后台执行
&& 表示前一条命令执行成功时,才执行后一条命令
| 表示管道,上一条命令的输出,作为下一条命令参数
|| 表示上一条命令执行失败后,才执行下一条命令

2020-3-10

Error : bfc00500: 40087801 mfc0 t0,$15,1

$pc:    0xbfc0051c   $hi:    0x00000000   $lo:    0x00000000
$ninstr: 00000000                  $instr: 40086000
$0 :0x00000000 $at:0x00000000 $v0:0x00000000 $v1:0x00000000
$a0:0x00000000 $a1:0x00000000 $a2:0x00000000 $a3:0x00000000
$t0:0x10400000 $t1:0x00000000 $t2:0x00000000 $t3:0x00000000
$t4:0x00000000 $t5:0x00000000 $t6:0x00000000 $t7:0x00000000
$s0:0x00000000 $s1:0x00000000 $s2:0x00000000 $s3:0x00000000
$s4:0x00000000 $s5:0x00000000 $s6:0x00000000 $s7:0x00000000
$t8:0x00000000 $t9:0x00000000 $k0:0x00000000 $k1:0x00000000
$gp:0x00000000 $sp:0x00000000 $fp:0x00000000 $ra:0x00000000
==============nemu status end===============
cycle 53: gpr[8]: nemu:10400000 <> dut:00000000

CP0 的 15 号寄存器: Processor Identification,主要是company和processor设计信息.

  val s0_value = Mux1H(Array(
  (cp0_addr === "b111000".U) -> base.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1000000".U) ->  badvaddr.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1001000".U) ->  count0.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1001001".U)  ->  count1.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1011000".U ) ->  compare.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1100000".U)  ->   status.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1101000".U )  ->  cause.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b1110000".U )  ->   epc.asTypeOf(UInt(conf.xprlen.W)),
  (cp0_addr === "b10000111".U )  ->   prid)
  ))

当初设计没有考虑Pid寄存器,直接置0了,所以现在在Mux1H()后面加上。(为什么我用二进制?好像当初switch结构一直失败报错?)后面的写如操作也要补上

Error:bfc0051c: 40086000 mfc0 t0,c0_status

==============nemu registers================
$pc:    0xbfc0051c   $hi:    0x00000000   $lo:    0x00000000
$ninstr: 00000000                  $instr: 40086000
$0 :0x00000000 $at:0x00000000 $v0:0x00000000 $v1:0x00000000
$a0:0x00000000 $a1:0x00000000 $a2:0x00000000 $a3:0x00000000
$t0:0x10400000 $t1:0x00000000 $t2:0x00000000 $t3:0x00000000
$t4:0x00000000 $t5:0x00000000 $t6:0x00000000 $t7:0x00000000
$s0:0x00000000 $s1:0x00000000 $s2:0x00000000 $s3:0x00000000
$s4:0x00000000 $s5:0x00000000 $s6:0x00000000 $s7:0x00000000
$t8:0x00000000 $t9:0x00000000 $k0:0x00000000 $k1:0x00000000
$gp:0x00000000 $sp:0x00000000 $fp:0x00000000 $ra:0x00000000
==============nemu status end===============
cycle 53: gpr[8]: nemu:10400000 <> dut:00000000

c0_status的初始值应该为10400000,之前设计的除了BEV置1其他全为0,
在这里插入图片描述按MIPS_Vol手册重新初始化,加入CU字段。
在scala语言中,class的init()方法不会默认调用(之前一直以为自动调用,所以status的初始值一直为0)

  when(reset.toBool){
    cause.init()
    status.init()
  }

Error:bfc00538: 40088000 mfc0 t0,c0_config

$pc:    0xbfc00538   $hi:    0x00000000   $lo:    0x00000000
$ninstr: 00000000                  $instr: 40088000
$0 :0x00000000 $at:0x00400004 $v0:0x00000000 $v1:0x00000000
$a0:0x00000000 $a1:0x00000000 $a2:0x00000000 $a3:0x00000000
$t0:0x80000080 $t1:0x00000000 $t2:0x00000000 $t3:0x00000000
$t4:0x00000000 $t5:0x00000000 $t6:0x00000000 $t7:0x00000000
$s0:0x00000000 $s1:0x00000000 $s2:0x00000000 $s3:0x00000000
$s4:0x00000000 $s5:0x00000000 $s6:0x00000000 $s7:0x00000000
$t8:0x00000000 $t9:0x00000000 $k0:0x00000000 $k1:0x00000000
$gp:0x00000000 $sp:0x00000000 $fp:0x00000000 $ra:0x00000000
==============nemu status end===============
cycle 104: gpr[8]: nemu:80000080 <> dut:00000000

CP0 的config寄存器之前也没加入,查询手册加入,并且按照80000080初始化赋值
在这里插入图片描述9:7位为MT位,表示MMU的类型,此处为1,即standrd TLB
在这里插入图片描述按照prid方式补充

Error bfc00544: 40088001 mfc0 t0,c0_config1

==============nemu registers================
$pc:    0xbfc00544   $hi:    0x00000000   $lo:    0x00000000
$ninstr: 00000000                  $instr: 40088001
$0 :0x00000000 $at:0x00400004 $v0:0x00000000 $v1:0x00000000
$a0:0x00000000 $a1:0x00000000 $a2:0x00000000 $a3:0x00000000
$t0:0x7e9b4d80 $t1:0x00000000 $t2:0x00000000 $t3:0x00000000
$t4:0x00000000 $t5:0x00000000 $t6:0x00000000 $t7:0x00000000
$s0:0x00000000 $s1:0x00000000 $s2:0x00000000 $s3:0x00000000
$s4:0x00000000 $s5:0x00000000 $s6:0x00000000 $s7:0x00000000
$t8:0x00000000 $t9:0x00000000 $k0:0x00000000 $k1:0x00000000
$gp:0x00000000 $sp:0x00000000 $fp:0x00000000 $ra:0x00000000
==============nemu status end===============
cycle 126: gpr[8]: nemu:7e9b4d80 <> dut:00000000

看来config1也需要加入,同上
在这里插入图片描述在这里插入图片描述config1主要规定了cache的配置参数,以及mips16/64,FPU,EJTAG等是否implemented。

其中 TLB entries 最多可支持64组.
我们来计算一下,MIPS32 processor的cache容量范围
$Cache capacity = sets per way * line size *associativity $(line_size 最高位均为reserved)
Icache=[0,6442,40961288]=[0,210,222]=[0,1kB,4MB]Icache = [0 , 64*4*2,4096*128*8] = [0,2^{10},2^{22} ] = [0,1kB,4MB]
Dcache=[0,6442,40961288]=[0,210,222]=[0,1kB,4MB]Dcache = [0 , 64*4*2,4096*128*8] = [0,2^{10},2^{22} ]= [0,1kB,4MB]
如果line_size最高位也可以使用,那么最大值为现在的两倍.

再来看看u-boot的初始配置,根据上面的"7e9b4d80"
0 111111 010 011 011 010 011 011 0 0 0 0 0 0 0

TLB Entries I/Dcache size
64 25683 = 2^11 *3 = 6KB

到此u-boot的基本配置结束了,进入了qemu的小黑框,下一步开始处理cache和TLB相关的异常和中断

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!