利用qemu触发short设备/dev/shortint中断的方法

记得2007年的时候,第一次开始学习ldd3这本书,到书的后面需要设计到真实硬件才可以验证学习的内容,当时废了好大的力气。为了验证书里面并口的内容,专门买了电脑、LED灯、电焊、锡、面包板什么的,然后把LED灯焊接在并口的9号和10号引脚并接到面包板上,通过拉高电平触发并口中断,看输出也要看LED灯的闪烁,费死劲了。这几天叫我弟驱动变成,突然想到用虚拟化设备来触发中断,让他验证short设备,于是就改了一下qemu,来从hypervisor里主动触发中断,这样妈妈再也不用担心我的电烙铁烫到我了。这样就大大降低了学习linux驱动的门槛,让我们这些软件程序猿再也不用苦恼于没有硬件设备,无法入门了。话不多说,这里来记录一下我的代码修改和实验方法,供新入行的小朋友参考,尽快入手驱动的编写。

我用的qemu版本是:v3.0.0-rc4

利用qemu触发short设备/dev/shortint中断的方法_第1张图片

首先我们知道LDD3的short设备占用的知名IO端口是并口的,端口地址是 0x378,有了这些知识后,就可以知道并口模拟代码在 hw/char/parallel.c中。触发中断的函数是:parallel_update_irq() ,可以看到做法是发现有中断pending,那么先拉高电平,处理完后,irq_pending为0,那么拉低电平,表示处理完成,以便下一次触发

static void parallel_update_irq(ParallelState *s)
{
    if (s->irq_pending)
        qemu_irq_raise(s->irq);
    else
        qemu_irq_lower(s->irq);
}

那么我们就可以增加我们的触发函数了,hmp_trigger_parallel_update_irq(), 注意我们把irq_pending设为1后,强制用parallel_update_irq拉高电平触发中断,但是千万注意还需要把 irq_pending 设置0,再次用parallel_update_irq把中断线的电平拉低,恢复状态,告诉虚拟中断控制器中断处理完成了。只有这样,才可以再次触发中断,千万注意!!

/*
 * begin liufeng
 * HMO trigger parallel dev intr 
 */
ParallelState *g_hmp_parallel_s = NULL;
void hmp_trigger_parallel_update_irq(void)
{
    int irq_pending_store = 0;
    if(!g_hmp_parallel_s){
        printf("%s: can not trigger intr because ParallelState is null \n",__func__);    
    }

    printf("%s: trigger a parallel intr\n",__func__);

    irq_pending_store = g_hmp_parallel_s->irq_pending;
    /*forece rasie up irq,*/
    g_hmp_parallel_s->irq_pending = 1;
    parallel_update_irq(g_hmp_parallel_s);
    /*remember to lower donw the level*/
    g_hmp_parallel_s->irq_pending = 0;
    parallel_update_irq(g_hmp_parallel_s);
    g_hmp_parallel_s->irq_pending = irq_pending_store;
    return;
}
/*end liufeng*/


static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
{
    static int index;
    ISADevice *isadev = ISA_DEVICE(dev);
    ISAParallelState *isa = ISA_PARALLEL(dev);
    ParallelState *s = &isa->state;

    /* begin liufeng 
     * hmp trigger intr
     */
    g_hmp_parallel_s = s;
    /*end liufeng*/

    int base;
    uint8_t dummy;
    //.................

}

 

同时把hmp_trigger_parallel_update_irq(), 声明到头文件里面 include/hw/char/parallel.h

/*
 * begin liufeng
 * HMO trigger parallel dev intr 
 */
void hmp_trigger_parallel_update_irq(void);
/*end liufeng*/

有了功能函数,下面,我们需要添加qemu命令行,就可以按需触发中断了

hmp-commands.hx 中加入

    {
        .name       = "parallel_intr_trigger",
        .args_type  = "",
        .params     = "",
        .help       = "trigger parallel interrupt",
        .cmd        = hmp_parallel_trigger_intr,
    },

STEXI
@item hmp_parallel_trigger_intr
@findex hmp_parallel_trigger_intr
trigger parallel interrupt. Parallel dev must be exsisted
ETEXI

hmp.c中加入

/* begin liufeng
 * trigger intr
 */
void hmp_parallel_trigger_intr(Monitor *mon, const QDict *qdict)
{
    monitor_printf(mon, "%s: begin trigger parallel intr\n", __func__);
    printf("%s: begin trigger parallel intr\n", __func__);
    hmp_trigger_parallel_update_irq();
    monitor_printf(mon, "%s: trigger parallel intr done\n", __func__);
    printf("%s: trigger parallel intr done\n", __func__);

}
/*end liufeng*/

hmp.h中加入声明

/*begin liufeng
 * trigger parallel dev
 */
void hmp_parallel_trigger_intr(Monitor *mon, const QDict *qdict);
/* end */

我们现在就可以启动虚拟机实验试一下了,注意qemu中加入如下参数 “ -monitor stdio  -parallel /dev/pts/2 ” 来是能hmp和并口设备,我的命令行如下

sudo gdb --args /home/liufeng/workspace/tools/bin/qemu-system-x86_64 -machine accel=kvm -m 4G \
-hda /home/kvm/disk/vm0.img \
-vnc 192.168.199.166:0 -monitor stdio \
-netdev type=tap,id=eth0,ifname=tap30,script=no,downscript=no -device e1000,netdev=eth0,mac=12:03:04:05:06:08 \
-parallel /dev/pts/2

启动后,看看qemu命令行是否存在 parallel_intr_trigger

利用qemu触发short设备/dev/shortint中断的方法_第2张图片

我们进入虚拟机,加载short驱动,我们可以看到 0x378开始的7个端口,给了short设备

利用qemu触发short设备/dev/shortint中断的方法_第3张图片

然后验证一下中断是否起作用,在qemu中运行命令行

利用qemu触发short设备/dev/shortint中断的方法_第4张图片

运行3次命令行后,在虚拟机中查看中断触发情况,可以看到 short设备注册的7号中断有3次触发

利用qemu触发short设备/dev/shortint中断的方法_第5张图片

运行short设备的实验情况,可以看到interrupt的中断正常触发了读写

利用qemu触发short设备/dev/shortint中断的方法_第6张图片

好了,到这里我们可以正常玩弄第十章的所有实验了,对入门同学最难找到环境的 硬件端口通信和中断就可以快速入手验证和学习了,希望对大家有所帮助,再见

 

你可能感兴趣的:(驱动,虚拟化)