【QEMU系统分析之启动篇(二十一)】

系列文章目录

第二十一章 QEMU系统仿真的加速器上电后设置分析


文章目录

  • 系列文章目录
    • 第二十一章 QEMU系统仿真的加速器上电后设置分析
  • 前言
  • 一、QEMU是什么?
  • 二、QEMU系统仿真的启动分析
    • 1.系统仿真的初始化代码
    • 2.主循环
    • 3. qemu_default_main()
    • 4. qemu_main_loop()
      • main_loop_should_exit()
        • qemu_debug_requested()
        • vm_stop()
          • qemu_in_vcpu_thread()
          • qemu_system_vmstop_request_prepare()
          • qemu_system_vmstop_request()
          • cpu_stop_current()
          • qemu_suspend_requested()
        • qemu_system_suspend()
        • qemu_shutdown_requested()
        • qemu_kill_report()
        • qemu_system_shutdown(request)
        • qemu_reset_requested()
        • pause_all_vcpus()
        • qemu_system_reset(request)
        • resume_all_vcpus()
        • runstate_check()
        • runstate_set()
        • qemu_wakeup_requested()
        • notifier_list_notify()
        • qapi_event_send_wakeup()
        • qemu_powerdown_requested()
        • qemu_system_powerdown()
        • qemu_vmstop_requested()
      • main_loop_wait()
        • qemu_soonest_timeout()
        • timerlistgroup_deadline_ns()
        • os_host_main_loop_wait()
        • icount_enabled()
        • icount_start_warp_timer()
        • qemu_clock_run_all_timers()
  • 总结


前言

本文以 QEMU 8.2.2 为例,分析其作为系统仿真工具的启动过程,并为读者展示各种 QEMU 系统仿真的启动配置实例。
本文读者需要具备一定的 QEMU 系统仿真使用经验,并对 C 语言编程有一定了解。


一、QEMU是什么?

QEMU 是一个通用且开源的机器模拟器和虚拟机。
其官方主页是:https://www.qemu.org/


二、QEMU系统仿真的启动分析

1.系统仿真的初始化代码

QEMU 作为系统仿真工具,其入口代码在 system/main.c 文件中,初始化函数 qemu_init() 的实现在 system/vl.c 文件中,在完成 QEMU 虚拟机初始设置后,接下来将进入主循环,本篇文章将完成以下代码部分的分析。

2.主循环

这部分代码在 system/vl.c 文件中,实现如下:

int (*qemu_main)(void) = qemu_default_main;

int main(int argc, char **argv)
{
    qemu_init(argc, argv);
    return qemu_main();
}

3. qemu_default_main()

函数 qemu_default_main() 在 /system/vl.c 文件中,定义如下:

int qemu_default_main(void)
{
    int status;

    status = qemu_main_loop();
    qemu_cleanup(status);

    return status;
}


4. qemu_main_loop()

函数 qemu_main_loop() 在 /system/runstate.c 文件中,定义如下:

int qemu_main_loop(void)
{
    int status = EXIT_SUCCESS;

    while (!main_loop_should_exit(&status)) {
        main_loop_wait(false);
    }

    return status;
}


main_loop_should_exit()

函数 main_loop_should_exit() 在 /system/runstate.c 文件中,定义如下:

static bool main_loop_should_exit(int *status)
{
    RunState r;
    ShutdownCause request;

    if (qemu_debug_requested()) {
        vm_stop(RUN_STATE_DEBUG);
    }
    if (qemu_suspend_requested()) {
        qemu_system_suspend();
    }
    request = qemu_shutdown_requested();
    if (request) {
        qemu_kill_report();
        qemu_system_shutdown(request);
        if (shutdown_action == SHUTDOWN_ACTION_PAUSE) {
            vm_stop(RUN_STATE_SHUTDOWN);
        } else {
            if (shutdown_exit_code != EXIT_SUCCESS) {
                *status = shutdown_exit_code;
            } else if (request == SHUTDOWN_CAUSE_GUEST_PANIC &&
                panic_action == PANIC_ACTION_EXIT_FAILURE) {
                *status = EXIT_FAILURE;
            }
            return true;
        }
    }
    request = qemu_reset_requested();
    if (request) {
        pause_all_vcpus();
        qemu_system_reset(request);
        resume_all_vcpus();
        /*
         * runstate can change in pause_all_vcpus()
         * as iothread mutex is unlocked
         */
        if (!runstate_check(RUN_STATE_RUNNING) &&
                !runstate_check(RUN_STATE_INMIGRATE) &&
                !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
            runstate_set(RUN_STATE_PRELAUNCH);
        }
    }
    if (qemu_wakeup_requested()) {
        pause_all_vcpus();
        qemu_system_wakeup();
        notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
        wakeup_reason = QEMU_WAKEUP_REASON_NONE;
        resume_all_vcpus();
        qapi_event_send_wakeup();
    }
    if (qemu_powerdown_requested()) {
        qemu_system_powerdown();
    }
    if (qemu_vmstop_requested(&r)) {
        vm_stop(r);
    }
    return false;
}
qemu_debug_requested()

函数 qemu_debug_requested() 在 /system/runstate.c 文件中,定义如下:

static int qemu_debug_requested(void)
{
    int r = debug_requested;
    debug_requested = 0;
    return r;
}
vm_stop()

函数 vm_stop() 在 /system/cpus.c 文件中,定义如下:

int vm_stop(RunState state)
{
    if (qemu_in_vcpu_thread()) {
        qemu_system_vmstop_request_prepare();
        qemu_system_vmstop_request(state);
        /*
         * FIXME: should not return to device code in case
         * vm_stop() has been requested.
         */
        cpu_stop_current();
        return 0;
    }

    return do_vm_stop(state, true);
}
qemu_in_vcpu_thread()

函数 qemu_in_vcpu_thread() 在 /system/cpus.c 文件中,定义如下:

bool qemu_in_vcpu_thread(void)
{
    return current_cpu && qemu_cpu_is_self(current_cpu);
}
qemu_system_vmstop_request_prepare()

函数 qemu_system_vmstop_request_prepare() 在 /system/runstate.c 文件中,定义如下:

void qemu_system_vmstop_request_prepare(void)
{
    qemu_mutex_lock(&vmstop_lock);
}

qemu_system_vmstop_request()

函数 qemu_system_vmstop_request() 在 /system/runstate.c 文件中,定义如下:

void qemu_system_vmstop_request(RunState state)
{
    vmstop_requested = state;
    qemu_mutex_unlock(&vmstop_lock);
    qemu_notify_event();
}
cpu_stop_current()

函数 cpu_stop_current() 在 /system/cpus.c 文件中,定义如下:

void cpu_stop_current(void)
{
    if (current_cpu) {
        current_cpu->stop = true;
        cpu_exit(current_cpu);
    }
}

函数 cpu_exit() 在 /hw/core/cpu-common.c 文件中,定义如下:

void cpu_exit(CPUState *cpu)
{
    qatomic_set(&cpu->exit_request, 1);
    /* Ensure cpu_exec will see the exit request after TCG has exited.  */
    smp_wmb();
    qatomic_set(&cpu->neg.icount_decr.u16.high, -1);
}
qemu_suspend_requested()
qemu_system_suspend()
qemu_shutdown_requested()
qemu_kill_report()
qemu_system_shutdown(request)
qemu_reset_requested()
pause_all_vcpus()
qemu_system_reset(request)
resume_all_vcpus()
runstate_check()
runstate_set()
qemu_wakeup_requested()
notifier_list_notify()
qapi_event_send_wakeup()
qemu_powerdown_requested()
qemu_system_powerdown()
qemu_vmstop_requested()

main_loop_wait()

函数 qemu_default_main() 在 /util/main-loop.c 文件中,定义如下:

void main_loop_wait(int nonblocking)
{
    MainLoopPoll mlpoll = {
        .state = MAIN_LOOP_POLL_FILL,
        .timeout = UINT32_MAX,
        .pollfds = gpollfds,
    };
    int ret;
    int64_t timeout_ns;

    if (nonblocking) {
        mlpoll.timeout = 0;
    }

    /* poll any events */
    g_array_set_size(gpollfds, 0); /* reset for new iteration */
    /* XXX: separate device handlers from system ones */
    notifier_list_notify(&main_loop_poll_notifiers, &mlpoll);

    if (mlpoll.timeout == UINT32_MAX) {
        timeout_ns = -1;
    } else {
        timeout_ns = (uint64_t)mlpoll.timeout * (int64_t)(SCALE_MS);
    }

    timeout_ns = qemu_soonest_timeout(timeout_ns,
                                      timerlistgroup_deadline_ns(
                                          &main_loop_tlg));

    ret = os_host_main_loop_wait(timeout_ns);
    mlpoll.state = ret < 0 ? MAIN_LOOP_POLL_ERR : MAIN_LOOP_POLL_OK;
    notifier_list_notify(&main_loop_poll_notifiers, &mlpoll);

    if (icount_enabled()) {
        /*
         * CPU thread can infinitely wait for event after
         * missing the warp
         */
        icount_start_warp_timer();
    }
    qemu_clock_run_all_timers();
}
qemu_soonest_timeout()
timerlistgroup_deadline_ns()
os_host_main_loop_wait()
icount_enabled()
icount_start_warp_timer()
qemu_clock_run_all_timers()

总结

以上分析了 QEMU 系统仿真在启动过程中,QEMU系统仿真通知字符设备后端驱动开始工作的代码部分。

在完成此动作后,QEMU 程序回到主循环,并开始等待轮询的事件处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/579262.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux多线程(三) 线程池C++实现

一、线程池原理 我们使用线程的时候就去创建一个线程&#xff0c;这样实现起来非常简便。但如果并发的线程数量很多&#xff0c;并且每个线程都是执行一个时间很短的任务就结束了&#xff0c;这样频繁创建线程就会大大降低系统的效率&#xff0c;因为频繁创建线程和销毁线程需…

华为MRS服务使用记录

背景&#xff1a;公司的业务需求是使用华为的这一套成品来进行开发&#xff0c;使用中发现&#xff0c;这个产品跟原生的Hadoop的那一套的使用&#xff0c;还是有很大的区别的&#xff0c;现记录一下&#xff0c;避免以后忘了 一、原始代码的下载 下载地址&#xff1a;MRS样例…

STM32HAL库++ESP8266+cJSON连接阿里云物联网平台

实验使用资源&#xff1a;正点原子F1 USART1&#xff1a;PA9P、A10&#xff08;串口打印调试&#xff09; USART3&#xff1a;PB10、PB11&#xff08;WiFi模块&#xff09; DHT11&#xff1a;PG11&#xff08;采集数据、上报&#xff09; LED0、1&#xff1a;PB5、PE5&#xff…

input框添加验证(如只允许输入数字)中文输入导致显示问题的解决方案

文章目录 input框添加验证(如只允许输入数字)中文输入导致显示问题的解决方案问题描述解决办法 onCompositionStart与onCompositionEnd input框添加验证(如只允许输入数字)中文输入导致显示问题的解决方案 问题描述 测试环境&#xff1a;react antd input (react的事件与原生…

浅谈在Java代码中创建线程的多种方式

文章目录 一、Thread 类1.1 跨平台性 二、Thread 类里的常用方法三、创建线程的方法1、自定义一个类&#xff0c;继承Thread类&#xff0c;重写run方法1.1、调用 start() 方法与调用 run() 方法来创建线程&#xff0c;有什么区别&#xff1f;1.2、sleep()方法 2、自定义一个类&…

嵌入式常见存储器

阅读引言&#xff1a; 在看一款芯片的数据手册的时候&#xff0c; 无意间翻到了它的启动模式(Boot Mode), 发现这种这么多种ROM&#xff0c;所以就写下了这篇文章。 目录 一、存储器汇总 二、易失性存储器(RAM) 1. SRAM 1.1 单口SRAM 1.2 双口SRAM 2. DRAM 2.1 SDRAM 2…

Fast-DetectGPT 无需训练的快速文本检测

本文提出了一种新的文本检测方法 ——Fast-DetectGPT&#xff0c;无需训练&#xff0c;直接使用开源小语言模型检测各种大语言模型&#xff0c;如GPT等生成的文本内容。 Fast-DetectGPT 将检测速度提高了 340 倍&#xff0c;将检测准确率相对提升了 75%&#xff0c;超过商用系…

有哪些好用电脑端时间定时软件?桌面日程安排软件推荐 桌面备忘录

随着现代生活节奏的加快&#xff0c;人们对于时间管理和任务提醒的需求越来越大。为了满足这一需求&#xff0c;市场上涌现出了众多桌面便签备忘录软件&#xff0c;它们不仅可以帮助我们记录待办事项&#xff0c;还能定时提醒我们完成任务。在这篇文章中&#xff0c;我将为大家…

计算机研究生如何在顶级会议了解行业方向

以为例子论文可视化 |WACV 2022 年 (thecvf.com)https://wacv2022.thecvf.com/papers-visualizations?filterprimary_subject_area&search3DComputerVision 这些图表适用于IEEE/CVF 计算机视觉冬季会议 (WACV) 2022。顶部图表是根据彼此相似性分布的会议主要会议论文的可…

微电子领域材料生长方法(六)液相外延(LPE)

微电子领域材料生长方法&#xff08;六&#xff09;液相外延&#xff08;LPE&#xff09; 液相外延&#xff08;Liquid Phase Epitaxy, LPE&#xff09;是一种用于生长单晶薄膜的技术&#xff0c;特别是在半导体材料的制备中。LPE技术允许在较低的温度下从熔体中生长出高质量的…

Visual 下载 NuGet包速度变慢

Visual 下载 NuGet包速度变慢 最近遇到一个问题&#xff0c;即我在使用 Visual Studio 下载 Nuget 包的时候会发现变得特别慢&#xff0c;那么该如何解决该问题呢 Visual Studio → 工具 → NuGet 包管理项 → 程序包管理设置 → 程序包源 从上面我们可以看到我使用的包源地址…

2024 最新免费听全网音乐神器

之前分享过几个的音乐软件挂了2024最新神器app&#xff0c;全网音乐免费听 &#xff0c;这里再整理分享下&#xff0c;下载地址 https://pan.quark.cn/s/b52ada313fbd 玩转互联网达人 苏生不惑备用号&#xff0c;分享各种黑科技软件资源和技巧&#xff0c;带你玩转互联网。 …

12.JAVAEE之网络原理2

1.网络层 网络层要做的事情,主要是两方面, 1)地址管理,制定一系列的规则,通过地址,描述出网络上一个设备的位置. 2)路由选择.网络环境比较复杂的,从一个节点到另一个节点之间,存在很多条不同的路径,就需要通过这种方式,筛选/规划出更合适的路径进行数据传输 IP协议 8位协议&…

HackMyVM-Convert

目录 信息收集 arp nmap WEB web信息收集 gobuster RCE漏洞 反弹shell 提权 get user.txt 提权 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 08:00:27:77:ed:84, IPv4: 192.168.9.126 Starting…

律师口才训练技巧课程介绍?

律师口才训练技巧课程介绍 一、课程背景与目标 律师口才作为法律职业的核心能力之一&#xff0c;对于律师在**辩论、法律咨询、谈判协商等场合的表现具有至关重要的作用。然而&#xff0c;许多律师在口才方面存在不足&#xff0c;难以充分发挥自己的专业能力。因此&#xff0c;…

CTF之eval

首先我们先了解一下eval&#xff08;&#xff09;函数 什么是eval()? eval() 函数把字符串按照 PHP 代码来计算。 该字符串必须是合法的 PHP 代码&#xff0c;且必须以分号结尾。 如果没有在代码字符串中调用 return 语句&#xff0c;则返回 NULL。如果代码中存在解析错误…

数据结构——二叉树的顺序存储(堆)(C++实现)

数据结构——二叉树的顺序存储&#xff08;堆&#xff09;&#xff08;C实现&#xff09; 二叉树可以顺序存储的前提堆的定义堆的分类大根堆小根堆 整体结构把握两种调整算法向上调整算法递归版本 非递归版本向下调整算法非递归版本 向上调整算法和向下调整算法的比较 我们接着…

【Linux系统化学习】生产者消费者模型(阻塞队列和环形队列)

目录 生产者消费者模型 什么是生产者消费者模型 为什么要使用生产者消费者模型 生产者消费者模型的优点 为什么生产者和生产者要互斥&#xff1f; 为什么消费者和消费者要互斥&#xff1f; 为什么生产者和消费者既是互斥又是同步&#xff1f; 基于BlockingQueue的生产者…

将数组中最大的数放在最后一位,最小的数放在第一位

#include <stdio.h> int main() {void input(int number[]);void output(int number[]);void swapmaxmin(int number[]);int number[10];input(number);//swapmaxmin(number);output(number);return 0; }//往一个数组里输入 void input(int number[]) {int i;for(i0;i<…

Bert类模型也具备指令遵循能力吗?

深度学习自然语言处理 原创作者&#xff1a;Winnie BERT模型&#xff0c;依托Transformer架构及其大规模预训练&#xff0c;为自然语言处理领域带来了深远的影响。BERT模型架构包含多层双向Transformer编码器&#xff0c;通过这种结构&#xff0c;BERT及其家族成员&#xff0c;…
最新文章