Pull hyperv updates from Wei Liu: - More patches for Hyper-V isolation VM support (Tianyu Lan) - Bug fixes and clean-up patches from various people * tag 'hyperv-next-signed-20220114' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: scsi: storvsc: Fix storvsc_queuecommand() memory leak x86/hyperv: Properly deal with empty cpumasks in hyperv_flush_tlb_multi() Drivers: hv: vmbus: Initialize request offers message for Isolation VM scsi: storvsc: Fix unsigned comparison to zero swiotlb: Add CONFIG_HAS_IOMEM check around swiotlb_mem_remap() x86/hyperv: Fix definition of hv_ghcb_pg variable Drivers: hv: Fix definition of hypercall input & output arg variables net: netvsc: Add Isolation VM support for netvsc driver scsi: storvsc: Add Isolation VM support for storvsc driver hyper-v: Enable swiotlb bounce buffer for Isolation VM x86/hyper-v: Add hyperv Isolation VM check in the cc_platform_has() swiotlb: Add swiotlb bounce buffer remap function for HV IVM
Unified · Split
| @@ -28,6 +28,7 @@ · 27 unmodified lines | |||
| 28 | #include <linux/syscore_ops.h> | 28 | #include <linux/syscore_ops.h> |
| 29 | #include <clocksource/hyperv_timer.h> | 29 | #include <clocksource/hyperv_timer.h> |
| 30 | #include <linux/highmem.h> | 30 | #include <linux/highmem.h> |
| 31 | #include <linux/swiotlb.h> | ||
| 31 | 32 | ||
| 32 | int hyperv_init_cpuhp; | 33 | int hyperv_init_cpuhp; |
| 33 | u64 hv_current_partition_id = ~0ull; | 34 | u64 hv_current_partition_id = ~0ull; |
| @@ -36,7 +37,7 @@ EXPORT_SYMBOL_GPL(hv_current_partition_id); · 2 unmodified lines | |||
| 36 | void *hv_hypercall_pg; | 37 | void *hv_hypercall_pg; |
| 37 | EXPORT_SYMBOL_GPL(hv_hypercall_pg); | 38 | EXPORT_SYMBOL_GPL(hv_hypercall_pg); |
| 38 | 39 | ||
| 39 | union hv_ghcb __percpu **hv_ghcb_pg; | 40 | union hv_ghcb * __percpu *hv_ghcb_pg; |
| 40 | 41 | ||
| 41 | /* Storage to save the hypercall page temporarily for hibernation */ | 42 | /* Storage to save the hypercall page temporarily for hibernation */ |
| 42 | static void *hv_hypercall_pg_saved; | 43 | static void *hv_hypercall_pg_saved; |
| @@ -498,6 +499,17 @@ void __init hyperv_init(void) · 455 unmodified lines | |||
| 498 | 499 | ||
| 499 | /* Query the VMs extended capability once, so that it can be cached. */ | 500 | /* Query the VMs extended capability once, so that it can be cached. */ |
| 500 | hv_query_ext_cap(0); | 501 | hv_query_ext_cap(0); |
| 502 | |||
| 503 | #ifdef CONFIG_SWIOTLB | ||
| 504 | /* | ||
| 505 | * Swiotlb bounce buffer needs to be mapped in extra address | ||
| 506 | * space. Map function doesn't work in the early place and so | ||
| 507 | * call swiotlb_update_mem_attributes() here. | ||
| 508 | */ | ||
| 509 | if (hv_is_isolation_supported()) | ||
| 510 | swiotlb_update_mem_attributes(); | ||
| 511 | #endif | ||
| 512 | |||
| 501 | return; | 513 | return; |
| 502 | 514 | ||
| 503 | clean_guest_os_id: | 515 | clean_guest_os_id: |
| @@ -287,3 +287,31 @@ int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visibl · 286 unmodified lines | |||
| 287 | kfree(pfn_array); | 287 | kfree(pfn_array); |
| 288 | return ret; | 288 | return ret; |
| 289 | } | 289 | } |
| 290 | |||
| 291 | /* | ||
| 292 | * hv_map_memory - map memory to extra space in the AMD SEV-SNP Isolation VM. | ||
| 293 | */ | ||
| 294 | void *hv_map_memory(void *addr, unsigned long size) | ||
| 295 | { | ||
| 296 | unsigned long *pfns = kcalloc(size / PAGE_SIZE, | ||
| 297 | sizeof(unsigned long), GFP_KERNEL); | ||
| 298 | void *vaddr; | ||
| 299 | int i; | ||
| 300 | |||
| 301 | if (!pfns) | ||
| 302 | return NULL; | ||
| 303 | |||
| 304 | for (i = 0; i < size / PAGE_SIZE; i++) | ||
| 305 | pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) + | ||
| 306 | (ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT); | ||
| 307 | |||
| 308 | vaddr = vmap_pfn(pfns, size / PAGE_SIZE, PAGE_KERNEL_IO); | ||
| 309 | kfree(pfns); | ||
| 310 | |||
| 311 | return vaddr; | ||
| 312 | } | ||
| 313 | |||
| 314 | void hv_unmap_memory(void *addr) | ||
| 315 | { | ||
| 316 | vunmap(addr); | ||
| 317 | } | ||
| @@ -68,15 +68,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 67 unmodified lines | |||
| 68 | 68 | ||
| 69 | local_irq_save(flags); | 69 | local_irq_save(flags); |
| 70 | 70 | ||
| 71 | /* | ||
| 72 | * Only check the mask _after_ interrupt has been disabled to avoid the | ||
| 73 | * mask changing under our feet. | ||
| 74 | */ | ||
| 75 | if (cpumask_empty(cpus)) { | ||
| 76 | local_irq_restore(flags); | ||
| 77 | return; | ||
| 78 | } | ||
| 79 | |||
| 80 | flush_pcpu = (struct hv_tlb_flush **) | 71 | flush_pcpu = (struct hv_tlb_flush **) |
| 81 | this_cpu_ptr(hyperv_pcpu_input_arg); | 72 | this_cpu_ptr(hyperv_pcpu_input_arg); |
| 82 | 73 | ||
| @@ -115,7 +106,9 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 32 unmodified lines | |||
| 115 | * must. We will also check all VP numbers when walking the | 106 | * must. We will also check all VP numbers when walking the |
| 116 | * supplied CPU set to remain correct in all cases. | 107 | * supplied CPU set to remain correct in all cases. |
| 117 | */ | 108 | */ |
| 118 | if (hv_cpu_number_to_vp_number(cpumask_last(cpus)) >= 64) | 109 | cpu = cpumask_last(cpus); |
| 110 | |||
| 111 | if (cpu < nr_cpumask_bits && hv_cpu_number_to_vp_number(cpu) >= 64) | ||
| 119 | goto do_ex_hypercall; | 112 | goto do_ex_hypercall; |
| 120 | 113 | ||
| 121 | for_each_cpu(cpu, cpus) { | 114 | for_each_cpu(cpu, cpus) { |
| @@ -131,6 +124,12 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 9 unmodified lines | |||
| 131 | __set_bit(vcpu, (unsigned long *) | 124 | __set_bit(vcpu, (unsigned long *) |
| 132 | &flush->processor_mask); | 125 | &flush->processor_mask); |
| 133 | } | 126 | } |
| 127 | |||
| 128 | /* nothing to flush if 'processor_mask' ends up being empty */ | ||
| 129 | if (!flush->processor_mask) { | ||
| 130 | local_irq_restore(flags); | ||
| 131 | return; | ||
| 132 | } | ||
| 134 | } | 133 | } |
| 135 | 134 | ||
| 136 | /* | 135 | /* |
| @@ -30,7 +30,7 @@ extern void *hv_hypercall_pg; · 29 unmodified lines | |||
| 30 | 30 | ||
| 31 | extern u64 hv_current_partition_id; | 31 | extern u64 hv_current_partition_id; |
| 32 | 32 | ||
| 33 | extern union hv_ghcb __percpu **hv_ghcb_pg; | 33 | extern union hv_ghcb * __percpu *hv_ghcb_pg; |
| 34 | 34 | ||
| 35 | int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); | 35 | int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); |
| 36 | int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); | 36 | int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/cc_platform.h> | 11 | #include <linux/cc_platform.h> |
| 12 | #include <linux/mem_encrypt.h> | 12 | #include <linux/mem_encrypt.h> |
| 13 | 13 | ||
| 14 | #include <asm/mshyperv.h> | ||
| 14 | #include <asm/processor.h> | 15 | #include <asm/processor.h> |
| 15 | 16 | ||
| 16 | static bool __maybe_unused intel_cc_platform_has(enum cc_attr attr) | 17 | static bool __maybe_unused intel_cc_platform_has(enum cc_attr attr) |
| @@ -66,12 +67,19 @@ static bool amd_cc_platform_has(enum cc_attr attr) · 49 unmodified lines | |||
| 66 | #endif | 67 | #endif |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 70 | static bool hyperv_cc_platform_has(enum cc_attr attr) | ||
| 71 | { | ||
| 72 | return attr == CC_ATTR_GUEST_MEM_ENCRYPT; | ||
| 73 | } | ||
| 69 | 74 | ||
| 70 | bool cc_platform_has(enum cc_attr attr) | 75 | bool cc_platform_has(enum cc_attr attr) |
| 71 | { | 76 | { |
| 72 | if (sme_me_mask) | 77 | if (sme_me_mask) |
| 73 | return amd_cc_platform_has(attr); | 78 | return amd_cc_platform_has(attr); |
| 74 | 79 | ||
| 80 | if (hv_is_isolation_supported()) | ||
| 81 | return hyperv_cc_platform_has(attr); | ||
| 82 | |||
| 75 | return false; | 83 | return false; |
| 76 | } | 84 | } |
| 77 | EXPORT_SYMBOL_GPL(cc_platform_has); | 85 | EXPORT_SYMBOL_GPL(cc_platform_has); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <linux/kexec.h> | 18 | #include <linux/kexec.h> |
| 19 | #include <linux/i8253.h> | 19 | #include <linux/i8253.h> |
| 20 | #include <linux/random.h> | 20 | #include <linux/random.h> |
| 21 | #include <linux/swiotlb.h> | ||
| 21 | #include <asm/processor.h> | 22 | #include <asm/processor.h> |
| 22 | #include <asm/hypervisor.h> | 23 | #include <asm/hypervisor.h> |
| 23 | #include <asm/hyperv-tlfs.h> | 24 | #include <asm/hyperv-tlfs.h> |
| @@ -329,8 +330,20 @@ static void __init ms_hyperv_init_platform(void) · 305 unmodified lines | |||
| 329 | pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n", | 330 | pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n", |
| 330 | ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); | 331 | ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); |
| 331 | 332 | ||
| 332 | if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) | 333 | if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) { |
| 333 | static_branch_enable(&isolation_type_snp); | 334 | static_branch_enable(&isolation_type_snp); |
| 335 | #ifdef CONFIG_SWIOTLB | ||
| 336 | swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary; | ||
| 337 | #endif | ||
| 338 | } | ||
| 339 | |||
| 340 | #ifdef CONFIG_SWIOTLB | ||
| 341 | /* | ||
| 342 | * Enable swiotlb force mode in Isolation VM to | ||
| 343 | * use swiotlb bounce buffer for dma transaction. | ||
| 344 | */ | ||
| 345 | swiotlb_force = SWIOTLB_FORCE; | ||
| 346 | #endif | ||
| 334 | } | 347 | } |
| 335 | 348 | ||
| 336 | if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { | 349 | if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { |
| @@ -1554,7 +1554,7 @@ int vmbus_request_offers(void) · 1553 unmodified lines | |||
| 1554 | struct vmbus_channel_msginfo *msginfo; | 1554 | struct vmbus_channel_msginfo *msginfo; |
| 1555 | int ret; | 1555 | int ret; |
| 1556 | 1556 | ||
| 1557 | msginfo = kmalloc(sizeof(*msginfo) + | 1557 | msginfo = kzalloc(sizeof(*msginfo) + |
| 1558 | sizeof(struct vmbus_channel_message_header), | 1558 | sizeof(struct vmbus_channel_message_header), |
| 1559 | GFP_KERNEL); | 1559 | GFP_KERNEL); |
| 1560 | if (!msginfo) | 1560 | if (!msginfo) |
| @@ -44,10 +44,10 @@ EXPORT_SYMBOL_GPL(hv_vp_index); · 43 unmodified lines | |||
| 44 | u32 hv_max_vp_index; | 44 | u32 hv_max_vp_index; |
| 45 | EXPORT_SYMBOL_GPL(hv_max_vp_index); | 45 | EXPORT_SYMBOL_GPL(hv_max_vp_index); |
| 46 | 46 | ||
| 47 | void __percpu **hyperv_pcpu_input_arg; | 47 | void * __percpu *hyperv_pcpu_input_arg; |
| 48 | EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); | 48 | EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); |
| 49 | 49 | ||
| 50 | void __percpu **hyperv_pcpu_output_arg; | 50 | void * __percpu *hyperv_pcpu_output_arg; |
| 51 | EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); | 51 | EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); |
| 52 | 52 | ||
| 53 | /* | 53 | /* |
| @@ -295,3 +295,14 @@ u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_s · 241 unmodified lines | |||
| 295 | return HV_STATUS_INVALID_PARAMETER; | 295 | return HV_STATUS_INVALID_PARAMETER; |
| 296 | } | 296 | } |
| 297 | EXPORT_SYMBOL_GPL(hv_ghcb_hypercall); | 297 | EXPORT_SYMBOL_GPL(hv_ghcb_hypercall); |
| 298 | |||
| 299 | void __weak *hv_map_memory(void *addr, unsigned long size) | ||
| 300 | { | ||
| 301 | return NULL; | ||
| 302 | } | ||
| 303 | EXPORT_SYMBOL_GPL(hv_map_memory); | ||
| 304 | |||
| 305 | void __weak hv_unmap_memory(void *addr) | ||
| 306 | { | ||
| 307 | } | ||
| 308 | EXPORT_SYMBOL_GPL(hv_unmap_memory); | ||
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | #include <linux/random.h> | 33 | #include <linux/random.h> |
| 34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
| 35 | #include <linux/syscore_ops.h> | 35 | #include <linux/syscore_ops.h> |
| 36 | #include <linux/dma-map-ops.h> | ||
| 36 | #include <clocksource/hyperv_timer.h> | 37 | #include <clocksource/hyperv_timer.h> |
| 37 | #include "hyperv_vmbus.h" | 38 | #include "hyperv_vmbus.h" |
| 38 | 39 | ||
| @@ -2078,6 +2079,7 @@ struct hv_device *vmbus_device_create(const guid_t *type, · 2039 unmodified lines | |||
| 2078 | return child_device_obj; | 2079 | return child_device_obj; |
| 2079 | } | 2080 | } |
| 2080 | 2081 | ||
| 2082 | static u64 vmbus_dma_mask = DMA_BIT_MASK(64); | ||
| 2081 | /* | 2083 | /* |
| 2082 | * vmbus_device_register - Register the child device | 2084 | * vmbus_device_register - Register the child device |
| 2083 | */ | 2085 | */ |
| @@ -2118,6 +2120,8 @@ int vmbus_device_register(struct hv_device *child_device_obj) · 34 unmodified lines | |||
| 2118 | } | 2120 | } |
| 2119 | hv_debug_add_dev_dir(child_device_obj); | 2121 | hv_debug_add_dev_dir(child_device_obj); |
| 2120 | 2122 | ||
| 2123 | child_device_obj->device.dma_mask = &vmbus_dma_mask; | ||
| 2124 | child_device_obj->device.dma_parms = &child_device_obj->dma_parms; | ||
| 2121 | return 0; | 2125 | return 0; |
| 2122 | 2126 | ||
| 2123 | err_kset_unregister: | 2127 | err_kset_unregister: |
| @@ -164,6 +164,7 @@ struct hv_netvsc_packet { · 163 unmodified lines | |||
| 164 | u32 total_bytes; | 164 | u32 total_bytes; |
| 165 | u32 send_buf_index; | 165 | u32 send_buf_index; |
| 166 | u32 total_data_buflen; | 166 | u32 total_data_buflen; |
| 167 | struct hv_dma_range *dma_range; | ||
| 167 | }; | 168 | }; |
| 168 | 169 | ||
| 169 | #define NETVSC_HASH_KEYLEN 40 | 170 | #define NETVSC_HASH_KEYLEN 40 |
| @@ -1074,6 +1075,7 @@ struct netvsc_device { · 904 unmodified lines | |||
| 1074 | 1075 | ||
| 1075 | /* Receive buffer allocated by us but manages by NetVSP */ | 1076 | /* Receive buffer allocated by us but manages by NetVSP */ |
| 1076 | void *recv_buf; | 1077 | void *recv_buf; |
| 1078 | void *recv_original_buf; | ||
| 1077 | u32 recv_buf_size; /* allocated bytes */ | 1079 | u32 recv_buf_size; /* allocated bytes */ |
| 1078 | struct vmbus_gpadl recv_buf_gpadl_handle; | 1080 | struct vmbus_gpadl recv_buf_gpadl_handle; |
| 1079 | u32 recv_section_cnt; | 1081 | u32 recv_section_cnt; |
| @@ -1082,6 +1084,7 @@ struct netvsc_device { · 2 unmodified lines | |||
| 1082 | 1084 | ||
| 1083 | /* Send buffer allocated by us */ | 1085 | /* Send buffer allocated by us */ |
| 1084 | void *send_buf; | 1086 | void *send_buf; |
| 1087 | void *send_original_buf; | ||
| 1085 | u32 send_buf_size; | 1088 | u32 send_buf_size; |
| 1086 | struct vmbus_gpadl send_buf_gpadl_handle; | 1089 | struct vmbus_gpadl send_buf_gpadl_handle; |
| 1087 | u32 send_section_cnt; | 1090 | u32 send_section_cnt; |
| @@ -1731,4 +1734,6 @@ struct rndis_message { · 643 unmodified lines | |||
| 1731 | #define RETRY_US_HI 10000 | 1734 | #define RETRY_US_HI 10000 |
| 1732 | #define RETRY_MAX 2000 /* >10 sec */ | 1735 | #define RETRY_MAX 2000 /* >10 sec */ |
| 1733 | 1736 | ||
| 1737 | void netvsc_dma_unmap(struct hv_device *hv_dev, | ||
| 1738 | struct hv_netvsc_packet *packet); | ||
| 1734 | #endif /* _HYPERV_NET_H */ | 1739 | #endif /* _HYPERV_NET_H */ |
| @@ -153,8 +153,21 @@ static void free_netvsc_device(struct rcu_head *head) · 152 unmodified lines | |||
| 153 | int i; | 153 | int i; |
| 154 | 154 | ||
| 155 | kfree(nvdev->extension); | 155 | kfree(nvdev->extension); |
| 156 | vfree(nvdev->recv_buf); | 156 | |
| 157 | vfree(nvdev->send_buf); | 157 | if (nvdev->recv_original_buf) { |
| 158 | hv_unmap_memory(nvdev->recv_buf); | ||
| 159 | vfree(nvdev->recv_original_buf); | ||
| 160 | } else { | ||
| 161 | vfree(nvdev->recv_buf); | ||
| 162 | } | ||
| 163 | |||
| 164 | if (nvdev->send_original_buf) { | ||
| 165 | hv_unmap_memory(nvdev->send_buf); | ||
| 166 | vfree(nvdev->send_original_buf); | ||
| 167 | } else { | ||
| 168 | vfree(nvdev->send_buf); | ||
| 169 | } | ||
| 170 | |||
| 158 | bitmap_free(nvdev->send_section_map); | 171 | bitmap_free(nvdev->send_section_map); |
| 159 | 172 | ||
| 160 | for (i = 0; i < VRSS_CHANNEL_MAX; i++) { | 173 | for (i = 0; i < VRSS_CHANNEL_MAX; i++) { |
| @@ -337,6 +350,7 @@ static int netvsc_init_buf(struct hv_device *device, · 176 unmodified lines | |||
| 337 | struct nvsp_message *init_packet; | 350 | struct nvsp_message *init_packet; |
| 338 | unsigned int buf_size; | 351 | unsigned int buf_size; |
| 339 | int i, ret = 0; | 352 | int i, ret = 0; |
| 353 | void *vaddr; | ||
| 340 | 354 | ||
| 341 | /* Get receive buffer area. */ | 355 | /* Get receive buffer area. */ |
| 342 | buf_size = device_info->recv_sections * device_info->recv_section_size; | 356 | buf_size = device_info->recv_sections * device_info->recv_section_size; |
| @@ -372,6 +386,17 @@ static int netvsc_init_buf(struct hv_device *device, · 29 unmodified lines | |||
| 372 | goto cleanup; | 386 | goto cleanup; |
| 373 | } | 387 | } |
| 374 | 388 | ||
| 389 | if (hv_isolation_type_snp()) { | ||
| 390 | vaddr = hv_map_memory(net_device->recv_buf, buf_size); | ||
| 391 | if (!vaddr) { | ||
| 392 | ret = -ENOMEM; | ||
| 393 | goto cleanup; | ||
| 394 | } | ||
| 395 | |||
| 396 | net_device->recv_original_buf = net_device->recv_buf; | ||
| 397 | net_device->recv_buf = vaddr; | ||
| 398 | } | ||
| 399 | |||
| 375 | /* Notify the NetVsp of the gpadl handle */ | 400 | /* Notify the NetVsp of the gpadl handle */ |
| 376 | init_packet = &net_device->channel_init_pkt; | 401 | init_packet = &net_device->channel_init_pkt; |
| 377 | memset(init_packet, 0, sizeof(struct nvsp_message)); | 402 | memset(init_packet, 0, sizeof(struct nvsp_message)); |
| @@ -475,6 +500,17 @@ static int netvsc_init_buf(struct hv_device *device, · 97 unmodified lines | |||
| 475 | goto cleanup; | 500 | goto cleanup; |
| 476 | } | 501 | } |
| 477 | 502 | ||
| 503 | if (hv_isolation_type_snp()) { | ||
| 504 | vaddr = hv_map_memory(net_device->send_buf, buf_size); | ||
| 505 | if (!vaddr) { | ||
| 506 | ret = -ENOMEM; | ||
| 507 | goto cleanup; | ||
| 508 | } | ||
| 509 | |||
| 510 | net_device->send_original_buf = net_device->send_buf; | ||
| 511 | net_device->send_buf = vaddr; | ||
| 512 | } | ||
| 513 | |||
| 478 | /* Notify the NetVsp of the gpadl handle */ | 514 | /* Notify the NetVsp of the gpadl handle */ |
| 479 | init_packet = &net_device->channel_init_pkt; | 515 | init_packet = &net_device->channel_init_pkt; |
| 480 | memset(init_packet, 0, sizeof(struct nvsp_message)); | 516 | memset(init_packet, 0, sizeof(struct nvsp_message)); |
| @@ -764,7 +800,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev, · 283 unmodified lines | |||
| 764 | 800 | ||
| 765 | /* Notify the layer above us */ | 801 | /* Notify the layer above us */ |
| 766 | if (likely(skb)) { | 802 | if (likely(skb)) { |
| 767 | const struct hv_netvsc_packet *packet | 803 | struct hv_netvsc_packet *packet |
| 768 | = (struct hv_netvsc_packet *)skb->cb; | 804 | = (struct hv_netvsc_packet *)skb->cb; |
| 769 | u32 send_index = packet->send_buf_index; | 805 | u32 send_index = packet->send_buf_index; |
| 770 | struct netvsc_stats *tx_stats; | 806 | struct netvsc_stats *tx_stats; |
| @@ -780,6 +816,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev, · 9 unmodified lines | |||
| 780 | tx_stats->bytes += packet->total_bytes; | 816 | tx_stats->bytes += packet->total_bytes; |
| 781 | u64_stats_update_end(&tx_stats->syncp); | 817 | u64_stats_update_end(&tx_stats->syncp); |
| 782 | 818 | ||
| 819 | netvsc_dma_unmap(ndev_ctx->device_ctx, packet); | ||
| 783 | napi_consume_skb(skb, budget); | 820 | napi_consume_skb(skb, budget); |
| 784 | } | 821 | } |
| 785 | 822 | ||
| @@ -944,6 +981,88 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device, · 158 unmodified lines | |||
| 944 | memset(dest, 0, padding); | 981 | memset(dest, 0, padding); |
| 945 | } | 982 | } |
| 946 | 983 | ||
| 984 | void netvsc_dma_unmap(struct hv_device *hv_dev, | ||
| 985 | struct hv_netvsc_packet *packet) | ||
| 986 | { | ||
| 987 | u32 page_count = packet->cp_partial ? | ||
| 988 | packet->page_buf_cnt - packet->rmsg_pgcnt : | ||
| 989 | packet->page_buf_cnt; | ||
| 990 | int i; | ||
| 991 | |||
| 992 | if (!hv_is_isolation_supported()) | ||
| 993 | return; | ||
| 994 | |||
| 995 | if (!packet->dma_range) | ||
| 996 | return; | ||
| 997 | |||
| 998 | for (i = 0; i < page_count; i++) | ||
| 999 | dma_unmap_single(&hv_dev->device, packet->dma_range[i].dma, | ||
| 1000 | packet->dma_range[i].mapping_size, | ||
| 1001 | DMA_TO_DEVICE); | ||
| 1002 | |||
| 1003 | kfree(packet->dma_range); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | /* netvsc_dma_map - Map swiotlb bounce buffer with data page of | ||
| 1007 | * packet sent by vmbus_sendpacket_pagebuffer() in the Isolation | ||
| 1008 | * VM. | ||
| 1009 | * | ||
| 1010 | * In isolation VM, netvsc send buffer has been marked visible to | ||
| 1011 | * host and so the data copied to send buffer doesn't need to use | ||
| 1012 | * bounce buffer. The data pages handled by vmbus_sendpacket_pagebuffer() | ||
| 1013 | * may not be copied to send buffer and so these pages need to be | ||
| 1014 | * mapped with swiotlb bounce buffer. netvsc_dma_map() is to do | ||
| 1015 | * that. The pfns in the struct hv_page_buffer need to be converted | ||
| 1016 | * to bounce buffer's pfn. The loop here is necessary because the | ||
| 1017 | * entries in the page buffer array are not necessarily full | ||
| 1018 | * pages of data. Each entry in the array has a separate offset and | ||
| 1019 | * len that may be non-zero, even for entries in the middle of the | ||
| 1020 | * array. And the entries are not physically contiguous. So each | ||
| 1021 | * entry must be individually mapped rather than as a contiguous unit. | ||
| 1022 | * So not use dma_map_sg() here. | ||
| 1023 | */ | ||
| 1024 | static int netvsc_dma_map(struct hv_device *hv_dev, | ||
| 1025 | struct hv_netvsc_packet *packet, | ||
| 1026 | struct hv_page_buffer *pb) | ||
| 1027 | { | ||
| 1028 | u32 page_count = packet->cp_partial ? | ||
| 1029 | packet->page_buf_cnt - packet->rmsg_pgcnt : | ||
| 1030 | packet->page_buf_cnt; | ||
| 1031 | dma_addr_t dma; | ||
| 1032 | int i; | ||
| 1033 | |||
| 1034 | if (!hv_is_isolation_supported()) | ||
| 1035 | return 0; | ||
| 1036 | |||
| 1037 | packet->dma_range = kcalloc(page_count, | ||
| 1038 | sizeof(*packet->dma_range), | ||
| 1039 | GFP_KERNEL); | ||
| 1040 | if (!packet->dma_range) | ||
| 1041 | return -ENOMEM; | ||
| 1042 | |||
| 1043 | for (i = 0; i < page_count; i++) { | ||
| 1044 | char *src = phys_to_virt((pb[i].pfn << HV_HYP_PAGE_SHIFT) | ||
| 1045 | + pb[i].offset); | ||
| 1046 | u32 len = pb[i].len; | ||
| 1047 | |||
| 1048 | dma = dma_map_single(&hv_dev->device, src, len, | ||
| 1049 | DMA_TO_DEVICE); | ||
| 1050 | if (dma_mapping_error(&hv_dev->device, dma)) { | ||
| 1051 | kfree(packet->dma_range); | ||
| 1052 | return -ENOMEM; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | /* pb[].offset and pb[].len are not changed during dma mapping | ||
| 1056 | * and so not reassign. | ||
| 1057 | */ | ||
| 1058 | packet->dma_range[i].dma = dma; | ||
| 1059 | packet->dma_range[i].mapping_size = len; | ||
| 1060 | pb[i].pfn = dma >> HV_HYP_PAGE_SHIFT; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | return 0; | ||
| 1064 | } | ||
| 1065 | |||
| 947 | static inline int netvsc_send_pkt( | 1066 | static inline int netvsc_send_pkt( |
| 948 | struct hv_device *device, | 1067 | struct hv_device *device, |
| 949 | struct hv_netvsc_packet *packet, | 1068 | struct hv_netvsc_packet *packet, |
| @@ -984,14 +1103,24 @@ static inline int netvsc_send_pkt( · 34 unmodified lines | |||
| 984 | 1103 | ||
| 985 | trace_nvsp_send_pkt(ndev, out_channel, rpkt); | 1104 | trace_nvsp_send_pkt(ndev, out_channel, rpkt); |
| 986 | 1105 | ||
| 1106 | packet->dma_range = NULL; | ||
| 987 | if (packet->page_buf_cnt) { | 1107 | if (packet->page_buf_cnt) { |
| 988 | if (packet->cp_partial) | 1108 | if (packet->cp_partial) |
| 989 | pb += packet->rmsg_pgcnt; | 1109 | pb += packet->rmsg_pgcnt; |
| 990 | 1110 | ||
| 1111 | ret = netvsc_dma_map(ndev_ctx->device_ctx, packet, pb); | ||
| 1112 | if (ret) { | ||
| 1113 | ret = -EAGAIN; | ||
| 1114 | goto exit; | ||
| 1115 | } | ||
| 1116 | |||
| 991 | ret = vmbus_sendpacket_pagebuffer(out_channel, | 1117 | ret = vmbus_sendpacket_pagebuffer(out_channel, |
| 992 | pb, packet->page_buf_cnt, | 1118 | pb, packet->page_buf_cnt, |
| 993 | &nvmsg, sizeof(nvmsg), | 1119 | &nvmsg, sizeof(nvmsg), |
| 994 | req_id); | 1120 | req_id); |
| 1121 | |||
| 1122 | if (ret) | ||
| 1123 | netvsc_dma_unmap(ndev_ctx->device_ctx, packet); | ||
| 995 | } else { | 1124 | } else { |
| 996 | ret = vmbus_sendpacket(out_channel, | 1125 | ret = vmbus_sendpacket(out_channel, |
| 997 | &nvmsg, sizeof(nvmsg), | 1126 | &nvmsg, sizeof(nvmsg), |
| @@ -999,6 +1128,7 @@ static inline int netvsc_send_pkt( · 1 unmodified line | |||
| 999 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 1128 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
| 1000 | } | 1129 | } |
| 1001 | 1130 | ||
| 1131 | exit: | ||
| 1002 | if (ret == 0) { | 1132 | if (ret == 0) { |
| 1003 | atomic_inc_return(&nvchan->queue_sends); | 1133 | atomic_inc_return(&nvchan->queue_sends); |
| 1004 | 1134 | ||
| @@ -2516,6 +2516,7 @@ static int netvsc_probe(struct hv_device *dev, · 2515 unmodified lines | |||
| 2516 | net->netdev_ops = &device_ops; | 2516 | net->netdev_ops = &device_ops; |
| 2517 | net->ethtool_ops = ðtool_ops; | 2517 | net->ethtool_ops = ðtool_ops; |
| 2518 | SET_NETDEV_DEV(net, &dev->device); | 2518 | SET_NETDEV_DEV(net, &dev->device); |
| 2519 | dma_set_min_align_mask(&dev->device, HV_HYP_PAGE_SIZE - 1); | ||
| 2519 | 2520 | ||
| 2520 | /* We always need headroom for rndis header */ | 2521 | /* We always need headroom for rndis header */ |
| 2521 | net->needed_headroom = RNDIS_AND_PPI_SIZE; | 2522 | net->needed_headroom = RNDIS_AND_PPI_SIZE; |
| @@ -361,6 +361,8 @@ static void rndis_filter_receive_response(struct net_device *ndev, · 360 unmodified lines | |||
| 361 | } | 361 | } |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | netvsc_dma_unmap(((struct net_device_context *) | ||
| 365 | netdev_priv(ndev))->device_ctx, &request->pkt); | ||
| 364 | complete(&request->wait_event); | 366 | complete(&request->wait_event); |
| 365 | } else { | 367 | } else { |
| 366 | netdev_err(ndev, | 368 | netdev_err(ndev, |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | |||
| 21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
| 22 | #include <linux/hyperv.h> | 22 | #include <linux/hyperv.h> |
| 23 | #include <linux/blkdev.h> | 23 | #include <linux/blkdev.h> |
| 24 | #include <linux/dma-mapping.h> | ||
| 25 | |||
| 24 | #include <scsi/scsi.h> | 26 | #include <scsi/scsi.h> |
| 25 | #include <scsi/scsi_cmnd.h> | 27 | #include <scsi/scsi_cmnd.h> |
| 26 | #include <scsi/scsi_host.h> | 28 | #include <scsi/scsi_host.h> |
| @@ -1336,6 +1338,7 @@ static void storvsc_on_channel_callback(void *context) · 1309 unmodified lines | |||
| 1336 | continue; | 1338 | continue; |
| 1337 | } | 1339 | } |
| 1338 | request = (struct storvsc_cmd_request *)scsi_cmd_priv(scmnd); | 1340 | request = (struct storvsc_cmd_request *)scsi_cmd_priv(scmnd); |
| 1341 | scsi_dma_unmap(scmnd); | ||
| 1339 | } | 1342 | } |
| 1340 | 1343 | ||
| 1341 | storvsc_on_receive(stor_device, packet, request); | 1344 | storvsc_on_receive(stor_device, packet, request); |
| @@ -1749,9 +1752,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 407 unmodified lines | |||
| 1749 | struct hv_host_device *host_dev = shost_priv(host); | 1752 | struct hv_host_device *host_dev = shost_priv(host); |
| 1750 | struct hv_device *dev = host_dev->dev; | 1753 | struct hv_device *dev = host_dev->dev; |
| 1751 | struct storvsc_cmd_request *cmd_request = scsi_cmd_priv(scmnd); | 1754 | struct storvsc_cmd_request *cmd_request = scsi_cmd_priv(scmnd); |
| 1752 | int i; | ||
| 1753 | struct scatterlist *sgl; | 1755 | struct scatterlist *sgl; |
| 1754 | unsigned int sg_count; | ||
| 1755 | struct vmscsi_request *vm_srb; | 1756 | struct vmscsi_request *vm_srb; |
| 1756 | struct vmbus_packet_mpb_array *payload; | 1757 | struct vmbus_packet_mpb_array *payload; |
| 1757 | u32 payload_sz; | 1758 | u32 payload_sz; |
| @@ -1824,17 +1825,17 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 66 unmodified lines | |||
| 1824 | memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); | 1825 | memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); |
| 1825 | 1826 | ||
| 1826 | sgl = (struct scatterlist *)scsi_sglist(scmnd); | 1827 | sgl = (struct scatterlist *)scsi_sglist(scmnd); |
| 1827 | sg_count = scsi_sg_count(scmnd); | ||
| 1828 | 1828 | ||
| 1829 | length = scsi_bufflen(scmnd); | 1829 | length = scsi_bufflen(scmnd); |
| 1830 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; | 1830 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; |
| 1831 | payload_sz = sizeof(cmd_request->mpb); | 1831 | payload_sz = sizeof(cmd_request->mpb); |
| 1832 | 1832 | ||
| 1833 | if (sg_count) { | 1833 | if (scsi_sg_count(scmnd)) { |
| 1834 | unsigned int hvpgoff, hvpfns_to_add; | ||
| 1835 | unsigned long offset_in_hvpg = offset_in_hvpage(sgl->offset); | 1834 | unsigned long offset_in_hvpg = offset_in_hvpage(sgl->offset); |
| 1836 | unsigned int hvpg_count = HVPFN_UP(offset_in_hvpg + length); | 1835 | unsigned int hvpg_count = HVPFN_UP(offset_in_hvpg + length); |
| 1837 | u64 hvpfn; | 1836 | struct scatterlist *sg; |
| 1837 | unsigned long hvpfn, hvpfns_to_add; | ||
| 1838 | int j, i = 0, sg_count; | ||
| 1838 | 1839 | ||
| 1839 | if (hvpg_count > MAX_PAGE_BUFFER_COUNT) { | 1840 | if (hvpg_count > MAX_PAGE_BUFFER_COUNT) { |
| 1840 | 1841 | ||
| @@ -1848,21 +1849,24 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 7 unmodified lines | |||
| 1848 | payload->range.len = length; | 1849 | payload->range.len = length; |
| 1849 | payload->range.offset = offset_in_hvpg; | 1850 | payload->range.offset = offset_in_hvpg; |
| 1850 | 1851 | ||
| 1852 | sg_count = scsi_dma_map(scmnd); | ||
| 1853 | if (sg_count < 0) { | ||
| 1854 | ret = SCSI_MLQUEUE_DEVICE_BUSY; | ||
| 1855 | goto err_free_payload; | ||
| 1856 | } | ||
| 1851 | 1857 | ||
| 1852 | for (i = 0; sgl != NULL; sgl = sg_next(sgl)) { | 1858 | for_each_sg(sgl, sg, sg_count, j) { |
| 1853 | /* | 1859 | /* |
| 1854 | * Init values for the current sgl entry. hvpgoff | 1860 | * Init values for the current sgl entry. hvpfns_to_add |
| 1855 | * and hvpfns_to_add are in units of Hyper-V size | 1861 | * is in units of Hyper-V size pages. Handling the |
| 1856 | * pages. Handling the PAGE_SIZE != HV_HYP_PAGE_SIZE | 1862 | * PAGE_SIZE != HV_HYP_PAGE_SIZE case also handles |
| 1857 | * case also handles values of sgl->offset that are | 1863 | * values of sgl->offset that are larger than PAGE_SIZE. |
| 1858 | * larger than PAGE_SIZE. Such offsets are handled | 1864 | * Such offsets are handled even on other than the first |
| 1859 | * even on other than the first sgl entry, provided | 1865 | * sgl entry, provided they are a multiple of PAGE_SIZE. |
| 1860 | * they are a multiple of PAGE_SIZE. | ||
| 1861 | */ | 1866 | */ |
| 1862 | hvpgoff = HVPFN_DOWN(sgl->offset); | 1867 | hvpfn = HVPFN_DOWN(sg_dma_address(sg)); |
| 1863 | hvpfn = page_to_hvpfn(sg_page(sgl)) + hvpgoff; | 1868 | hvpfns_to_add = HVPFN_UP(sg_dma_address(sg) + |
| 1864 | hvpfns_to_add = HVPFN_UP(sgl->offset + sgl->length) - | 1869 | sg_dma_len(sg)) - hvpfn; |
| 1865 | hvpgoff; | ||
| 1866 | 1870 | ||
| 1867 | /* | 1871 | /* |
| 1868 | * Fill the next portion of the PFN array with | 1872 | * Fill the next portion of the PFN array with |
| @@ -1872,7 +1876,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 3 unmodified lines | |||
| 1872 | * the PFN array is filled. | 1876 | * the PFN array is filled. |
| 1873 | */ | 1877 | */ |
| 1874 | while (hvpfns_to_add--) | 1878 | while (hvpfns_to_add--) |
| 1875 | payload->range.pfn_array[i++] = hvpfn++; | 1879 | payload->range.pfn_array[i++] = hvpfn++; |
| 1876 | } | 1880 | } |
| 1877 | } | 1881 | } |
| 1878 | 1882 | ||
| @@ -1884,13 +1888,18 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 5 unmodified lines | |||
| 1884 | put_cpu(); | 1888 | put_cpu(); |
| 1885 | 1889 | ||
| 1886 | if (ret == -EAGAIN) { | 1890 | if (ret == -EAGAIN) { |
| 1887 | if (payload_sz > sizeof(cmd_request->mpb)) | ||
| 1888 | kfree(payload); | ||
| 1889 | /* no more space */ | 1891 | /* no more space */ |
| 1890 | return SCSI_MLQUEUE_DEVICE_BUSY; | 1892 | ret = SCSI_MLQUEUE_DEVICE_BUSY; |
| 1893 | goto err_free_payload; | ||
| 1891 | } | 1894 | } |
| 1892 | 1895 | ||
| 1893 | return 0; | 1896 | return 0; |
| 1897 | |||
| 1898 | err_free_payload: | ||
| 1899 | if (payload_sz > sizeof(cmd_request->mpb)) | ||
| 1900 | kfree(payload); | ||
| 1901 | |||
| 1902 | return ret; | ||
| 1894 | } | 1903 | } |
| 1895 | 1904 | ||
| 1896 | static struct scsi_host_template scsi_driver = { | 1905 | static struct scsi_host_template scsi_driver = { |
| @@ -2016,6 +2025,7 @@ static int storvsc_probe(struct hv_device *device, · 119 unmodified lines | |||
| 2016 | stor_device->vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); | 2025 | stor_device->vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); |
| 2017 | spin_lock_init(&stor_device->lock); | 2026 | spin_lock_init(&stor_device->lock); |
| 2018 | hv_set_drvdata(device, stor_device); | 2027 | hv_set_drvdata(device, stor_device); |
| 2028 | dma_set_min_align_mask(&device->device, HV_HYP_PAGE_SIZE - 1); | ||
| 2019 | 2029 | ||
| 2020 | stor_device->port_number = host->host_no; | 2030 | stor_device->port_number = host->host_no; |
| 2021 | ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size, is_fc); | 2031 | ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size, is_fc); |
| @@ -49,8 +49,8 @@ struct ms_hyperv_info { · 48 unmodified lines | |||
| 49 | }; | 49 | }; |
| 50 | extern struct ms_hyperv_info ms_hyperv; | 50 | extern struct ms_hyperv_info ms_hyperv; |
| 51 | 51 | ||
| 52 | extern void __percpu **hyperv_pcpu_input_arg; | 52 | extern void * __percpu *hyperv_pcpu_input_arg; |
| 53 | extern void __percpu **hyperv_pcpu_output_arg; | 53 | extern void * __percpu *hyperv_pcpu_output_arg; |
| 54 | 54 | ||
| 55 | extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr); | 55 | extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr); |
| 56 | extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); | 56 | extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); |
| @@ -269,6 +269,8 @@ bool hv_isolation_type_snp(void); · 212 unmodified lines | |||
| 269 | u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size); | 269 | u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size); |
| 270 | void hyperv_cleanup(void); | 270 | void hyperv_cleanup(void); |
| 271 | bool hv_query_ext_cap(u64 cap_query); | 271 | bool hv_query_ext_cap(u64 cap_query); |
| 272 | void *hv_map_memory(void *addr, unsigned long size); | ||
| 273 | void hv_unmap_memory(void *addr); | ||
| 272 | #else /* CONFIG_HYPERV */ | 274 | #else /* CONFIG_HYPERV */ |
| 273 | static inline bool hv_is_hyperv_initialized(void) { return false; } | 275 | static inline bool hv_is_hyperv_initialized(void) { return false; } |
| 274 | static inline bool hv_is_hibernation_supported(void) { return false; } | 276 | static inline bool hv_is_hibernation_supported(void) { return false; } |
| @@ -1261,6 +1261,7 @@ struct hv_device { · 1260 unmodified lines | |||
| 1261 | 1261 | ||
| 1262 | struct vmbus_channel *channel; | 1262 | struct vmbus_channel *channel; |
| 1263 | struct kset *channels_kset; | 1263 | struct kset *channels_kset; |
| 1264 | struct device_dma_parameters dma_parms; | ||
| 1264 | 1265 | ||
| 1265 | /* place holder to keep track of the dir for hv device in debugfs */ | 1266 | /* place holder to keep track of the dir for hv device in debugfs */ |
| 1266 | struct dentry *debug_dir; | 1267 | struct dentry *debug_dir; |
| @@ -1583,6 +1584,11 @@ struct hyperv_service_callback { · 316 unmodified lines | |||
| 1583 | void (*callback)(void *context); | 1584 | void (*callback)(void *context); |
| 1584 | }; | 1585 | }; |
| 1585 | 1586 | ||
| 1587 | struct hv_dma_range { | ||
| 1588 | dma_addr_t dma; | ||
| 1589 | u32 mapping_size; | ||
| 1590 | }; | ||
| 1591 | |||
| 1586 | #define MAX_SRV_VER 0x7ffffff | 1592 | #define MAX_SRV_VER 0x7ffffff |
| 1587 | extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, u32 buflen, | 1593 | extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, u32 buflen, |
| 1588 | const int *fw_version, int fw_vercnt, | 1594 | const int *fw_version, int fw_vercnt, |
| @@ -73,6 +73,9 @@ extern enum swiotlb_force swiotlb_force; · 72 unmodified lines | |||
| 73 | * @end: The end address of the swiotlb memory pool. Used to do a quick | 73 | * @end: The end address of the swiotlb memory pool. Used to do a quick |
| 74 | * range check to see if the memory was in fact allocated by this | 74 | * range check to see if the memory was in fact allocated by this |
| 75 | * API. | 75 | * API. |
| 76 | * @vaddr: The vaddr of the swiotlb memory pool. The swiotlb memory pool | ||
| 77 | * may be remapped in the memory encrypted case and store virtual | ||
| 78 | * address for bounce buffer operation. | ||
| 76 | * @nslabs: The number of IO TLB blocks (in groups of 64) between @start and | 79 | * @nslabs: The number of IO TLB blocks (in groups of 64) between @start and |
| 77 | * @end. For default swiotlb, this is command line adjustable via | 80 | * @end. For default swiotlb, this is command line adjustable via |
| 78 | * setup_io_tlb_npages. | 81 | * setup_io_tlb_npages. |
| @@ -92,6 +95,7 @@ extern enum swiotlb_force swiotlb_force; · 13 unmodified lines | |||
| 92 | struct io_tlb_mem { | 95 | struct io_tlb_mem { |
| 93 | phys_addr_t start; | 96 | phys_addr_t start; |
| 94 | phys_addr_t end; | 97 | phys_addr_t end; |
| 98 | void *vaddr; | ||
| 95 | unsigned long nslabs; | 99 | unsigned long nslabs; |
| 96 | unsigned long used; | 100 | unsigned long used; |
| 97 | unsigned int index; | 101 | unsigned int index; |
| @@ -186,4 +190,6 @@ static inline bool is_swiotlb_for_alloc(struct device *dev) · 88 unmodified lines | |||
| 186 | } | 190 | } |
| 187 | #endif /* CONFIG_DMA_RESTRICTED_POOL */ | 191 | #endif /* CONFIG_DMA_RESTRICTED_POOL */ |
| 188 | 192 | ||
| 193 | extern phys_addr_t swiotlb_unencrypted_base; | ||
| 194 | |||
| 189 | #endif /* __LINUX_SWIOTLB_H */ | 195 | #endif /* __LINUX_SWIOTLB_H */ |
| @@ -50,6 +50,7 @@ · 49 unmodified lines | |||
| 50 | #include <asm/io.h> | 50 | #include <asm/io.h> |
| 51 | #include <asm/dma.h> | 51 | #include <asm/dma.h> |
| 52 | 52 | ||
| 53 | #include <linux/io.h> | ||
| 53 | #include <linux/init.h> | 54 | #include <linux/init.h> |
| 54 | #include <linux/memblock.h> | 55 | #include <linux/memblock.h> |
| 55 | #include <linux/iommu-helper.h> | 56 | #include <linux/iommu-helper.h> |
| @@ -72,6 +73,8 @@ enum swiotlb_force swiotlb_force; · 16 unmodified lines | |||
| 72 | 73 | ||
| 73 | struct io_tlb_mem io_tlb_default_mem; | 74 | struct io_tlb_mem io_tlb_default_mem; |
| 74 | 75 | ||
| 76 | phys_addr_t swiotlb_unencrypted_base; | ||
| 77 | |||
| 75 | /* | 78 | /* |
| 76 | * Max segment that we can provide which (if pages are contingous) will | 79 | * Max segment that we can provide which (if pages are contingous) will |
| 77 | * not be bounced (unless SWIOTLB_FORCE is set). | 80 | * not be bounced (unless SWIOTLB_FORCE is set). |
| @@ -155,6 +158,34 @@ static inline unsigned long nr_slots(u64 val) · 77 unmodified lines | |||
| 155 | return DIV_ROUND_UP(val, IO_TLB_SIZE); | 158 | return DIV_ROUND_UP(val, IO_TLB_SIZE); |
| 156 | } | 159 | } |
| 157 | 160 | ||
| 161 | /* | ||
| 162 | * Remap swioltb memory in the unencrypted physical address space | ||
| 163 | * when swiotlb_unencrypted_base is set. (e.g. for Hyper-V AMD SEV-SNP | ||
| 164 | * Isolation VMs). | ||
| 165 | */ | ||
| 166 | #ifdef CONFIG_HAS_IOMEM | ||
| 167 | static void *swiotlb_mem_remap(struct io_tlb_mem *mem, unsigned long bytes) | ||
| 168 | { | ||
| 169 | void *vaddr = NULL; | ||
| 170 | |||
| 171 | if (swiotlb_unencrypted_base) { | ||
| 172 | phys_addr_t paddr = mem->start + swiotlb_unencrypted_base; | ||
| 173 | |||
| 174 | vaddr = memremap(paddr, bytes, MEMREMAP_WB); | ||
| 175 | if (!vaddr) | ||
| 176 | pr_err("Failed to map the unencrypted memory %pa size %lx.\n", | ||
| 177 | &paddr, bytes); | ||
| 178 | } | ||
| 179 | |||
| 180 | return vaddr; | ||
| 181 | } | ||
| 182 | #else | ||
| 183 | static void *swiotlb_mem_remap(struct io_tlb_mem *mem, unsigned long bytes) | ||
| 184 | { | ||
| 185 | return NULL; | ||
| 186 | } | ||
| 187 | #endif | ||
| 188 | |||
| 158 | /* | 189 | /* |
| 159 | * Early SWIOTLB allocation may be too early to allow an architecture to | 190 | * Early SWIOTLB allocation may be too early to allow an architecture to |
| 160 | * perform the desired operations. This function allows the architecture to | 191 | * perform the desired operations. This function allows the architecture to |
| @@ -172,7 +203,12 @@ void __init swiotlb_update_mem_attributes(void) · 11 unmodified lines | |||
| 172 | vaddr = phys_to_virt(mem->start); | 203 | vaddr = phys_to_virt(mem->start); |
| 173 | bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT); | 204 | bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT); |
| 174 | set_memory_decrypted((unsigned long)vaddr, bytes >> PAGE_SHIFT); | 205 | set_memory_decrypted((unsigned long)vaddr, bytes >> PAGE_SHIFT); |
| 175 | memset(vaddr, 0, bytes); | 206 | |
| 207 | mem->vaddr = swiotlb_mem_remap(mem, bytes); | ||
| 208 | if (!mem->vaddr) | ||
| 209 | mem->vaddr = vaddr; | ||
| 210 | |||
| 211 | memset(mem->vaddr, 0, bytes); | ||
| 176 | } | 212 | } |
| 177 | 213 | ||
| 178 | static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start, | 214 | static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start, |
| @@ -196,7 +232,17 @@ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start, · 17 unmodified lines | |||
| 196 | mem->slots[i].orig_addr = INVALID_PHYS_ADDR; | 232 | mem->slots[i].orig_addr = INVALID_PHYS_ADDR; |
| 197 | mem->slots[i].alloc_size = 0; | 233 | mem->slots[i].alloc_size = 0; |
| 198 | } | 234 | } |
| 235 | |||
| 236 | /* | ||
| 237 | * If swiotlb_unencrypted_base is set, the bounce buffer memory will | ||
| 238 | * be remapped and cleared in swiotlb_update_mem_attributes. | ||
| 239 | */ | ||
| 240 | if (swiotlb_unencrypted_base) | ||
| 241 | return; | ||
| 242 | |||
| 199 | memset(vaddr, 0, bytes); | 243 | memset(vaddr, 0, bytes); |
| 244 | mem->vaddr = vaddr; | ||
| 245 | return; | ||
| 200 | } | 246 | } |
| 201 | 247 | ||
| 202 | int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | 248 | int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) |
| @@ -371,7 +417,7 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size · 168 unmodified lines | |||
| 371 | phys_addr_t orig_addr = mem->slots[index].orig_addr; | 417 | phys_addr_t orig_addr = mem->slots[index].orig_addr; |
| 372 | size_t alloc_size = mem->slots[index].alloc_size; | 418 | size_t alloc_size = mem->slots[index].alloc_size; |
| 373 | unsigned long pfn = PFN_DOWN(orig_addr); | 419 | unsigned long pfn = PFN_DOWN(orig_addr); |
| 374 | unsigned char *vaddr = phys_to_virt(tlb_addr); | 420 | unsigned char *vaddr = mem->vaddr + tlb_addr - mem->start; |
| 375 | unsigned int tlb_offset, orig_addr_offset; | 421 | unsigned int tlb_offset, orig_addr_offset; |
| 376 | 422 | ||
| 377 | if (orig_addr == INVALID_PHYS_ADDR) | 423 | if (orig_addr == INVALID_PHYS_ADDR) |