小编Mar*_*oom的帖子

符合C标准的方法来访问空指针地址?

在C中,引用空指针是未定义行为,但是空指针值具有位表示,在某些体系结构中它使其指向有效地址(例如地址0).为了清楚起见,
我们将此地址称为空指针地址.

假设我想在C中编写一个软件,在一个无限制访问内存的环境中.假设我想在空指针地址处写一些数据:我将如何以符合标准的方式实现这一点?

示例案例(IA32e):

#include <stdint.h>

int main()
{
   uintptr_t zero = 0;

   char* p = (char*)zero;

   return *p;
}
Run Code Online (Sandbox Code Playgroud)

当使用带有-O3的 gcc与IA32e 编译时,此代码将转换为

movzx eax, BYTE PTR [0]
ud2
Run Code Online (Sandbox Code Playgroud)

由于UB(0是空指针的位表示).

由于C接近低级编程,我相信必须有一种方法来访问空指针地址并避免UB.


为了清楚
起见,我问的是标准对此有何看法,而不是如何以实现定义的方式实现这一点.
我知道后者的答案.

c null-pointer undefined-behavior language-lawyer

32
推荐指数
2
解决办法
1005
查看次数

了解lfence对具有两个长依赖链的循环的影响,以增加长度

我正在玩这个答案的代码,稍微修改一下:

BITS 64

GLOBAL _start

SECTION .text

_start:
 mov ecx, 1000000

.loop:

 ;T is a symbol defined with the CLI (-DT=...)

 TIMES T imul eax, eax
 lfence
 TIMES T imul edx, edx


 dec ecx
jnz .loop

 mov eax, 60           ;sys_exit
 xor edi, edi
 syscall
Run Code Online (Sandbox Code Playgroud)

没有lfence我,我得到的结果与答案中的静态分析一致.

当我介绍一个单一 lfence我期望的CPU执行imul edx, edx的序列的第k个平行于迭代imul eax, eax的下一个(的序列K + 1个)迭代.
像这样的东西(调用一个imul eax, eax序列和dimul edx, edx一个): …

performance x86 assembly cpu-architecture perf

13
推荐指数
2
解决办法
472
查看次数

NUMA系统中的操作系统如何路由和处理MMIO,IO和PCI配置请求?

TL; DR

MMIO,IO和PCI配置请求如何路由到NUMA系统中的正确节点?
每个节点都有一个“路由表”,但我认为操作系统应该不知道它。
如果操作系统无法更改“路由表”,该如何重新映射设备?


有关“路由表”(即源地址解码器(SAD))的正确介绍,请参阅Intel Xeon v3 / v4 CPU中的物理地址解码:补充数据表

我将首先回顾一下我从论文和几乎未记录的数据表中收集到的内容。不幸的是,这将延长问题的时间,并且可能无法解决所有问题。

当请求传出LLC 1时,非核心需要知道将其路由到何处。

工作站CPU上,目标是DRAM,PCIe根端口/集成设备或DMI接口。
由于iMC寄存器2或PCIe根端口3 /集成设备之一,该内核可以轻松判断出内存请求是否属于DRAM,并且最终将退回到DMI。
当然,这还包括MMIO,并且与端口映射的IO几乎相同(仅跳过DRAM检查)。
PCI配置请求(CFG)按照规范进行路由,唯一的警告是,总线0上的CFG请求(不针对集成设备)是通过DMI接口4发送的。

服务器CPU上,物理地址的目标可以是未分配的。
表用于查找节点ID(NID)5。该表称为SAD。

实际上,SAD由两个解码器组成:DRAM解码器(使用表)和IO解码器6(由大多数固定范围和启用位组成,但也包含表)。
如果需要,IO解码器将覆盖DRAM解码器。

DRAM解码器使用范围列表,每个范围与目标NID 7的列表相关联。如果内存,MMIO或PCIe内存映射配置请求(MMCFG)匹配范围,则非内核将沿着QPI / UPI路径将请求发送到所选目标(尚不清楚SAD是否可以将请求者节点本身作为目标)。
IO解码器可以使用具有固定目标的固定范围的启用位(例如,将旧版BIOS窗口回收到“ BIOS NID”),或者具有可变范围(其中部分地址用于索引目标列表)。

在映射为的表中查找端口映射的IO目的地IO[yyy]
在名为的表中查找MMCFG IO目标PCI[zzz]
CFG目标重用该PCI[zzz]表。并在
此处表示索引功能,即请求地址的一部分(是CFG的总线号)。 yyyzzzzzz

所有这些对我来说都很有意义,但是这些表未在数据表中记录,因此类似的符号PCI[zzz]可能实际上意味着完全不同的含义。


尽管关于这些解码器的文档很少甚至没有文档,但对于原始的心理模型来说已经足够了。

对于我来说还是不清楚的是,即使是将SAD用于目标为本地资源的请求,还是仅将其用于出口请求。
稍后将很重要。

假设当请求离开LLC时,SAD用于将其路由到组件(最终在同一套接字中),然后按照与工作站案例8类似的方式处理它。

只要不更改硬件配置,就可以通过固件来配置SAD,而OS可以完全与它们无关。
但是,如果操作系统重新映射位于节点本地PCIe链接后面的PCIe设备,会发生什么情况?

对于MMIO请求到达这样的设备,它必须首先到达设备的节点(因为它是与系统其余部分的唯一链接),但这只有在正确重新配置SAD的情况下才能发生。即使对于源自与设备9 相同的节点的请求,
也可能需要重新配置SAD 。 …

io x86 cpu-architecture numa

11
推荐指数
1
解决办法
331
查看次数

LSD可以从检测到的循环的下一次迭代中发出uOP吗?

我正在使用一个非常简单的循环开始调查我的Haswell端口0上的分支单元的功能:

BITS 64
GLOBAL _start

SECTION .text

_start:

 mov ecx, 10000000

.loop:

 dec ecx             ;|
  jz .end            ;| 1 uOP (call it D)

jmp .loop            ;| 1 uOP (call it J)

.end:
 mov eax, 60
 xor edi, edi
 syscall
Run Code Online (Sandbox Code Playgroud)

使用perf我们看到循环以1c/iter运行

Performance counter stats for './main' (50 runs):

        10,001,055      uops_executed_port_port_6   ( +-  0.00% )
         9,999,973      uops_executed_port_port_0   ( +-  0.00% )
        10,015,414      cycles:u                    ( +-  0.02% )
                23      resource_stalls_rs          ( +- 64.05% )
Run Code Online (Sandbox Code Playgroud)

我对这些结果的解释是:

  • D和J都是并行发送的.
  • J具有1个周期的倒数吞吐量.
  • D和J都以最佳方式发送.

但是,我们也可以看到RS永远不会满员.
它最多可以以2 uOPs/c的速率发送uOP,但理论上可以得到4 …

x86 assembly cpu-architecture intel-pmu

9
推荐指数
1
解决办法
286
查看次数

A20 产品线能否在 Haswell 和继任者身上被掩盖?

维基百科从英特尔手册中引用了此声明

A20M# 的功能主要由较旧的操作系统使用,现代操作系统不使用。在较新的 Intel 64 处理器上,A20M# 可能不存在。

这是一个短语,它现在实际上在手册中,但它是模棱两可的:

  1. 是否A20M#实际上仅指或整个遮蔽事情的针?
  2. 许多指令(例如 TXTGETSEC或 VMX 指令)的描述中都命名了 A20M 事件/中断。

我所知道的

A20M# 引脚本身已经消失,它在某个时候被 DMI 中的 VLW(虚拟传统线)接口所取代。DMI 协议足够丰富,可以提供用于断言各种传统引脚的消息:

PCH 支持 VLW 消息作为将以下传统边带接口信号的状态传达给处理器的替代方法: • A20M#、INTR、SMI#、INIT#、NMI

这句话来自PCH系列8(Haswell时代)。


迄今为止,PCH 具有 A20GATE 直通功能。
当 PCH 配置为捕获对传统 8042 IO 端口(60h、64h)的访问并提供 SMI(用于 USB 键盘/鼠标的 PS2 模拟)时,它可以选择让 A20 线路启用序列通过而不会被捕获.

根据 PCH 的配置方式,这允许 EC(移动)或 SuperIO 芯片(台式机)成为命令序列的目标。


奇怪的是,PCH 系列 8(Haswell 时代)数据表报告:

注意:不支持 A20M# 功能。

然而,在 LPC 部分(EC/SuperIO 所连接的部分),这可能仅意味着 PCH本身不模拟 A20 门并且外部芯片(EC 或 SuperIO)必须处理它。

在这种情况下,PCI 必须有一个引脚才能由外部芯片断言。数据表没有提到任何内容。

但是,我在中文网站的某处找到了我以前的 Haswell 笔记本电脑的原理图,并且原理图显示引脚(实际上是球)AN10(又名 …

legacy x86 chipset

8
推荐指数
2
解决办法
347
查看次数

MSBDS(辐射)背后的微架构细节是什么?

CVE-2018-12126 已分配给 MSBDS(微架构 StoreBuffer 数据采样),这是英特尔处理器的一个漏洞,属于新创建的MDS(微架构数据采样)类。

我正在尝试获取这些漏洞背后的微架构细节。我已经开始使用 MSBDS,也称为 Fallout (cfr Meltdown),它允许攻击者泄漏存储缓冲区的内容。

出于某种原因,讨论微架构细节的网络安全论文通常不准确。
幸运的是,MSBDS 论文引用了专利 US 2008/0082765 A1(图片来自该专利)。

对于我收集到的信息,似乎在 MSBDS 的情况下,漏洞存在于内存消歧算法如何处理具有无效物理地址的负载。

这是据称用于检查存储缓冲区中的负载是否匹配的算法:

加载和存储的内存消歧算法

302检查load所引用的页面的偏移量是否与存储缓冲区中任何先前存储所引用的页面的偏移量匹配。
如果此检查失败,则加载与任何存储都不匹配,并且可以在304处执行(已分派)。
如果302检查,则将负载的虚拟地址的上半部分与存储的虚拟地址进行检查1
如果找到匹配,则加载匹配并且在308,如果转发不可能(例如从窄存储到更宽加载),则转发它需要的数据或阻止加载本身​​(直到匹配的存储提交)。
笔记同一个虚拟地址可以映射到两个不同的物理地址(在不同的时间但在存储转发窗口内)。不正确的转发不是通过该算法而是通过排空存储缓冲区(例如,使用mov cr3, X正在序列化的 a)2来防止的。
如果加载的虚拟地址与存储的任何虚拟地址都不匹配,则在310处检查物理地址。
这对于处理不同的虚拟地址映射到相同的物理地址的情况是必要的。

[0026]段补充说:

在一个实施例中,如果在操作302有命中并且加载或存储操作的物理地址无效,则在操作310的物理地址检查可以被认为是命中并且方法300可以在操作308继续。在一种情况下,如果加载指令的物理地址无效,则加载指令可能由于DTLB 118未命中而被阻塞。此外,如果存储操作的物理地址无效,则在一个实施例中结果可以基于finenet命中/未命中结果,或者可以在该存储操作上阻塞加载操作,直到解析存储操作的物理地址在一个实施例中。

这意味着如果物理地址不可用,CPU 将仅考虑地址的低 (12) 位3
考虑到 TLB 未命中的情况正在下面几行处理,这仅留下访问的页面不存在的情况。

这确实是研究人员如何展示他们的攻击:

char * victim_page = mmap (... , PAGE_SIZE …
Run Code Online (Sandbox Code Playgroud)

security x86 cpu-architecture speculative-execution cpu-mds

7
推荐指数
1
解决办法
471
查看次数

Ice Lake 的 48KiB L1 数据缓存的索引是如何工作的?

英特尔手动优化(2019 年 9 月修订版)显示了用于 Ice Lake 微架构的 48 KiB 8 路关联 L1 数据缓存。

Ice Lake 的 48KiB L1 数据缓存及其 8 路关联性 1软件可见的延迟/带宽会因访问模式和其他因素而异。

这让我感到困惑,因为:

  • 有 96 组(48 KiB / 64 / 8),不是二的幂。
  • 集合的索引位和字节偏移的索引位相加超过 12 位,这使得4KiB 页面无法使用便宜的 PIPT-as-VIPT-trick

总而言之,缓存的处理成本似乎更高,但延迟仅略有增加(如果确实如此,则取决于英特尔对该数字的确切含义)。

有一点创造力,我仍然可以想象一种快速索引 96 组的方法,但第二点对我来说似乎是一个重要的突破性变化。

我错过了什么?

x86 intel cpu-architecture cpu-cache micro-architecture

7
推荐指数
2
解决办法
234
查看次数

PCOMMIT指令有什么作用?

在英特尔ISA扩展手册中,描述pcommit有点神秘:

PCOMMIT指令导致某些商店到内存的操作,以永久内存范围,以成为持续性(断电保护).具体而言,PCOMMIT适用于已被内存接受的那些商店.
[...]
如果PCOMMIT在存储器接受到持久存储器范围的存储之后执行,则当存储PCOMMIT变为全局可见时,存储将变为持久存储.
[...]
只有在已经写入目标非易失性设备或某些中间电源故障保护存储/缓冲区之后,存储到持久性存储器的数据才会变得持久(持久).

它将持久存储器范围,存储器接受的存储,存储成为持久存储器非易失性设备1等概念命名.

确切的背景是什么?


1这不是传统的NV设备,如NOR Flash ROM或NVMe设备(读取:新的SSD),因为它们位于可控数量的桥之后,包括减法解码,这是CPU无法控制的.

memory x86 non-volatile

6
推荐指数
1
解决办法
588
查看次数

内存映射的I / O和编程的I / O之间的区别

在研究计算机体系结构时,我了解了控制I / O设备的不同方法,

  1. 编程的I / O
  2. 中断I / O
  3. DMA

我学习了所有三种方法。
但是我遇到了另一个术语“ 内存映射I / O”

编程I / O和内存映射I / O之间有什么关系 ?
我对这两个感到困惑。它们相似吗?

computer-science cpu-architecture

5
推荐指数
2
解决办法
7208
查看次数

为什么这种谱线在Kaby湖上不起作用?

我正在尝试在我的Kabe湖7600U上创建一个光谱线(cfr。Henry Wong),正在运行CentOS 7。

完整的测试库可在GitHub找到

我的specpoline版本如下(cfr。spec.asm):

specpoline:
        ;Long dependancy chain
        fld1
        TIMES 4 f2xm1
        fcos
        TIMES 4 f2xm1
        fcos
        TIMES 4 f2xm1

        %ifdef ARCH_STORE
            mov DWORD [buffer], 241     ;Store in the first line
        %endif

        add rsp, 8
        ret
Run Code Online (Sandbox Code Playgroud)

此版本与黄宏Henry的版本不同,流程被转移到建筑路径中。当原始版本使用固定地址时,我将目标传递到堆栈中。
这样,add rsp, 8将删除原始的寄信人地址并使用人工地址。

在函数的第一部分中,我使用一些旧的FPU指令创建了一个长延迟依赖关系链,然后创建了一个独立的链,试图欺骗CPU返回堆栈预测变量。


代码说明

使用FLUSH + RELOAD 1将specpoline插入到配置文件上下文中,同一程序集文件还包含:

buffer

一个连续的缓冲区,它跨越256个不同的高速缓存行,每个高速缓存行之间用GAP-1行分隔开来,总共为256*64*GAP字节。

GAP用于防止硬件预取。

随后是图形描述(每个索引紧接另一个)。

F + R缓冲区

timings

256个DWORD数组,每个条目保存访问F + R缓冲区中相应行所需的时间(以核心周期为单位)。

flush

一个小功能,可以触摸F + R缓冲区的每一页(带有存储,请确保COW在我们这一边)并逐出指定的行。

“个人资料”

标准配置文件功能 …

assembly x86-64 cpu-architecture speculative-execution branch-prediction

5
推荐指数
1
解决办法
84
查看次数