qemu添加hmp和qmp接口_qemu qmp-程序员宅基地

技术标签: i6300esb  qmp  虚拟化  qemu  hmp  qemu入门讲解  


本文是一个简单的demo,基于开源qemu2.8,演示了如何添加qmp和hmp接口,同时实现从hmp命令打通到底层外设函数的通道,此处为i6300esb 1的测试函数。注意:此处的调用路径仅供演示,实际上并不合理,会出现一些告警,而在实际云平台编译环境中,rpmbuild编译链接,是不允许的warning存在的,若想添加接口,还是应该参考已有的接口走回调函数的方式,或者使用object property方式注册处理函数。

1.添加qmp接口

1.1.添加接口原型

在qapi-schema.json末尾添加接口原型daxiatou-watchdog-set-timeout


{
     'command': 'daxiatou-watchdog-set-timeout' ,'data':{
    '*time':'int'}}

int对应的int64_t,正常应该是在这一步先执行编译,再进行下一步,此处节省篇幅,一步搞定,详细用法,查阅qemu官方文档《writing-qmp-commands.txt》

1.2.添加接口函数体


/*qmp.c*/

void qmp_daxiatou_watchdog_set_timeout(bool has_time, int64_t time, Error **errp)

{
    

    if (has_time)

        {
    

        printf("%ld\n", time);

     }

    else

        {
     printf("Please input time\n"); }

}

1.3.测试接口

1.3.1.启动虚拟机

qemu启动脚本需要增加以下参数


-chardev socket,id=qmp,port=4444,host=localhost,server  -mon chardev=qmp,mode=control,pretty=on

这样,qemu monitor就可以接受qmp协议报文,随后另起一个shell,使用如下命令连接qemu monitor


[root@localhost qemu-2.8.0]# telnet localhost 4444

Trying ::1...

Connected to localhost.

Escape character is '^]'.

{
    

    "QMP": {
    

        "version": {
    

            "qemu": {
    

                "micro": 0,

                "minor": 8,

                "major": 2

            },

            "package": ""

        },

        "capabilities": [

        ]

    }

}

1.3.2.执行测试命令

打开command mode


{ "execute": "qmp_capabilities" }

执行带参数命令


{ "execute": "daxiatou-watchdog-set-timeout", "arguments": { "time": 1000 } }

查看qemu端的效果


(qemu) 1000

执行不带参数的命令


{ "execute": "daxiatou-watchdog-set-timeout"}

查看qemu端的效果


(qemu) Please input time

1.3.3.查看编译后自动生成的代码


[root@localhost qemu-2.8.0]# grep -rn 'daxiatou'

qapi-types.h:1936:typedef struct q_obj_daxiatou_watchdog_set_timeout_arg q_obj_daxiatou_watchdog_set_timeout_arg;

qapi-types.h:5596:struct q_obj_daxiatou_watchdog_set_timeout_arg {
    

qapi-visit.c:15673:void visit_type_q_obj_daxiatou_watchdog_set_timeout_arg_members(Visitor *v, q_obj_daxiatou_watchdog_set_timeout_arg *obj, Error **errp)

qapi-visit.h:986:void visit_type_q_obj_daxiatou_watchdog_set_timeout_arg_members(Visitor *v, q_obj_daxiatou_watchdog_set_timeout_arg *obj, Error **errp);

Binary file qmp.o matches

qmp-commands.h:97:void qmp_daxiatou_watchdog_set_timeout(bool has_time, int64_t time, Error **errp);

qmp-commands.h:98:void qmp_marshal_daxiatou_watchdog_set_timeout(QDict *args, QObject **ret, Error **errp);

qmp.c:719:void qmp_daxiatou_watchdog_set_timeout(bool has_time, int64_t time, Error **errp)

Binary file qemu-nbd matches

qmp-introspect.c:91:    "{
    \"arg-type\": \"67\", \"meta-type\": \"command\", \"name\": \"daxiatou-watchdog-set-timeout\", \"ret-type\": \"17\"}, "

Binary file x86_64-softmmu/qemu-system-x86_64 matches

qmp-marshal.c:1286:void qmp_marshal_daxiatou_watchdog_set_timeout(QDict *args, QObject **ret, Error **errp)

qmp-marshal.c:1290:    q_obj_daxiatou_watchdog_set_timeout_arg arg = {
    0};

qmp-marshal.c:1297:    visit_type_q_obj_daxiatou_watchdog_set_timeout_arg_members(v, &arg, &err);

qmp-marshal.c:1306:    qmp_daxiatou_watchdog_set_timeout(arg.has_time, arg.time, &err);

qmp-marshal.c:1313:    visit_type_q_obj_daxiatou_watchdog_set_timeout_arg_members(v, &arg, NULL);

qmp-marshal.c:6147:    qmp_register_command("daxiatou-watchdog-set-timeout", qmp_marshal_daxiatou_watchdog_set_timeout, QCO_NO_OPTIONS);

Binary file qapi-visit.o matches

Binary file qemu-io matches

Binary file qmp-introspect.o matches

Binary file qemu-img matches

Binary file qmp-marshal.o matches

qapi-schema.json:4779:{
     'command': 'daxiatou-watchdog-set-timeout' ,'data':{
    '*time':'int'}}

Binary file i386-softmmu/qemu-system-i386 matches

Binary file libqemuutil.a matches

Binary file qemu-ga matches



会生成很多东西,绝大多数不用理会,主要看这两个地方,


/* qmp-marshal.c*/

void qmp_marshal_daxiatou_watchdog_set_timeout(QDict *args, QObject **ret, Error **errp)

{
    

    Error *err = NULL;

    Visitor *v;

    q_obj_daxiatou_watchdog_set_timeout_arg arg = {
    0};



    v = qobject_input_visitor_new(QOBJECT(args), true);

    visit_start_struct(v, NULL, NULL, 0, &err);

    if (err) {
    

        goto out;

    }

    visit_type_q_obj_daxiatou_watchdog_set_timeout_arg_members(v, &arg, &err);

    if (!err) {
    

        visit_check_struct(v, &err);

    }

    visit_end_struct(v, NULL);

    if (err) {
    

        goto out;

    }



    qmp_daxiatou_watchdog_set_timeout(arg.has_time, arg.time, &err);



out:

    error_propagate(errp, err);

    visit_free(v);

    v = qapi_dealloc_visitor_new();

    visit_start_struct(v, NULL, NULL, 0, NULL);

    visit_type_q_obj_daxiatou_watchdog_set_timeout_arg_members(v, &arg, NULL);

    visit_end_struct(v, NULL);

    visit_free(v);

}



qmp_register_command("daxiatou-watchdog-set-timeout", qmp_marshal_daxiatou_watchdog_set_timeout, QCO_NO_OPTIONS);



qmp_register_command会注册一个qmp命令行"daxiatou-watchdog-set-timeout",上一节中使用到的命令,就是这里注册的,相关联的函数qmp_marshal_daxiatou_watchdog_set_timeout,会调用1.2节里面添加的自定义函数qmp_daxiatou_watchdog_set_timeout,这种设计方式,可以让’qmp_'开头的函数在另外的文件内单独定义函数体,而不影响框架自动生成的代码。

2.添加hmp命令

HMP就是humanmonitor,在qemu monitor敲的命令就属于这一类,这是面向用户直接使用的命令

2.1.添加命令行


/*hmp-commands.hx */

{

        .name       = "daxiatou-watchdog-set-timeout",

        .args_type  = "time:i?",

        .params     = "daxiatou2 [time]",

        .help       = "set timeout of i6300esb",

        .cmd        = hmp_daxiatou_watchdog_set_timeout,

    },



STEXI

@item daxiatou-watchdog-set-timeout @var{message}

Print message to the standard output

ETEXI



第一个参数.name代表命令本身的名字

第三个参数.params的作用是显示使用方式,如下所示


(qemu) help daxiatou-watchdog-set-timeout

daxiatou-watchdog-set-timeout daxiatou2 [time] -- set timeout of i6300esb

2.2.添加调用函数

添加函数声明


/*hmp.h*/

void hmp_daxiatou_watchdog_set_timeout(Monitor *mon, const QDict *qdict);

添加函数体


/*hmp.c*/

void hmp_daxiatou_watchdog_set_timeout(Monitor *mon, const QDict *qdict)

{
    

    int time = qdict_get_try_int(qdict, "time",30);

    Error *err = NULL;



    qmp_daxiatou_watchdog_set_timeout(!!time, time, &err);

    if (err) {
    

        monitor_printf(mon, "%s\n", error_get_pretty(err));

        error_free(err);

        return;

    }

}

查看运行效果


(qemu) daxiatou-watchdog-set-timeout 100

100

(qemu) daxiatou-watchdog-set-timeout

30

3.增加外设接口

此处希望通过命令行,能直接操作i6300esb的相关变量,首先,需要让命令行的函数感知到设备的存在

3.1.在设备代码文件中增加测试函数


/*code 3-1*/

/*hw/watchdog/wdt_i6300esb.c*/

static void i6300esb_test(void)

{
    

   i6300esb_debug("daxiatou-i6300esb\n");

}

在命令行中直接增加以上函数i6300esb_test()的调用


/*code 3-2 qmp.c*/

void qmp_daxiatou_watchdog_set_timeout(bool has_time, int64_t time, Error **errp)

{
    

    if (has_time)

        {
    

        printf("%ld\n", time);

        i6300esb_test();

     }

    else

        {
     printf("Please input time\n"); }

}

编译失败


[root@localhost qemu-2.8.0]# make -j4

    CHK version_gen.h

  CC      hw/watchdog/wdt_i6300esb.o

hw/watchdog/wdt_i6300esb.c:467:13: warning: ‘i6300esb_test’ defined but not used [-Wunused-function]

static void i6300esb_test(void)

             ^

  LINK    i386-softmmu/qemu-system-i386

  LINK    x86_64-softmmu/qemu-system-x86_64

../qmp.o: In function `qmp_daxiatou_watchdog_set_timeout':

/home/qemu-2.8.0/qmp.c:741: undefined reference to `i6300esb_test'

collect2: error: ld returned 1 exit status

make[1]: *** [qemu-system-i386] Error 1

make: *** [subdir-i386-softmmu] Error 2

make: *** Waiting for unfinished jobs....

../qmp.o: In function `qmp_daxiatou_watchdog_set_timeout':

/home/qemu-2.8.0/qmp.c:741: undefined reference to `i6300esb_test'

collect2: error: ld returned 1 exit status

make[1]: *** [qemu-system-x86_64] Error 1

make: *** [subdir-x86_64-softmmu] Error 2

说明,这两个c文件无法直接感知对方的存在,中间走了很多层,现在需要借助qemu自带的接口,一级级寻找能够操作到设备的路线


//qmp.c

void qmp_daxiatou_watchdog_set_timeout(bool has_time, int64_t time, Error **errp)

{
    

    const char *id = "watchdog0";

    Error *err = NULL;



    qmp_device_del(id, &err);

    if (has_time)

        {
    

        printf("%ld\n", time);

        //i6300esb_test();



     }

    else

        {
     printf("Please input time\n"); }

}

可以成功调用删除函数,,但是qmp_device_del内部的语句,无法被识别,因此,只能模仿qmp_device_del函数,移动到qdev-monitor.c中定义,顺着这条路往下跟

3.2.在qdev中调用pci函数


//qdev-monitor.c

void qmp_daxiatou_watchdog_set_timeout(bool has_time, int64_t time, Error **errp)

{
    

    const char *id = "watchdog0";

    Error *err = NULL;

    DeviceState *dev = find_device_state(id, errp);

    PCIDevice *pci_dev = (PCIDevice *)dev;

//PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);

    qdev_daxiatou_watchdog_set_timeout(dev,errp);

//    qmp_device_del(id, &err);

    if (has_time)

        {
    

        printf("%ld\n", time);

        //i6300esb_test();



     }

    else

        {
     printf("Please input time\n"); }

}




//include/hw/qdev-core.h

void qdev_daxiatou_watchdog_set_timeout(DeviceState *dev, Error **errp);


//hw/core/qdev.c

void qdev_daxiatou_watchdog_set_timeout(DeviceState *dev, Error **errp)

{
    

   PCIDevice *pci_dev = (PCIDevice *)dev;

   DeviceClass *dc = DEVICE_GET_CLASS(dev);

   printf("daxiatou = %p\n",dc);

   pci_daxiatou();

}


//include/hw/pci/pci.h

void pci_daxiatou( );


//hw/pci/pci.c

void pci_daxiatou( )

{
    

   printf("daxiatou-pci-test\n");

}

说明在以上代码块中定义函数,qdev可以调用,下一步就是要在pci的函数里面,调用到具体设备的函数了,此处是i6300esb,测试效果如下,


(qemu) daxiatou-watchdog-set-timeout

daxiatou = 0x558e01bdb090

daxiatou-pci-test

30

3.3.在pci中调用设备函数

和3.2节中的方式一样,直接调用i6300esb_test函数


//hw/pci/pci.c

//extern void i6300esb_test(void);如果不添加这个,会告警

void pci_daxiatou()

{
    

   printf("daxiatou-pci-test\n");

   i6300esb_test();

}

编译会产生告警,这是因为没有在头文件中声明,此处没有同名的头文件,先暂时忽略告警,强行安装运行


[root@localhost qemu-2.8.0]# make -j4

    CHK version_gen.h

  CC      hw/watchdog/wdt_i6300esb.o

hw/watchdog/wdt_i6300esb.c:467:6: warning: no previous prototype for ‘i6300esb_test’ [-Wmissing-prototypes]

void i6300esb_test(void)

      ^

  LINK    x86_64-softmmu/qemu-system-x86_64

  LINK    i386-softmmu/qemu-system-i386



成功调用到设备源代码中的函数


(qemu) daxiatou-watchdog-set-timeout

daxiatou = 0x55b4dff00090

daxiatou-pci-test

i6300esb: i6300esb_test: daxiatou-i6300esb

30

reference


  1. qemu intel i6300esb watchdog虚拟外设分析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/daxiatou/article/details/100152212

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签