brintos

brintos / linux-shallow public Read only

0
0
Text · 33.8 KiB · 7fdb5ed Raw
1371 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012, Microsoft Corporation.4 *5 * Author:6 *   Haiyang Zhang <haiyangz@microsoft.com>7 */8 9/*10 * Hyper-V Synthetic Video Frame Buffer Driver11 *12 * This is the driver for the Hyper-V Synthetic Video, which supports13 * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows14 * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R215 * or earlier.16 *17 * It also solves the double mouse cursor issue of the emulated video mode.18 *19 * The default screen resolution is 1152x864, which may be changed by a20 * kernel parameter:21 *     video=hyperv_fb:<width>x<height>22 *     For example: video=hyperv_fb:1280x102423 *24 * Portrait orientation is also supported:25 *     For example: video=hyperv_fb:864x115226 *27 * When a Windows 10 RS5+ host is used, the virtual machine screen28 * resolution is obtained from the host. The "video=hyperv_fb" option is29 * not needed, but still can be used to overwrite what the host specifies.30 * The VM resolution on the host could be set by executing the powershell31 * "set-vmvideo" command. For example32 *     set-vmvideo -vmname name -horizontalresolution:1920 \33 * -verticalresolution:1200 -resolutiontype single34 *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's38 * CMA memory allocator. To enable this, supply a kernel parameter to give39 * enough memory space to CMA allocator for framebuffer. For example:40 *    cma=130m41 * This gives 130MB memory to CMA allocator that can be allocated to42 * framebuffer. For reference, 8K resolution (7680x4320) takes about43 * 127MB memory.44 */45 46#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt47 48#include <linux/aperture.h>49#include <linux/module.h>50#include <linux/kernel.h>51#include <linux/vmalloc.h>52#include <linux/init.h>53#include <linux/completion.h>54#include <linux/fb.h>55#include <linux/pci.h>56#include <linux/panic_notifier.h>57#include <linux/efi.h>58#include <linux/console.h>59 60#include <linux/hyperv.h>61 62/* Hyper-V Synthetic Video Protocol definitions and structures */63#define MAX_VMBUS_PKT_SIZE 0x400064 65#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))66/* Support for VERSION_WIN7 is removed. #define is retained for reference. */67#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)68#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)69#define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5)70 71#define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff)72#define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16)73 74#define SYNTHVID_DEPTH_WIN8 3275#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)76 77enum pipe_msg_type {78	PIPE_MSG_INVALID,79	PIPE_MSG_DATA,80	PIPE_MSG_MAX81};82 83struct pipe_msg_hdr {84	u32 type;85	u32 size; /* size of message after this field */86} __packed;87 88 89enum synthvid_msg_type {90	SYNTHVID_ERROR			= 0,91	SYNTHVID_VERSION_REQUEST	= 1,92	SYNTHVID_VERSION_RESPONSE	= 2,93	SYNTHVID_VRAM_LOCATION		= 3,94	SYNTHVID_VRAM_LOCATION_ACK	= 4,95	SYNTHVID_SITUATION_UPDATE	= 5,96	SYNTHVID_SITUATION_UPDATE_ACK	= 6,97	SYNTHVID_POINTER_POSITION	= 7,98	SYNTHVID_POINTER_SHAPE		= 8,99	SYNTHVID_FEATURE_CHANGE		= 9,100	SYNTHVID_DIRT			= 10,101	SYNTHVID_RESOLUTION_REQUEST	= 13,102	SYNTHVID_RESOLUTION_RESPONSE	= 14,103 104	SYNTHVID_MAX			= 15105};106 107#define		SYNTHVID_EDID_BLOCK_SIZE	128108#define		SYNTHVID_MAX_RESOLUTION_COUNT	64109 110struct hvd_screen_info {111	u16 width;112	u16 height;113} __packed;114 115struct synthvid_msg_hdr {116	u32 type;117	u32 size;  /* size of this header + payload after this field*/118} __packed;119 120struct synthvid_version_req {121	u32 version;122} __packed;123 124struct synthvid_version_resp {125	u32 version;126	u8 is_accepted;127	u8 max_video_outputs;128} __packed;129 130struct synthvid_supported_resolution_req {131	u8 maximum_resolution_count;132} __packed;133 134struct synthvid_supported_resolution_resp {135	u8 edid_block[SYNTHVID_EDID_BLOCK_SIZE];136	u8 resolution_count;137	u8 default_resolution_index;138	u8 is_standard;139	struct hvd_screen_info140		supported_resolution[SYNTHVID_MAX_RESOLUTION_COUNT];141} __packed;142 143struct synthvid_vram_location {144	u64 user_ctx;145	u8 is_vram_gpa_specified;146	u64 vram_gpa;147} __packed;148 149struct synthvid_vram_location_ack {150	u64 user_ctx;151} __packed;152 153struct video_output_situation {154	u8 active;155	u32 vram_offset;156	u8 depth_bits;157	u32 width_pixels;158	u32 height_pixels;159	u32 pitch_bytes;160} __packed;161 162struct synthvid_situation_update {163	u64 user_ctx;164	u8 video_output_count;165	struct video_output_situation video_output[1];166} __packed;167 168struct synthvid_situation_update_ack {169	u64 user_ctx;170} __packed;171 172struct synthvid_pointer_position {173	u8 is_visible;174	u8 video_output;175	s32 image_x;176	s32 image_y;177} __packed;178 179 180#define CURSOR_MAX_X 96181#define CURSOR_MAX_Y 96182#define CURSOR_ARGB_PIXEL_SIZE 4183#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE)184#define CURSOR_COMPLETE (-1)185 186struct synthvid_pointer_shape {187	u8 part_idx;188	u8 is_argb;189	u32 width; /* CURSOR_MAX_X at most */190	u32 height; /* CURSOR_MAX_Y at most */191	u32 hot_x; /* hotspot relative to upper-left of pointer image */192	u32 hot_y;193	u8 data[4];194} __packed;195 196struct synthvid_feature_change {197	u8 is_dirt_needed;198	u8 is_ptr_pos_needed;199	u8 is_ptr_shape_needed;200	u8 is_situ_needed;201} __packed;202 203struct rect {204	s32 x1, y1; /* top left corner */205	s32 x2, y2; /* bottom right corner, exclusive */206} __packed;207 208struct synthvid_dirt {209	u8 video_output;210	u8 dirt_count;211	struct rect rect[1];212} __packed;213 214struct synthvid_msg {215	struct pipe_msg_hdr pipe_hdr;216	struct synthvid_msg_hdr vid_hdr;217	union {218		struct synthvid_version_req ver_req;219		struct synthvid_version_resp ver_resp;220		struct synthvid_vram_location vram;221		struct synthvid_vram_location_ack vram_ack;222		struct synthvid_situation_update situ;223		struct synthvid_situation_update_ack situ_ack;224		struct synthvid_pointer_position ptr_pos;225		struct synthvid_pointer_shape ptr_shape;226		struct synthvid_feature_change feature_chg;227		struct synthvid_dirt dirt;228		struct synthvid_supported_resolution_req resolution_req;229		struct synthvid_supported_resolution_resp resolution_resp;230	};231} __packed;232 233 234/* FB driver definitions and structures */235#define HVFB_WIDTH 1152 /* default screen width */236#define HVFB_HEIGHT 864 /* default screen height */237#define HVFB_WIDTH_MIN 640238#define HVFB_HEIGHT_MIN 480239 240#define RING_BUFSIZE (256 * 1024)241#define VSP_TIMEOUT (10 * HZ)242#define HVFB_UPDATE_DELAY (HZ / 20)243#define HVFB_ONDEMAND_THROTTLE (HZ / 20)244 245struct hvfb_par {246	struct fb_info *info;247	struct resource *mem;248	bool fb_ready; /* fb device is ready */249	struct completion wait;250	u32 synthvid_version;251 252	struct delayed_work dwork;253	bool update;254	bool update_saved; /* The value of 'update' before hibernation */255 256	u32 pseudo_palette[16];257	u8 init_buf[MAX_VMBUS_PKT_SIZE];258	u8 recv_buf[MAX_VMBUS_PKT_SIZE];259 260	/* If true, the VSC notifies the VSP on every framebuffer change */261	bool synchronous_fb;262 263	/* If true, need to copy from deferred IO mem to framebuffer mem */264	bool need_docopy;265 266	struct notifier_block hvfb_panic_nb;267 268	/* Memory for deferred IO and frame buffer itself */269	unsigned char *dio_vp;270	unsigned char *mmio_vp;271	phys_addr_t mmio_pp;272 273	/* Dirty rectangle, protected by delayed_refresh_lock */274	int x1, y1, x2, y2;275	bool delayed_refresh;276	spinlock_t delayed_refresh_lock;277};278 279static uint screen_width = HVFB_WIDTH;280static uint screen_height = HVFB_HEIGHT;281static uint screen_depth;282static uint screen_fb_size;283static uint dio_fb_size; /* FB size for deferred IO */284 285/* Send message to Hyper-V host */286static inline int synthvid_send(struct hv_device *hdev,287				struct synthvid_msg *msg)288{289	static atomic64_t request_id = ATOMIC64_INIT(0);290	int ret;291 292	msg->pipe_hdr.type = PIPE_MSG_DATA;293	msg->pipe_hdr.size = msg->vid_hdr.size;294 295	ret = vmbus_sendpacket(hdev->channel, msg,296			       msg->vid_hdr.size + sizeof(struct pipe_msg_hdr),297			       atomic64_inc_return(&request_id),298			       VM_PKT_DATA_INBAND, 0);299 300	if (ret)301		pr_err_ratelimited("Unable to send packet via vmbus; error %d\n", ret);302 303	return ret;304}305 306 307/* Send screen resolution info to host */308static int synthvid_send_situ(struct hv_device *hdev)309{310	struct fb_info *info = hv_get_drvdata(hdev);311	struct synthvid_msg msg;312 313	if (!info)314		return -ENODEV;315 316	memset(&msg, 0, sizeof(struct synthvid_msg));317 318	msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE;319	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +320		sizeof(struct synthvid_situation_update);321	msg.situ.user_ctx = 0;322	msg.situ.video_output_count = 1;323	msg.situ.video_output[0].active = 1;324	msg.situ.video_output[0].vram_offset = 0;325	msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel;326	msg.situ.video_output[0].width_pixels = info->var.xres;327	msg.situ.video_output[0].height_pixels = info->var.yres;328	msg.situ.video_output[0].pitch_bytes = info->fix.line_length;329 330	synthvid_send(hdev, &msg);331 332	return 0;333}334 335/* Send mouse pointer info to host */336static int synthvid_send_ptr(struct hv_device *hdev)337{338	struct synthvid_msg msg;339 340	memset(&msg, 0, sizeof(struct synthvid_msg));341	msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;342	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +343		sizeof(struct synthvid_pointer_position);344	msg.ptr_pos.is_visible = 1;345	msg.ptr_pos.video_output = 0;346	msg.ptr_pos.image_x = 0;347	msg.ptr_pos.image_y = 0;348	synthvid_send(hdev, &msg);349 350	memset(&msg, 0, sizeof(struct synthvid_msg));351	msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;352	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +353		sizeof(struct synthvid_pointer_shape);354	msg.ptr_shape.part_idx = CURSOR_COMPLETE;355	msg.ptr_shape.is_argb = 1;356	msg.ptr_shape.width = 1;357	msg.ptr_shape.height = 1;358	msg.ptr_shape.hot_x = 0;359	msg.ptr_shape.hot_y = 0;360	msg.ptr_shape.data[0] = 0;361	msg.ptr_shape.data[1] = 1;362	msg.ptr_shape.data[2] = 1;363	msg.ptr_shape.data[3] = 1;364	synthvid_send(hdev, &msg);365 366	return 0;367}368 369/* Send updated screen area (dirty rectangle) location to host */370static int371synthvid_update(struct fb_info *info, int x1, int y1, int x2, int y2)372{373	struct hv_device *hdev = device_to_hv_device(info->device);374	struct synthvid_msg msg;375 376	memset(&msg, 0, sizeof(struct synthvid_msg));377	if (x2 == INT_MAX)378		x2 = info->var.xres;379	if (y2 == INT_MAX)380		y2 = info->var.yres;381 382	msg.vid_hdr.type = SYNTHVID_DIRT;383	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +384		sizeof(struct synthvid_dirt);385	msg.dirt.video_output = 0;386	msg.dirt.dirt_count = 1;387	msg.dirt.rect[0].x1 = (x1 > x2) ? 0 : x1;388	msg.dirt.rect[0].y1 = (y1 > y2) ? 0 : y1;389	msg.dirt.rect[0].x2 =390		(x2 < x1 || x2 > info->var.xres) ? info->var.xres : x2;391	msg.dirt.rect[0].y2 =392		(y2 < y1 || y2 > info->var.yres) ? info->var.yres : y2;393 394	synthvid_send(hdev, &msg);395 396	return 0;397}398 399static void hvfb_docopy(struct hvfb_par *par,400			unsigned long offset,401			unsigned long size)402{403	if (!par || !par->mmio_vp || !par->dio_vp || !par->fb_ready ||404	    size == 0 || offset >= dio_fb_size)405		return;406 407	if (offset + size > dio_fb_size)408		size = dio_fb_size - offset;409 410	memcpy(par->mmio_vp + offset, par->dio_vp + offset, size);411}412 413/* Deferred IO callback */414static void synthvid_deferred_io(struct fb_info *p, struct list_head *pagereflist)415{416	struct hvfb_par *par = p->par;417	struct fb_deferred_io_pageref *pageref;418	unsigned long start, end;419	int y1, y2, miny, maxy;420 421	miny = INT_MAX;422	maxy = 0;423 424	/*425	 * Merge dirty pages. It is possible that last page cross426	 * over the end of frame buffer row yres. This is taken care of427	 * in synthvid_update function by clamping the y2428	 * value to yres.429	 */430	list_for_each_entry(pageref, pagereflist, list) {431		start = pageref->offset;432		end = start + PAGE_SIZE - 1;433		y1 = start / p->fix.line_length;434		y2 = end / p->fix.line_length;435		miny = min_t(int, miny, y1);436		maxy = max_t(int, maxy, y2);437 438		/* Copy from dio space to mmio address */439		if (par->fb_ready && par->need_docopy)440			hvfb_docopy(par, start, PAGE_SIZE);441	}442 443	if (par->fb_ready && par->update)444		synthvid_update(p, 0, miny, p->var.xres, maxy + 1);445}446 447static struct fb_deferred_io synthvid_defio = {448	.delay		= HZ / 20,449	.deferred_io	= synthvid_deferred_io,450};451 452/*453 * Actions on received messages from host:454 * Complete the wait event.455 * Or, reply with screen and cursor info.456 */457static void synthvid_recv_sub(struct hv_device *hdev)458{459	struct fb_info *info = hv_get_drvdata(hdev);460	struct hvfb_par *par;461	struct synthvid_msg *msg;462 463	if (!info)464		return;465 466	par = info->par;467	msg = (struct synthvid_msg *)par->recv_buf;468 469	/* Complete the wait event */470	if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||471	    msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE ||472	    msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {473		memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);474		complete(&par->wait);475		return;476	}477 478	/* Reply with screen and cursor info */479	if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {480		if (par->fb_ready) {481			synthvid_send_ptr(hdev);482			synthvid_send_situ(hdev);483		}484 485		par->update = msg->feature_chg.is_dirt_needed;486		if (par->update)487			schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);488	}489}490 491/* Receive callback for messages from the host */492static void synthvid_receive(void *ctx)493{494	struct hv_device *hdev = ctx;495	struct fb_info *info = hv_get_drvdata(hdev);496	struct hvfb_par *par;497	struct synthvid_msg *recv_buf;498	u32 bytes_recvd;499	u64 req_id;500	int ret;501 502	if (!info)503		return;504 505	par = info->par;506	recv_buf = (struct synthvid_msg *)par->recv_buf;507 508	do {509		ret = vmbus_recvpacket(hdev->channel, recv_buf,510				       MAX_VMBUS_PKT_SIZE,511				       &bytes_recvd, &req_id);512		if (bytes_recvd > 0 &&513		    recv_buf->pipe_hdr.type == PIPE_MSG_DATA)514			synthvid_recv_sub(hdev);515	} while (bytes_recvd > 0 && ret == 0);516}517 518/* Check if the ver1 version is equal or greater than ver2 */519static inline bool synthvid_ver_ge(u32 ver1, u32 ver2)520{521	if (SYNTHVID_VER_GET_MAJOR(ver1) > SYNTHVID_VER_GET_MAJOR(ver2) ||522	    (SYNTHVID_VER_GET_MAJOR(ver1) == SYNTHVID_VER_GET_MAJOR(ver2) &&523	     SYNTHVID_VER_GET_MINOR(ver1) >= SYNTHVID_VER_GET_MINOR(ver2)))524		return true;525 526	return false;527}528 529/* Check synthetic video protocol version with the host */530static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)531{532	struct fb_info *info = hv_get_drvdata(hdev);533	struct hvfb_par *par = info->par;534	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;535	int ret = 0;536	unsigned long t;537 538	memset(msg, 0, sizeof(struct synthvid_msg));539	msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;540	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +541		sizeof(struct synthvid_version_req);542	msg->ver_req.version = ver;543	synthvid_send(hdev, msg);544 545	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);546	if (!t) {547		pr_err("Time out on waiting version response\n");548		ret = -ETIMEDOUT;549		goto out;550	}551	if (!msg->ver_resp.is_accepted) {552		ret = -ENODEV;553		goto out;554	}555 556	par->synthvid_version = ver;557	pr_info("Synthvid Version major %d, minor %d\n",558		SYNTHVID_VER_GET_MAJOR(ver), SYNTHVID_VER_GET_MINOR(ver));559 560out:561	return ret;562}563 564/* Get current resolution from the host */565static int synthvid_get_supported_resolution(struct hv_device *hdev)566{567	struct fb_info *info = hv_get_drvdata(hdev);568	struct hvfb_par *par = info->par;569	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;570	int ret = 0;571	unsigned long t;572	u8 index;573 574	memset(msg, 0, sizeof(struct synthvid_msg));575	msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST;576	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +577		sizeof(struct synthvid_supported_resolution_req);578 579	msg->resolution_req.maximum_resolution_count =580		SYNTHVID_MAX_RESOLUTION_COUNT;581	synthvid_send(hdev, msg);582 583	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);584	if (!t) {585		pr_err("Time out on waiting resolution response\n");586		ret = -ETIMEDOUT;587		goto out;588	}589 590	if (msg->resolution_resp.resolution_count == 0) {591		pr_err("No supported resolutions\n");592		ret = -ENODEV;593		goto out;594	}595 596	index = msg->resolution_resp.default_resolution_index;597	if (index >= msg->resolution_resp.resolution_count) {598		pr_err("Invalid resolution index: %d\n", index);599		ret = -ENODEV;600		goto out;601	}602 603	screen_width =604		msg->resolution_resp.supported_resolution[index].width;605	screen_height =606		msg->resolution_resp.supported_resolution[index].height;607 608out:609	return ret;610}611 612/* Connect to VSP (Virtual Service Provider) on host */613static int synthvid_connect_vsp(struct hv_device *hdev)614{615	struct fb_info *info = hv_get_drvdata(hdev);616	struct hvfb_par *par = info->par;617	int ret;618 619	ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,620			 NULL, 0, synthvid_receive, hdev);621	if (ret) {622		pr_err("Unable to open vmbus channel\n");623		return ret;624	}625 626	/* Negotiate the protocol version with host */627	switch (vmbus_proto_version) {628	case VERSION_WIN10:629	case VERSION_WIN10_V5:630		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10);631		if (!ret)632			break;633		fallthrough;634	case VERSION_WIN8:635	case VERSION_WIN8_1:636		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);637		break;638	default:639		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10);640		break;641	}642 643	if (ret) {644		pr_err("Synthetic video device version not accepted\n");645		goto error;646	}647 648	screen_depth = SYNTHVID_DEPTH_WIN8;649	if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) {650		ret = synthvid_get_supported_resolution(hdev);651		if (ret)652			pr_info("Failed to get supported resolution from host, use default\n");653	}654 655	screen_fb_size = hdev->channel->offermsg.offer.656				mmio_megabytes * 1024 * 1024;657 658	return 0;659 660error:661	vmbus_close(hdev->channel);662	return ret;663}664 665/* Send VRAM and Situation messages to the host */666static int synthvid_send_config(struct hv_device *hdev)667{668	struct fb_info *info = hv_get_drvdata(hdev);669	struct hvfb_par *par = info->par;670	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;671	int ret = 0;672	unsigned long t;673 674	/* Send VRAM location */675	memset(msg, 0, sizeof(struct synthvid_msg));676	msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;677	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +678		sizeof(struct synthvid_vram_location);679	msg->vram.user_ctx = msg->vram.vram_gpa = par->mmio_pp;680	msg->vram.is_vram_gpa_specified = 1;681	synthvid_send(hdev, msg);682 683	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);684	if (!t) {685		pr_err("Time out on waiting vram location ack\n");686		ret = -ETIMEDOUT;687		goto out;688	}689	if (msg->vram_ack.user_ctx != par->mmio_pp) {690		pr_err("Unable to set VRAM location\n");691		ret = -ENODEV;692		goto out;693	}694 695	/* Send pointer and situation update */696	synthvid_send_ptr(hdev);697	synthvid_send_situ(hdev);698 699out:700	return ret;701}702 703 704/*705 * Delayed work callback:706 * It is scheduled to call whenever update request is received and it has707 * not been called in last HVFB_ONDEMAND_THROTTLE time interval.708 */709static void hvfb_update_work(struct work_struct *w)710{711	struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);712	struct fb_info *info = par->info;713	unsigned long flags;714	int x1, x2, y1, y2;715	int j;716 717	spin_lock_irqsave(&par->delayed_refresh_lock, flags);718	/* Reset the request flag */719	par->delayed_refresh = false;720 721	/* Store the dirty rectangle to local variables */722	x1 = par->x1;723	x2 = par->x2;724	y1 = par->y1;725	y2 = par->y2;726 727	/* Clear dirty rectangle */728	par->x1 = par->y1 = INT_MAX;729	par->x2 = par->y2 = 0;730 731	spin_unlock_irqrestore(&par->delayed_refresh_lock, flags);732 733	if (x1 > info->var.xres || x2 > info->var.xres ||734	    y1 > info->var.yres || y2 > info->var.yres || x2 <= x1)735		return;736 737	/* Copy the dirty rectangle to frame buffer memory */738	if (par->need_docopy)739		for (j = y1; j < y2; j++)740			hvfb_docopy(par,741				    j * info->fix.line_length +742				    (x1 * screen_depth / 8),743				    (x2 - x1) * screen_depth / 8);744 745	/* Refresh */746	if (par->fb_ready && par->update)747		synthvid_update(info, x1, y1, x2, y2);748}749 750/*751 * Control the on-demand refresh frequency. It schedules a delayed752 * screen update if it has not yet.753 */754static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par,755					   int x1, int y1, int w, int h)756{757	unsigned long flags;758	int x2 = x1 + w;759	int y2 = y1 + h;760 761	spin_lock_irqsave(&par->delayed_refresh_lock, flags);762 763	/* Merge dirty rectangle */764	par->x1 = min_t(int, par->x1, x1);765	par->y1 = min_t(int, par->y1, y1);766	par->x2 = max_t(int, par->x2, x2);767	par->y2 = max_t(int, par->y2, y2);768 769	/* Schedule a delayed screen update if not yet */770	if (par->delayed_refresh == false) {771		schedule_delayed_work(&par->dwork,772				      HVFB_ONDEMAND_THROTTLE);773		par->delayed_refresh = true;774	}775 776	spin_unlock_irqrestore(&par->delayed_refresh_lock, flags);777}778 779static int hvfb_on_panic(struct notifier_block *nb,780			 unsigned long e, void *p)781{782	struct hv_device *hdev;783	struct hvfb_par *par;784	struct fb_info *info;785 786	par = container_of(nb, struct hvfb_par, hvfb_panic_nb);787	info = par->info;788	hdev = device_to_hv_device(info->device);789 790	if (hv_ringbuffer_spinlock_busy(hdev->channel))791		return NOTIFY_DONE;792 793	par->synchronous_fb = true;794	if (par->need_docopy)795		hvfb_docopy(par, 0, dio_fb_size);796	synthvid_update(info, 0, 0, INT_MAX, INT_MAX);797 798	return NOTIFY_DONE;799}800 801/* Framebuffer operation handlers */802 803static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)804{805	if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN ||806	    var->xres > screen_width || var->yres >  screen_height ||807	    var->bits_per_pixel != screen_depth)808		return -EINVAL;809 810	var->xres_virtual = var->xres;811	var->yres_virtual = var->yres;812 813	return 0;814}815 816static int hvfb_set_par(struct fb_info *info)817{818	struct hv_device *hdev = device_to_hv_device(info->device);819 820	return synthvid_send_situ(hdev);821}822 823 824static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)825{826	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;827}828 829static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,830			  unsigned blue, unsigned transp, struct fb_info *info)831{832	u32 *pal = info->pseudo_palette;833 834	if (regno > 15)835		return -EINVAL;836 837	pal[regno] = chan_to_field(red, &info->var.red)838		| chan_to_field(green, &info->var.green)839		| chan_to_field(blue, &info->var.blue)840		| chan_to_field(transp, &info->var.transp);841 842	return 0;843}844 845static int hvfb_blank(int blank, struct fb_info *info)846{847	return 1;	/* get fb_blank to set the colormap to all black */848}849 850static void hvfb_ops_damage_range(struct fb_info *info, off_t off, size_t len)851{852	/* TODO: implement damage handling */853}854 855static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)856{857	struct hvfb_par *par = info->par;858 859	if (par->synchronous_fb)860		synthvid_update(info, 0, 0, INT_MAX, INT_MAX);861	else862		hvfb_ondemand_refresh_throttle(par, x, y, width, height);863}864 865/*866 * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the867 *       driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases.868 */869FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(hvfb_ops,870				  hvfb_ops_damage_range,871				  hvfb_ops_damage_area)872 873static const struct fb_ops hvfb_ops = {874	.owner = THIS_MODULE,875	FB_DEFAULT_DEFERRED_OPS(hvfb_ops),876	.fb_check_var = hvfb_check_var,877	.fb_set_par = hvfb_set_par,878	.fb_setcolreg = hvfb_setcolreg,879	.fb_blank = hvfb_blank,880};881 882/* Get options from kernel paramenter "video=" */883static void hvfb_get_option(struct fb_info *info)884{885	struct hvfb_par *par = info->par;886	char *opt = NULL, *p;887	uint x = 0, y = 0;888 889	if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt)890		return;891 892	p = strsep(&opt, "x");893	if (!*p || kstrtouint(p, 0, &x) ||894	    !opt || !*opt || kstrtouint(opt, 0, &y)) {895		pr_err("Screen option is invalid: skipped\n");896		return;897	}898 899	if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||900	    (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) &&901	    (x * y * screen_depth / 8 > screen_fb_size)) ||902	    (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&903	     x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8)) {904		pr_err("Screen resolution option is out of range: skipped\n");905		return;906	}907 908	screen_width = x;909	screen_height = y;910	return;911}912 913/*914 * Allocate enough contiguous physical memory.915 * Return physical address if succeeded or -1 if failed.916 */917static phys_addr_t hvfb_get_phymem(struct hv_device *hdev,918				   unsigned int request_size)919{920	struct page *page = NULL;921	dma_addr_t dma_handle;922	void *vmem;923	phys_addr_t paddr = 0;924	unsigned int order = get_order(request_size);925 926	if (request_size == 0)927		return -1;928 929	if (order <= MAX_PAGE_ORDER) {930		/* Call alloc_pages if the size is less than 2^MAX_PAGE_ORDER */931		page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);932		if (!page)933			return -1;934 935		paddr = (page_to_pfn(page) << PAGE_SHIFT);936	} else {937		/* Allocate from CMA */938		hdev->device.coherent_dma_mask = DMA_BIT_MASK(64);939 940		vmem = dma_alloc_coherent(&hdev->device,941					  round_up(request_size, PAGE_SIZE),942					  &dma_handle,943					  GFP_KERNEL | __GFP_NOWARN);944 945		if (!vmem)946			return -1;947 948		paddr = virt_to_phys(vmem);949	}950 951	return paddr;952}953 954/* Release contiguous physical memory */955static void hvfb_release_phymem(struct hv_device *hdev,956				phys_addr_t paddr, unsigned int size)957{958	unsigned int order = get_order(size);959 960	if (order <= MAX_PAGE_ORDER)961		__free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order);962	else963		dma_free_coherent(&hdev->device,964				  round_up(size, PAGE_SIZE),965				  phys_to_virt(paddr),966				  paddr);967}968 969 970/* Get framebuffer memory from Hyper-V video pci space */971static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)972{973	struct hvfb_par *par = info->par;974	struct pci_dev *pdev  = NULL;975	void __iomem *fb_virt;976	int gen2vm = efi_enabled(EFI_BOOT);977	resource_size_t base = 0;978	resource_size_t size = 0;979	phys_addr_t paddr;980	int ret;981 982	if (!gen2vm) {983		pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,984			PCI_DEVICE_ID_HYPERV_VIDEO, NULL);985		if (!pdev) {986			pr_err("Unable to find PCI Hyper-V video\n");987			return -ENODEV;988		}989 990		base = pci_resource_start(pdev, 0);991		size = pci_resource_len(pdev, 0);992 993		/*994		 * For Gen 1 VM, we can directly use the contiguous memory995		 * from VM. If we succeed, deferred IO happens directly996		 * on this allocated framebuffer memory, avoiding extra997		 * memory copy.998		 */999		paddr = hvfb_get_phymem(hdev, screen_fb_size);1000		if (paddr != (phys_addr_t) -1) {1001			par->mmio_pp = paddr;1002			par->mmio_vp = par->dio_vp = __va(paddr);1003 1004			info->fix.smem_start = paddr;1005			info->fix.smem_len = screen_fb_size;1006			info->screen_base = par->mmio_vp;1007			info->screen_size = screen_fb_size;1008 1009			par->need_docopy = false;1010			goto getmem_done;1011		}1012		pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n");1013	}1014 1015	/*1016	 * Cannot use the contiguous physical memory.1017	 * Allocate mmio space for framebuffer.1018	 */1019	dio_fb_size =1020		screen_width * screen_height * screen_depth / 8;1021 1022	ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1,1023				  screen_fb_size, 0x100000, true);1024	if (ret != 0) {1025		pr_err("Unable to allocate framebuffer memory\n");1026		goto err1;1027	}1028 1029	/*1030	 * Map the VRAM cacheable for performance. This is also required for1031	 * VM Connect to display properly for ARM64 Linux VM, as the host also1032	 * maps the VRAM cacheable.1033	 */1034	fb_virt = ioremap_cache(par->mem->start, screen_fb_size);1035	if (!fb_virt)1036		goto err2;1037 1038	/* Allocate memory for deferred IO */1039	par->dio_vp = vzalloc(round_up(dio_fb_size, PAGE_SIZE));1040	if (par->dio_vp == NULL)1041		goto err3;1042 1043	/* Physical address of FB device */1044	par->mmio_pp = par->mem->start;1045	/* Virtual address of FB device */1046	par->mmio_vp = (unsigned char *) fb_virt;1047 1048	info->fix.smem_start = par->mem->start;1049	info->fix.smem_len = dio_fb_size;1050	info->screen_base = par->dio_vp;1051	info->screen_size = dio_fb_size;1052 1053getmem_done:1054	if (base && size)1055		aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);1056	else1057		aperture_remove_all_conflicting_devices(KBUILD_MODNAME);1058 1059	if (!gen2vm)1060		pci_dev_put(pdev);1061 1062	return 0;1063 1064err3:1065	iounmap(fb_virt);1066err2:1067	vmbus_free_mmio(par->mem->start, screen_fb_size);1068	par->mem = NULL;1069err1:1070	if (!gen2vm)1071		pci_dev_put(pdev);1072 1073	return -ENOMEM;1074}1075 1076/* Release the framebuffer */1077static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)1078{1079	struct hvfb_par *par = info->par;1080 1081	if (par->need_docopy) {1082		vfree(par->dio_vp);1083		iounmap(info->screen_base);1084		vmbus_free_mmio(par->mem->start, screen_fb_size);1085	} else {1086		hvfb_release_phymem(hdev, info->fix.smem_start,1087				    screen_fb_size);1088	}1089 1090	par->mem = NULL;1091}1092 1093 1094static int hvfb_probe(struct hv_device *hdev,1095		      const struct hv_vmbus_device_id *dev_id)1096{1097	struct fb_info *info;1098	struct hvfb_par *par;1099	int ret;1100 1101	info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);1102	if (!info)1103		return -ENOMEM;1104 1105	par = info->par;1106	par->info = info;1107	par->fb_ready = false;1108	par->need_docopy = true;1109	init_completion(&par->wait);1110	INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);1111 1112	par->delayed_refresh = false;1113	spin_lock_init(&par->delayed_refresh_lock);1114	par->x1 = par->y1 = INT_MAX;1115	par->x2 = par->y2 = 0;1116 1117	/* Connect to VSP */1118	hv_set_drvdata(hdev, info);1119	ret = synthvid_connect_vsp(hdev);1120	if (ret) {1121		pr_err("Unable to connect to VSP\n");1122		goto error1;1123	}1124 1125	hvfb_get_option(info);1126	pr_info("Screen resolution: %dx%d, Color depth: %d, Frame buffer size: %d\n",1127		screen_width, screen_height, screen_depth, screen_fb_size);1128 1129	ret = hvfb_getmem(hdev, info);1130	if (ret) {1131		pr_err("No memory for framebuffer\n");1132		goto error2;1133	}1134 1135	/* Set up fb_info */1136	info->var.xres_virtual = info->var.xres = screen_width;1137	info->var.yres_virtual = info->var.yres = screen_height;1138	info->var.bits_per_pixel = screen_depth;1139 1140	if (info->var.bits_per_pixel == 16) {1141		info->var.red = (struct fb_bitfield){11, 5, 0};1142		info->var.green = (struct fb_bitfield){5, 6, 0};1143		info->var.blue = (struct fb_bitfield){0, 5, 0};1144		info->var.transp = (struct fb_bitfield){0, 0, 0};1145	} else {1146		info->var.red = (struct fb_bitfield){16, 8, 0};1147		info->var.green = (struct fb_bitfield){8, 8, 0};1148		info->var.blue = (struct fb_bitfield){0, 8, 0};1149		info->var.transp = (struct fb_bitfield){24, 8, 0};1150	}1151 1152	info->var.activate = FB_ACTIVATE_NOW;1153	info->var.height = -1;1154	info->var.width = -1;1155	info->var.vmode = FB_VMODE_NONINTERLACED;1156 1157	strcpy(info->fix.id, KBUILD_MODNAME);1158	info->fix.type = FB_TYPE_PACKED_PIXELS;1159	info->fix.visual = FB_VISUAL_TRUECOLOR;1160	info->fix.line_length = screen_width * screen_depth / 8;1161	info->fix.accel = FB_ACCEL_NONE;1162 1163	info->fbops = &hvfb_ops;1164	info->pseudo_palette = par->pseudo_palette;1165 1166	/* Initialize deferred IO */1167	info->fbdefio = &synthvid_defio;1168	fb_deferred_io_init(info);1169 1170	/* Send config to host */1171	ret = synthvid_send_config(hdev);1172	if (ret)1173		goto error;1174 1175	ret = register_framebuffer(info);1176	if (ret) {1177		pr_err("Unable to register framebuffer\n");1178		goto error;1179	}1180 1181	par->fb_ready = true;1182 1183	par->synchronous_fb = false;1184 1185	/*1186	 * We need to be sure this panic notifier runs _before_ the1187	 * vmbus disconnect, so order it by priority. It must execute1188	 * before the function hv_panic_vmbus_unload() [drivers/hv/vmbus_drv.c],1189	 * which is almost at the end of list, with priority = INT_MIN + 1.1190	 */1191	par->hvfb_panic_nb.notifier_call = hvfb_on_panic;1192	par->hvfb_panic_nb.priority = INT_MIN + 10;1193	atomic_notifier_chain_register(&panic_notifier_list,1194				       &par->hvfb_panic_nb);1195 1196	return 0;1197 1198error:1199	fb_deferred_io_cleanup(info);1200	hvfb_putmem(hdev, info);1201error2:1202	vmbus_close(hdev->channel);1203error1:1204	cancel_delayed_work_sync(&par->dwork);1205	hv_set_drvdata(hdev, NULL);1206	framebuffer_release(info);1207	return ret;1208}1209 1210static void hvfb_remove(struct hv_device *hdev)1211{1212	struct fb_info *info = hv_get_drvdata(hdev);1213	struct hvfb_par *par = info->par;1214 1215	atomic_notifier_chain_unregister(&panic_notifier_list,1216					 &par->hvfb_panic_nb);1217 1218	par->update = false;1219	par->fb_ready = false;1220 1221	fb_deferred_io_cleanup(info);1222 1223	unregister_framebuffer(info);1224	cancel_delayed_work_sync(&par->dwork);1225 1226	vmbus_close(hdev->channel);1227	hv_set_drvdata(hdev, NULL);1228 1229	hvfb_putmem(hdev, info);1230	framebuffer_release(info);1231}1232 1233static int hvfb_suspend(struct hv_device *hdev)1234{1235	struct fb_info *info = hv_get_drvdata(hdev);1236	struct hvfb_par *par = info->par;1237 1238	console_lock();1239 1240	/* 1 means do suspend */1241	fb_set_suspend(info, 1);1242 1243	cancel_delayed_work_sync(&par->dwork);1244	cancel_delayed_work_sync(&info->deferred_work);1245 1246	par->update_saved = par->update;1247	par->update = false;1248	par->fb_ready = false;1249 1250	vmbus_close(hdev->channel);1251 1252	console_unlock();1253 1254	return 0;1255}1256 1257static int hvfb_resume(struct hv_device *hdev)1258{1259	struct fb_info *info = hv_get_drvdata(hdev);1260	struct hvfb_par *par = info->par;1261	int ret;1262 1263	console_lock();1264 1265	ret = synthvid_connect_vsp(hdev);1266	if (ret != 0)1267		goto out;1268 1269	ret = synthvid_send_config(hdev);1270	if (ret != 0) {1271		vmbus_close(hdev->channel);1272		goto out;1273	}1274 1275	par->fb_ready = true;1276	par->update = par->update_saved;1277 1278	schedule_delayed_work(&info->deferred_work, info->fbdefio->delay);1279	schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);1280 1281	/* 0 means do resume */1282	fb_set_suspend(info, 0);1283 1284out:1285	console_unlock();1286 1287	return ret;1288}1289 1290 1291static const struct pci_device_id pci_stub_id_table[] = {1292	{1293		.vendor      = PCI_VENDOR_ID_MICROSOFT,1294		.device      = PCI_DEVICE_ID_HYPERV_VIDEO,1295	},1296	{ /* end of list */ }1297};1298 1299static const struct hv_vmbus_device_id id_table[] = {1300	/* Synthetic Video Device GUID */1301	{HV_SYNTHVID_GUID},1302	{}1303};1304 1305MODULE_DEVICE_TABLE(pci, pci_stub_id_table);1306MODULE_DEVICE_TABLE(vmbus, id_table);1307 1308static struct hv_driver hvfb_drv = {1309	.name = KBUILD_MODNAME,1310	.id_table = id_table,1311	.probe = hvfb_probe,1312	.remove = hvfb_remove,1313	.suspend = hvfb_suspend,1314	.resume = hvfb_resume,1315	.driver = {1316		.probe_type = PROBE_PREFER_ASYNCHRONOUS,1317	},1318};1319 1320static int hvfb_pci_stub_probe(struct pci_dev *pdev,1321			       const struct pci_device_id *ent)1322{1323	return 0;1324}1325 1326static void hvfb_pci_stub_remove(struct pci_dev *pdev)1327{1328}1329 1330static struct pci_driver hvfb_pci_stub_driver = {1331	.name =		KBUILD_MODNAME,1332	.id_table =	pci_stub_id_table,1333	.probe =	hvfb_pci_stub_probe,1334	.remove =	hvfb_pci_stub_remove,1335	.driver = {1336		.probe_type = PROBE_PREFER_ASYNCHRONOUS,1337	}1338};1339 1340static int __init hvfb_drv_init(void)1341{1342	int ret;1343 1344	if (fb_modesetting_disabled("hyper_fb"))1345		return -ENODEV;1346 1347	ret = vmbus_driver_register(&hvfb_drv);1348	if (ret != 0)1349		return ret;1350 1351	ret = pci_register_driver(&hvfb_pci_stub_driver);1352	if (ret != 0) {1353		vmbus_driver_unregister(&hvfb_drv);1354		return ret;1355	}1356 1357	return 0;1358}1359 1360static void __exit hvfb_drv_exit(void)1361{1362	pci_unregister_driver(&hvfb_pci_stub_driver);1363	vmbus_driver_unregister(&hvfb_drv);1364}1365 1366module_init(hvfb_drv_init);1367module_exit(hvfb_drv_exit);1368 1369MODULE_LICENSE("GPL");1370MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");1371