QEMU如何模拟目标机上的原子指令?

Qemu行为级emulator而非simulator,在模拟目标架构时,会利用HOST架构的支持特性实现目标架构的行为,下面分析一下QEMU对目标架构原子指令的模拟方式。

HOST架构自然是X86,为了搭建环境的方便,选择RISCV架构作为目标架构,参考这篇文章搭建RISCV QEMU运行环境:

https://blog.csdn.net/tugouxp/article/details/137614570?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22137614570%22%2C%22source%22%3A%22tugouxp%22%7D

验证方案

1.首先,确保初始目标架构程序没有调用任何原子指令,验证方法是在QEMU中模拟TARGE架构流程的必经之路do_atomic_op_i32/do_atomic_op_i64打断点,确保初始程序没有调用任何目标架构上的原子操作指令。以本测试为例,riscv_programming_practice/chapter_2/benos下的初始测试程序就没有调用任何原子指令,先在do_atomic_op_i32/do_atomic_op_i64打上断点,之后运行程序,不会进入断点。

2.之后加入断点程序:

#include "uart.h"                                                                                                                                                                                           
 
static void arch_atomic_add(int i, unsigned long *v) 
{
        __asm__ __volatile__ ( "amoadd.d  zero, %1, %0"
                : "+A" (*v) :
                "r" (i) 
                ¦: "memory");
}
 
unsigned long abc;
void kernel_main(void)
{
        arch_atomic_add(1, &abc);
        uart_init();
        uart_send_string("Welcome RISC-V!\r\n");
 
        while (1) {
                ;
        }   
}

再次打上断点,发现这次拦截到了对原子操作指令的调用:

上述调用栈完成了对原子指令的翻译之后,之后开始执行GEN BUFFER中的指令,ATOMIC ADD指令具体由helper_atomic_fetch_addq_le函数实现:

helper_atomic_fetch_addq_le函数最终调用了X86 HOST主机的 "lock xadd"指令完成了对RISCV AMOADD指令的模拟操作。

所以,这一种模拟方式是使用HOST架构CPU上的原子指令来模拟目标主机架构上的原子指令。

RISCV amoswap.d指令的模拟

测试代码:

#include "uart.h"
           
unsigned long xchg(volatile void *ptr, unsigned long new)
{          
        unsigned long result;
           
        asm volatile (
                " amoswap.d %[result], %[new], (%[ptr])\n"
                : [result]"=r"(result), [ptr]"+r"(ptr)
                : [new]"r"(new)
                : "memory");
           
        return result;                                                                                                                                                                                      
}          
           
void kernel_main(void)
{          
        unsigned long abc = 0;
        xchg(&abc, 2); 
        uart_init();
        uart_send_string("Welcome RISC-V!\r\n");
           
        while (1) {
                ;
        }  
}

运行时抓到的调用堆栈如下,可以看到,最终是通过helper_atomic_xchgq_le helper函数实现的,顾名思义,那一定是调用了X86 HOST主机上的xchgq指令了:

不知为何,这里没有在HOST指令xchg前加LOCK,可能是个问题吧,不管怎样,TARGET机到HOST机上的原子指令映射关系找到了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值