4.支持psci情况
上面说了pin-table的多核启动方式,看似很繁琐,实际上并不复杂,无外乎主处理器唤醒从处理器到指定地址上去执行指令,说他简单是相对于功能来说的,因为他只是实现了从处理器的启动,仅此而已,所以,现在社区几乎很少使用spin-table这种方式,取而代之的是psci,他不仅可以启动从处理器,还可以关闭,挂起等其他核操作,现在基本上arm64平台上使用多核启动方式都是psci。下面我们来揭开他神秘的面纱,其实理解了spin-table的启动方式,psci并不难(说白了也是需要主处理器给从处理器一个启动地址,然后从处理器从这个地址执行指令,实际上比这要复杂的多)。
首先,我们先来看下设备树cpu节点对psci的支持:
arch/arm64/boot/dts/xxx.dtsi:cpu0: cpu@0{ device_type ="cpu"; compatible ="arm,armv8"; reg = <0x0 >; enable-method ="psci"; }; psci { compatible ="arm,psci"; method ="smc"; cpu_suspend = <0xC4000001 >; cpu_off = <0x84000002 >; cpu_on = <0xC4000003 >; };
psci节点的详细说明可以参考内核文档:Documentation/devicetree/bindings/arm/psci.txt
可以看到现在enable-method 属性已经是psci,说明使用的多核启动方式是psci, 下面还有psci节点,用于psci驱动使用,method用于说明调用psci功能使用什么指令,可选有两个smc和hvc。其实smc, hvc和svc都是从低运行级别向高运行级别请求服务的指令,我们最常用的就是svc指令了,这是实现系统调用的指令。高级别的运行级别会根据传递过来的参数来决定提供什么样的服务。smc是用于陷入el3(安全), hvc用于陷入el2(虚拟化, 虚拟化场景中一般通过hvc指令陷入el2来请求唤醒vcpu), svc用于陷入el1(系统)。
注:本文只讲解smc陷入el3启动多核的情况。
下面开始分析源代码:
我们都知道armv8将异常等级分为el0 - el3,其中,el3为安全监控器,为了实现对它的支持,arm公司设计了一种firmware叫做ATF(ARM Trusted firmware),下面是atf源码readme.rst文件的一段介绍:
TrustedFirmware-A(TF-A)providesareferenceimplementationofsecureworldsoftwarefor`Armv7-AandArmv8-A`_,includinga`SecureMonitor`_executingatExceptionLevel3(EL3).ItimplementsvariousArminterfacestandards,suchas:-The`PowerStateCoordinationInterface(PSCI)`_-TrustedBoardBootRequirements(TBBR, Arm DEN0006C-1)-`SMCCallingConvention`_-`SystemControlandManagementInterface(SCMI)`_-`SoftwareDelegatedExceptionInterface(SDEI)`_ATF代码运行在EL3, 是实现安全相关的软件部分固件,其中会为其他特权级别提供服务,也就是说提供了在EL3中服务的手段,我们本文介绍的PSCI的实现就是在这里面,本文不会过多的讲解(注:其实本文只会涉及到atf如何响应服务el1的smc发过来的psci的服务请求,仅此而已,有关ATF(Trustzone)请参考其他资料)。
那么就开始我们的正题:
下面从源代码角度分析服务的注册处理流程:
4.1 el31处理总体流程
atf/bl31/aarch64/bl31_entrypoint.S://架构相关bl31_entrypoint->el3_entrypoint_common _exception_vectors=runtime_exceptions//设置el3的异常向量表->bl bl31_early_platform_setup//跳转到平台早期设置->bl bl31_plat_arch_setup//跳转到平台架构设置->bl bl31_main//跳转到bl31_main atf/bl31/aarch64/bl31_main.c:->NOTICE("BL31: %s\\n", version_string);//打印版本信息->NOTICE("BL31: %s\\n", build_message);//打印编译信息->bl31_platform_setup//执行平台设置->/* Initialize the runtime services e.g. psci. */初始化运行时服务 如psciINFO("BL31: Initializing runtime services\\n")//打印log信息->runtime_svc_init//调用各种运行时服务历程...