私はしばらくqemu kvmを使っていますので、PCIデバイスをパススルーする必要があります。 iommu、modprobed vfioモジュール、vfioにバインドされたデバイスを確認して、vfioグループが実際に作成されたことなどを確認しました。 しかし、qemuを任意のpciデバイスで起動すると、エラーメッセージが表示されます。vfioのpciデバイスのファイル記述子でプレアドを使用できません
vfio:デバイスのコンフィグスペース
を読み取ることができませんでしたが、私は問題があるかもしれないものを見るためにQEMUのコードに掘ると、問題がデバイスにPREADに発生することが分かりました。これはオフセットが0であっても発生します。ファイル記述子の通常の読み込みは、テストするコードを変更したときに問題なく動作します。 エラーが発生したためにerrnoをチェックすると、「Illegal seek」というエラーメッセージが表示されます。
私はこれがqemuコンテキストの外で起こっているかどうかを確認するためのコードを書いています(これは、デバイスと干渉していたqemuのコードの中にあるかもしれないと思っていました)。
#define BUF_SIZE 4096
int main(){
char buf[BUF_SIZE], buf1[BUF_SIZE], buf2[BUF_SIZE];
int ret,group_fd, fd, fd2;
size_t nbytes = 4096;
ssize_t bytes_read;
int iommu1, iommu2;
int container, group, device, i;
struct vfio_group_status group_status = { .argsz = sizeof(group_status) };
struct vfio_iommu_type1_info iommu_info = { .argsz = sizeof(iommu_info) };
struct vfio_iommu_type1_dma_map dma_map = { .argsz = sizeof(dma_map) };
struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
container = open("/dev/vfio/vfio",O_RDWR);
if(ioctl(container,VFIO_GET_API_VERSION)!=VFIO_API_VERSION){
printf("Unknown api version: %m\n");
}
group_fd = open("/dev/vfio/22",O_RDWR); printf("Group fd = %d\n", group_fd);
ioctl(group_fd, VFIO_GROUP_GET_STATUS, &group_status);
if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)){
printf("Group not viable\n");
return 1;
}
ret = ioctl(group_fd, VFIO_GROUP_SET_CONTAINER,&container);
ret = ioctl(container,VFIO_SET_IOMMU,VFIO_TYPE1_IOMMU);
ioctl(container, VFIO_IOMMU_GET_INFO, &iommu_info);
/* Allocate some space and setup a DMA mapping */
dma_map.vaddr = (unsigned long int) mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
dma_map.size = 1024 * 1024;
dma_map.iova = 0; /* 1MB starting at 0x0 from device view */
dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
printf("\n\nGETTING DEVICE FD\n");
fd = ioctl(group_fd,VFIO_GROUP_GET_DEVICE_FD,"0000:08:00.0");
printf("Fd = %d\n",fd);
printf("VFIO_GROUP_GET_DEV_ID = %lu\n",VFIO_GROUP_GET_DEVICE_FD);
:私もPREADと通常のファイルを読み込もうとしましたが、それが完璧に動作...ここで私はそれをテストするために書いたコードがある、私はより多くの関連する部分を指摘することができるように少しそれを壊しました
この読み取りがこのPREADは、RETコードで失敗-1およびerrnoを
ret = pread(fd,buf,nbytes,0);
if(ret<0){
printf("ERROR: %m \n");
}
0 'を違法求める'、正常に動作してくれnバイト
ret = read(fd,buf,nbytes);
if(ret<1){
printf("ERROR: %m \n");
}
のRETコードを与えます
ここに私が読んで、PREAD sysfsの中に共通のファイルにPREADが失敗したかどうかを確認するために、この場合の読み取りおよびPREAD仕事上だけで罰金してみてください:
printf("TESTING PREAD ON A COMMON FILE\n");
fd2 = open("/sys/bus/pci/devices/0000:08:00.0/device",O_RDONLY);
ret = read(fd2,buf1,nbytes);
if(ret<0){
printf("ERROR: %m\n");
}
printf("Result from read: ret = %d, content = %s\n",ret,buf1);
ret = pread(fd2,buf2,nbytes,2);
if(ret<0){
printf("ERROR: %m\n"); #
}
printf("Result from pread: ret = %d, content = %s\n",ret,buf2);
close(fd2);
getchar();
close(fd);
close(container);
close(group_fd);
return 0;
}
私は、一般的なLinuxカーネルを使用しています組み込みシステムのためにuClibcでコンパイルされたv4.7.8 ....これはなぜ起こっているのかも知りません。私は今は無名です! TU
更新: 私は同じマシンにubuntu 16.04(kernel v4.4.0)をインストールし、手順を繰り返し、pciパススルーがうまく動作し、テストコードのプレアドも完全に動作します。だから私はカスタムジェネリックカーネルで何がうまくいかないのか分かりません。アラシュの提案を1として
、私はPREAD(FD、bufが、nbytesは、SEEK_CUR)を試してみましたが、それは私に同じ '違法求める' というエラーを与えました。 ftellから得たオフセットは、ubuntuと汎用カーネルの両方で0xffffffffです。
[pread](https://github.com/lattera/glossc/blob/master/sysdeps/posix/pread.c)には(1)シーク現在のオフセットを取得し、old_offsetとして保存する、(2)要求のオフセットをシークする、(3)読み込む、(4)最後に元のオフセット(old_offset)を検索する明らかに、あなたが見ていることは、これらのシークの少なくとも1つが違法だということです。私はこれが 'pread(fd、buf、nbytes、SEEK_CUR)'や 'long int ftell(FILE * stream) 'からの現在のオフセットの値であるかどうか疑問です。 – Arash
QEMUのコマンドラインも投稿してくださいconfig vfio devices) – Codeguard
qemu-system-x86_64 -enable-kvm -m 1024 -device vfio-pci、host = 01:00.0 -driveファイル=/disk0/vdisk.qcow2、id =ディスク、フォーマット= qcow2。これはubuntuで正常に動作します – igalvez