31
31
* "set-vmvideo" command. For example
32
32
* set-vmvideo -vmname name -horizontalresolution:1920 \
33
33
* -verticalresolution:1200 -resolutiontype single
34
+ *
35
+ * Gen 1 VMs also support direct using VM's physical memory for framebuffer.
36
+ * It could improve the efficiency and performance for framebuffer and VM.
37
+ * This requires to allocate contiguous physical memory from Linux kernel's
38
+ * CMA memory allocator. To enable this, supply a kernel parameter to give
39
+ * enough memory space to CMA allocator for framebuffer. For example:
40
+ * cma=130m
41
+ * This gives 130MB memory to CMA allocator that can be allocated to
42
+ * framebuffer. For reference, 8K resolution (7680x4320) takes about
43
+ * 127MB memory.
34
44
*/
35
45
36
46
#define pr_fmt (fmt ) KBUILD_MODNAME ": " fmt
@@ -228,7 +238,6 @@ struct synthvid_msg {
228
238
} __packed ;
229
239
230
240
231
-
232
241
/* FB driver definitions and structures */
233
242
#define HVFB_WIDTH 1152 /* default screen width */
234
243
#define HVFB_HEIGHT 864 /* default screen height */
@@ -258,12 +267,15 @@ struct hvfb_par {
258
267
/* If true, the VSC notifies the VSP on every framebuffer change */
259
268
bool synchronous_fb ;
260
269
270
+ /* If true, need to copy from deferred IO mem to framebuffer mem */
271
+ bool need_docopy ;
272
+
261
273
struct notifier_block hvfb_panic_nb ;
262
274
263
275
/* Memory for deferred IO and frame buffer itself */
264
276
unsigned char * dio_vp ;
265
277
unsigned char * mmio_vp ;
266
- unsigned long mmio_pp ;
278
+ phys_addr_t mmio_pp ;
267
279
268
280
/* Dirty rectangle, protected by delayed_refresh_lock */
269
281
int x1 , y1 , x2 , y2 ;
@@ -434,7 +446,7 @@ static void synthvid_deferred_io(struct fb_info *p,
434
446
maxy = max_t (int , maxy , y2 );
435
447
436
448
/* Copy from dio space to mmio address */
437
- if (par -> fb_ready )
449
+ if (par -> fb_ready && par -> need_docopy )
438
450
hvfb_docopy (par , start , PAGE_SIZE );
439
451
}
440
452
@@ -751,12 +763,12 @@ static void hvfb_update_work(struct work_struct *w)
751
763
return ;
752
764
753
765
/* Copy the dirty rectangle to frame buffer memory */
754
- for ( j = y1 ; j < y2 ; j ++ ) {
755
- hvfb_docopy ( par ,
756
- j * info -> fix . line_length +
757
- ( x1 * screen_depth / 8 ),
758
- (x2 - x1 ) * screen_depth / 8 );
759
- }
766
+ if ( par -> need_docopy )
767
+ for ( j = y1 ; j < y2 ; j ++ )
768
+ hvfb_docopy ( par ,
769
+ j * info -> fix . line_length +
770
+ (x1 * screen_depth / 8 ),
771
+ ( x2 - x1 ) * screen_depth / 8 );
760
772
761
773
/* Refresh */
762
774
if (par -> fb_ready && par -> update )
@@ -801,7 +813,8 @@ static int hvfb_on_panic(struct notifier_block *nb,
801
813
par = container_of (nb , struct hvfb_par , hvfb_panic_nb );
802
814
par -> synchronous_fb = true;
803
815
info = par -> info ;
804
- hvfb_docopy (par , 0 , dio_fb_size );
816
+ if (par -> need_docopy )
817
+ hvfb_docopy (par , 0 , dio_fb_size );
805
818
synthvid_update (info , 0 , 0 , INT_MAX , INT_MAX );
806
819
807
820
return NOTIFY_DONE ;
@@ -940,6 +953,62 @@ static void hvfb_get_option(struct fb_info *info)
940
953
return ;
941
954
}
942
955
956
+ /*
957
+ * Allocate enough contiguous physical memory.
958
+ * Return physical address if succeeded or -1 if failed.
959
+ */
960
+ static phys_addr_t hvfb_get_phymem (struct hv_device * hdev ,
961
+ unsigned int request_size )
962
+ {
963
+ struct page * page = NULL ;
964
+ dma_addr_t dma_handle ;
965
+ void * vmem ;
966
+ phys_addr_t paddr = 0 ;
967
+ unsigned int order = get_order (request_size );
968
+
969
+ if (request_size == 0 )
970
+ return -1 ;
971
+
972
+ if (order < MAX_ORDER ) {
973
+ /* Call alloc_pages if the size is less than 2^MAX_ORDER */
974
+ page = alloc_pages (GFP_KERNEL | __GFP_ZERO , order );
975
+ if (!page )
976
+ return -1 ;
977
+
978
+ paddr = (page_to_pfn (page ) << PAGE_SHIFT );
979
+ } else {
980
+ /* Allocate from CMA */
981
+ hdev -> device .coherent_dma_mask = DMA_BIT_MASK (64 );
982
+
983
+ vmem = dma_alloc_coherent (& hdev -> device ,
984
+ round_up (request_size , PAGE_SIZE ),
985
+ & dma_handle ,
986
+ GFP_KERNEL | __GFP_NOWARN );
987
+
988
+ if (!vmem )
989
+ return -1 ;
990
+
991
+ paddr = virt_to_phys (vmem );
992
+ }
993
+
994
+ return paddr ;
995
+ }
996
+
997
+ /* Release contiguous physical memory */
998
+ static void hvfb_release_phymem (struct hv_device * hdev ,
999
+ phys_addr_t paddr , unsigned int size )
1000
+ {
1001
+ unsigned int order = get_order (size );
1002
+
1003
+ if (order < MAX_ORDER )
1004
+ __free_pages (pfn_to_page (paddr >> PAGE_SHIFT ), order );
1005
+ else
1006
+ dma_free_coherent (& hdev -> device ,
1007
+ round_up (size , PAGE_SIZE ),
1008
+ phys_to_virt (paddr ),
1009
+ paddr );
1010
+ }
1011
+
943
1012
944
1013
/* Get framebuffer memory from Hyper-V video pci space */
945
1014
static int hvfb_getmem (struct hv_device * hdev , struct fb_info * info )
@@ -949,22 +1018,61 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
949
1018
void __iomem * fb_virt ;
950
1019
int gen2vm = efi_enabled (EFI_BOOT );
951
1020
resource_size_t pot_start , pot_end ;
1021
+ phys_addr_t paddr ;
952
1022
int ret ;
953
1023
954
- dio_fb_size =
955
- screen_width * screen_height * screen_depth / 8 ;
1024
+ info -> apertures = alloc_apertures (1 );
1025
+ if (!info -> apertures )
1026
+ return - ENOMEM ;
956
1027
957
- if (gen2vm ) {
958
- pot_start = 0 ;
959
- pot_end = -1 ;
960
- } else {
1028
+ if (!gen2vm ) {
961
1029
pdev = pci_get_device (PCI_VENDOR_ID_MICROSOFT ,
962
- PCI_DEVICE_ID_HYPERV_VIDEO , NULL );
1030
+ PCI_DEVICE_ID_HYPERV_VIDEO , NULL );
963
1031
if (!pdev ) {
964
1032
pr_err ("Unable to find PCI Hyper-V video\n" );
1033
+ kfree (info -> apertures );
965
1034
return - ENODEV ;
966
1035
}
967
1036
1037
+ info -> apertures -> ranges [0 ].base = pci_resource_start (pdev , 0 );
1038
+ info -> apertures -> ranges [0 ].size = pci_resource_len (pdev , 0 );
1039
+
1040
+ /*
1041
+ * For Gen 1 VM, we can directly use the contiguous memory
1042
+ * from VM. If we succeed, deferred IO happens directly
1043
+ * on this allocated framebuffer memory, avoiding extra
1044
+ * memory copy.
1045
+ */
1046
+ paddr = hvfb_get_phymem (hdev , screen_fb_size );
1047
+ if (paddr != (phys_addr_t ) - 1 ) {
1048
+ par -> mmio_pp = paddr ;
1049
+ par -> mmio_vp = par -> dio_vp = __va (paddr );
1050
+
1051
+ info -> fix .smem_start = paddr ;
1052
+ info -> fix .smem_len = screen_fb_size ;
1053
+ info -> screen_base = par -> mmio_vp ;
1054
+ info -> screen_size = screen_fb_size ;
1055
+
1056
+ par -> need_docopy = false;
1057
+ goto getmem_done ;
1058
+ }
1059
+ pr_info ("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n" );
1060
+ } else {
1061
+ info -> apertures -> ranges [0 ].base = screen_info .lfb_base ;
1062
+ info -> apertures -> ranges [0 ].size = screen_info .lfb_size ;
1063
+ }
1064
+
1065
+ /*
1066
+ * Cannot use the contiguous physical memory.
1067
+ * Allocate mmio space for framebuffer.
1068
+ */
1069
+ dio_fb_size =
1070
+ screen_width * screen_height * screen_depth / 8 ;
1071
+
1072
+ if (gen2vm ) {
1073
+ pot_start = 0 ;
1074
+ pot_end = -1 ;
1075
+ } else {
968
1076
if (!(pci_resource_flags (pdev , 0 ) & IORESOURCE_MEM ) ||
969
1077
pci_resource_len (pdev , 0 ) < screen_fb_size ) {
970
1078
pr_err ("Resource not available or (0x%lx < 0x%lx)\n" ,
@@ -993,20 +1101,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
993
1101
if (par -> dio_vp == NULL )
994
1102
goto err3 ;
995
1103
996
- info -> apertures = alloc_apertures (1 );
997
- if (!info -> apertures )
998
- goto err4 ;
999
-
1000
- if (gen2vm ) {
1001
- info -> apertures -> ranges [0 ].base = screen_info .lfb_base ;
1002
- info -> apertures -> ranges [0 ].size = screen_info .lfb_size ;
1003
- remove_conflicting_framebuffers (info -> apertures ,
1004
- KBUILD_MODNAME , false);
1005
- } else {
1006
- info -> apertures -> ranges [0 ].base = pci_resource_start (pdev , 0 );
1007
- info -> apertures -> ranges [0 ].size = pci_resource_len (pdev , 0 );
1008
- }
1009
-
1010
1104
/* Physical address of FB device */
1011
1105
par -> mmio_pp = par -> mem -> start ;
1012
1106
/* Virtual address of FB device */
@@ -1017,13 +1111,15 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
1017
1111
info -> screen_base = par -> dio_vp ;
1018
1112
info -> screen_size = dio_fb_size ;
1019
1113
1114
+ getmem_done :
1115
+ remove_conflicting_framebuffers (info -> apertures ,
1116
+ KBUILD_MODNAME , false);
1020
1117
if (!gen2vm )
1021
1118
pci_dev_put (pdev );
1119
+ kfree (info -> apertures );
1022
1120
1023
1121
return 0 ;
1024
1122
1025
- err4 :
1026
- vfree (par -> dio_vp );
1027
1123
err3 :
1028
1124
iounmap (fb_virt );
1029
1125
err2 :
@@ -1032,18 +1128,25 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
1032
1128
err1 :
1033
1129
if (!gen2vm )
1034
1130
pci_dev_put (pdev );
1131
+ kfree (info -> apertures );
1035
1132
1036
1133
return - ENOMEM ;
1037
1134
}
1038
1135
1039
1136
/* Release the framebuffer */
1040
- static void hvfb_putmem (struct fb_info * info )
1137
+ static void hvfb_putmem (struct hv_device * hdev , struct fb_info * info )
1041
1138
{
1042
1139
struct hvfb_par * par = info -> par ;
1043
1140
1044
- vfree (par -> dio_vp );
1045
- iounmap (info -> screen_base );
1046
- vmbus_free_mmio (par -> mem -> start , screen_fb_size );
1141
+ if (par -> need_docopy ) {
1142
+ vfree (par -> dio_vp );
1143
+ iounmap (info -> screen_base );
1144
+ vmbus_free_mmio (par -> mem -> start , screen_fb_size );
1145
+ } else {
1146
+ hvfb_release_phymem (hdev , info -> fix .smem_start ,
1147
+ screen_fb_size );
1148
+ }
1149
+
1047
1150
par -> mem = NULL ;
1048
1151
}
1049
1152
@@ -1062,6 +1165,7 @@ static int hvfb_probe(struct hv_device *hdev,
1062
1165
par = info -> par ;
1063
1166
par -> info = info ;
1064
1167
par -> fb_ready = false;
1168
+ par -> need_docopy = true;
1065
1169
init_completion (& par -> wait );
1066
1170
INIT_DELAYED_WORK (& par -> dwork , hvfb_update_work );
1067
1171
@@ -1147,7 +1251,7 @@ static int hvfb_probe(struct hv_device *hdev,
1147
1251
1148
1252
error :
1149
1253
fb_deferred_io_cleanup (info );
1150
- hvfb_putmem (info );
1254
+ hvfb_putmem (hdev , info );
1151
1255
error2 :
1152
1256
vmbus_close (hdev -> channel );
1153
1257
error1 :
@@ -1177,7 +1281,7 @@ static int hvfb_remove(struct hv_device *hdev)
1177
1281
vmbus_close (hdev -> channel );
1178
1282
hv_set_drvdata (hdev , NULL );
1179
1283
1180
- hvfb_putmem (info );
1284
+ hvfb_putmem (hdev , info );
1181
1285
framebuffer_release (info );
1182
1286
1183
1287
return 0 ;
0 commit comments