From 93de2a6a4b91b72607136dd656edf03fb399d27f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 23 Sep 2026 09:37:21 -0700 Subject: KVM: SEV: Do cache maintenance on the source VM during intra-host migration Manually perform cache maintenance on the source VM during intra-host migration to ensure no stale data is left in CPU caches after the VM is destroyed. Because the source VM is "converted" to a non-SEV VM, KVM's memory reclaim flows won't trigger cache maintenance, e.g. when all guest memory is reclaimed in response to detaching from the mmu_notifier. Note, relying on the destination VM to do cache maintenance isn't an option as KVM doesn't require identical guest memory configurations, i.e. the source VM may have access to memory that the destination VM does not. Enforcing equivalent memory configurations is infeasible, as it would require a *deep* comparison of memslots, e.g. to verify that not only are the memslot identical, but what the memslots point at is also identical. Fixes: b56639318bb2 ("KVM: SEV: Add support for SEV intra host migration") Cc: stable@vger.kernel.org Reported-by: Stefan Teodorescu Signed-off-by: Sean Christopherson Message-ID: <20260923163721.1584779-3-seanjc@google.com> Signed-off-by: Paolo Bonzini --- drivers/net/usb/gl620a.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 drivers/net/usb/gl620a.c (limited to 'drivers/net/usb/gl620a.c') diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c new file mode 100644 index 000000000..09afd137b --- /dev/null +++ b/drivers/net/usb/gl620a.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GeneSys GL620USB-A based links + * Copyright (C) 2001 by Jiun-Jie Huang + * Copyright (C) 2001 by Stanislav Brabec + */ + +// #define DEBUG // error path messages, extra info +// #define VERBOSE // more; success messages + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * GeneSys GL620USB-A (www.genesyslogic.com.tw) + * + * ... should partially interop with the Win32 driver for this hardware. + * The GeneSys docs imply there's some NDIS issue motivating this framing. + * + * Some info from GeneSys: + * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk. + * (Some cables, like the BAFO-100c, use the half duplex version.) + * - For the full duplex model, the low bit of the version code says + * which side is which ("left/right"). + * - For the half duplex type, a control/interrupt handshake settles + * the transfer direction. (That's disabled here, partially coded.) + * A control URB would block until other side writes an interrupt. + * + * Original code from Jiun-Jie Huang + * and merged into "usbnet" by Stanislav Brabec . + */ + +// control msg write command +#define GENELINK_CONNECT_WRITE 0xF0 +// interrupt pipe index +#define GENELINK_INTERRUPT_PIPE 0x03 +// interrupt read buffer size +#define INTERRUPT_BUFSIZE 0x08 +// interrupt pipe interval value +#define GENELINK_INTERRUPT_INTERVAL 0x10 +// max transmit packet number per transmit +#define GL_MAX_TRANSMIT_PACKETS 32 +// max packet length +#define GL_MAX_PACKET_LEN 1514 +// max receive buffer size +#define GL_RCV_BUF_SIZE \ + (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4) + +struct gl_packet { + __le32 packet_length; + char packet_data[]; +}; + +struct gl_header { + __le32 packet_count; + struct gl_packet packets; +}; + +static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + struct gl_header *header; + struct gl_packet *packet; + struct sk_buff *gl_skb; + u32 size; + u32 count; + + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + + header = (struct gl_header *) skb->data; + + // get the packet count of the received skb + count = le32_to_cpu(header->packet_count); + if (count > GL_MAX_TRANSMIT_PACKETS) { + netdev_dbg(dev->net, + "genelink: invalid received packet count %u\n", + count); + return 0; + } + + // set the current packet pointer to the first packet + packet = &header->packets; + + // decrement the length for the packet count size 4 bytes + skb_pull(skb, 4); + + while (count > 1) { + // get the packet length + size = le32_to_cpu(packet->packet_length); + + // this may be a broken packet + if (size > GL_MAX_PACKET_LEN) { + netdev_dbg(dev->net, "genelink: invalid rx length %d\n", + size); + return 0; + } + + if (!skb_pull(skb, size + 4)) + return 0; + + // allocate the skb for the individual packet + gl_skb = alloc_skb(size, GFP_ATOMIC); + if (gl_skb) { + + // copy the packet data to the new skb + skb_put_data(gl_skb, packet->packet_data, size); + usbnet_skb_return(dev, gl_skb); + } + + // advance to the next packet + packet = (struct gl_packet *)&packet->packet_data[size]; + count--; + } + + // skip the packet length field 4 bytes + skb_pull(skb, 4); + + if (skb->len > GL_MAX_PACKET_LEN) { + netdev_dbg(dev->net, "genelink: invalid rx length %d\n", + skb->len); + return 0; + } + return 1; +} + +static struct sk_buff * +genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) +{ + int padlen; + int length = skb->len; + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + __le32 *packet_count; + __le32 *packet_len; + + // FIXME: magic numbers, bleech + padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1; + + if ((!skb_cloned(skb)) + && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) { + if ((headroom < (4 + 4*1)) || (tailroom < padlen)) { + skb->data = memmove(skb->head + (4 + 4*1), + skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + } + } else { + struct sk_buff *skb2; + skb2 = skb_copy_expand(skb, (4 + 4*1) , padlen, flags); + dev_kfree_skb_any(skb); + skb = skb2; + if (!skb) + return NULL; + } + + // attach the packet count to the header + packet_count = skb_push(skb, (4 + 4 * 1)); + packet_len = packet_count + 1; + + *packet_count = cpu_to_le32(1); + *packet_len = cpu_to_le32(length); + + // add padding byte + if ((skb->len % dev->maxpacket) == 0) + skb_put(skb, 1); + + return skb; +} + +static int genelink_bind(struct usbnet *dev, struct usb_interface *intf) +{ + dev->hard_mtu = GL_RCV_BUF_SIZE; + dev->net->hard_header_len += 4; + return usbnet_get_endpoints(dev, intf); +} + +static const struct driver_info genelink_info = { + .description = "Genesys GeneLink", + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_GL | FLAG_NO_SETINT, + .bind = genelink_bind, + .rx_fixup = genelink_rx_fixup, + .tx_fixup = genelink_tx_fixup, + + .in = 1, .out = 2, + +#ifdef GENELINK_ACK + .check_connect =genelink_check_connect, +#endif +}; + +static const struct usb_device_id products [] = { + +{ + USB_DEVICE(0x05e3, 0x0502), // GL620USB-A + .driver_info = (unsigned long) &genelink_info, +}, + /* NOT: USB_DEVICE(0x05e3, 0x0501), // GL620USB + * that's half duplex, not currently supported + */ + { }, // END +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver gl620a_driver = { + .name = "gl620a", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, + .disable_hub_initiated_lpm = 1, +}; + +module_usb_driver(gl620a_driver); + +MODULE_AUTHOR("Jiun-Jie Huang"); +MODULE_DESCRIPTION("GL620-USB-A Host-to-Host Link cables"); +MODULE_LICENSE("GPL"); + -- cgit v1.3.1