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

virtio_bt.c (8487B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2
      3#include <linux/module.h>
      4#include <linux/virtio.h>
      5#include <linux/virtio_config.h>
      6#include <linux/skbuff.h>
      7
      8#include <uapi/linux/virtio_ids.h>
      9#include <uapi/linux/virtio_bt.h>
     10
     11#include <net/bluetooth/bluetooth.h>
     12#include <net/bluetooth/hci_core.h>
     13
     14#define VERSION "0.1"
     15
     16enum {
     17	VIRTBT_VQ_TX,
     18	VIRTBT_VQ_RX,
     19	VIRTBT_NUM_VQS,
     20};
     21
     22struct virtio_bluetooth {
     23	struct virtio_device *vdev;
     24	struct virtqueue *vqs[VIRTBT_NUM_VQS];
     25	struct work_struct rx;
     26	struct hci_dev *hdev;
     27};
     28
     29static int virtbt_add_inbuf(struct virtio_bluetooth *vbt)
     30{
     31	struct virtqueue *vq = vbt->vqs[VIRTBT_VQ_RX];
     32	struct scatterlist sg[1];
     33	struct sk_buff *skb;
     34	int err;
     35
     36	skb = alloc_skb(1000, GFP_KERNEL);
     37	if (!skb)
     38		return -ENOMEM;
     39
     40	sg_init_one(sg, skb->data, 1000);
     41
     42	err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
     43	if (err < 0) {
     44		kfree_skb(skb);
     45		return err;
     46	}
     47
     48	return 0;
     49}
     50
     51static int virtbt_open(struct hci_dev *hdev)
     52{
     53	struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
     54
     55	if (virtbt_add_inbuf(vbt) < 0)
     56		return -EIO;
     57
     58	virtqueue_kick(vbt->vqs[VIRTBT_VQ_RX]);
     59	return 0;
     60}
     61
     62static int virtbt_close(struct hci_dev *hdev)
     63{
     64	struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
     65	int i;
     66
     67	cancel_work_sync(&vbt->rx);
     68
     69	for (i = 0; i < ARRAY_SIZE(vbt->vqs); i++) {
     70		struct virtqueue *vq = vbt->vqs[i];
     71		struct sk_buff *skb;
     72
     73		while ((skb = virtqueue_detach_unused_buf(vq)))
     74			kfree_skb(skb);
     75	}
     76
     77	return 0;
     78}
     79
     80static int virtbt_flush(struct hci_dev *hdev)
     81{
     82	return 0;
     83}
     84
     85static int virtbt_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
     86{
     87	struct virtio_bluetooth *vbt = hci_get_drvdata(hdev);
     88	struct scatterlist sg[1];
     89	int err;
     90
     91	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
     92
     93	sg_init_one(sg, skb->data, skb->len);
     94	err = virtqueue_add_outbuf(vbt->vqs[VIRTBT_VQ_TX], sg, 1, skb,
     95				   GFP_KERNEL);
     96	if (err) {
     97		kfree_skb(skb);
     98		return err;
     99	}
    100
    101	virtqueue_kick(vbt->vqs[VIRTBT_VQ_TX]);
    102	return 0;
    103}
    104
    105static int virtbt_setup_zephyr(struct hci_dev *hdev)
    106{
    107	struct sk_buff *skb;
    108
    109	/* Read Build Information */
    110	skb = __hci_cmd_sync(hdev, 0xfc08, 0, NULL, HCI_INIT_TIMEOUT);
    111	if (IS_ERR(skb))
    112		return PTR_ERR(skb);
    113
    114	bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
    115
    116	hci_set_fw_info(hdev, "%s", skb->data + 1);
    117
    118	kfree_skb(skb);
    119	return 0;
    120}
    121
    122static int virtbt_set_bdaddr_zephyr(struct hci_dev *hdev,
    123				    const bdaddr_t *bdaddr)
    124{
    125	struct sk_buff *skb;
    126
    127	/* Write BD_ADDR */
    128	skb = __hci_cmd_sync(hdev, 0xfc06, 6, bdaddr, HCI_INIT_TIMEOUT);
    129	if (IS_ERR(skb))
    130		return PTR_ERR(skb);
    131
    132	kfree_skb(skb);
    133	return 0;
    134}
    135
    136static int virtbt_setup_intel(struct hci_dev *hdev)
    137{
    138	struct sk_buff *skb;
    139
    140	/* Intel Read Version */
    141	skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT);
    142	if (IS_ERR(skb))
    143		return PTR_ERR(skb);
    144
    145	kfree_skb(skb);
    146	return 0;
    147}
    148
    149static int virtbt_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
    150{
    151	struct sk_buff *skb;
    152
    153	/* Intel Write BD Address */
    154	skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
    155	if (IS_ERR(skb))
    156		return PTR_ERR(skb);
    157
    158	kfree_skb(skb);
    159	return 0;
    160}
    161
    162static int virtbt_setup_realtek(struct hci_dev *hdev)
    163{
    164	struct sk_buff *skb;
    165
    166	/* Read ROM Version */
    167	skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
    168	if (IS_ERR(skb))
    169		return PTR_ERR(skb);
    170
    171	bt_dev_info(hdev, "ROM version %u", *((__u8 *) (skb->data + 1)));
    172
    173	kfree_skb(skb);
    174	return 0;
    175}
    176
    177static int virtbt_shutdown_generic(struct hci_dev *hdev)
    178{
    179	struct sk_buff *skb;
    180
    181	/* Reset */
    182	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
    183	if (IS_ERR(skb))
    184		return PTR_ERR(skb);
    185
    186	kfree_skb(skb);
    187	return 0;
    188}
    189
    190static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb)
    191{
    192	__u8 pkt_type;
    193
    194	pkt_type = *((__u8 *) skb->data);
    195	skb_pull(skb, 1);
    196
    197	switch (pkt_type) {
    198	case HCI_EVENT_PKT:
    199	case HCI_ACLDATA_PKT:
    200	case HCI_SCODATA_PKT:
    201	case HCI_ISODATA_PKT:
    202		hci_skb_pkt_type(skb) = pkt_type;
    203		hci_recv_frame(vbt->hdev, skb);
    204		break;
    205	default:
    206		kfree_skb(skb);
    207		break;
    208	}
    209}
    210
    211static void virtbt_rx_work(struct work_struct *work)
    212{
    213	struct virtio_bluetooth *vbt = container_of(work,
    214						    struct virtio_bluetooth, rx);
    215	struct sk_buff *skb;
    216	unsigned int len;
    217
    218	skb = virtqueue_get_buf(vbt->vqs[VIRTBT_VQ_RX], &len);
    219	if (!skb)
    220		return;
    221
    222	skb->len = len;
    223	virtbt_rx_handle(vbt, skb);
    224
    225	if (virtbt_add_inbuf(vbt) < 0)
    226		return;
    227
    228	virtqueue_kick(vbt->vqs[VIRTBT_VQ_RX]);
    229}
    230
    231static void virtbt_tx_done(struct virtqueue *vq)
    232{
    233	struct sk_buff *skb;
    234	unsigned int len;
    235
    236	while ((skb = virtqueue_get_buf(vq, &len)))
    237		kfree_skb(skb);
    238}
    239
    240static void virtbt_rx_done(struct virtqueue *vq)
    241{
    242	struct virtio_bluetooth *vbt = vq->vdev->priv;
    243
    244	schedule_work(&vbt->rx);
    245}
    246
    247static int virtbt_probe(struct virtio_device *vdev)
    248{
    249	vq_callback_t *callbacks[VIRTBT_NUM_VQS] = {
    250		[VIRTBT_VQ_TX] = virtbt_tx_done,
    251		[VIRTBT_VQ_RX] = virtbt_rx_done,
    252	};
    253	const char *names[VIRTBT_NUM_VQS] = {
    254		[VIRTBT_VQ_TX] = "tx",
    255		[VIRTBT_VQ_RX] = "rx",
    256	};
    257	struct virtio_bluetooth *vbt;
    258	struct hci_dev *hdev;
    259	int err;
    260	__u8 type;
    261
    262	if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
    263		return -ENODEV;
    264
    265	type = virtio_cread8(vdev, offsetof(struct virtio_bt_config, type));
    266
    267	switch (type) {
    268	case VIRTIO_BT_CONFIG_TYPE_PRIMARY:
    269	case VIRTIO_BT_CONFIG_TYPE_AMP:
    270		break;
    271	default:
    272		return -EINVAL;
    273	}
    274
    275	vbt = kzalloc(sizeof(*vbt), GFP_KERNEL);
    276	if (!vbt)
    277		return -ENOMEM;
    278
    279	vdev->priv = vbt;
    280	vbt->vdev = vdev;
    281
    282	INIT_WORK(&vbt->rx, virtbt_rx_work);
    283
    284	err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, callbacks,
    285			      names, NULL);
    286	if (err)
    287		return err;
    288
    289	hdev = hci_alloc_dev();
    290	if (!hdev) {
    291		err = -ENOMEM;
    292		goto failed;
    293	}
    294
    295	vbt->hdev = hdev;
    296
    297	hdev->bus = HCI_VIRTIO;
    298	hdev->dev_type = type;
    299	hci_set_drvdata(hdev, vbt);
    300
    301	hdev->open  = virtbt_open;
    302	hdev->close = virtbt_close;
    303	hdev->flush = virtbt_flush;
    304	hdev->send  = virtbt_send_frame;
    305
    306	if (virtio_has_feature(vdev, VIRTIO_BT_F_VND_HCI)) {
    307		__u16 vendor;
    308
    309		virtio_cread(vdev, struct virtio_bt_config, vendor, &vendor);
    310
    311		switch (vendor) {
    312		case VIRTIO_BT_CONFIG_VENDOR_ZEPHYR:
    313			hdev->manufacturer = 1521;
    314			hdev->setup = virtbt_setup_zephyr;
    315			hdev->shutdown = virtbt_shutdown_generic;
    316			hdev->set_bdaddr = virtbt_set_bdaddr_zephyr;
    317			break;
    318
    319		case VIRTIO_BT_CONFIG_VENDOR_INTEL:
    320			hdev->manufacturer = 2;
    321			hdev->setup = virtbt_setup_intel;
    322			hdev->shutdown = virtbt_shutdown_generic;
    323			hdev->set_bdaddr = virtbt_set_bdaddr_intel;
    324			set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
    325			set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
    326			set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
    327			break;
    328
    329		case VIRTIO_BT_CONFIG_VENDOR_REALTEK:
    330			hdev->manufacturer = 93;
    331			hdev->setup = virtbt_setup_realtek;
    332			hdev->shutdown = virtbt_shutdown_generic;
    333			set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
    334			set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
    335			break;
    336		}
    337	}
    338
    339	if (virtio_has_feature(vdev, VIRTIO_BT_F_MSFT_EXT)) {
    340		__u16 msft_opcode;
    341
    342		virtio_cread(vdev, struct virtio_bt_config,
    343			     msft_opcode, &msft_opcode);
    344
    345		hci_set_msft_opcode(hdev, msft_opcode);
    346	}
    347
    348	if (virtio_has_feature(vdev, VIRTIO_BT_F_AOSP_EXT))
    349		hci_set_aosp_capable(hdev);
    350
    351	if (hci_register_dev(hdev) < 0) {
    352		hci_free_dev(hdev);
    353		err = -EBUSY;
    354		goto failed;
    355	}
    356
    357	return 0;
    358
    359failed:
    360	vdev->config->del_vqs(vdev);
    361	return err;
    362}
    363
    364static void virtbt_remove(struct virtio_device *vdev)
    365{
    366	struct virtio_bluetooth *vbt = vdev->priv;
    367	struct hci_dev *hdev = vbt->hdev;
    368
    369	hci_unregister_dev(hdev);
    370	virtio_reset_device(vdev);
    371
    372	hci_free_dev(hdev);
    373	vbt->hdev = NULL;
    374
    375	vdev->config->del_vqs(vdev);
    376	kfree(vbt);
    377}
    378
    379static struct virtio_device_id virtbt_table[] = {
    380	{ VIRTIO_ID_BT, VIRTIO_DEV_ANY_ID },
    381	{ 0 },
    382};
    383
    384MODULE_DEVICE_TABLE(virtio, virtbt_table);
    385
    386static const unsigned int virtbt_features[] = {
    387	VIRTIO_BT_F_VND_HCI,
    388	VIRTIO_BT_F_MSFT_EXT,
    389	VIRTIO_BT_F_AOSP_EXT,
    390};
    391
    392static struct virtio_driver virtbt_driver = {
    393	.driver.name         = KBUILD_MODNAME,
    394	.driver.owner        = THIS_MODULE,
    395	.feature_table       = virtbt_features,
    396	.feature_table_size  = ARRAY_SIZE(virtbt_features),
    397	.id_table            = virtbt_table,
    398	.probe               = virtbt_probe,
    399	.remove              = virtbt_remove,
    400};
    401
    402module_virtio_driver(virtbt_driver);
    403
    404MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
    405MODULE_DESCRIPTION("Generic Bluetooth VIRTIO driver ver " VERSION);
    406MODULE_VERSION(VERSION);
    407MODULE_LICENSE("GPL");