# Biscuit-VM **Repository Path**: shinian9712/biscuit ## Basic Information - **Project Name**: Biscuit-VM - **Description**: 模块化RISC-V虚拟机. - **Primary Language**: C - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2021-09-03 - **Last Updated**: 2023-09-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: 虚拟机 ## README # Biscuit-VM ## 关于这个小项目... 简易硬件接口的虚拟机,能极大降低OS开发难度. ## 设计思想 为了给OS提供尽可能强大的功能,虚拟机按模块化设计,OS通过控制虚拟机的模块来获得自己想要的功能.一个模块可以是一个指令集,一个中断记录器,一种内存映射功能,一种分页方法或是一种设备管理器. ## 目前状态 已验证RV32IM+Zicsr指令集和虚拟内存方案,并已支持时钟设备和Console设备等一些简单设备(具体参照dev.md). 已支持xv6部分功能,HTIF设备和Block设备完成后可支持xv6全部功能. ## 整体结构 项目分为两个部分,一个是核心core部分,另一个是模块module部分.core仅提供最基本的虚拟机功能和module接入点. module则提供尽可能强大的功能,将module加载至core即可获得相应的功能. ### CORE #### 基本结构 ``` C /* 基于riscv32的抽象CPU */ struct rv32cpu { magic_t magic; word pc; enum cpu_mode mode; struct { bool enable; bool hdsig; // handle 信号,置1将在下一个clock立即处理中断 bool pending; word source; word cause; struct { uint64 head; uint64 tail; struct intrp_desc data[NR_RING_ITEM]; struct plock plk; } intrp_ring; // 中断环,未决中断在此排队 } intrp; uint64 mtime; // 机器时间 uint64 mtimcmp; // 机器时间比较 bool mtie; // 时钟中断使能 struct { bool stopsig; bool running; //struct plock plk; // 一般情况下只会有CPU线程和另外一个线程同时访问,使用Peterson lock大概率是安全的(已弃用) } stat; struct environ* env; word regs[x_num]; struct { modid_t exhdlr_modid[MAX_MOD_ITEM]; // module的id struct module * exhdlr_base[MAX_MOD_ITEM]; // 指向module本体的指针 cpu_exhdlr exhdlr_func[MAX_MOD_ITEM]; // module挂载在此的处理函数 void * exhdlr_ctx[MAX_MOD_ITEM]; // module的上下文 modid_t csrrw_modid[MAX_MOD_ITEM]; struct module * csrrw_base[MAX_MOD_ITEM]; cpu_csrrw csrrw_func[MAX_MOD_ITEM]; void * csrrw_ctx[MAX_MOD_ITEM]; modid_t decoder_modid[MAX_MOD_ITEM]; struct module * decoder_base[MAX_MOD_ITEM]; cpu_decoder decoder_func[MAX_MOD_ITEM]; void * decoder_ctx[MAX_MOD_ITEM]; } mods; struct { pthread_t id; pthread_attr_t attr; pthread_mutex_t mlk; } thread_info; pthread_mutex_t ctrl_mlk; }; /* 外设控制器 */ struct devctl { magic_t magic; struct environ* env; struct { uint64 head; uint64 tail; struct dev_csrrw_req data[NR_RING_ITEM]; struct plock plk; } csrrw_ring; // csr异步写环,支持异步启动外设 struct { uint64 head; uint64 tail; struct intrp_desc data[NR_RING_ITEM]; pthread_mutex_t mlk; } intrp_ring; // csr中断环,挂在devctl上的设备中断会在此排队 struct { bool stopsig; bool running; bool pausesig; bool paused; pthread_mutex_t blk; // pause用,阻塞线程 pthread_mutex_t mlk; // 设置sig时用 } stat; struct { modid_t csrrw_modid[MAX_MOD_ITEM]; struct module * csrrw_base[MAX_MOD_ITEM]; dev_csrrw csrrw_func[MAX_MOD_ITEM]; void * csrrw_ctx[MAX_MOD_ITEM]; } mods; struct { pthread_t id; pthread_attr_t attr; pthread_mutex_t mlk; } thread_info; pthread_mutex_t ctrl_mlk; }; /* 内存 */ struct memory { magic_t magic; struct environ* env; int8 * data; memaddr_t size; struct { modid_t virtrw_modid[MAX_MOD_ITEM]; struct module * virtrw_base[MAX_MOD_ITEM]; mem_virtrw virtrw_func[MAX_MOD_ITEM]; void * virtrw_ctx[MAX_MOD_ITEM]; modid_t phyrw_modid[MAX_MOD_ITEM]; struct module * phyrw_base[MAX_MOD_ITEM]; mem_phyrw phyrw_func[MAX_MOD_ITEM]; void * phyrw_ctx[MAX_MOD_ITEM]; } mods; }; struct environ { uint64 magic; enum { ENV_STOPPED = 0x0, ENV_RUNNING = 0x1, ENV_PAUSED = 0x2 } stat; struct rv32cpu cpu; struct memory mem; struct devctl dctl; struct module* mods[MAX_MODS]; count_t mod_n; pthread_mutex_t ctrl_mlk; pthread_mutex_t mod_ctrl_mlk; }; ``` #### 可用功能 (待完善) ``` C /* 主要是核心内部使用 */ status cpu_init (struct rv32cpu* cpu, struct environ* env); /* CPU控制接口,可用值: RESET, START, STOP */ status cpu_ctrl (struct rv32cpu * cpu, enum cpu_ctl_arg arg); /* 发起同步异常,无视其他异常,下一时钟立即执行 (通常是CPU内部异常) */ status cpu_raise_excep_sync (struct rv32cpu * cpu, word cause); /* 发起异步异常,等待轮询 (通常是DEVCTL发起的中断) */ status cpu_raise_excep_async (struct rv32cpu * cpu, word cause); /* 添加模块中的CPU功能 */ status cpu_add_module (struct rv32cpu * cpu, struct module * mod); /* 移除模块中的CPU功能 */ status cpu_remove_module(struct rv32cpu * cpu, modid_t modid); status env_init (struct environ * env, uint32 memsz); /* 环境控制接口,可用值: RESET, START, STOP, PAUSE, RESUME */ status env_ctrl (struct environ * env, enum env_ctl_arg arg); /* 添加模块 */ status env_add_module (struct environ * env, struct module * mod); /* 移除模块 */ status env_remove_module (struct environ * env, modid_t modid); /* 模块控制接口,可用值: START, STOP, PAUSE, RESUME, CTRL(自定义接口) */ status env_mod_ctrl (struct environ * env, modid_t modid, enum mod_ctl_arg arg, uint64 exarg); /* 同步读写控制寄存器,等待CPU控制寄存器读写函数和DEVCTL控制寄存器读写函数全部执行完毕 (通常用于启动外设) */ status env_csrrw_sync (struct environ * env, csraddr_t addr, word send, word * recv, enum rwmod rw); /* 异步读写控制寄存器,只等待CPU控制寄存器读写函数执行完毕后(通常用于控制CPU的某些功能) */ status env_csrrw_async (struct environ* env, csraddr_t addr, word send, word * recv, enum rwmod rw, struct req_stat * async_stat); status mem_init (struct memory * mem, uint32 size, struct environ * env); status mem_add_module (struct memory * mem, struct module * mod); status mem_remove_module (struct memory * mem, modid_t modid); /* 以保护(分页)模式访存 */ status mem_rw_virt (struct environ* env, memaddr_t addr, word send, word * recv, enum rwmod rw); /* 以物理方式访存 */ status mem_rw_phy (struct environ* env, memaddr_t addr, word send, word * recv, enum rwmod rw); status devctl_init (struct devctl * dctl, struct environ * env); /* 发起异步异常,通常是设备(模块)发起的. 相较CPU中异步异常处理速度会很慢.主要是为了协调CPU和外设之间的速度差距(大概...也许会有用吧) */ status devctl_raise_excep_async (struct devctl * dctl, word cause); status devctl_add_module (struct devctl * dctl, struct module * mod); status devctl_remove_module(struct devctl * dctl, modid_t modid); /* 设备控制器控制函数, 可用值: START, STOP, PAUSE, RESUME*/ status devctl_ctrl(struct devctl * dctl, enum dev_ctl_arg arg); status modlist_add (struct modlist * list, struct module * mod); status modlist_init (struct modlist * list); ``` ### MODULE #### 基本结构 - module_item : 模块项目描述 ``` C struct module_item { magic_t magic; modid_t modid; // 模块id enum module_item_type type; // 模块类型,描述挂载位置 void * context; // 当前mod上下文(可以理解为C++的this指针) union { void * ptr; cpu_csrrw cpu_csrrw_func; // CPU控制寄存器访问函数,挂载至cpu.mods.csrrw_func cpu_exhdlr cpu_exhdlr_func; // CPU中断处理函数,挂载至cpu.mods.exhdlr_func cpu_decoder cpu_decoder_func; // CPU指令译码函数,挂载至cpu.mods.decoder_func dev_csrrw dev_csrrw_func; // 设备控制寄存器访问函数,挂载至 devctl.mods.csrrw_func mem_virtrw mem_virtrw_func; // 内存访问(保护)函数,挂载至 mem.mods.virtrw_func mem_phyrw mem_phyrw_func; // 内存访问(物理)函数,挂载至 mem.mods.phyrw_func } func; }; ``` ``` C struct module { magic_t magic; modid_t modid; #define MAX_MOD_NAME_SZ 256 char name[MAX_MOD_NAME_SZ]; //模块名 void * context; mod_fn init; // 初始化 mod_fn start; // 启动 mod_fn stop; // 终止 mod_fn pause; // 暂停 mod_fn resume; // 恢复 mod_fn migratable; // 当前状态是否可迁移 mod_exfn modctl; //mod 控制接口 struct { count_t item_n; struct module_item item_list[MAX_MOD_ITEM]; } items; //模块项目描述列表 }; ``` #### 可用功能 (待完善) ``` C /* 封装好的功能,给模块使用 */ /* 发起同步异常,通常是CPU内部模块发起(例如译码模块) */ status raise_excep_sync (struct environ* env, word cause); /* 发起异步异常,通常是外设发起(例如输入输入模块) */ status raise_excep_async (struct environ* env, word cause); /* 物理访存 */ status memrw_phy (struct environ* env, memaddr_t addr, word send, word * recv, enum rwmod rw); /* 保护(分页)访存 */ status memrw_virt (struct environ* env, memaddr_t addr, word send, word * recv, enum rwmod rw); /* 只等待CPU控制寄存器读写函数执行完毕后返回(高效,通常只用于CPU内部控制寄存器读写) */ status csrrw_lazy (struct environ* env, csraddr_t addr, word send, word * recv, enum rwmod rw, struct req_stat * async_stat); /* 等待CPU和DEVCTL控制寄存器读写函数执行完毕后返回(低效,通常用于外设控制寄存器读写) */ status csrrw_sync (struct environ* env, csraddr_t addr, word send, word * recv, enum rwmod rw); /* 封装模块时用,将模块功能添加至模块 */ status module_add_item (struct module * mod, enum module_item_type type, void * context, void * func); /* 环境模块控制接口,可用值: START, STOP, PAUSE, RESUME, CTRL(自定义接口) */ status env_ctrl_mod (struct environ* env, modid_t modid, enum mod_ctl_arg arg, uint64 exarg); /* 为环境添加模块 */ status env_add_mod (struct environ * env, struct module * mod); /* 为环境移除模块 */ status env_remove_mod (struct environ * env, modid_t modid); ``` ## 一些设想 ### 运行时切换指令集 描述:一种运行时切换指令集设想.假设CPU支持同时支持RV32G和MIPS指令集,RV32G可运行在M,S和U态,MIPS只可运行在U态,那么虚拟机中的OS就能同时运行RV32G系统程序和MIPS用户态程序.这在现实世界是很难做到的. ### 内存内计算 描述:另一种很新奇的想法就是启用内存内计算,因为系统的访存方法全部都由模块提供,且访存方法是可编程的,这就为内存内计算提供了可能. ### 热迁移 描述:OS能直接控制虚拟机的模块,因此OS可以完成更强大的功能.其中最典型的就是OS自身可以和其他Biscuit-VM通信.无需外界介入即可实现热迁移. ### OS按需生成设备 描述:虚拟设备是可编程模块,模块可以动态生成和加载,因此OS可以根据自己需要告知Biscuit-VM生成对应的设备. ### 使用HTIF 描述:在没有实现OS全部功能时,使用Host-Target interface(HTIF)可以使虚拟机中用户态程序直接使用宿主机提供的系统调用. ### 使用MagicFS 描述:OS没有实现文件系统时,可使用虚拟机提供的MagicFS设备.MagicFS设备提供了十分强大的文件接口,能极大简化OS开发. ### 环境信息记录/重放 描述:Biscuit-VM提供了比较全面的接口,因此可以对虚拟机状态进行记录,同时也可以将这些记录重放.