5252#include <linux/acpi.h>
5353#include <linux/sizes.h>
5454#include <linux/of_irq.h>
55+ #include <linux/swiotlb.h>
5556#include <asm/mshyperv.h>
5657
5758/*
@@ -468,6 +469,42 @@ struct pci_eject_response {
468469
469470static int pci_ring_size = VMBUS_RING_SIZE (SZ_16K );
470471
472+ static phys_addr_t hv_pci_swiotlb_base ;
473+ static size_t hv_pci_swiotlb_size ;
474+ static bool hv_pci_swiotlb_published ;
475+
476+ #ifndef MODULE
477+ /*
478+ * Parse hv_pci_swiotlb=<size>; the base is picked when the driver
479+ * initializes. early_param is only available in built-in builds, so the
480+ * dedicated pool feature is effectively built-in only; module builds fall
481+ * back to the default swiotlb pool.
482+ */
483+ static int __init early_hv_pci_swiotlb (char * p )
484+ {
485+ char * end ;
486+
487+ if (!* p )
488+ return 0 ;
489+
490+ hv_pci_swiotlb_size = memparse (p , & end );
491+ if (* end != '\0' ) {
492+ pr_warn ("hv_pci: ignoring hv_pci_swiotlb=%s; expected hv_pci_swiotlb=<size>\n" ,
493+ p );
494+ hv_pci_swiotlb_size = 0 ;
495+ return 0 ;
496+ }
497+
498+ if (hv_pci_swiotlb_size )
499+ hv_pci_swiotlb_size = ALIGN (hv_pci_swiotlb_size , SZ_2M );
500+
501+ return 0 ;
502+ }
503+ early_param ("hv_pci_swiotlb" , early_hv_pci_swiotlb );
504+ #endif /* !MODULE */
505+
506+ static struct io_tlb_mem * hv_pci_swiotlb_pool ;
507+
471508/*
472509 * Driver specific state.
473510 */
@@ -2510,6 +2547,25 @@ static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
25102547 }
25112548}
25122549
2550+ /**
2551+ * hv_pci_assign_swiotlb() - assign dedicated swiotlb pool to bus devices
2552+ * @bus: PCI bus whose devices should use the pool
2553+ *
2554+ * If a dedicated swiotlb pool was configured via hv_pci_swiotlb=,
2555+ * assign it to every device on the bus so their DMA bounce buffering
2556+ * uses the restricted region.
2557+ */
2558+ static void hv_pci_assign_swiotlb (struct pci_bus * bus )
2559+ {
2560+ struct pci_dev * dev ;
2561+
2562+ if (!hv_pci_swiotlb_pool )
2563+ return ;
2564+
2565+ list_for_each_entry (dev , & bus -> devices , bus_list )
2566+ dev -> dev .dma_io_tlb_mem = hv_pci_swiotlb_pool ;
2567+ }
2568+
25132569/**
25142570 * create_root_hv_pci_bus() - Expose a new root PCI bus
25152571 * @hbus: Root PCI bus, as understood by this driver
@@ -2533,6 +2589,7 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
25332589 hv_pci_assign_numa_node (hbus );
25342590 pci_bus_assign_resources (bridge -> bus );
25352591 hv_pci_assign_slots (hbus );
2592+ hv_pci_assign_swiotlb (bridge -> bus );
25362593 pci_bus_add_devices (bridge -> bus );
25372594 pci_unlock_rescan_remove ();
25382595 hbus -> state = hv_pcibus_installed ;
@@ -2803,6 +2860,7 @@ static void pci_devices_present_work(struct work_struct *work)
28032860 pci_scan_child_bus (hbus -> bridge -> bus );
28042861 hv_pci_assign_numa_node (hbus );
28052862 hv_pci_assign_slots (hbus );
2863+ hv_pci_assign_swiotlb (hbus -> bridge -> bus );
28062864 pci_unlock_rescan_remove ();
28072865 break ;
28082866
@@ -4202,10 +4260,52 @@ static struct hv_driver hv_pci_drv = {
42024260 .resume = hv_pci_resume ,
42034261};
42044262
4263+ /* Publish swiotlb_{base,size} so userspace can forward the GPA to the host. */
4264+ static ssize_t swiotlb_base_show (struct device_driver * drv , char * buf )
4265+ {
4266+ return sysfs_emit (buf , "0x%llx\n" ,
4267+ (unsigned long long )hv_pci_swiotlb_base );
4268+ }
4269+ static DRIVER_ATTR_RO (swiotlb_base );
4270+
4271+ static ssize_t swiotlb_size_show (struct device_driver * drv , char * buf )
4272+ {
4273+ return sysfs_emit (buf , "%zu\n" , hv_pci_swiotlb_size );
4274+ }
4275+ static DRIVER_ATTR_RO (swiotlb_size );
4276+
4277+ static void hv_pci_swiotlb_unpublish (void )
4278+ {
4279+ if (!hv_pci_swiotlb_published )
4280+ return ;
4281+ driver_remove_file (& hv_pci_drv .driver , & driver_attr_swiotlb_size );
4282+ driver_remove_file (& hv_pci_drv .driver , & driver_attr_swiotlb_base );
4283+ hv_pci_swiotlb_published = false;
4284+ }
4285+
4286+ static void hv_pci_swiotlb_publish (void )
4287+ {
4288+ if (driver_create_file (& hv_pci_drv .driver , & driver_attr_swiotlb_base ))
4289+ goto warn ;
4290+ if (driver_create_file (& hv_pci_drv .driver , & driver_attr_swiotlb_size )) {
4291+ driver_remove_file (& hv_pci_drv .driver , & driver_attr_swiotlb_base );
4292+ goto warn ;
4293+ }
4294+ hv_pci_swiotlb_published = true;
4295+ return ;
4296+
4297+ warn :
4298+ pr_warn ("hv_pci: failed to publish swiotlb range to sysfs\n" );
4299+ }
4300+
42054301static void __exit exit_hv_pci_drv (void )
42064302{
4303+ hv_pci_swiotlb_unpublish ();
4304+
42074305 vmbus_driver_unregister (& hv_pci_drv );
42084306
4307+ /* No swiotlb_destroy_pool() exists, so the backing pages are leaked. */
4308+
42094309 hvpci_block_ops .read_block = NULL ;
42104310 hvpci_block_ops .write_block = NULL ;
42114311 hvpci_block_ops .reg_blk_invalidate = NULL ;
@@ -4233,8 +4333,83 @@ static int __init init_hv_pci_drv(void)
42334333 hvpci_block_ops .write_block = hv_write_config_block ;
42344334 hvpci_block_ops .reg_blk_invalidate = hv_register_block_invalidate ;
42354335
4236- return vmbus_driver_register (& hv_pci_drv );
4336+ ret = vmbus_driver_register (& hv_pci_drv );
4337+ if (ret )
4338+ return ret ;
4339+
4340+ if (hv_pci_swiotlb_pool )
4341+ hv_pci_swiotlb_publish ();
4342+
4343+ return 0 ;
4344+ }
4345+
4346+ #ifndef MODULE
4347+ /*
4348+ * The dedicated swiotlb pool feature is built-in only: the cmdline parser
4349+ * uses early_param (unavailable in modules) and the allocation runs as a
4350+ * core_initcall so the buddy allocator hands us a 64 MiB DMA32 contiguous
4351+ * range with minimal fragmentation risk. In module builds
4352+ * hv_pci_swiotlb_size stays 0 and the rest of the file's pool plumbing
4353+ * (probe, publish, exit) is naturally inert.
4354+ */
4355+ #ifdef CONFIG_CONTIG_ALLOC
4356+ /*
4357+ * Reserve the hv_pci swiotlb pool from the buddy allocator. __GFP_DMA32
4358+ * keeps the range below 4 GiB; kernel ownership keeps Hyper-V page
4359+ * reporting from yanking the backing. Gated on CONFIG_CONTIG_ALLOC.
4360+ */
4361+ static int __init hv_pci_swiotlb_alloc_pool (void )
4362+ {
4363+ phys_addr_t end ;
4364+ unsigned long nr_pages ;
4365+ struct page * pages ;
4366+
4367+ if (!hv_pci_swiotlb_size )
4368+ return 0 ;
4369+
4370+ nr_pages = hv_pci_swiotlb_size >> PAGE_SHIFT ;
4371+
4372+ /* UMA on WSL; first_online_node biases nothing in practice. */
4373+ pages = alloc_contig_pages (nr_pages ,
4374+ GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO ,
4375+ first_online_node , & node_online_map );
4376+ if (!pages ) {
4377+ pr_warn ("hv_pci: failed to allocate %zu-byte swiotlb pool below 4G; feature disabled\n" ,
4378+ hv_pci_swiotlb_size );
4379+ hv_pci_swiotlb_size = 0 ;
4380+ return 0 ;
4381+ }
4382+
4383+ hv_pci_swiotlb_base = page_to_phys (pages );
4384+ end = hv_pci_swiotlb_base + hv_pci_swiotlb_size ;
4385+
4386+ pr_info ("hv_pci: reserved swiotlb pool [%pa..%pa)\n" ,
4387+ & hv_pci_swiotlb_base , & end );
4388+
4389+ hv_pci_swiotlb_pool = swiotlb_create_pool (hv_pci_swiotlb_base ,
4390+ hv_pci_swiotlb_size ,
4391+ "hv-pci-swiotlb" );
4392+ if (IS_ERR (hv_pci_swiotlb_pool )) {
4393+ pr_err ("hv_pci: failed to create swiotlb pool: %ld\n" ,
4394+ PTR_ERR (hv_pci_swiotlb_pool ));
4395+ hv_pci_swiotlb_pool = NULL ;
4396+ free_contig_range (page_to_pfn (pages ), nr_pages );
4397+ hv_pci_swiotlb_base = 0 ;
4398+ hv_pci_swiotlb_size = 0 ;
4399+ }
4400+
4401+ return 0 ;
42374402}
4403+ #else
4404+ static int __init hv_pci_swiotlb_alloc_pool (void )
4405+ {
4406+ if (hv_pci_swiotlb_size )
4407+ pr_warn ("hv_pci: CONFIG_CONTIG_ALLOC disabled; hv_pci_swiotlb= ignored\n" );
4408+ return 0 ;
4409+ }
4410+ #endif
4411+ core_initcall (hv_pci_swiotlb_alloc_pool );
4412+ #endif /* !MODULE */
42384413
42394414module_init (init_hv_pci_drv );
42404415module_exit (exit_hv_pci_drv );
0 commit comments