CPUID,CPUID 在 SGX 中使用。
CPUID官网手册
返回值汇总表位于《Intel® 64 and IA-32 Architectures Software Developer's Manual Combined Volumes 2A Vol》的Table 3-8. Information Returned by CPUID Instruction。
这个表占了足足19页,吓人。不过很丰富,很有用。
官网下载地址如下,注意是在2A卷中。
https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-software-developers-manual-volume-2a-instruction-set-reference-a-l.html
下完以后搜索Table 3-8. Information Returned by CPUID Instruction就能快速找到。
SGX中使用CPUID
正常来说,Enclave内部是不可以使用CPUID指令的(SGX手册上有说)。但实际中Enclave内部却有cpuid硬件的直接使用,挺奇怪?难道是SGX更新了?
至于为什么Enclave内部为什么不能用CPUID硬件指令,相关资料挺少,我的猜测是CPUID硬件指令需要系统权限(但似乎并不是)或者存在某些安全影响(什么安全影响尚不清楚)。
总之,Enclave内部不能使用cpuid指令,不可信世界是可以任意使用cpuid指令。
1. 不可信世界端(可任意调用cpuid硬件指令)
如下几个是壳函数,最终会调用实际执行CPUID的函数
//位于/psw/urts/cpu_features.h
inline void sgx_cpuid(unsigned int in_eax, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
{
int cpu_info[4] = {0};
__cpuid(cpu_info, in_eax);
*eax = cpu_info[0];
*ebx = cpu_info[1];
*ecx = cpu_info[2];
*edx = cpu_info[3];
}
//位于/psw/urts/cpu_features.h
inline void sgx_cpuidex(unsigned int in_eax, unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
{
int cpu_info[4] = {0};
__cpuidex(cpu_info, in_eax, leaf);
*eax = cpu_info[0];
*ebx = cpu_info[1];
*ecx = cpu_info[2];
*edx = cpu_info[3];
}
下面这个函数是一个OCALL函数,专门承载Enclave内部对CPUID指令调用的需求,因为Enclave内部是不能使用CPUID硬件指令。这个OCALL已经被写到了psw/urts/linux/urts{_internal}.lds符号文件、common/inc/sgx_tstdc.edl这个Enclave接口描述文件中,方便Enclave内部调用。
//psw/urts/se_ocalls.cpp
extern "C" void sgx_oc_cpuidex(int cpuinfo[4], int leaf, int subleaf)
{
__cpuidex(cpuinfo, leaf, subleaf);
}
上述几个壳函数都是最终调用__cpuid{ex}这个壳函数
//位于common/inc/internal/linux/cpuid_gnu.h
static inline void __cpuidex(int a[4], int b, int c)
{
a[0] = b;
a[2] = c;
cpuid(&a[0], &a[1], &a[2], &a[3]);
}
//位于common/inc/internal/linux/cpuid_gnu.h
static inline void __cpuid(int a[4], int b)
{
a[0] = b;
a[2] = 0;
cpuid(&a[0], &a[1], &a[2], &a[3]);
}
__cpuid{ex}壳函数最终会调用下面这个cpuid函数,并执行CPUID硬件指令。这些函数定义下common文件夹下面,这个common指代的是什么意思。
//位于common/inc/internal/linux/cpuid_gnu.h
/* This is a PIC-compliant version of CPUID */
static inline void cpuid(int *eax, int *ebx, int *ecx, int *edx)
{
#if defined(__x86_64__)
asm("cpuid"
: "=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "0" (*eax), "2" (*ecx));
#else
/*on 32bit, ebx can NOT be used as PIC code*/
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
: "=a" (*eax), "=r" (*ebx), "=c" (*ecx), "=d" (*edx)
: "0" (*eax), "2" (*ecx));
#endif
}
2. Enclave内部(不能直接使用cpuid硬件指令)
//位于sdk/tlibc/gen/se_cpuid.c
sgx_status_t sgx_cpuid(int cpuinfo[4], int leaf)
{
return sgx_cpuidex(cpuinfo, leaf, 0);
}
//位于sdk/tlibc/gen/se_cpuid.c
sgx_status_t sgx_cpuidex(int cpuinfo[4], int leaf, int subleaf)
{
if (cpuinfo == NULL)
return SGX_ERROR_INVALID_PARAMETER;
return sgx_oc_cpuidex(cpuinfo, leaf, subleaf);
}
Enclave内部的壳函数会通过sgx_oc_cpuidex这个OCALL函数切换到不可新世界调用CPUID硬件指令
下面这两个函数位于sdk内(sdk是Enclave内部程序所依赖的静态库),这就很奇怪了,为什么Enclave内部会需要定义这两个函数,难道能直接用?
//位于sdk/gperftools/gperftools-2.7/src/base/atomicops-internals-x86.cc
// Inline cpuid instruction. In PIC compilations, %ebx contains the address
// of the global offset table. To avoid breaking such executables, this code
// must preserve that register's value across cpuid instructions.
#if defined(__i386__)
#define cpuid(a, b, c, d, inp) \
asm ("mov %%ebx, %%edi\n" \
"cpuid\n" \
"xchg %%edi, %%ebx\n" \
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
#elif defined (__x86_64__)
#define cpuid(a, b, c, d, inp) \
asm ("mov %%rbx, %%rdi\n" \
"cpuid\n" \
"xchg %%rdi, %%rbx\n" \
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
#endif
//位于sdk/libcapable/linux/sgx_capable.cpp
/* __cpuid(unsinged int info[4], unsigned int leaf, unsigned int subleaf); */
/* Because gcc's __get_cpuid() intrinsic is difficult to work with */
#define __cpuid(x,y,z) asm volatile("cpuid":"=a"(x[0]),"=b"(x[1]),"=c"(x[2]),"=d"(x[3]):"a"(y),"c"(z))
推荐阅读
-
使用 cgo 在 Golang 中调用 C 语言库:"runtime/cgo "软件包完整指南 - 摘要
-
使用 WangEditor 富文本编辑器在 Vue 中实现文本编辑和显示
-
使用 MailKit 在 C# 中收发电子邮件
-
在 R 中绘制箱线图 - 0x02 使用 ggplot2 软件包
-
使用 xpath 在 HTML 中精确定位元素的基本方法
-
如何使用Poppler库在C++中读取PDF文件(二) - PDF目录
-
Mysql 新陈代谢 10 - 使用 SQL99 在 7 中执行 JOIN 操作
-
Java 8新特性探究(十三)JavaFX 8新特性以及开发2048游戏-JavaFX历史## 跟java在服务器端和web端成绩相比,桌面一直是java的软肋,于是Sun公司在2008年推出JavaFX,弥补桌面软件的缺陷,请看下图JavaFX一路走过来的改进 从上图看出,一开始推出时候,开发者需使用一种名为JavaFX Script的静态的、声明式的编程语言来开发JavaFX应用程序。因为JavaFX Script将会被编译为Java bytecode,程序员可以使用Java代码代替。 JavaFX 2.0之后的版本摒弃了JavaFX Script语言,而作为一个Java API来使用。因此使用JavaFX平台实现的应用程序将直接通过标准Java代码来实现。 JavaFX 2.0 包含非常丰富的 UI 控件、图形和多媒体特性用于简化可视化应用的开发,WebView可直接在应用中嵌入网页;另外 2.0 版本允许使用 FXML 进行 UI 定义,这是一个脚本化基于 XML 的标识语言。 从JDK 7u6开始,JavaFx就与JDK捆绑在一起了,JavaFX团队称,下一个版本将是8.0,目前所有的工作都已经围绕8.0库进行。这是因为JavaFX将捆绑在Java 8中,因此该团队决定跳过几个版本号,迎头赶上Java 8。 ##JavaFx8的新特性 ## ###全新现代主题:Modena 新的Modena主题来替换原来的Caspian主题。不过在Application的start方法中,可以通过setUserAgentStylesheet(STYLESHEET_CASPIAN)来继续使用Caspian主题。 参考http://fxexperience.com/2013/03/modena-theme-update/ ###JavaFX 3D 在JavaFX8中提供了3D图像处理API,包括Shape3D (Box, Cylinder, MeshView, Sphere子类),SubScene, Material, PickResult, LightBase (AmbientLight 和PointLight子类),SceneAntialiasing等。Camera类也得到了更新。从JavaDoc中可以找到更多信息。 ###富文本 强化了富文本的支持 ###TreeTableView ###日期控件DatePicker 增加日期控件 ###用于 CSS 结构的公共 API
-
在Linux中通过Windows共享文件夹直接挂载并使用(实验操作)
-
在Linux中,如何使用rclone将网盘挂载到本地