@@ -130,6 +130,7 @@ virtio_set_io_bar(struct virtio_base *base, int barnum)
130
130
*/
131
131
size = VIRTIO_CR_CFG1 + base -> vops -> cfgsize ;
132
132
pci_emul_alloc_bar (base -> dev , barnum , PCIBAR_IO , size );
133
+ base -> legacy_pio_bar_idx = barnum ;
133
134
}
134
135
135
136
/*
@@ -561,7 +562,7 @@ virtio_pci_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
561
562
}
562
563
563
564
/* XXX probably should do something better than just assert() */
564
- assert (baridx == 0 );
565
+ assert (baridx == base -> legacy_pio_bar_idx );
565
566
566
567
if (base -> mtx )
567
568
pthread_mutex_lock (base -> mtx );
@@ -683,7 +684,7 @@ virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
683
684
}
684
685
685
686
/* XXX probably should do something better than just assert() */
686
- assert (baridx == 0 );
687
+ assert (baridx == base -> legacy_pio_bar_idx );
687
688
688
689
if (base -> mtx )
689
690
pthread_mutex_lock (base -> mtx );
@@ -798,3 +799,134 @@ virtio_pci_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
798
799
if (base -> mtx )
799
800
pthread_mutex_unlock (base -> mtx );
800
801
}
802
+
803
+ /*
804
+ * Set virtio modern MMIO BAR (usually 4) to map the 4 capabilities.
805
+ */
806
+ static int
807
+ virtio_set_modern_mmio_bar (struct virtio_base * base , int barnum )
808
+ {
809
+ struct virtio_ops * vops ;
810
+ int rc ;
811
+ struct virtio_pci_cap cap = {
812
+ .cap_vndr = PCIY_VENDOR ,
813
+ .cap_next = 0 ,
814
+ .cap_len = sizeof (cap ),
815
+ .bar = barnum ,
816
+ };
817
+ struct virtio_pci_notify_cap notify = {
818
+ .cap .cap_vndr = PCIY_VENDOR ,
819
+ .cap .cap_next = 0 ,
820
+ .cap .cap_len = sizeof (notify ),
821
+ .cap .cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG ,
822
+ .cap .bar = barnum ,
823
+ .cap .offset = VIRTIO_CAP_NOTIFY_OFFSET ,
824
+ .cap .length = VIRTIO_CAP_NOTIFY_SIZE ,
825
+ .notify_off_multiplier = VIRTIO_MODERN_NOTIFY_OFF_MULT ,
826
+ };
827
+ struct virtio_pci_cfg_cap cfg = {
828
+ .cap .cap_vndr = PCIY_VENDOR ,
829
+ .cap .cap_next = 0 ,
830
+ .cap .cap_len = sizeof (cfg ),
831
+ .cap .cfg_type = VIRTIO_PCI_CAP_PCI_CFG ,
832
+ };
833
+
834
+ vops = base -> vops ;
835
+
836
+ if (vops -> cfgsize > VIRTIO_CAP_DEVICE_SIZE ) {
837
+ fprintf (stderr ,
838
+ "%s: cfgsize %lu > max %d\r\n" ,
839
+ vops -> name , vops -> cfgsize , VIRTIO_CAP_DEVICE_SIZE );
840
+ return -1 ;
841
+ }
842
+
843
+ /* common configuration capability */
844
+ cap .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG ;
845
+ cap .offset = VIRTIO_CAP_COMMON_OFFSET ;
846
+ cap .length = VIRTIO_CAP_COMMON_SIZE ;
847
+ rc = pci_emul_add_capability (base -> dev , (u_char * )& cap , sizeof (cap ));
848
+ assert (rc == 0 );
849
+
850
+ /* isr status capability */
851
+ cap .cfg_type = VIRTIO_PCI_CAP_ISR_CFG ;
852
+ cap .offset = VIRTIO_CAP_ISR_OFFSET ;
853
+ cap .length = VIRTIO_CAP_ISR_SIZE ;
854
+ rc = pci_emul_add_capability (base -> dev , (u_char * )& cap , sizeof (cap ));
855
+ assert (rc == 0 );
856
+
857
+ /* device specific configuration capability */
858
+ cap .cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG ;
859
+ cap .offset = VIRTIO_CAP_DEVICE_OFFSET ;
860
+ cap .length = VIRTIO_CAP_DEVICE_SIZE ;
861
+ rc = pci_emul_add_capability (base -> dev , (u_char * )& cap , sizeof (cap ));
862
+ assert (rc == 0 );
863
+
864
+ /* notification capability */
865
+ rc = pci_emul_add_capability (base -> dev , (u_char * )& notify ,
866
+ sizeof (notify ));
867
+ assert (rc == 0 );
868
+
869
+ /* pci alternative configuration access capability */
870
+ rc = pci_emul_add_capability (base -> dev , (u_char * )& cfg , sizeof (cfg ));
871
+ assert (rc == 0 );
872
+
873
+ /* allocate and register modern memory bar */
874
+ rc = pci_emul_alloc_bar (base -> dev , barnum , PCIBAR_MEM64 ,
875
+ VIRTIO_MODERN_MEM_BAR_SIZE );
876
+ assert (rc == 0 );
877
+
878
+ base -> modern_mmio_bar_idx = barnum ;
879
+ return 0 ;
880
+ }
881
+
882
+ /*
883
+ * Set virtio modern PIO BAR (usually 2) to map notify capability.
884
+ */
885
+ static int
886
+ virtio_set_modern_pio_bar (struct virtio_base * base , int barnum )
887
+ {
888
+ int rc ;
889
+ struct virtio_pci_notify_cap notify_pio = {
890
+ .cap .cap_vndr = PCIY_VENDOR ,
891
+ .cap .cap_next = 0 ,
892
+ .cap .cap_len = sizeof (notify_pio ),
893
+ .cap .cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG ,
894
+ .cap .bar = barnum ,
895
+ .cap .offset = 0 ,
896
+ .cap .length = 4 ,
897
+ .notify_off_multiplier = 0 ,
898
+ };
899
+
900
+ /* notification capability */
901
+ rc = pci_emul_add_capability (base -> dev , (u_char * )& notify_pio ,
902
+ sizeof (notify_pio ));
903
+ assert (rc == 0 );
904
+
905
+ /* allocate and register modern pio bar */
906
+ rc = pci_emul_alloc_bar (base -> dev , barnum , PCIBAR_IO , 4 );
907
+ assert (rc == 0 );
908
+
909
+ base -> modern_pio_bar_idx = barnum ;
910
+ return 0 ;
911
+ }
912
+
913
+ int
914
+ virtio_set_modern_bar (struct virtio_base * base , bool use_notify_pio )
915
+ {
916
+ struct virtio_ops * vops ;
917
+ int rc = 0 ;
918
+
919
+ vops = base -> vops ;
920
+
921
+ if (!vops || (vops -> hv_caps & VIRTIO_F_VERSION_1 ) == 0 )
922
+ return -1 ;
923
+
924
+ if (use_notify_pio )
925
+ rc = virtio_set_modern_pio_bar (base ,
926
+ VIRTIO_MODERN_PIO_BAR_IDX );
927
+ if (!rc )
928
+ rc = virtio_set_modern_mmio_bar (base ,
929
+ VIRTIO_MODERN_MMIO_BAR_IDX );
930
+
931
+ return rc ;
932
+ }
0 commit comments