当前位置: 首页 > news >正文

ARM64 Trust Firmware [五]

本章介绍 ATF 中的 Runtime Service 是如何定义和被调用的。

要了解 SMC,必须从 SMC 指令本身开始,其指令如下图:

指令格式为:SMC #<imm>,从官方文档了解到该指令只能在 EL1 以及更高的异常等级上调用,用户空间 EL0 是无法直接调用该指令的。

同时根据 ARM 官方文档关于 SMCCC 的描述如下:

可以知道 SMC 可以根据不同的 OEN(Owning Entity Number)区分不同分服务的功能,当注册具体了 SMC runtime service 时,需要为对应的 service 指定正确的 OEN 范围。

这里比较抽象,我们来举个例子就明白了,比如我在 Hypervisor 中介绍的关于虚拟机管理器通过 SMC 系统调用去 ATF 通过 PSCI 协议拉起从核,其中启动从核的 PSIC 的 function id 为:PSCI_CPU_ON_AARCH64(0xc4000003),不考虑后面跟的参数,也就是最终调用了:

smc #0xc4000003

按照其 32bit 划分:

  • bit[31] = 1:Fast call;
  • bit[32] = 0:SMC64 call convention;
  • bit[29 : 24] = 4:Standard service call;
  • bit[15 : 0] = 3:该类型的 call type 下的 function number;

我们对 runtime service 进行了如下的定义和分类:

  • ARM Architecture Calls:获取 smcc 版本,arch features 等;
  • CPU Service Calls:提供针对该平台的 CPU 实现特定服务的接口;
  • SIP Service Calls:System IP 的驱动;
  • OEM Service Calls:OEM 服务的接口;
  • Standard Secure Service:PSCI call 就属于这个服务类型;
  • ... ...

Runtime Service 的注册:

BL31 通过宏定义 DECLARE_RT_SVC 注册一个服务:

比如 Standard Service 的注册:

/* Register Standard Service Calls as runtime service */
DECLARE_RT_SVC(std_svc,OEN_STD_START,OEN_STD_END,SMC_TYPE_FAST,std_svc_setup,std_svc_smc_handler
);

比如 SIP Service 的注册:

/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(arm_sip_svc,OEN_SIP_START,OEN_SIP_END,SMC_TYPE_FAST,arm_sip_setup,arm_sip_handler
);

在注册处理 SMC 命令服务时,DECLARE_RT_SVC 空定义定义了一个结构体__svc_desc_##_name,并将其放到了 OS 镜像的一个特殊的段.rt_svc_descs 中,其中__RT_SVC_DESCS_START__ 和__RT_SVC_DESCS_END__ 是该断的起始地址和结束地址,并且可以通过地址范围计算出服务的数量 RT_SVC_DECS_NUM:

/** Convenience macros to declare a service descriptor*/
#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch)	\static const rt_svc_desc_t __svc_desc_ ## _name			\__section(".rt_svc_descs") __used = {			\.start_oen = (_start),				\.end_oen = (_end),				\.call_type = (_type),				\.name = #_name,					\.init = (_setup),				\.handle = (_smch)				\}#define RT_SVC_DESCS					\. = ALIGN(STRUCT_ALIGN);			\__RT_SVC_DESCS_START__ = .;			\KEEP(*(.rt_svc_descs))				\__RT_SVC_DESCS_END__ = .;

Runtime Service 的启动:

void __init runtime_svc_init(void)
{int rc = 0;uint8_t index, start_idx, end_idx;rt_svc_desc_t *rt_svc_descs;/* Assert the number of descriptors detected are less than maximum indices */assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) &&(RT_SVC_DECS_NUM < MAX_RT_SVCS));/* If no runtime services are implemented then simply bail out */if (RT_SVC_DECS_NUM == 0U)return;/* Initialise internal variables to invalid state */(void)memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices));rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;for (index = 0U; index < RT_SVC_DECS_NUM; index++) {rt_svc_desc_t *service = &rt_svc_descs[index];/** An invalid descriptor is an error condition since it is* difficult to predict the system behaviour in the absence* of this service.*/rc = validate_rt_svc_desc(service);if (rc != 0) {ERROR("Invalid runtime service descriptor %p\n",(void *) service);panic();}/** The runtime service may have separate rt_svc_desc_t* for its fast smc and yielding smc. Since the service itself* need to be initialized only once, only one of them will have* an initialisation routine defined. Call the initialisation* routine for this runtime service, if it is defined.*/if (service->init != NULL) {rc = service->init();if (rc != 0) {ERROR("Error initializing runtime service %s\n",service->name);continue;}}/** Fill the indices corresponding to the start and end* owning entity numbers with the index of the* descriptor which will handle the SMCs for this owning* entity range.*/start_idx = (uint8_t)get_unique_oen(service->start_oen,service->call_type);end_idx = (uint8_t)get_unique_oen(service->end_oen,service->call_type);assert(start_idx <= end_idx);assert(end_idx < MAX_RT_SVCS);for (; start_idx <= end_idx; start_idx++)rt_svc_descs_indices[start_idx] = index;}
}
  • 先通过RT_SVC_DESCS_START 和RT_SVC_DESCS_END 之间的大小,计算出当前的服务数量RT_SVC_DECS_NUM;
  • 从RT_SVC_DESCS_START 位置开始遍历所有服务,拿到其结构体地址service;
  • 通过validate_rt_svc_desc 对该服务的参数进行校验;
  • 通过 service->init 初始化该服务,当然有些服务可能不需要 init setup;
  • 初始化rt_svc_descs_indices 表;

在 EL1/EL2 发起 SMC 调用时,smc_fid 作为第一个参数传递给 ATF,ATF 需要根据 smc_fid 定位到是哪种 service。由于 service 有两种 type 组成,每种 type 的 oen 最多有 64 个,所以 type 和 oen 的组合会有 128 中可能。为了加快查找 service 类别,ATF 在初始化 runtime service 时会维护一个表,我们用如下两个服务作为例子:

DECLARE_RT_SVC(arm_sip_svc,OEN_SIP_START,      == 2OEN_SIP_END,		== 2SMC_TYPE_FAST,		== 1arm_sip_setup,arm_sip_handler
);start_idx = SMC_TYPE_FAST << 6 | OEN_SIP_START = 66
end_idx   = SMC_TYPE_FAST << 6 | OEN_SIP_END   = 66DECLARE_RT_SVC(tos_svc,OEN_TOS_START,  == 50OEN_TOS_END,	== 63SMC_TYPE_YIELD,	== 0tos_svc_setup,tos_svc_smc_handler
);start_idx = SMC_TYPE_YIELD << 6 | OEN_TOS_START = 50
end_idx   = SMC_TYPE_YIELD << 6 | OEN_TOS_END   = 63

SMC 的处理流程:

根据 bl31/aarch64/runtime_exceptions.S 中异常向量表 runtime_exceptions 的定义,当 EL1/EL2 发起 SMC 调用后,会触发sync_exception_aarch64,并在最终的 smc_handler64 处理中跳转到相应的服务处理函数中:

runtime_exceptions-->sync_exception_aarch64-->handle_sync_exception-->sync_handler64

sync_handler64 中根据参数 1 中 smc_fid 的 type 和 oen 得到 desc_index,由rt_svc_descs_indices[desc_index] 可以得到 svc_index,再 由rt_svc_descs[svc_index] 就可以得到对应 runtime service 描述符的指针rt_svc_desc_t,最后调用其 handler 处理函数:

	and	x16, x0, #(FUNCID_SVE_HINT_MASK << FUNCID_SVE_HINT_SHIFT)orr	x7, x7, x16bic	x0, x0, #(FUNCID_SVE_HINT_MASK << FUNCID_SVE_HINT_SHIFT)/* Get the unique owning entity number */ubfx	x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTHubfx	x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTHorr	x16, x16, x15, lsl #FUNCID_OEN_WIDTH/* Load descriptor index from array of indices */adrp	x14, rt_svc_descs_indicesadd	x14, x14, :lo12:rt_svc_descs_indicesldrb	w15, [x14, x16]/* Any index greater than 127 is invalid. Check bit 7. */tbnz	w15, 7, smc_unknown/** Get the descriptor using the index* x11 = (base + off), w15 = index** handler = (base + off) + (index << log2(size))*/adr_l	x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE)lsl	w10, w15, #RT_SVC_SIZE_LOG2ldr	x15, [x11, w10, uxtw]/** Call the Secure Monitor Call handler and then drop directly into* el3_exit() which will program any remaining architectural state* prior to issuing the ERET to the desired lower EL.*/
#if DEBUGcbz	x15, rt_svc_fw_critical_error
#endifblr	x15

以 psci 为例,由于 psci 属于 standard service,所以会调用std_svc_smc_handler,在std_svc_smc_handler 中再根据smc_fid 区分不同的细分服务,然后调用psci_smc_handler 去处理 psci 协议:

static uintptr_t std_svc_smc_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void *cookie,void *handle,u_register_t flags)
{if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) {/* 32-bit SMC function, clear top parameter bits */x1 &= UINT32_MAX;x2 &= UINT32_MAX;x3 &= UINT32_MAX;x4 &= UINT32_MAX;}/** Dispatch PSCI calls to PSCI SMC handler and return its return* value*/if (is_psci_fid(smc_fid)) {uint64_t ret;ret = psci_smc_handler(smc_fid, x1, x2, x3, x4,cookie, handle, flags);...
}

相关文章:

ARM64 Trust Firmware [五]

本章介绍 ATF 中的 Runtime Service 是如何定义和被调用的。 要了解 SMC&#xff0c;必须从 SMC 指令本身开始&#xff0c;其指令如下图&#xff1a; 指令格式为&#xff1a;SMC #<imm>&#xff0c;从官方文档了解到该指令只能在 EL1 以及更高的异常等级上调用&#xff…...

rkipc main.c 中 rk_param_init函数分析

rk_param_init函数 这个函数是用来读取配置文件进行参数配置 这个函数在 luckfox-pico/project/app/rk_smart_door/smart_door/common/uvc/param/param.c 中 这个函数在main函数中被调用 //通过-c 配置文件路径 把配置文件传进来 case c:rkipc_ini_path_ optarg;//调用&am…...

正确清理C盘空间

一.系统清理 正确清理C盘空间主要是删除不需要的文件和应用程序&#xff0c;以释放磁盘空间。以下是一些常用的方法&#xff1a; 删除临时文件&#xff1a;在Windows搜索框中输入“%temp%”&#xff0c;打开临时文件夹&#xff0c;将其中的文件全部删除。 清理回收站&#xf…...

http代理IP怎么实现?如何解决代理IP访问不了问题?

HTTP代理是一种网络服务&#xff0c;它充当客户端和目标服务器之间的中介。当客户端发送请求时&#xff0c;请求首先发送到代理服务器&#xff0c;然后由代理服务器转发到目标服务器。同样&#xff0c;目标服务器的响应也会先发送到代理服务器&#xff0c;再由代理服务器返回给…...

【Gin-Web】Bluebell社区项目梳理5:投票功能分析与实现

本文目录 一、投票功能投票流程实现代码redis投票 一、投票功能 投票流程 首先我们要明确&#xff0c;就是 谁&#xff08;哪个用户&#xff1a;userID&#xff09; 给 哪个帖子&#xff08;postID&#xff09; 投了 什么票&#xff08;赞成票or反对票&#xff09;。 赞成票…...

多人协同创作gitea

多人协同创作gitea 在多台设备上协同使用Gitea&#xff0c;主要是通过网络访问Gitea服务器上的仓库来进行代码管理和协作。以下是一些关键步骤和建议&#xff0c;帮助你在多台设备上高效地使用Gitea进行协作&#xff1a; 1. 确保Gitea服务可访问 首先&#xff0c;你需要确保…...

Java 大视界 -- Java 大数据未来十年的技术蓝图与发展愿景(95)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

idea连接gitee完整教程

文章目录 idea连接gitee(使用idea远程兼容gitee) 使用idea远程兼容gitee并反向创建仓库和分支...

问卷数据分析|SPSS实操之相关分析

皮尔逊还是斯皮尔曼的选取主要看数据的分布 当数据满足正态分布且具有线性关系时&#xff0c;用皮尔逊相关系数 当有一个不满住时&#xff0c;用斯皮尔曼相关系数 1. 选择分析--相关--双变量 2. 将Z1-Y2加入到变量中&#xff0c;选择皮尔逊 3. 此处为结果&#xff0c;可看我案…...

汽配出库软件助力企业数字化转型,佳易王汽配出入库管理系统操作教程

一、概述 本实例以佳易王汽配出入库管理系统V17.1版本为例说明&#xff0c;其他版本可参考本实例。试用版软件资源可到文章最后了解&#xff0c;下载的文件为压缩包文件&#xff0c;请使用免费版的解压工具解压即可试用。 软件特点&#xff1a; 1、软件为绿色免安装版&#…...

二叉树(中等题)

1、先序&#xff0c;中序遍历确定二叉树 105 方法一、 前提 ① 必须不能有重复元素② 只有先序&#xff0b;中序和后序&#xff0b;中序才能实现唯一树 思考要点&#xff1a; 不要想着用for循环&#xff0c;递归一定更好解决输入是vector&#xff0c;递归就得考虑传入索…...

Versal - 基础6(Linux 开发 AIE-ML + 自动化脚本解析)

目录 1. 简介 2. 步骤解析 2.1 概览 2.1.1 步骤依赖关系 2.1.2 总目录结构 2.2 Vitis XPFM 2.2.1 Dir 2.2.2 Makefile 2.2.3 vitis_pfm.py 2.3 Kernels 2.3.1 Dir 2.3.2 Makefile 2.3.3 config 文件 2.4 AIE_app 2.4.1 Dir 2.4.2 Makefile 2.4.3 aie 要点 2.…...

什么是矩阵账号?如何高效运营tiktok矩阵账号

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌​‌‌​‌‌‌‍‌​‌​‌​​​‍‌​​‌​‌‌​‍‌​​​​‌‌​‍‌​‌​​‌‌‌‍‌​​‌‌​‌​‍‌​‌​​‌‌‌‍‌​‌‌‌​​‌‍‌‌​​‌‌‌​‍‌‌​​‌‌​​‍‌…...

tortoiseSVN 如何克隆项目到本地

导入项目成功&#xff0c;如下图&#xff1a;...

趣解PostGet请求的原理、应用场景及区别

趣解Post&Get请求的原理、应用场景及区别 POST 和 GET 的「身份之谜」&#xff1a;快递员与侦探的终极对决 一、角色设定&#xff1a;快递员&#xff08;POST&#xff09; vs 侦探&#xff08;GET&#xff09; GET&#xff08;侦探&#xff09;&#xff1a; 任务&#xff…...

在PHP Web开发中,实现异步处理有几种常见方式的优缺点,以及最佳实践推荐方法

1. 消息队列 使用消息队列&#xff08;如RabbitMQ、Beanstalkd、Redis&#xff09;将任务放入队列&#xff0c;由后台进程异步处理。 优点&#xff1a; 任务持久化&#xff0c;系统崩溃后任务不丢失。 支持分布式处理&#xff0c;扩展性强。 实现步骤&#xff1a; 安装消息…...

深入解析过滤器模式:数据筛选与处理的高效工具

过滤器模式&#xff1a;数据筛选与处理的高效工具 在软件开发的复杂领域中&#xff0c;数据的筛选与处理是常见的任务。过滤器模式作为一种实用的设计模式&#xff0c;为解决这类问题提供了有效的解决方案。它允许开发者根据不同的标准对一组对象进行过滤操作&#xff0c;从而…...

DeepSeek R1/V3满血版——在线体验与API调用

前言&#xff1a;在人工智能的大模型发展进程中&#xff0c;每一次新模型的亮相都宛如一颗投入湖面的石子&#xff0c;激起层层波澜。如今&#xff0c;DeepSeek R1/V3 满血版强势登场&#xff0c;为大模型应用领域带来了全新的活力与变革。 本文不但介绍在线体验 DeepSeek R1/…...

排序链表--字节跳动

少年的书桌上没有虚度的光阴 题目描述 请你对链表进行排序 思路分析 核心思想&#xff1a;归并排序 有三个部分 链表排序实现 1. merge 函数 21.见 合并两个有序链表&#xff0c; 首先创建一个虚拟头节点 newhead&#xff0c;并使用指针 tail 来构建合并后的链表。 通过…...

Python爬虫-批量爬取股票数据猫各股票代码

前言 本文是该专栏的第47篇,后面会持续分享python爬虫干货知识,记得关注。 本文笔者以股票数据猫为例子,基于Python爬虫,批量获取各股票代码数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。废话不多说,下面跟着笔者直接往下看正文详细内容。(附…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了&#xff0c;很多小伙伴想体验鸿蒙电脑版操作系统&#xff0c;可惜&#xff0c;鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机&#xff0c;来体验大家心心念念的鸿蒙系统啦&#xff01;注意&#xff1a;虚拟…...