2024年最新TinyEMU源码分析之虚拟机初始化(3),Linux运维事件分发机制收藏这一篇就够了

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

本文属于《
TinyEMU模拟器基础系列教程》之一,欢迎查看其它文章。

本文中使用的代码,均为伪代码,删除了部分源码。

1 初始化结构参数

虚拟机的初始化,主要在virt_machine_init函数中完成。
virt_machine_init函数,如下:

static VirtMachine \*riscv\_machine\_init(const VirtMachineParams \*p)
{
    RISCVMachine \*s;
    VIRTIODevice \*blk_dev;
    VIRTIOBusDef vbus_s, \*vbus = &vbus_s;
    
	// 初始化结构参数
    s->common.vmc = p->vmc;
    s->ram_size = p->ram_size;
    s->max_xlen = max_xlen;
    s->mem_map = phys\_mem\_map\_init();
    s->mem_map->opaque = s;
    s->mem_map->flush_tlb_write_range = riscv_flush_tlb_write_range;
    s->cpu_state = riscv\_cpu\_init(s->mem_map, max_xlen);
	
	// 配置RAM地址空间
    /\* RAM \*/
    ram_flags = 0;
    cpu\_register\_ram(s->mem_map, RAM_BASE_ADDR, p->ram_size, ram_flags);
    cpu\_register\_ram(s->mem_map, 0x00000000, LOW_RAM_SIZE, 0);
    cpu\_register\_device(s->mem_map, CLINT_BASE_ADDR, CLINT_SIZE, s,
                        clint_read, clint_write, DEVIO_SIZE32);
    cpu\_register\_device(s->mem_map, PLIC_BASE_ADDR, PLIC_SIZE, s,
                        plic_read, plic_write, DEVIO_SIZE32);
    cpu\_register\_device(s->mem_map, HTIF_BASE_ADDR, 16,
                        s, htif_read, htif_write, DEVIO_SIZE32);
    vbus->addr = VIRTIO_BASE_ADDR;
	
	// 初始化设备
    /\* virtio console \*/
    if (p->console) {
        s->common.console_dev = virtio\_console\_init(vbus, p->console);
        vbus->addr += VIRTIO_SIZE;
    }
    
	...

    if (p->input_device) {
    	// 键盘
		s->keyboard_dev = virtio\_input\_init(vbus,
											VIRTIO_INPUT_TYPE_KEYBOARD);
		vbus->addr += VIRTIO_SIZE;

		// 鼠标
		s->mouse_dev = virtio\_input\_init(vbus,
										 VIRTIO_INPUT_TYPE_TABLET);
		vbus->addr += VIRTIO_SIZE;
    }
	
	// 拷贝BIOS和Kernel;手动写入5条指令
    copy\_bios(s, p->files[VM_FILE_BIOS].buf, p->files[VM_FILE_BIOS].len,
              p->files[VM_FILE_KERNEL].buf, p->files[VM_FILE_KERNEL].len,
              p->files[VM_FILE_INITRD].buf, p->files[VM_FILE_INITRD].len,
              p->cmdline);
    
    return (VirtMachine \*)s;
}

首先,初始化VirtMachineClass、ram大小、max_xlen,以及内存映射初始化等。
然后,在riscv_cpu_init函数中,会完成pc赋初值和TLB初始化(赋值为-1)。

s->pc = 0x1000; 
s->cpu_state = riscv\_cpu\_init(s->mem_map, max_xlen);

cpu_state的类型为RISCVCPUState结构,该结构中,包含mstatus、mtvec、mscratch等CSR寄存器定义。

我们猜测,第一条指令地址,就是0x1000

初始化结构参数,其实就是把一些参数,保存到RISCVMachine对象中。

2 配置RAM地址空间

我们对本部分代码,进行分析,并结合以下常量定义。

#define LOW\_RAM\_SIZE 0x00010000 /\* 64KB \*/
#define RAM\_BASE\_ADDR 0x80000000
#define CLINT\_BASE\_ADDR 0x02000000
#define CLINT\_SIZE 0x000c0000
#define HTIF\_BASE\_ADDR 0x40008000
#define IDE\_BASE\_ADDR 0x40009000
#define VIRTIO\_BASE\_ADDR 0x40010000
#define VIRTIO\_SIZE 0x1000
#define VIRTIO\_IRQ 1
#define PLIC\_BASE\_ADDR 0x40100000
#define PLIC\_SIZE 0x00400000
#define FRAMEBUFFER\_BASE\_ADDR 0x41000000

发现代码,构成了,如下的内存地址空间:
在这里插入图片描述
这里,主要是,确定Low Dram、CLINT、HTIF、VBUS、PLIC、High Dram的地址空间范围(申请内存),可以结合上面代码,好好看看,比较简单。

因为,在执行指令时,必须要知道具体的内存空间,是如何分布的,以便正确访问内存。

3 初始化设备

初始化console、net device、block device、filesystem、display device、input device。
不详述,自己看源码。

4 拷贝BIOS和Kernel

在copy_bios函数中,完成拷贝BIOS和Kernel,其代码如下:

static void copy\_bios(RISCVMachine \*s, const uint8\_t \*buf, int buf_len,
                      const uint8\_t \*kernel_buf, int kernel_buf_len,
                      const uint8\_t \*initrd_buf, int initrd_buf_len,
                      const char \*cmd_line)
{


### 最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

### 资料预览

给大家整理的视频资料:

![](https://img-blog.csdnimg.cn/img_convert/2e39cbd1358bb8a7c43899824105fd06.png)

给大家整理的电子书资料:

  

![](https://img-blog.csdnimg.cn/img_convert/b94a2453f5081a6aa5f4078f4eeae73a.png)



**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值