#DynamoRIO 遇到了大问题。对于类似
这可咋办了,感觉要识别这种序列,然后特殊处理了,先睡觉吧。
lr beq sc 这种指令序列,因为中间的 cbr 存在,所以这个序列会被 DynamoRIO 撕成两个 basic block,然后两个 basic block 中间,就不可避免的会执行一些访存指令。这在 Unmatched 上就会直接卡死,这是正常的,因为 spec 不允许 lr sc 中间插访存。这可咋办了,感觉要识别这种序列,然后特殊处理了,先睡觉吧。
ksco 的工作日志
#DynamoRIO 目前针对 thread pointer 的做法是:在进入 guest 之前,把 tp 存起来,然后把 tp 指向 spill state。guest 所有的访问 tp 的指令当然都需要 mangle。从 guest 中退出的时候,再把 tp 恢复即可。这样有个好处就是,不需要再偷一个寄存器放 tp 的原始值(host thread pointer)了。 但今天发现一个大问题是,如果 client 设置了 itimer,跳转的地方是 guest 代码时,tp 的值其实是 spill state…
花了两天刚把 thread pointer 问题修好了,又遇到
lr sc ,不知道什么时候才能推进多线程的支持了。😞^ If the host also supports LL/SC, one may think of using them for emulating the target’s LL/SC. This is dangerous, however, because most processors constrain the instructions that can appear between an LL/SC pair. If these restrictions are not respected, the store might fail spuriously. The extra overhead of dynamic translation, such as TLB lookups and register spills, may thus cause the store to fail forever.
跨架构模拟 LL/SC 大概有 4 种方案:
1. 执行的时候停掉其他 CPU,执行完再恢复(文章中说这是 QEMU “目前”的做法)
2. 用 CAS 模拟,会有 ABA 问题,但据称这个问题 “almost never matters for real programs”
3. 监控所有 CPU 的 store
4. 如果 host 硬件支持 hardware transactional memory,则可以精确模拟
1. 执行的时候停掉其他 CPU,执行完再恢复(文章中说这是 QEMU “目前”的做法)
2. 用 CAS 模拟,会有 ABA 问题,但据称这个问题 “almost never matters for real programs”
3. 监控所有 CPU 的 store
4. 如果 host 硬件支持 hardware transactional memory,则可以精确模拟
❤3
同架构模拟的情况基本类似,DynamoRIO AArch64 提供了两种方案:
1. 默认方案:用 CAS 模拟
2. 可选方案:搞了一条超级指令,把整个 LL/SC block 打包成一条指令来处理(除了精确和性能好之外,缺点多多)
1. 默认方案:用 CAS 模拟
2. 可选方案:搞了一条超级指令,把整个 LL/SC block 打包成一条指令来处理(除了精确和性能好之外,缺点多多)
ksco 的工作日志
同架构模拟的情况基本类似,DynamoRIO AArch64 提供了两种方案: 1. 默认方案:用 CAS 模拟 2. 可选方案:搞了一条超级指令,把整个 LL/SC block 打包成一条指令来处理(除了精确和性能好之外,缺点多多)
打算和 AArch64 一样,先给 RISC-V 用 amoswap 模拟实现,之后再实现可选的 super-instruction 选项。明天再写吧。
👏2
基础的 codegen,没有考虑 stolen reg 和 tp reg,把这两个考虑进来后情况还要更复杂一点。
# ---> lr.w/d.aq?.rl? rd, (rs1)
sd scratch1, [scratch_1_slot]
fence rl?
ld rd, 0(rs1)
fence aq?
sd rs1, [tls_lrsc_addr]
li scratch1, SIZE
sd scratch1, [tls_lrsc_size]
sd rd, [tls_lrsc_value]
ld scratch1, [scratch_1_slot]
# ---> sc.w/d.aq?.rl? rd, rs2, (rs1)
sd scratch1, [scratch_1_slot]
sd scratch2, [scratch_2_slot]
ld scratch1, [tls_lrsc_addr]
bne scratch1, rs1, fail
ld scratch1, [tls_lrsc_size]
li scratch2, SIZE
bne scratch1, scratch2, fail
amoswap.aq?.rl? rd, rs2, (rs1)
sne rd, rd, value
j finally
fail:
fence aq?rl?
li rd, 1
finally:
li scratch1, -1
sd scratch1, [tls_lrsc_addr]
ld scratch1, [scratch_1_slot]
ld scratch2, [scratch_2_slot]