cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hyperv-keyboard.c (10528B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Copyright (c) 2013, Microsoft Corporation.
      4 */
      5
      6#include <linux/init.h>
      7#include <linux/module.h>
      8#include <linux/device.h>
      9#include <linux/completion.h>
     10#include <linux/hyperv.h>
     11#include <linux/serio.h>
     12#include <linux/slab.h>
     13
     14/*
     15 * Current version 1.0
     16 *
     17 */
     18#define SYNTH_KBD_VERSION_MAJOR 1
     19#define SYNTH_KBD_VERSION_MINOR	0
     20#define SYNTH_KBD_VERSION		(SYNTH_KBD_VERSION_MINOR | \
     21					 (SYNTH_KBD_VERSION_MAJOR << 16))
     22
     23
     24/*
     25 * Message types in the synthetic input protocol
     26 */
     27enum synth_kbd_msg_type {
     28	SYNTH_KBD_PROTOCOL_REQUEST = 1,
     29	SYNTH_KBD_PROTOCOL_RESPONSE = 2,
     30	SYNTH_KBD_EVENT = 3,
     31	SYNTH_KBD_LED_INDICATORS = 4,
     32};
     33
     34/*
     35 * Basic message structures.
     36 */
     37struct synth_kbd_msg_hdr {
     38	__le32 type;
     39};
     40
     41struct synth_kbd_msg {
     42	struct synth_kbd_msg_hdr header;
     43	char data[]; /* Enclosed message */
     44};
     45
     46union synth_kbd_version {
     47	__le32 version;
     48};
     49
     50/*
     51 * Protocol messages
     52 */
     53struct synth_kbd_protocol_request {
     54	struct synth_kbd_msg_hdr header;
     55	union synth_kbd_version version_requested;
     56};
     57
     58#define PROTOCOL_ACCEPTED	BIT(0)
     59struct synth_kbd_protocol_response {
     60	struct synth_kbd_msg_hdr header;
     61	__le32 proto_status;
     62};
     63
     64#define IS_UNICODE	BIT(0)
     65#define IS_BREAK	BIT(1)
     66#define IS_E0		BIT(2)
     67#define IS_E1		BIT(3)
     68struct synth_kbd_keystroke {
     69	struct synth_kbd_msg_hdr header;
     70	__le16 make_code;
     71	__le16 reserved0;
     72	__le32 info; /* Additional information */
     73};
     74
     75
     76#define HK_MAXIMUM_MESSAGE_SIZE 256
     77
     78#define KBD_VSC_SEND_RING_BUFFER_SIZE	VMBUS_RING_SIZE(36 * 1024)
     79#define KBD_VSC_RECV_RING_BUFFER_SIZE	VMBUS_RING_SIZE(36 * 1024)
     80
     81#define XTKBD_EMUL0     0xe0
     82#define XTKBD_EMUL1     0xe1
     83#define XTKBD_RELEASE   0x80
     84
     85
     86/*
     87 * Represents a keyboard device
     88 */
     89struct hv_kbd_dev {
     90	struct hv_device *hv_dev;
     91	struct serio *hv_serio;
     92	struct synth_kbd_protocol_request protocol_req;
     93	struct synth_kbd_protocol_response protocol_resp;
     94	/* Synchronize the request/response if needed */
     95	struct completion wait_event;
     96	spinlock_t lock; /* protects 'started' field */
     97	bool started;
     98};
     99
    100static void hv_kbd_on_receive(struct hv_device *hv_dev,
    101			      struct synth_kbd_msg *msg, u32 msg_length)
    102{
    103	struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
    104	struct synth_kbd_keystroke *ks_msg;
    105	unsigned long flags;
    106	u32 msg_type = __le32_to_cpu(msg->header.type);
    107	u32 info;
    108	u16 scan_code;
    109
    110	switch (msg_type) {
    111	case SYNTH_KBD_PROTOCOL_RESPONSE:
    112		/*
    113		 * Validate the information provided by the host.
    114		 * If the host is giving us a bogus packet,
    115		 * drop the packet (hoping the problem
    116		 * goes away).
    117		 */
    118		if (msg_length < sizeof(struct synth_kbd_protocol_response)) {
    119			dev_err(&hv_dev->device,
    120				"Illegal protocol response packet (len: %d)\n",
    121				msg_length);
    122			break;
    123		}
    124
    125		memcpy(&kbd_dev->protocol_resp, msg,
    126			sizeof(struct synth_kbd_protocol_response));
    127		complete(&kbd_dev->wait_event);
    128		break;
    129
    130	case SYNTH_KBD_EVENT:
    131		/*
    132		 * Validate the information provided by the host.
    133		 * If the host is giving us a bogus packet,
    134		 * drop the packet (hoping the problem
    135		 * goes away).
    136		 */
    137		if (msg_length < sizeof(struct  synth_kbd_keystroke)) {
    138			dev_err(&hv_dev->device,
    139				"Illegal keyboard event packet (len: %d)\n",
    140				msg_length);
    141			break;
    142		}
    143
    144		ks_msg = (struct synth_kbd_keystroke *)msg;
    145		info = __le32_to_cpu(ks_msg->info);
    146
    147		/*
    148		 * Inject the information through the serio interrupt.
    149		 */
    150		spin_lock_irqsave(&kbd_dev->lock, flags);
    151		if (kbd_dev->started) {
    152			if (info & IS_E0)
    153				serio_interrupt(kbd_dev->hv_serio,
    154						XTKBD_EMUL0, 0);
    155			if (info & IS_E1)
    156				serio_interrupt(kbd_dev->hv_serio,
    157						XTKBD_EMUL1, 0);
    158			scan_code = __le16_to_cpu(ks_msg->make_code);
    159			if (info & IS_BREAK)
    160				scan_code |= XTKBD_RELEASE;
    161
    162			serio_interrupt(kbd_dev->hv_serio, scan_code, 0);
    163		}
    164		spin_unlock_irqrestore(&kbd_dev->lock, flags);
    165
    166		/*
    167		 * Only trigger a wakeup on key down, otherwise
    168		 * "echo freeze > /sys/power/state" can't really enter the
    169		 * state because the Enter-UP can trigger a wakeup at once.
    170		 */
    171		if (!(info & IS_BREAK))
    172			pm_wakeup_hard_event(&hv_dev->device);
    173
    174		break;
    175
    176	default:
    177		dev_err(&hv_dev->device,
    178			"unhandled message type %d\n", msg_type);
    179	}
    180}
    181
    182static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
    183					  struct vmpacket_descriptor *desc,
    184					  u32 bytes_recvd,
    185					  u64 req_id)
    186{
    187	struct synth_kbd_msg *msg;
    188	u32 msg_sz;
    189
    190	switch (desc->type) {
    191	case VM_PKT_COMP:
    192		break;
    193
    194	case VM_PKT_DATA_INBAND:
    195		/*
    196		 * We have a packet that has "inband" data. The API used
    197		 * for retrieving the packet guarantees that the complete
    198		 * packet is read. So, minimally, we should be able to
    199		 * parse the payload header safely (assuming that the host
    200		 * can be trusted.  Trusting the host seems to be a
    201		 * reasonable assumption because in a virtualized
    202		 * environment there is not whole lot you can do if you
    203		 * don't trust the host.
    204		 *
    205		 * Nonetheless, let us validate if the host can be trusted
    206		 * (in a trivial way).  The interesting aspect of this
    207		 * validation is how do you recover if we discover that the
    208		 * host is not to be trusted? Simply dropping the packet, I
    209		 * don't think is an appropriate recovery.  In the interest
    210		 * of failing fast, it may be better to crash the guest.
    211		 * For now, I will just drop the packet!
    212		 */
    213
    214		msg_sz = bytes_recvd - (desc->offset8 << 3);
    215		if (msg_sz <= sizeof(struct synth_kbd_msg_hdr)) {
    216			/*
    217			 * Drop the packet and hope
    218			 * the problem magically goes away.
    219			 */
    220			dev_err(&hv_dev->device,
    221				"Illegal packet (type: %d, tid: %llx, size: %d)\n",
    222				desc->type, req_id, msg_sz);
    223			break;
    224		}
    225
    226		msg = (void *)desc + (desc->offset8 << 3);
    227		hv_kbd_on_receive(hv_dev, msg, msg_sz);
    228		break;
    229
    230	default:
    231		dev_err(&hv_dev->device,
    232			"unhandled packet type %d, tid %llx len %d\n",
    233			desc->type, req_id, bytes_recvd);
    234		break;
    235	}
    236}
    237
    238static void hv_kbd_on_channel_callback(void *context)
    239{
    240	struct vmpacket_descriptor *desc;
    241	struct hv_device *hv_dev = context;
    242	u32 bytes_recvd;
    243	u64 req_id;
    244
    245	foreach_vmbus_pkt(desc, hv_dev->channel) {
    246		bytes_recvd = desc->len8 * 8;
    247		req_id = desc->trans_id;
    248
    249		hv_kbd_handle_received_packet(hv_dev, desc, bytes_recvd,
    250					      req_id);
    251	}
    252}
    253
    254static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev)
    255{
    256	struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
    257	struct synth_kbd_protocol_request *request;
    258	struct synth_kbd_protocol_response *response;
    259	u32 proto_status;
    260	int error;
    261
    262	reinit_completion(&kbd_dev->wait_event);
    263
    264	request = &kbd_dev->protocol_req;
    265	memset(request, 0, sizeof(struct synth_kbd_protocol_request));
    266	request->header.type = __cpu_to_le32(SYNTH_KBD_PROTOCOL_REQUEST);
    267	request->version_requested.version = __cpu_to_le32(SYNTH_KBD_VERSION);
    268
    269	error = vmbus_sendpacket(hv_dev->channel, request,
    270				 sizeof(struct synth_kbd_protocol_request),
    271				 (unsigned long)request,
    272				 VM_PKT_DATA_INBAND,
    273				 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
    274	if (error)
    275		return error;
    276
    277	if (!wait_for_completion_timeout(&kbd_dev->wait_event, 10 * HZ))
    278		return -ETIMEDOUT;
    279
    280	response = &kbd_dev->protocol_resp;
    281	proto_status = __le32_to_cpu(response->proto_status);
    282	if (!(proto_status & PROTOCOL_ACCEPTED)) {
    283		dev_err(&hv_dev->device,
    284			"synth_kbd protocol request failed (version %d)\n",
    285		        SYNTH_KBD_VERSION);
    286		return -ENODEV;
    287	}
    288
    289	return 0;
    290}
    291
    292static int hv_kbd_start(struct serio *serio)
    293{
    294	struct hv_kbd_dev *kbd_dev = serio->port_data;
    295	unsigned long flags;
    296
    297	spin_lock_irqsave(&kbd_dev->lock, flags);
    298	kbd_dev->started = true;
    299	spin_unlock_irqrestore(&kbd_dev->lock, flags);
    300
    301	return 0;
    302}
    303
    304static void hv_kbd_stop(struct serio *serio)
    305{
    306	struct hv_kbd_dev *kbd_dev = serio->port_data;
    307	unsigned long flags;
    308
    309	spin_lock_irqsave(&kbd_dev->lock, flags);
    310	kbd_dev->started = false;
    311	spin_unlock_irqrestore(&kbd_dev->lock, flags);
    312}
    313
    314static int hv_kbd_probe(struct hv_device *hv_dev,
    315			const struct hv_vmbus_device_id *dev_id)
    316{
    317	struct hv_kbd_dev *kbd_dev;
    318	struct serio *hv_serio;
    319	int error;
    320
    321	kbd_dev = kzalloc(sizeof(struct hv_kbd_dev), GFP_KERNEL);
    322	hv_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
    323	if (!kbd_dev || !hv_serio) {
    324		error = -ENOMEM;
    325		goto err_free_mem;
    326	}
    327
    328	kbd_dev->hv_dev = hv_dev;
    329	kbd_dev->hv_serio = hv_serio;
    330	spin_lock_init(&kbd_dev->lock);
    331	init_completion(&kbd_dev->wait_event);
    332	hv_set_drvdata(hv_dev, kbd_dev);
    333
    334	hv_serio->dev.parent  = &hv_dev->device;
    335	hv_serio->id.type = SERIO_8042_XL;
    336	hv_serio->port_data = kbd_dev;
    337	strlcpy(hv_serio->name, dev_name(&hv_dev->device),
    338		sizeof(hv_serio->name));
    339	strlcpy(hv_serio->phys, dev_name(&hv_dev->device),
    340		sizeof(hv_serio->phys));
    341
    342	hv_serio->start = hv_kbd_start;
    343	hv_serio->stop = hv_kbd_stop;
    344
    345	error = vmbus_open(hv_dev->channel,
    346			   KBD_VSC_SEND_RING_BUFFER_SIZE,
    347			   KBD_VSC_RECV_RING_BUFFER_SIZE,
    348			   NULL, 0,
    349			   hv_kbd_on_channel_callback,
    350			   hv_dev);
    351	if (error)
    352		goto err_free_mem;
    353
    354	error = hv_kbd_connect_to_vsp(hv_dev);
    355	if (error)
    356		goto err_close_vmbus;
    357
    358	serio_register_port(kbd_dev->hv_serio);
    359
    360	device_init_wakeup(&hv_dev->device, true);
    361
    362	return 0;
    363
    364err_close_vmbus:
    365	vmbus_close(hv_dev->channel);
    366err_free_mem:
    367	kfree(hv_serio);
    368	kfree(kbd_dev);
    369	return error;
    370}
    371
    372static int hv_kbd_remove(struct hv_device *hv_dev)
    373{
    374	struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
    375
    376	serio_unregister_port(kbd_dev->hv_serio);
    377	vmbus_close(hv_dev->channel);
    378	kfree(kbd_dev);
    379
    380	hv_set_drvdata(hv_dev, NULL);
    381
    382	return 0;
    383}
    384
    385static int hv_kbd_suspend(struct hv_device *hv_dev)
    386{
    387	vmbus_close(hv_dev->channel);
    388
    389	return 0;
    390}
    391
    392static int hv_kbd_resume(struct hv_device *hv_dev)
    393{
    394	int ret;
    395
    396	ret = vmbus_open(hv_dev->channel,
    397			 KBD_VSC_SEND_RING_BUFFER_SIZE,
    398			 KBD_VSC_RECV_RING_BUFFER_SIZE,
    399			 NULL, 0,
    400			 hv_kbd_on_channel_callback,
    401			 hv_dev);
    402	if (ret == 0)
    403		ret = hv_kbd_connect_to_vsp(hv_dev);
    404
    405	return ret;
    406}
    407
    408static const struct hv_vmbus_device_id id_table[] = {
    409	/* Keyboard guid */
    410	{ HV_KBD_GUID, },
    411	{ },
    412};
    413
    414MODULE_DEVICE_TABLE(vmbus, id_table);
    415
    416static struct  hv_driver hv_kbd_drv = {
    417	.name = KBUILD_MODNAME,
    418	.id_table = id_table,
    419	.probe = hv_kbd_probe,
    420	.remove = hv_kbd_remove,
    421	.suspend = hv_kbd_suspend,
    422	.resume = hv_kbd_resume,
    423	.driver = {
    424		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
    425	},
    426};
    427
    428static int __init hv_kbd_init(void)
    429{
    430	return vmbus_driver_register(&hv_kbd_drv);
    431}
    432
    433static void __exit hv_kbd_exit(void)
    434{
    435	vmbus_driver_unregister(&hv_kbd_drv);
    436}
    437
    438MODULE_LICENSE("GPL");
    439MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Keyboard Driver");
    440
    441module_init(hv_kbd_init);
    442module_exit(hv_kbd_exit);