Message ID | 20190905091120.16761-1-weh@microsoft.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4] video: hyperv: hyperv_fb: Obtain screen resolution from Hyper-V host | expand |
From: Wei Hu <weh@microsoft.com> Sent: Thursday, September 5, 2019 2:12 AM > > Beginning from Windows 10 RS5+, VM screen resolution is obtained from host. > The "video=hyperv_fb" boot time option is not needed, but still can be > used to overwrite what the host specifies. The VM resolution on the host > could be set by executing the powershell "set-vmvideo" command. > > Signed-off-by: Iouri Tarassov <iourit@microsoft.com> > Signed-off-by: Wei Hu <weh@microsoft.com> > --- > v2: > - Implemented fallback when version negotiation failed. > - Defined full size for supported_resolution array. > > v3: > - Corrected the synthvid major and minor version comparison problem. > > v4: > - Changed function name to synthvid_ver_ge(). > > drivers/video/fbdev/hyperv_fb.c | 159 +++++++++++++++++++++++++++++--- > 1 file changed, 147 insertions(+), 12 deletions(-) > Reviewed-by: Michael Kelley <mikelley@microsoft.com>
> From: Michael Kelley <mikelley@microsoft.com> > Sent: Thursday, September 5, 2019 7:06 AM > > From: Wei Hu <weh@microsoft.com> Sent: Thursday, September 5, 2019 2:12 > AM > > > > Beginning from Windows 10 RS5+, VM screen resolution is obtained from > host. > > The "video=hyperv_fb" boot time option is not needed, but still can be > > used to overwrite what the host specifies. The VM resolution on the host > > could be set by executing the powershell "set-vmvideo" command. > > > > Signed-off-by: Iouri Tarassov <iourit@microsoft.com> > > Signed-off-by: Wei Hu <weh@microsoft.com> > > --- > > v2: > > - Implemented fallback when version negotiation failed. > > - Defined full size for supported_resolution array. > > > > v3: > > - Corrected the synthvid major and minor version comparison problem. > > > > v4: > > - Changed function name to synthvid_ver_ge(). > > > > drivers/video/fbdev/hyperv_fb.c | 159 > +++++++++++++++++++++++++++++--- > > 1 file changed, 147 insertions(+), 12 deletions(-) > > > > Reviewed-by: Michael Kelley <mikelley@microsoft.com> Looks good to me. Reviewed-by: Dexuan Cui <decui@microsoft.com>
> From: linux-hyperv-owner@vger.kernel.org > <linux-hyperv-owner@vger.kernel.org> On Behalf Of Dexuan Cui > Sent: Thursday, September 12, 2019 11:39 PM > To: Michael Kelley <mikelley@microsoft.com>; Wei Hu <weh@microsoft.com>; > b.zolnierkie@samsung.com; linux-hyperv@vger.kernel.org; > dri-devel@lists.freedesktop.org; linux-fbdev@vger.kernel.org; > linux-kernel@vger.kernel.org; Stephen Hemminger > <sthemmin@microsoft.com>; sashal@kernel.org; Haiyang Zhang > <haiyangz@microsoft.com>; KY Srinivasan <kys@microsoft.com> > Cc: Iouri Tarassov <iourit@microsoft.com> > Subject: RE: [PATCH v4] video: hyperv: hyperv_fb: Obtain screen resolution > from Hyper-V host > > > From: Michael Kelley <mikelley@microsoft.com> > > Sent: Thursday, September 5, 2019 7:06 AM > > > > From: Wei Hu <weh@microsoft.com> Sent: Thursday, September 5, 2019 > 2:12 > > AM > > > > > > Beginning from Windows 10 RS5+, VM screen resolution is obtained from > > host. > > > The "video=hyperv_fb" boot time option is not needed, but still can be > > > used to overwrite what the host specifies. The VM resolution on the host > > > could be set by executing the powershell "set-vmvideo" command. > > > > > > Signed-off-by: Iouri Tarassov <iourit@microsoft.com> > > > Signed-off-by: Wei Hu <weh@microsoft.com> > > > --- > > > v2: > > > - Implemented fallback when version negotiation failed. > > > - Defined full size for supported_resolution array. > > > > > > v3: > > > - Corrected the synthvid major and minor version comparison > problem. > > > > > > v4: > > > - Changed function name to synthvid_ver_ge(). > > > > > > drivers/video/fbdev/hyperv_fb.c | 159 > > +++++++++++++++++++++++++++++--- > > > 1 file changed, 147 insertions(+), 12 deletions(-) > > > > > > > Reviewed-by: Michael Kelley <mikelley@microsoft.com> > > Looks good to me. > > Reviewed-by: Dexuan Cui <decui@microsoft.com> Hi Wei, It turns out we need to make a further fix. :-) The patch forgets to take par->update into consideration. When the VM Connection window is closed (or minimized?), the host sends a message to the guest, and the guest sets par->update to false in synthvid_recv_sub(). If par->update is false, the guest doesn't need to call synthvid_update(). Thanks, -- Dexuan
> From: Dexuan Cui > Sent: Monday, September 16, 2019 2:46 PM > To: Michael Kelley <mikelley@microsoft.com>; Wei Hu <weh@microsoft.com>; > b.zolnierkie@samsung.com; linux-hyperv@vger.kernel.org; > dri-devel@lists.freedesktop.org; linux-fbdev@vger.kernel.org; > linux-kernel@vger.kernel.org; Stephen Hemminger > <sthemmin@microsoft.com>; sashal@kernel.org; Haiyang Zhang > <haiyangz@microsoft.com>; KY Srinivasan <kys@microsoft.com> > Cc: Iouri Tarassov <iourit@microsoft.com> > Subject: RE: [PATCH v4] video: hyperv: hyperv_fb: Obtain screen resolution > from Hyper-V host > > > From: linux-hyperv-owner@vger.kernel.org > > <linux-hyperv-owner@vger.kernel.org> On Behalf Of Dexuan Cui > > Sent: Thursday, September 12, 2019 11:39 PM > > To: Michael Kelley <mikelley@microsoft.com>; Wei Hu > <weh@microsoft.com>; > > b.zolnierkie@samsung.com; linux-hyperv@vger.kernel.org; > > dri-devel@lists.freedesktop.org; linux-fbdev@vger.kernel.org; > > linux-kernel@vger.kernel.org; Stephen Hemminger > > <sthemmin@microsoft.com>; sashal@kernel.org; Haiyang Zhang > > <haiyangz@microsoft.com>; KY Srinivasan <kys@microsoft.com> > > Cc: Iouri Tarassov <iourit@microsoft.com> > > Subject: RE: [PATCH v4] video: hyperv: hyperv_fb: Obtain screen resolution > > from Hyper-V host > > > > > From: Michael Kelley <mikelley@microsoft.com> > > > Sent: Thursday, September 5, 2019 7:06 AM > > > > > > From: Wei Hu <weh@microsoft.com> Sent: Thursday, September 5, 2019 > > 2:12 > > > AM > > > > > > > > Beginning from Windows 10 RS5+, VM screen resolution is obtained from > > > host. > > > > The "video=hyperv_fb" boot time option is not needed, but still can be > > > > used to overwrite what the host specifies. The VM resolution on the host > > > > could be set by executing the powershell "set-vmvideo" command. > > > > > > > > Signed-off-by: Iouri Tarassov <iourit@microsoft.com> > > > > Signed-off-by: Wei Hu <weh@microsoft.com> > > > > --- > > > > v2: > > > > - Implemented fallback when version negotiation failed. > > > > - Defined full size for supported_resolution array. > > > > > > > > v3: > > > > - Corrected the synthvid major and minor version comparison > > problem. > > > > > > > > v4: > > > > - Changed function name to synthvid_ver_ge(). > > > > > > > > drivers/video/fbdev/hyperv_fb.c | 159 > > > +++++++++++++++++++++++++++++--- > > > > 1 file changed, 147 insertions(+), 12 deletions(-) > > > > > > > > > > Reviewed-by: Michael Kelley <mikelley@microsoft.com> > > > > Looks good to me. > > > > Reviewed-by: Dexuan Cui <decui@microsoft.com> > > Hi Wei, > It turns out we need to make a further fix. :-) > > The patch forgets to take par->update into consideration. > > When the VM Connection window is closed (or minimized?), > the host sends a message to the guest, and the guest sets > par->update to false in synthvid_recv_sub(). > > If par->update is false, the guest doesn't need to call > synthvid_update(). > > Thanks, > -- Dexuan Please ignore the last reply from me. It was meant to reply another mail: RE: [PATCH v5] video: hyperv: hyperv_fb: Support deferred IO for Hyper-V frame buffer driver Sorry for the confusion. Thanks, -- Dexuan
On Fri, Sep 13, 2019 at 06:38:42AM +0000, Dexuan Cui wrote: >> From: Michael Kelley <mikelley@microsoft.com> >> Sent: Thursday, September 5, 2019 7:06 AM >> >> From: Wei Hu <weh@microsoft.com> Sent: Thursday, September 5, 2019 2:12 >> AM >> > >> > Beginning from Windows 10 RS5+, VM screen resolution is obtained from >> host. >> > The "video=hyperv_fb" boot time option is not needed, but still can be >> > used to overwrite what the host specifies. The VM resolution on the host >> > could be set by executing the powershell "set-vmvideo" command. >> > >> > Signed-off-by: Iouri Tarassov <iourit@microsoft.com> >> > Signed-off-by: Wei Hu <weh@microsoft.com> >> > --- >> > v2: >> > - Implemented fallback when version negotiation failed. >> > - Defined full size for supported_resolution array. >> > >> > v3: >> > - Corrected the synthvid major and minor version comparison problem. >> > >> > v4: >> > - Changed function name to synthvid_ver_ge(). >> > >> > drivers/video/fbdev/hyperv_fb.c | 159 >> +++++++++++++++++++++++++++++--- >> > 1 file changed, 147 insertions(+), 12 deletions(-) >> > >> >> Reviewed-by: Michael Kelley <mikelley@microsoft.com> > >Looks good to me. > >Reviewed-by: Dexuan Cui <decui@microsoft.com> Queued up for hyperv-next, thank you. -- Thanks, Sasha
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 00f5bdcc6c6f..fe319fc39bec 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -23,6 +23,14 @@ * * Portrait orientation is also supported: * For example: video=hyperv_fb:864x1152 + * + * When a Windows 10 RS5+ host is used, the virtual machine screen + * resolution is obtained from the host. The "video=hyperv_fb" option is + * not needed, but still can be used to overwrite what the host specifies. + * The VM resolution on the host could be set by executing the powershell + * "set-vmvideo" command. For example + * set-vmvideo -vmname name -horizontalresolution:1920 \ + * -verticalresolution:1200 -resolutiontype single */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -44,6 +52,10 @@ #define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major)) #define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0) #define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2) +#define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5) + +#define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff) +#define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16) #define SYNTHVID_DEPTH_WIN7 16 #define SYNTHVID_DEPTH_WIN8 32 @@ -82,16 +94,25 @@ enum synthvid_msg_type { SYNTHVID_POINTER_SHAPE = 8, SYNTHVID_FEATURE_CHANGE = 9, SYNTHVID_DIRT = 10, + SYNTHVID_RESOLUTION_REQUEST = 13, + SYNTHVID_RESOLUTION_RESPONSE = 14, - SYNTHVID_MAX = 11 + SYNTHVID_MAX = 15 }; +#define SYNTHVID_EDID_BLOCK_SIZE 128 +#define SYNTHVID_MAX_RESOLUTION_COUNT 64 + +struct hvd_screen_info { + u16 width; + u16 height; +} __packed; + struct synthvid_msg_hdr { u32 type; u32 size; /* size of this header + payload after this field*/ } __packed; - struct synthvid_version_req { u32 version; } __packed; @@ -102,6 +123,19 @@ struct synthvid_version_resp { u8 max_video_outputs; } __packed; +struct synthvid_supported_resolution_req { + u8 maximum_resolution_count; +} __packed; + +struct synthvid_supported_resolution_resp { + u8 edid_block[SYNTHVID_EDID_BLOCK_SIZE]; + u8 resolution_count; + u8 default_resolution_index; + u8 is_standard; + struct hvd_screen_info + supported_resolution[SYNTHVID_MAX_RESOLUTION_COUNT]; +} __packed; + struct synthvid_vram_location { u64 user_ctx; u8 is_vram_gpa_specified; @@ -187,6 +221,8 @@ struct synthvid_msg { struct synthvid_pointer_shape ptr_shape; struct synthvid_feature_change feature_chg; struct synthvid_dirt dirt; + struct synthvid_supported_resolution_req resolution_req; + struct synthvid_supported_resolution_resp resolution_resp; }; } __packed; @@ -224,6 +260,8 @@ struct hvfb_par { static uint screen_width = HVFB_WIDTH; static uint screen_height = HVFB_HEIGHT; +static uint screen_width_max = HVFB_WIDTH; +static uint screen_height_max = HVFB_HEIGHT; static uint screen_depth; static uint screen_fb_size; @@ -354,6 +392,7 @@ static void synthvid_recv_sub(struct hv_device *hdev) /* Complete the wait event */ if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE || + msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE || msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) { memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE); complete(&par->wait); @@ -400,6 +439,17 @@ static void synthvid_receive(void *ctx) } while (bytes_recvd > 0 && ret == 0); } +/* Check if the ver1 version is equal or greater than ver2 */ +static inline bool synthvid_ver_ge(u32 ver1, u32 ver2) +{ + if (SYNTHVID_VER_GET_MAJOR(ver1) > SYNTHVID_VER_GET_MAJOR(ver2) || + (SYNTHVID_VER_GET_MAJOR(ver1) == SYNTHVID_VER_GET_MAJOR(ver2) && + SYNTHVID_VER_GET_MINOR(ver1) >= SYNTHVID_VER_GET_MINOR(ver2))) + return true; + + return false; +} + /* Check synthetic video protocol version with the host */ static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver) { @@ -428,6 +478,64 @@ static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver) } par->synthvid_version = ver; + pr_info("Synthvid Version major %d, minor %d\n", + SYNTHVID_VER_GET_MAJOR(ver), SYNTHVID_VER_GET_MINOR(ver)); + +out: + return ret; +} + +/* Get current resolution from the host */ +static int synthvid_get_supported_resolution(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; + int ret = 0; + unsigned long t; + u8 index; + int i; + + memset(msg, 0, sizeof(struct synthvid_msg)); + msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST; + msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_supported_resolution_req); + + msg->resolution_req.maximum_resolution_count = + SYNTHVID_MAX_RESOLUTION_COUNT; + synthvid_send(hdev, msg); + + t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); + if (!t) { + pr_err("Time out on waiting resolution response\n"); + ret = -ETIMEDOUT; + goto out; + } + + if (msg->resolution_resp.resolution_count == 0) { + pr_err("No supported resolutions\n"); + ret = -ENODEV; + goto out; + } + + index = msg->resolution_resp.default_resolution_index; + if (index >= msg->resolution_resp.resolution_count) { + pr_err("Invalid resolution index: %d\n", index); + ret = -ENODEV; + goto out; + } + + for (i = 0; i < msg->resolution_resp.resolution_count; i++) { + screen_width_max = max_t(unsigned int, screen_width_max, + msg->resolution_resp.supported_resolution[i].width); + screen_height_max = max_t(unsigned int, screen_height_max, + msg->resolution_resp.supported_resolution[i].height); + } + + screen_width = + msg->resolution_resp.supported_resolution[index].width; + screen_height = + msg->resolution_resp.supported_resolution[index].height; out: return ret; @@ -448,11 +556,27 @@ static int synthvid_connect_vsp(struct hv_device *hdev) } /* Negotiate the protocol version with host */ - if (vmbus_proto_version == VERSION_WS2008 || - vmbus_proto_version == VERSION_WIN7) - ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7); - else + switch (vmbus_proto_version) { + case VERSION_WIN10: + case VERSION_WIN10_V5: + ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10); + if (!ret) + break; + /* Fallthrough */ + case VERSION_WIN8: + case VERSION_WIN8_1: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8); + if (!ret) + break; + /* Fallthrough */ + case VERSION_WS2008: + case VERSION_WIN7: + ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7); + break; + default: + ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10); + break; + } if (ret) { pr_err("Synthetic video device version not accepted\n"); @@ -464,6 +588,12 @@ static int synthvid_connect_vsp(struct hv_device *hdev) else screen_depth = SYNTHVID_DEPTH_WIN8; + if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) { + ret = synthvid_get_supported_resolution(hdev); + if (ret) + pr_info("Failed to get supported resolution from host, use default\n"); + } + screen_fb_size = hdev->channel->offermsg.offer. mmio_megabytes * 1024 * 1024; @@ -653,6 +783,8 @@ static void hvfb_get_option(struct fb_info *info) } if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN || + (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) && + (x > screen_width_max || y > screen_height_max)) || (par->synthvid_version == SYNTHVID_VERSION_WIN8 && x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) || (par->synthvid_version == SYNTHVID_VERSION_WIN7 && @@ -689,8 +821,12 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || - pci_resource_len(pdev, 0) < screen_fb_size) + pci_resource_len(pdev, 0) < screen_fb_size) { + pr_err("Resource not available or (0x%lx < 0x%lx)\n", + (unsigned long) pci_resource_len(pdev, 0), + (unsigned long) screen_fb_size); goto err1; + } pot_end = pci_resource_end(pdev, 0); pot_start = pot_end - screen_fb_size + 1; @@ -781,17 +917,16 @@ static int hvfb_probe(struct hv_device *hdev, goto error1; } + hvfb_get_option(info); + pr_info("Screen resolution: %dx%d, Color depth: %d\n", + screen_width, screen_height, screen_depth); + ret = hvfb_getmem(hdev, info); if (ret) { pr_err("No memory for framebuffer\n"); goto error2; } - hvfb_get_option(info); - pr_info("Screen resolution: %dx%d, Color depth: %d\n", - screen_width, screen_height, screen_depth); - - /* Set up fb_info */ info->flags = FBINFO_DEFAULT;