2017-05-15 4 views
1

ゲストマシンからQemuのホストマシンに通信するためにvirtioドライバをテストしています。今のところただ一つのバッファを送りたいだけです。virtioを使ってホストからゲストに空のバッファをvirtioデバイス/ドライバで送信

私の問題は、仮想キューに関連付けられたコールバックが呼び出されたときにデバイスが空のバッファを受け取ることです。

奇妙なことは、ドライバから送信されたバッファの長さが変わったときに、デバイスで受信したバッファの長さが変わってしまうことです。私のドライバで

static int virt_test_probe(struct virtio_device *vdev) 
{ 
    struct virt_test_info *vi; 
    int retvalue = 0; 
    struct scatterlist sg[1]; 
    char *str = vmalloc(1000*sizeof(char)); 
    int err; 
    memset(str, 121, 1000*sizeof(char)); 
    vi = kzalloc(sizeof(struct virt_test_info), GFP_KERNEL); 
    if (!vi) 
     return -ENOMEM; 

    printk(KERN_ERR "TEST VIRTIO LINUX: %s. Value of str: %s\n", __FUNCTION__, str); 

    vi->vq = virtio_find_single_vq(vdev, protector_recv_done, "input"); 
    if (IS_ERR(vi->vq)) { 
     retvalue = PTR_ERR(vi->vq); 
     goto err_free; 
    } 

    vdev->priv = vi; 
    virtio_device_ready(vdev); 
    sg_init_one(sg, str, 1000*sizeof(char));  
    err = virtqueue_add_outbuf(vi->vq, sg, 1, str, GFP_ATOMIC); 
    virtqueue_kick(vi->vq); 

    return 0; 

err_free: 
    kfree(vi); 
    return retvalue; 
} 

そして、私のQEMUデバイスに:

static void handle_output(VirtIODevice *vdev, VirtQueue *vq) 
{ 
    //VirtIOTEST *vtest = VIRTIO_TEST(vdev); 
    char *buf = malloc(1000*sizeof(char)); 
    VirtQueueElement *elem; 
    int len; 
    printf("TEST VIRTIO: %s\n", __FUNCTION__); 

    for(;;) { 
     elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); 
     if (elem) 
      break; 
    } 
    memset(buf,122, 1000*sizeof(char)); // I nitialised the buffer with y char 

    len = iov_to_buf(elem->out_sg, elem->out_num, 0, buf, 1000*sizeof(char)); 

    printf("TEST VIRTIO: %s: content %s, len:%i\n", __FUNCTION__, buf, len); //the value length here changes with the the length of the driver's buffer 
    for(len=0; len<10; len++) { 
     printf("%02x",buf[len]); // here we're printing 0s 
    } 
} 

私はarm64のLinuxを使用しています。 バッファの値は、qemuの呼び出しによって一貫しているようです。だから私は問題は、Linuxカーネルや何かから来ていると思います。私は、スキャッタリストがわかりやすくなり、add_output_bufからエラーを受け取らないことを確認しました。

答えて

1

私はちょうどそれが働かない理由が分かった: 使用kmallocの代わりvmallocsg_init_oneに渡すバッファを割り当てます。理由は次のとおりです。

スキャッタリストはバッファを1ページとして保存します。 したがって、バッファをpage_to_virtを使用してページに変換する必要があります。これは基本的に仮想アドレスにオフセットを適用してページの物理アドレスを取得します。

vmallocは、kmallocのように、連続した物理アドレス空間にメモリをマップしません。したがって、非連続的な物理アドレスを連続した仮想アドレスにマッピングするようにページテーブルを変更します。したがって、関数page_to_virtは、vmallocでは物理アドレス空間に入るためにオフセットを適用する以上のものを必要とするため、機能しないようです。

関連する問題