gpt4 book ai didi

c - Qemu 如何模拟 PCIe 设备?

转载 作者:行者123 更新时间:2023-12-04 15:10:47 25 4
gpt4 key购买 nike

我正在写一个关于 qemu 内部的开源文档,所以如果你帮助我,你就是在帮助 Qemu 项目的发展
我找到的最接近的答案是:In which conditions the ioctl KVM_RUN returns?
这是在 KVM 上运行的单个 CPU 的线程循环:

static void *qemu_kvm_cpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
int r;

rcu_register_thread();

qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
cpu->can_do_io = 1;
current_cpu = cpu;

r = kvm_init_vcpu(cpu);
if (r < 0) {
error_report("kvm_init_vcpu failed: %s", strerror(-r));
exit(1);
}

kvm_init_cpu_signals(cpu);

/* signal CPU creation */
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
qemu_guest_random_seed_thread_part2(cpu->random_seed);

do {
if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(cpu);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
}
}
qemu_wait_io_event(cpu);
} while (!cpu->unplug || cpu_can_run(cpu));

qemu_kvm_destroy_vcpu(cpu);
cpu->created = false;
qemu_cond_signal(&qemu_cpu_cond);
qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
}
你可以在这里看到:
do {
if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(cpu);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
}
}
qemu_wait_io_event(cpu);
} while (!cpu->unplug || cpu_can_run(cpu));
每次 KVM 返回时,它都为 Qemu 提供了模拟事物的机会。我想当 guest 上的内核尝试访问 PCIe 设备时,主机上的 KVM 会返回。不知道KVM怎么知道怎么返回。也许 KVM 维护了 PCIe 设备的地址,并告诉 Intel 的 VT-D 或 AMD 的 IOV 哪些地址应该产生异常。有人可以澄清这一点吗?
好吧,从 qemu_kvm_cpu_thread_fn 的外观来看,唯一可以模拟 PCIe 访问的地方是 qemu_wait_io_event(cpu) ,这里定义: https://github.com/qemu/qemu/blob/stable-4.2/cpus.c#L1266并调用 qemu_wait_io_event_common此处定义: https://github.com/qemu/qemu/blob/stable-4.2/cpus.c#L1241其中调用 process_queued_cpu_work此处定义: https://github.com/qemu/qemu/blob/stable-4.2/cpus-common.c#L309
让我们看看执行队列函数的代码:
 while (cpu->queued_work_first != NULL) {
wi = cpu->queued_work_first;
cpu->queued_work_first = wi->next;
if (!cpu->queued_work_first) {
cpu->queued_work_last = NULL;
}
qemu_mutex_unlock(&cpu->work_mutex);
if (wi->exclusive) {
/* Running work items outside the BQL avoids the following deadlock:
* 1) start_exclusive() is called with the BQL taken while another
* CPU is running; 2) cpu_exec in the other CPU tries to takes the
* BQL, so it goes to sleep; start_exclusive() is sleeping too, so
* neither CPU can proceed.
*/
qemu_mutex_unlock_iothread();
start_exclusive();
wi->func(cpu, wi->data);
看起来VCPU线程唯一的动力 qemu_kvm_cpu_thread_fn has 当 KVM 返回时,就是执行排队的函数:
wi->func(cpu, wi->data);
这意味着 PCIe 设备必须不断地将自身排队作为 qemu 执行的功能。我不明白它会如何运作。
能够在这个 CPU 上排队工作的函数有 run_on_cpu在它的名字上。通过在 VSCode 上搜索,我发现了一些排队工作但与 PCIe 甚至仿真无关的函数。我发现最好的功能是这个显然修补指令的功能: https://github.com/qemu/qemu/blob/stable-4.2/hw/i386/kvmvapic.c#L446 .不错,我也想知道。

最佳答案

KVM 下的设备仿真(所有设备,不仅仅是 PCI)由“case KVM_EXIT_IO”(对于 x86 风格的 IO 端口)和“case KVM_EXIT_MMIO”(对于包括 PCI 的内存映射 IO)在“开关(运行-> exit_reason)”在 kvm_cpu_exec() 中。 qemu_wait_io_event() 无关。
想知道执行如何“模拟在 PCI 设备上读取的寄存器”?在 gdb 下运行 QEMU,在您使用的以太网 PCI 卡的寄存器读/写功能上设置断点,然后当您进入调试器时查看堆栈回溯。 (编译 QEMU --enable-debug 以获得更好的调试信息。)
PS:如果您出于教育目的检查 QEMU 内部结构,最好使用当前代码,而不是它的一年前版本。

关于c - Qemu 如何模拟 PCIe 设备?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65246928/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com