当前位置: 首页 > news >正文

qemu/kvm学习笔记

qemu/kvm架构

cpu虚拟化的示例

Reference: kvmtest.c [LWN.net]

主要步骤:

  1. QEMU通过/dev/kvm设备文件发起KVM_CREATE_VM ioctl,请求KVM创建一个虚拟机。KVM创建虚拟机相应的结构体,并为QEMU返回一个虚拟机文件描述符
  2. QEMU通过虚拟机文件描述符发起KVM_CREATE_VCPU ioctl,请求KVM创建一个vCPU。KVM创建vCPU相应的结构体并初始化,返回一个vCPU文件描述符。
  3. QEMU通过vCPU文件描述符发起KVM_RUN ioctl,vCPU线程执行VMLAUNCH指令进入非根模式,执行虚拟机代码直至发生VM-Exit。
  4. KVM根据VM-Exit的原因进行相应处理,如果与IO有关,则需要进一步返回到QEMU中进行处理。

运行结果: 

代码实现:

/* Sample code for /dev/kvm API */#include <err.h>
#include <fcntl.h>
#include <linux/kvm.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>int main(void)
{int kvm, vmfd, vcpufd, ret;const uint8_t code[] = {/* 写入指定端口 0x3f8,输出 Hello */0xba, 0xf8, 0x03, /* mov $0x3f8, %dx */0x00, 0xd8,       /* add %bl, %al */0x04, '0',        /* add $'0', %al */0xee,             /* out %al, (%dx) */0xb0, '\n',       /* mov $'\n', %al */0xee,             /* out %al, (%dx) */0xb0, 'H',        /* mov $'H', %al */0xee,             /* out %al, (%dx) */0xb0, 'e',        /* mov $'e', %al */0xee,             /* out %al, (%dx) */0xb0, 'l',        /* mov $'l', %al */0xee,             /* out %al, (%dx) */0xb0, 'l',        /* mov $'l', %al */0xee,             /* out %al, (%dx) */0xb0, 'o',        /* mov $'o', %al */0xee,             /* out %al, (%dx) */0xb0, '\n',       /* mov $'\n', %al */0xee,             /* out %al, (%dx) */0xf4,             /* hlt */};uint8_t *mem;struct kvm_sregs sregs;size_t mmap_size;struct kvm_run *run;// ** step 1. 打开 KVM 模块设备文件kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);if (kvm == -1)err(1, "/dev/kvm");// 获取 KVM API 版本/* Make sure we have the stable version of the API */ret = ioctl(kvm, KVM_GET_API_VERSION, NULL);if (ret == -1)err(1, "KVM_GET_API_VERSION");if (ret != 12)errx(1, "KVM_GET_API_VERSION %d, expected 12", ret);// ** step 2. KVM_CREATE_VM 创建虚拟机获得虚拟机文件描述符vmfd = ioctl(kvm, KVM_CREATE_VM, (unsigned long)0);if (vmfd == -1)err(1, "KVM_CREATE_VM");// 分配 4KB 内存空间存放二进制代码// 这里的 0x1000(HVA)/* Allocate one aligned page of guest memory to hold the code. */mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);if (!mem)err(1, "allocating guest memory");// 将二进制代码复制至分配的内存页中memcpy(mem, code, sizeof(code));// KVM_SET_USER_MEMORY_REGION 将该内存页映射至虚拟机物理地址 0x1000(GPA) 处/* Map it to the second page frame (to avoid the real-mode IDT at 0). */struct kvm_userspace_memory_region region = {.slot = 0,.guest_phys_addr = 0x1000,.memory_size = 0x1000,.userspace_addr = (uint64_t)mem,};ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region);if (ret == -1)err(1, "KVM_SET_USER_MEMORY_REGION");// ** step 3. KVM_CREATE_VCPU 创建 vCPU 获得 vCPU 文件描述符vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0);if (vcpufd == -1)err(1, "KVM_CREATE_VCPU");// ** step 4. 获取 QEMU/KVM 共享内存空间大小,并映射 kvm_run 结构体/* Map the shared kvm_run structure and following data. */ret = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL);if (ret == -1)err(1, "KVM_GET_VCPU_MMAP_SIZE");mmap_size = ret;if (mmap_size < sizeof(*run))errx(1, "KVM_GET_VCPU_MMAP_SIZE unexpectedly small");// 使用 vCPU 文件描述符// 映射 kvm_run 结构体run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);if (!run)err(1, "mmap vcpu");// ** step 5. 设置 CS 寄存器和 RIP 寄存器,使得 vCPU 从 0x1000 处开始执行/* Initialize CS to point at 0, via a read-modify-write of sregs. */ret = ioctl(vcpufd, KVM_GET_SREGS, &sregs);if (ret == -1)err(1, "KVM_GET_SREGS");sregs.cs.base = 0;sregs.cs.selector = 0;ret = ioctl(vcpufd, KVM_SET_SREGS, &sregs);if (ret == -1)err(1, "KVM_SET_SREGS");/* Initialize registers: instruction pointer for our code, addends, and* initial flags required by x86 architecture. */struct kvm_regs regs = {.rip = 0x1000,.rax = 2,.rbx = 2,.rflags = 0x2,};ret = ioctl(vcpufd, KVM_SET_REGS, &regs);if (ret == -1)err(1, "KVM_SET_REGS");/* Repeatedly run code and handle VM exits. */while (1) {// ** step 6. KVM_RUN 运行 vCPUret = ioctl(vcpufd, KVM_RUN, NULL);if (ret == -1)err(1, "KVM_RUN");// ** step 7. 处理 VM-Exitswitch (run->exit_reason) {case KVM_EXIT_HLT: // hlt 指令触发 VM-Exitputs("KVM_EXIT_HLT");return 0; // 退出程序case KVM_EXIT_IO: // 依次调用 out 指令向 0x3f8 端口写入字符时,会触发 VM-Exit,使得程序返回到用户态处理// 输出写入 0x3f8 端口的字符if (run->io.direction == KVM_EXIT_IO_OUT && run->io.size == 1 && run->io.port == 0x3f8 && run->io.count == 1)// 调用 putchar 函数输出字符putchar(*(((char *)run) + run->io.data_offset));elseerrx(1, "unhandled KVM_EXIT_IO");break;case KVM_EXIT_FAIL_ENTRY:errx(1, "KVM_EXIT_FAIL_ENTRY: hardware_entry_failure_reason = 0x%llx",(unsigned long long)run->fail_entry.hardware_entry_failure_reason);case KVM_EXIT_INTERNAL_ERROR:errx(1, "KVM_EXIT_INTERNAL_ERROR: suberror = 0x%x", run->internal.suberror);default:errx(1, "exit_reason = 0x%x", run->exit_reason);}}
}

KVM API

/usr/include/linux/kvm.h 

ioctlKVM APIDescriptionExample

ioctls for /dev/kvm fds

KVM_GET_API_VERSION

获取 KVM API 版本

kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC)

ret = ioctl(kvm, KVM_GET_API_VERSION, NULL)

KVM_CREATE_VM

创建虚拟机获得虚拟机文件描述符

vmfd = ioctl(kvm, KVM_CREATE_VM, 0)

ioctls for VM fds

KVM_SET_USER_MEMORY_REGION

将内存页映射至虚拟机物理地址处

ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region)

KVM_CREATE_VCPU

创建 vCPU 获得 vCPU 文件描述符

vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0)

KVM_GET_VCPU_MMAP_SIZE

获取 QEMU/KVM 共享内存空间大小

mmap_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL);

使用 vCPU 文件描述符,映射 kvm_run 结构体

run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0)

ioctls for vcpu fds

KVM_GET_SREGS

获取 CS 寄存器和 RIP 寄存器

ret = ioctl(vcpufd, KVM_GET_SREGS, &sregs)

KVM_SET_SREGS

设置 CS 寄存器和 RIP 寄存器

sregs.cs.base = 0

sregs.cs.selector = 0

ret = ioctl(vcpufd, KVM_SET_SREGS, &sregs)

struct kvm_regs regs = {

.rip = 0x1000,

.rax = 2,

.rbx = 2,

.rflags = 0x2,

}

ret = ioctl(vcpufd, KVM_SET_REGS, &regs)

KVM_RUN

运行 vCPU

ret = ioctl(vcpufd, KVM_RUN, NULL)

相关文章:

qemu/kvm学习笔记

qemu/kvm架构 cpu虚拟化的示例 Reference: kvmtest.c [LWN.net] 主要步骤&#xff1a; QEMU通过/dev/kvm设备文件发起KVM_CREATE_VM ioctl&#xff0c;请求KVM创建一个虚拟机。KVM创建虚拟机相应的结构体&#xff0c;并为QEMU返回一个虚拟机文件描述符QEMU通过虚拟机文件描述…...

android 车载widget小部件部分详细源码实战开发-千里马车载车机framework开发实战课程

官网参考链接&#xff1a;https://developer.android.google.cn/develop/ui/views/appwidgets/overview 1、什么是小部件 App widgets are miniature application views that can be embedded in other applications (such as the home screen) and receive periodic updates…...

如何使用CSS画一个三角形

原理&#xff1a;其实就是规定元素的四个边框颜色及边框宽度&#xff0c;将元素宽高设置为0。如果要哪个方向的三角形&#xff0c;将对应其他三个方向的边框宽和颜色设置为0和透明transparent即可 1.元素设置边框&#xff0c;宽高&#xff0c;背景色 <style>.border {w…...

第15章_锁: (表级锁、页级锁、行锁、悲观锁、乐观锁、全局锁、死锁)

3.2 从数据操作的粒度划分&#xff1a;表级锁、页级锁、行锁 为了提高数据库并发度&#xff0c;每次锁定的数据范围越小越好&#xff0c;理论上每次只锁定当前操作的数据的方案会得到最大的并发度&#xff0c;但管理锁是很耗资源&#xff08;涉及获取、检查、释放锁等动作)。因…...

python音频转文字调用baidu

python音频转文字调用的是百度智能云的接口&#xff0c;因业务需求会涉及比较多数字&#xff0c;所以这里做了数字的处理&#xff0c;可根据自己的需求修改。 from flask import Flask, request, jsonify import requestsfrom flask_limiter import Limiterapp Flask(__name_…...

靶场溯源第二题

关卡描述&#xff1a;1. 网站后台登陆地址是多少&#xff1f;&#xff08;相对路径&#xff09; 首先这种确定的网站访问的都是http或者https协议&#xff0c;搜索http看看。关于http的就这两个信息&#xff0c;然后172.16.60.199出现最多&#xff0c;先过滤这个ip看看 这个很…...

mysql 的增删改查以及模糊查询、字符集语句的使用

一、mysql启动与登陆(windows下的mysql操作) 1.启动mysql服务 net start mysql81 2.登陆mysql mysql -uroot -p 3.查看所有数据库 show databases; 二、模糊查询&#xff08;like&#xff09; 1. _代表查询单个 2.%代表查询多个 3.查找所有含有schema的数据库&#xff1b;…...

Python Django框架中文教程:学习简单、灵活、高效的Web应用程序框架

概述: Python Django是一种流行的Web应用程序框架&#xff0c;被广泛应用于开发高效、可扩展的网站和Web应用程序。Django以其简单、灵活和高效而受到开发者们的青睐。它提供了强大的工具和功能&#xff0c;使开发过程更加容易和高效。 Django的主要目标是帮助开发者快速构建…...

Docker认识即安装

Docker及相关概念 Docker和虚拟机方式的区别&#xff1a;虚拟机技术是虚拟出一套硬件后&#xff0c;在其上运行一个完整的操作系统&#xff0c;在该系统上在运行所需应用进程&#xff1b;而容器内的应用进程是直接运行于宿主的内核&#xff0c;容器内没有自己的内核&#xff0…...

chrome 谷歌浏览器 导出插件拓展和导入插件拓展

给同事部署 微软 RPA时&#xff0c;需要用到对应的chrome浏览器插件&#xff1b;谷歌浏览器没有外网是不能直接下载拓展弄了半小时后才弄好&#xff0c;竟发现没有现成的教程&#xff0c;遂补充&#xff1b; 如何打包导出 谷歌浏览器 地址栏敲 chrome://extensions/在对应的地…...

fastjson漏洞批量检测工具

JsonExp 简介 版本&#xff1a;1.3.5 1. 根据现有payload&#xff0c;检测目标是否存在fastjson或jackson漏洞&#xff08;工具仅用于检测漏洞&#xff09;2. 若存在漏洞&#xff0c;可根据对应payload进行后渗透利用3. 若出现新的漏洞时&#xff0c;可将最新的payload新增至…...

Vue进阶(六十七)页面刷新路由传参丢失问题分析及解决

文章目录 一、前言二、问题排查三、延伸阅读3.1 Apache服务器access_log日志3.2 浏览器的常见User Agent 各字段的解释 一、前言 问题描述&#xff1a;Vue项目上线后&#xff0c;在IE浏览器上&#xff0c;从A页面跳转至B页面&#xff0c;B页面通过data中接收来自A页面的参数信…...

阿里云ubuntu服务器搭建ftp服务器

阿里云ubuntu服务器搭建ftp服务器 服务器环境安装步骤一.创建用户二.安装 vsftp三 配置vsftp四.配置阿里云安全组 服务器环境 阿里云上的云服务器&#xff0c;操作系统为 ubuntu20.04。 安装步骤 一.创建用户 为什么需要创建用户&#xff1f; 这里的用户&#xff0c;指的是…...

03 卷积操作图片

一、均值滤波 # 卷积操作 # 输入图片. input, 必须是4维tensor(图片数量, 图片高度, 图片的宽度, 图片的通道数) # filters, 卷积核, 必须是4维的tensor(卷积核的高度和宽度, 输入图片的通道数, 卷积核的个数) # strides, 步长, 卷积核在图片的各个维度上的移动步长, (1, 1, 1,…...

软考:中级软件设计师:程序语言基础:表达式,标准分类,法律法规,程序语言特点,函数传值传址

软考&#xff1a;中级软件设计师:程序语言基础&#xff1a;表达式 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都…...

Java“牵手”1688商品详情数据,1688商品详情API接口,1688API接口申请指南

1688平台商品详情接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取1688商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品详情接口API是一种用于获取电商平台上商品详情数据的接口&#xff0c;通过…...

stable diffusion实践操作-批次出图

系列文章目录 stable diffusion实践操作 文章目录 系列文章目录前言一、批次出图介绍1.1 webUI设置1.2 参数介绍 二、批次出图使用2.1 如何设置2.1 效果展示 总结 前言 本章主要介绍SD批次出图。 想要一次产生多张图片的时候使用。 一、批次出图介绍 1.1 webUI设置 1.2 参数…...

LeetCode热题100 【cpp】题解(一)哈希表和双指针

文章目录 1. 两数之和49. 字母异位词分组128. 最长连续序列283. 移动零11. 盛最多水的容器15. 三数之和42. 接雨水 题单链接&#xff1a; LeetCode 热题 100 1. 两数之和 leetcode题目链接 题解1&#xff1a;暴力枚举 时间复杂度&#xff1a; O ( n 2 ) O(n^2) O(n2) class …...

Python爬虫常见代理池实现和优化

在这篇文章中&#xff0c;我们将探讨Python爬虫中常见的代理池实现和优化方法。在爬取网站数据时&#xff0c;为防止被目标网站封禁IP&#xff0c;我们通常会使用代理IP进行访问。一个高效且稳定的代理池可以帮助我们轻松应对各种反爬策略。   首先&#xff0c;我们来了解一下…...

前端面试的话术集锦第 3 篇:进阶篇上

这是记录前端面试的话术集锦第三篇博文——进阶篇上,我会不断更新前端面试话术的博文。❗❗❗ 1 谈谈变量提升 当执⾏JS代码时,会⽣成执⾏环境,只要代码不是写在函数中的,就是在全局执⾏环境中,函数中的代码会产⽣函数执⾏环境,只此两种执⾏环境。 b() // call b conso…...

【AI绘画构图生死线】:为什么你的提示词再精准也出不了大片?——透视层级、视觉动线与负空间权重分配全拆解

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;AI绘画构图的底层认知革命 传统构图理论建立在人眼视觉经验与经典美学范式之上&#xff0c;而AI绘画的构图逻辑则根植于高维特征空间中的统计分布、注意力权重映射与跨模态对齐机制。当用户输入“晨雾中的孤松…...

全栈开发简历:避免 “样样通样样松”,突出核心技术栈

一、开篇暴击:你的全栈简历,可能正在被HR当“笑话”看 “熟练掌握HTML、CSS、JavaScript、Python、Java、PHP、MySQL、MongoDB、AWS、Docker、K8s……” 当你在简历上敲下这串“技术彩虹屁”时,是不是觉得自己就是传说中“一人顶一个团队”的全栈大神?醒醒!某互联网公司…...

泛微发布300+可落地AI应用 让组织业务数智升级

5月20日&#xff0c;泛微300AI应用场景体验大会在上海举办。大会以“组织的AI范式数字员工与业务流程AI新生”为主题&#xff0c; 展示泛微全场景AI应用。泛微搭载五大智能引擎&#xff0c;提供300可快速落地的AI应用场景&#xff0c;覆盖市场、销售、项目、合同、采购、财务、…...

汽车零部件三维扫描检测:精密制造新标杆,全链路质量管控升级

当下&#xff0c;汽车产业正加速向轻量化、电动化、集成化转型&#xff0c;零部件作为整车质量的核心基石&#xff0c;其制造精度与检测标准持续攀升。主机厂对零部件的形位公差、曲面轮廓度、装配匹配度要求日趋严苛&#xff0c;尤其在新能源汽车领域&#xff0c;薄壁件、复杂…...

创业团队如何利用Taotoken统一技术栈并降低AI接入门槛

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 创业团队如何利用Taotoken统一技术栈并降低AI接入门槛 对于资源有限的创业团队而言&#xff0c;在产品中集成人工智能能力是提升竞…...

HS2-HF Patch:如何用5分钟为HoneySelect2实现完整汉化与MOD整合

HS2-HF Patch&#xff1a;如何用5分钟为HoneySelect2实现完整汉化与MOD整合 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch HS2-HF Patch是HoneySelect2玩家的终…...

PaddleOCR训练集制作避坑指南:从text_renderer合成到roLabelImg标注的全链路解析

PaddleOCR训练集制作全流程实战&#xff1a;从数据合成到模型调优的完整方法论 在工业级OCR项目落地过程中&#xff0c;数据集质量往往比模型架构更能决定最终效果上限。不同于学术界的标准benchmark竞赛&#xff0c;真实业务场景面临字体缺失、背景干扰、版式多变等复杂挑战。…...

Windows 11系统优化终极指南:用Win11Debloat免费让你的电脑飞起来

Windows 11系统优化终极指南&#xff1a;用Win11Debloat免费让你的电脑飞起来 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declu…...

【开源软件移植】鸿蒙 PC 三方库适配实战:从 7-Zip Native 编译到 ArkTS 调用完整跑通

【开源软件移植】鸿蒙 PC 三方库适配实战&#xff1a;从 7-Zip Native 编译到 ArkTS 调用完整跑通 一、写在前面 欢迎加入开源鸿蒙PC社区&#xff1a;https://harmonypc.csdn.net/ 这篇文章记录的是把 7-Zip 的 .7z 压缩、校验、解压能力适配成 HarmonyOS / OpenHarmony PC …...

5步快速上手ComfyUI JoyCaption插件:AI图片字幕生成的终极指南

5步快速上手ComfyUI JoyCaption插件&#xff1a;AI图片字幕生成的终极指南 【免费下载链接】ComfyUI_SLK_joy_caption_two ComfyUI Node 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI_SLK_joy_caption_two 你知道吗&#xff1f;现在你可以用AI为任何图片自动生…...