之前介绍了cca设计的一个目的是让hypervisor可以创建和调度rme虚拟机和vcpu,并且给它分配内存等资源,但是一旦这些资源分配给rme虚拟机之后,hypervisor就失去了访问这些rme所有的内存内容的权限。这是通过el3的monitor软件修改gpt表项实现的。从而实现虚拟机的机密计算。
arm和开源社区提供一个参考设计,其中包括包括:
1. linux kernel kvm模块的支持:
支持由rme通过rmi接口创建,运行虚拟机vcpu,可以服务rme虚拟的ris host call增加了kvm uabi用于管理realms增加了linux kernel作为cca的host, 也可以做为cca的guest(运行于rme虚拟机,支持rsi接口)目前运行hypervisor的host linux运行在non secure el2, 并且运行于vhe模式。
2. 开源的rmm实现:tf-rmm,主要是服务host hypervisor发过来的rmi请求,创建在realm状态下对应host linux kvm里struct kvm的虚拟机的描述和状态,和对应host linux vcpu的虚拟cpu状态和上下文的结构,并且负责realm中vcpu的context的save/restore. rmm还负责通过realm的stage 2实现多个realm虚拟机间的隔离。
3. 扩展现有的 arm trusted firmware,使它支持rme引入的4个secure状态和它们间切换时的context swithing,增加了rmi调用的支持和gpt页表的管理。
tf-rmm采用了类似hafnium, optee的工作方式,主要目的是将原来在host linux kernel做的部分事情(如和vcpu context,stage 2页表配置相关的)通过rmi调用转到realm world实现,这部分事情放在host linux中的话,可以导致host可以获得修改vm的信息和控制vm的执行。但是tf-rmm和hafnium, optee一样没有调度和复杂的内存管理功能,tf-rmm的执行主要是服务host linux的rmi调用和guest linux的rsi调用。
概况
host linux支持创建普通的虚拟机和realm虚拟机,现有的kvm api还是可以使用。host linux通过kvm_cap_arm_rme告诉user space的vmm,平台是否支持rme的kvm。如果要创建realm虚拟机,vmm可以通过kvm module的ioctl kvm_enable_cap调用并传入.cap = kvm_cap_arm_rme参数。host linux kernel为之创建的struct kvm结构中的kvm->arch.is_realm记录,后面kernel通过kvm_is_realm(kvm)检查是否为realm vm. kvm_cap_arm_rme会导致kvm调用kvm_create_realm->realm_create_rd->rmi_realm_create 这会引起rmi realm.create的smc调用,atf会将这个调用dispatch给tf-rmm处理,tf-rmm会为之创建realm descriptor (rd,struct rd)的结构,对应于host linux kernel的struct kvm结构。tf-rmm的rmm_handler通过一下handler来服务这些rmi调用:
static const struct smc_handler smc_handlers[] = { handler(version, 0, 0, smc_version, true, true), handler(features, 1, 1, smc_read_feature_register, true, true), handler(granule_delegate, 1, 0, smc_granule_delegate, false, true), handler(granule_undelegate, 1, 0, smc_granule_undelegate, false, true), handler(realm_create, 2, 0, smc_realm_create, true, true), handler(realm_destroy, 1, 0, smc_realm_destroy, true, true), handler(realm_activate, 1, 0, smc_realm_activate, true, true), handler(rec_create, 3, 0, smc_rec_create, true, true), handler(rec_destroy, 1, 0, smc_rec_destroy, true, true), handler(rec_enter, 2, 0, smc_rec_enter, false, true), handler(data_create, 5, 0, smc_data_create, false, false), handler(data_create_unknown, 3, 0, smc_data_create_unknown, false, false), handler(data_destroy, 2, 0, smc_data_destroy, false, true), handler(rtt_create, 4, 0, smc_rtt_create, false, true), handler(rtt_destroy, 4, 0, smc_rtt_destroy, false, true), handler(rtt_fold, 4, 0, smc_rtt_fold, false, true), handler(rtt_map_unprotected, 4, 0, smc_rtt_map_unprotected, false, false), handler(rtt_unmap_unprotected, 3, 0, smc_rtt_unmap_unprotected, false, false), handler(rtt_read_entry, 3, 4, smc_rtt_read_entry, false, true), handler(psci_complete, 2, 0, smc_psci_complete, true, true), handler(rec_aux_count, 1, 1, smc_rec_aux_count, true, true), handler(rtt_init_ripas, 3, 0, smc_rtt_init_ripas, false, true), handler(rtt_set_ripas, 5, 0, smc_rtt_set_ripas, false, true)然后vmm通过kvm_create_vcpu的kvm ioctl调用kvm_vm_ioctl_create_vcpu ->kvm_arch_vcpu_create创建了vcpu之后,对于realm vmh还需要通过kvm_arm_vcpu_finalize kvm_arch_vcpu_ioctl系统调用, kvm_arm_vcpu_finalize kvm_create_rec->rmi_rec_create, 通过rmi rec_create调用(通过smc指令)到atf,atf再将此调用dispatch到tf-rmm,tf-rmm通过smc_rec_create在realm状态创建对应于host linux kvm struct kvm_vcpu的struct rec结构体。host kernel kvm通过vcpu_is_rec()检查vcpu是否运行在realm中。
struct rec { struct granule *g_rec; /* the granule in which this rec lives */ unsigned long rec_idx; /* which rec is this */ bool runnable; unsigned long regs[31]; /* * pauth state of realm. * note that we do not need to save ns state as el3 will save this as part of world switch. */ struct pauth_state pauth; unsigned long pc; unsigned long pstate; struct sysreg_state sysregs; struct common_sysreg_state common_sysregs; struct { unsigned long start; unsigned long end; unsigned long addr; enum ripas ripas; } set_ripas; /* * common values across all recs in a realm. */ struct { unsigned long ipa_bits; int s2_starting_level; struct granule *g_rtt; struct granule *g_rd; bool pmu_enabled; unsigned int pmu_num_cnts; bool sve_enabled; uint8_t sve_vq; } realm_info; struct { /* * the contents of the *_el2 system registers at the last time * the rec exited to the host due to a synchronous exception. * these are the unsanitized register values which may differ * from the value returned to the host in rec_exit structure. */ unsigned long esr; unsigned long hpfar; unsigned long far; } last_run_info; /* pointer to per-cpu non-secure state */ struct ns_state *ns; struct { /* * set to 'true' when there is a pending psci * command that must be resolved by the host. * the command is encoded in rec- >regs[0]. * * a rec with pending psci is not schedulable. */ bool pending; } psci_info; /* number of auxiliary granules */ unsigned int num_rec_aux; /* addresses of auxiliary granules */ struct granule *g_aux[max_rec_aux_granules]; struct rec_aux_data aux_data; unsigned char rmm_realm_token_buf[sz_1k]; size_t rmm_realm_token_len; struct token_sign_ctx token_sign_ctx; /* buffer allocation info used for heap init and management */ struct { struct buffer_alloc_ctx ctx; bool ctx_initialised; } alloc_info; struct { unsigned long vsesr_el2; bool inject; } serror_info; /* true if host call is pending */ bool host_call;};然后vmm通过kvm_run 的ioctl运行vcpu,对于realm vm, 这是通过kvm_arch_vcpu_ioctl_run ->kvm_rec_enter->rmi_rec_enter,rmi_rec_enter通过rmi rec_enter的调用(通过smc指令)到atf,atf将它dispatch到tf-rmm,tf-rmm调用smc_rec_enter,然后通过rec_run_loop将物理cpu的执行转交给realm el0&el1的realm vm。
完整的vcpu运转图如下:
由此看出,对于host linux kvm, 与正常的kvm vm, pkvm vm类似,realm虚拟机的vcpu的创建是由host linux上的vmm管理的,每个realm vcpu对于host linux来说也只是vm进程的一个线程,也是由host linux负责调度的。只是realm vcpu运行于realm el0&el1状态。但是realm vm和realm vcpu的信息host linux是看不到的,这点与正常的kvm vm不同。
从上图也可以看出,realm vcpu执行的进入和退出需要经过更长的路径,如进入vcpu的执行需要经过host linux kvm->atf->tf-rmm->realm vm,每个步骤都涉及到context save/restore. 但根据初步的研究发现,这个过程中带来的overhead并不是很明显。
stage 2 table的管理rmm的stage 2用于realm vm之间的隔离。在tf-rmm中维护一个rtt,相当于normal kvm vm中的stage 2页表,对于realm vm, 这是由tf-rmm管理的rtt.
realm vm的ipa空间包括一个受保护的地址范围(par),rmm确保只能将其映射到realm pas。
对于在par内的访问,rmm保证给realm的机密性和完整性;在par之外,hypervisor可以自由地映射ns pas内存页或模拟访问。这为在realm vm上运行的os提供了一个可靠的机制来确定它是访问自己的私有内存,还是可以与不受信任的其他部分共享的内存。
在realm创建期间,hypervisor可以将一个内存页分配给realm,在par内的特定ipa处,并从ns内存页复制数据到它。ipa和数据经过加密哈希,哈希包含在realm的认证令牌中。认证令牌允许realm的所有者推理其初始状态和内容。一旦realm被激活,只能将内存添加到其他未使用的ipa。
hypervisor可以随时从realm回收内存。rmm在回收内存页并将其返回给hypervisor之前将此内存页清零。后续访问realm回收内存的ipa会导致rmm的stage 2异常,这会阻止realm进一步执行并保持arm cca的完整性保证。
在host linux kvm中它可以请求map或是unmap realm vm的stage 2映射,让rmm管理realm stage 2页表,但它不能获取修改到realm rmm的stage 2页表内容。例如host linux kvm可以通过unmap_stage2_range来请求unmap一些stage 2映射,这个过程是:
unmap_stage2_range- >__unmap_stage2_range- >kvm_realm_unmap_range- >realm_tear_down_rtt_range,在这里会通过rmi的rtt_destroy,rtt_creat调用(通过smc指令)到atf, atf再将它dispatch到tf-rmm的smc_rtt_create,smc_rtt_create进行rmm rtt页表操作。
中断处理目前没有gic没有专门对realm vm的虚拟中断支持,因此realm vm的中断需要在host linux kernel中通过其vgic中断产生虚拟中断。
由代码可知,rmm在rec_run_loop中准备运行realm时(参见前面realm vcpu运行流程图),它调用restore_realm_state
static void restore_realm_state(struct rec *rec){ write_cnthctl_el2(rec- >sysregs.cnthctl_el2); isb(); restore_sysreg_state(&rec- >sysregs); write_elr_el2(rec- >pc); write_spsr_el2(rec- >pstate); write_hcr_el2(rec- >sysregs.hcr_el2);设置realm el2的hcr_el2寄存器的值为
hcr_flags (hcr_fwb | hcr_e2h | hcr_rw | hcr_tsc | hcr_amo |hcr_bsu_is | hcr_imo | hcr_fmo | hcr_ptw | hcr_swio | hcr_vm | hcr_tid3 | hcr_tea | hcr_api | hcr_apk)这个设置中hcr_imo, hcr_fmo让当运行在realm el0&el1 (realm vm)时产生的irq和fiq会route到realm el2 (rmm)中处理。
rmm对于这些route到realm el2的处理为
el2_irq_lel: stp x0, x1, [sp, #-16]! mov x0, #arm_exception_irq_lel b realm_exitendproc(el2_sync_lel)el2_fiq_lel: stp x0, x1, [sp, #-16]! mov x0, #arm_exception_fiq_lel b realm_exitendproc(el2_sync_lel)realm_exit使执行回到handle_realm_exit,然后继续退回到atf,atf继续退回到host linux kvm, 再在host linux kernel里进行这个物理中断的处理,如果要产生一个虚拟中断给realm vm,host linux kernel利用其gic driver的vgic产生一个虚拟中断,然后通过atf进入到rmm,rmm再回到realm vm的执行,这是realm vm就能处理这个pending的虚拟中断。
atf的支持atf对cca支持主要包括:
1. 加载rmm image和启动rmm
2. 负责root,non secure,secure和realm四个secure world的切换,增加了rmm的dispatcher
3. 管理gpt页表
host linux kvm可以通过alloc_delegated_page ,free_delegated_page 等函数来请求atf改变一个物理内存页在gpt页表中的pas, 这是通过host linux kvm调用rmi_granule_delegate, rmi_granule_undelegate也就是rmi granule_undelegate ,rmi granule_undelegate的rmi调用(通过smc指令),这会进入到atf的rmmd_rmi_handler进行处理,它将这个rmi请求forward到rmm中处理,rmm处理之后,rmm可以调用rmm_gtsi_delegate或smc_rmm_gtsi_undelegate调用(通过smc)回到atf,在atf中的rmmd_rmm_el3_handler中调用gpt_delegate_pas或是gpt_undelegate_pas来修改gpt页表,最终修改了此物理页对应的pas。
不受信任的hypervisor总能停止调度一个realm,并总是可以回收分配给realm的内存,但在任何情况下,它都不能访问realm的cpu或内存状态。这是通过一个简单但功能强大delegate(分批/委托)来实现的。hypervisor将内存delegate给realm world,和回收到non secure world。所有由realms使用的内存首先必须由hypervisor delegate;rmm本身不管理realm的内存池。
一旦内存被delegate给realm world,hypervisor可以请求rmm将其用于各种目的,例如保存realm的元数据或数据。当一个内存页被delegate给realm world但未被rmm使用时,rmm确保该内存页清零,从而降低了内存页被重用或回收时意外信息泄露风险。
rmm为hypervisor提供了一个realm管理接口(rmi),要求rmm delegate内存、创建realms、执行realms和为realms分配内存。每一个rmi命令都是作为一个smc实现的,所以当hypervisor调用该命令时,它会陷入到el3 monitor,然后切换执行到realm world的rmm来处理命令。在rmi命令完成后,rmm向el3 monitor发出一个smc,将执行切换回ns world的hypervisor。
为了维护realms的安全保证,rmm必须知道系统上每个内存页的状态,它通过维护自己的内存页状态表(gst)来实现,以跟踪每个内存页的delegate状态和使用情况。当hypervisor delegate一个内存页时,rmm检查其gst,以确认内存页尚未被delegate,rmm然后向el3 monitor发出一个smc请求更改realm pas。
el3 monitor检查该内存页当前是否位于ns pas,然后更新gpt将其移至realm pas。最后,rmm更新其gst以记录该内存页已被delegate。如果hypervisor试图delegate已被delegate的内存页,或回收rmm正在使用的内存页,rmm会返回一个错误代码给不受信任的hypervisor。与gpt不同,gst不是由硬件检查的,而只是一个软件记录机制。
目前的限制目前没有gic没有专门对realm vm的虚拟中断支持,因此realm vm的中断需要在host linux kernel中通过其vgic中断产生虚拟中断。未来的gic会支持realm虚拟中断的注入暂时没有 device assignment的支持,随着smmu的进化和软件的开放,后面会支持目前在arm构架上的kvm有四种不同的支持方式:armv7-a/armv8.0-a的kvm支持方式,自armv8.1-a开始支持的vhe方式,google推的pkvm方式,realm支持的方式。软件构架上需要提供更clear的实现。
小米将全球首发自主研发的无线快充技术
小米发布新款手机小米 Max,以及 MIUI 8
随着AI技术的快速发展,智能家居从幻想变为现实的速度加快
基于RSA算法电子系统认证芯片的电源规划
油烟在线监测系统对餐饮行业进行监管
如何在KVM上使用CCA RME虚拟机?
上汽新款柴油机--上汽π功能介绍
利用可编程电源平衡输入纹波电流的解决方案
基于机器人的充电站让你充电不再下车
苹果败诉ipad商标侵权案教训:无形资产不可小觑?
基于热电偶传感器对冷结点补偿的实现
云网协同实现专线端到端管控,测评体系为专线品质提升保驾护航
适用于虚幻引擎的NVIDIA插件
Apple Watch Series 7京东预售已开启
影响激光干涉仪测量精度的主要因素有哪些?
关于printf重定向到串口的问题分析
贸泽开售Analog Devices低功耗AD4021和AD4022差分SAR ADC
中国物联网公司排行榜_中国物联网企业龙头
解析三相异步电动机的工作原理及应用
基于ARM920T处理器和SNMP协议实现交换机重启装置的设计