Skip to content

Commit 0fed89a

Browse files
committed
Merge tag 'hyperv-fixes-signed-20250311' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv fixes from Wei Liu: - Patches to fix Hyper-v framebuffer code (Michael Kelley and Saurabh Sengar) - Fix for Hyper-V output argument to hypercall that changes page visibility (Michael Kelley) - Fix for Hyper-V VTL mode (Naman Jain) * tag 'hyperv-fixes-signed-20250311' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio() x86/hyperv: Fix output argument to hypercall that changes page visibility fbdev: hyperv_fb: Allow graceful removal of framebuffer fbdev: hyperv_fb: Simplify hvfb_putmem fbdev: hyperv_fb: Fix hang in kdump kernel when on Hyper-V Gen 2 VMs drm/hyperv: Fix address space leak when Hyper-V DRM device is removed fbdev: hyperv_fb: iounmap() the correct memory when removing a device x86/hyperv/vtl: Stop kernel from probing VTL0 low memory
2 parents 0b46b04 + 73fe907 commit 0fed89a

File tree

5 files changed

+51
-20
lines changed

5 files changed

+51
-20
lines changed

arch/x86/hyperv/hv_vtl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ void __init hv_vtl_init_platform(void)
3030
x86_platform.realmode_init = x86_init_noop;
3131
x86_init.irqs.pre_vector_init = x86_init_noop;
3232
x86_init.timers.timer_init = x86_init_noop;
33+
x86_init.resources.probe_roms = x86_init_noop;
3334

3435
/* Avoid searching for BIOS MP tables */
3536
x86_init.mpparse.find_mptable = x86_init_noop;

arch/x86/hyperv/ivm.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,6 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
464464
enum hv_mem_host_visibility visibility)
465465
{
466466
struct hv_gpa_range_for_visibility *input;
467-
u16 pages_processed;
468467
u64 hv_status;
469468
unsigned long flags;
470469

@@ -493,7 +492,7 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
493492
memcpy((void *)input->gpa_page_list, pfn, count * sizeof(*pfn));
494493
hv_status = hv_do_rep_hypercall(
495494
HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY, count,
496-
0, input, &pages_processed);
495+
0, input, NULL);
497496
local_irq_restore(flags);
498497

499498
if (hv_result_success(hv_status))

drivers/gpu/drm/hyperv/hyperv_drm_drv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
154154
return 0;
155155

156156
err_free_mmio:
157+
iounmap(hv->vram);
157158
vmbus_free_mmio(hv->mem->start, hv->fb_size);
158159
err_vmbus_close:
159160
vmbus_close(hdev->channel);
@@ -172,6 +173,7 @@ static void hyperv_vmbus_remove(struct hv_device *hdev)
172173
vmbus_close(hdev->channel);
173174
hv_set_drvdata(hdev, NULL);
174175

176+
iounmap(hv->vram);
175177
vmbus_free_mmio(hv->mem->start, hv->fb_size);
176178
}
177179

drivers/hv/vmbus_drv.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,12 +2262,25 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size)
22622262
struct resource *iter;
22632263

22642264
mutex_lock(&hyperv_mmio_lock);
2265+
2266+
/*
2267+
* If all bytes of the MMIO range to be released are within the
2268+
* special case fb_mmio shadow region, skip releasing the shadow
2269+
* region since no corresponding __request_region() was done
2270+
* in vmbus_allocate_mmio().
2271+
*/
2272+
if (fb_mmio && start >= fb_mmio->start &&
2273+
(start + size - 1 <= fb_mmio->end))
2274+
goto skip_shadow_release;
2275+
22652276
for (iter = hyperv_mmio; iter; iter = iter->sibling) {
22662277
if ((iter->start >= start + size) || (iter->end <= start))
22672278
continue;
22682279

22692280
__release_region(iter, start, size);
22702281
}
2282+
2283+
skip_shadow_release:
22712284
release_mem_region(start, size);
22722285
mutex_unlock(&hyperv_mmio_lock);
22732286

drivers/video/fbdev/hyperv_fb.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ static uint screen_depth;
282282
static uint screen_fb_size;
283283
static uint dio_fb_size; /* FB size for deferred IO */
284284

285+
static void hvfb_putmem(struct fb_info *info);
286+
285287
/* Send message to Hyper-V host */
286288
static inline int synthvid_send(struct hv_device *hdev,
287289
struct synthvid_msg *msg)
@@ -862,6 +864,17 @@ static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width,
862864
hvfb_ondemand_refresh_throttle(par, x, y, width, height);
863865
}
864866

867+
/*
868+
* fb_ops.fb_destroy is called by the last put_fb_info() call at the end
869+
* of unregister_framebuffer() or fb_release(). Do any cleanup related to
870+
* framebuffer here.
871+
*/
872+
static void hvfb_destroy(struct fb_info *info)
873+
{
874+
hvfb_putmem(info);
875+
framebuffer_release(info);
876+
}
877+
865878
/*
866879
* TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the
867880
* driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases.
@@ -877,6 +890,7 @@ static const struct fb_ops hvfb_ops = {
877890
.fb_set_par = hvfb_set_par,
878891
.fb_setcolreg = hvfb_setcolreg,
879892
.fb_blank = hvfb_blank,
893+
.fb_destroy = hvfb_destroy,
880894
};
881895

882896
/* Get options from kernel paramenter "video=" */
@@ -952,15 +966,15 @@ static phys_addr_t hvfb_get_phymem(struct hv_device *hdev,
952966
}
953967

954968
/* Release contiguous physical memory */
955-
static void hvfb_release_phymem(struct hv_device *hdev,
969+
static void hvfb_release_phymem(struct device *device,
956970
phys_addr_t paddr, unsigned int size)
957971
{
958972
unsigned int order = get_order(size);
959973

960974
if (order <= MAX_PAGE_ORDER)
961975
__free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order);
962976
else
963-
dma_free_coherent(&hdev->device,
977+
dma_free_coherent(device,
964978
round_up(size, PAGE_SIZE),
965979
phys_to_virt(paddr),
966980
paddr);
@@ -989,6 +1003,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
9891003

9901004
base = pci_resource_start(pdev, 0);
9911005
size = pci_resource_len(pdev, 0);
1006+
aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);
9921007

9931008
/*
9941009
* For Gen 1 VM, we can directly use the contiguous memory
@@ -1010,11 +1025,21 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
10101025
goto getmem_done;
10111026
}
10121027
pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n");
1028+
} else {
1029+
aperture_remove_all_conflicting_devices(KBUILD_MODNAME);
10131030
}
10141031

10151032
/*
1016-
* Cannot use the contiguous physical memory.
1017-
* Allocate mmio space for framebuffer.
1033+
* Cannot use contiguous physical memory, so allocate MMIO space for
1034+
* the framebuffer. At this point in the function, conflicting devices
1035+
* that might have claimed the framebuffer MMIO space based on
1036+
* screen_info.lfb_base must have already been removed so that
1037+
* vmbus_allocate_mmio() does not allocate different MMIO space. If the
1038+
* kdump image were to be loaded using kexec_file_load(), the
1039+
* framebuffer location in the kdump image would be set from
1040+
* screen_info.lfb_base at the time that kdump is enabled. If the
1041+
* framebuffer has moved elsewhere, this could be the wrong location,
1042+
* causing kdump to hang when efifb (for example) loads.
10181043
*/
10191044
dio_fb_size =
10201045
screen_width * screen_height * screen_depth / 8;
@@ -1051,11 +1076,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
10511076
info->screen_size = dio_fb_size;
10521077

10531078
getmem_done:
1054-
if (base && size)
1055-
aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);
1056-
else
1057-
aperture_remove_all_conflicting_devices(KBUILD_MODNAME);
1058-
10591079
if (!gen2vm)
10601080
pci_dev_put(pdev);
10611081

@@ -1074,16 +1094,16 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
10741094
}
10751095

10761096
/* Release the framebuffer */
1077-
static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)
1097+
static void hvfb_putmem(struct fb_info *info)
10781098
{
10791099
struct hvfb_par *par = info->par;
10801100

10811101
if (par->need_docopy) {
10821102
vfree(par->dio_vp);
1083-
iounmap(info->screen_base);
1103+
iounmap(par->mmio_vp);
10841104
vmbus_free_mmio(par->mem->start, screen_fb_size);
10851105
} else {
1086-
hvfb_release_phymem(hdev, info->fix.smem_start,
1106+
hvfb_release_phymem(info->device, info->fix.smem_start,
10871107
screen_fb_size);
10881108
}
10891109

@@ -1172,7 +1192,7 @@ static int hvfb_probe(struct hv_device *hdev,
11721192
if (ret)
11731193
goto error;
11741194

1175-
ret = register_framebuffer(info);
1195+
ret = devm_register_framebuffer(&hdev->device, info);
11761196
if (ret) {
11771197
pr_err("Unable to register framebuffer\n");
11781198
goto error;
@@ -1197,7 +1217,7 @@ static int hvfb_probe(struct hv_device *hdev,
11971217

11981218
error:
11991219
fb_deferred_io_cleanup(info);
1200-
hvfb_putmem(hdev, info);
1220+
hvfb_putmem(info);
12011221
error2:
12021222
vmbus_close(hdev->channel);
12031223
error1:
@@ -1220,14 +1240,10 @@ static void hvfb_remove(struct hv_device *hdev)
12201240

12211241
fb_deferred_io_cleanup(info);
12221242

1223-
unregister_framebuffer(info);
12241243
cancel_delayed_work_sync(&par->dwork);
12251244

12261245
vmbus_close(hdev->channel);
12271246
hv_set_drvdata(hdev, NULL);
1228-
1229-
hvfb_putmem(hdev, info);
1230-
framebuffer_release(info);
12311247
}
12321248

12331249
static int hvfb_suspend(struct hv_device *hdev)

0 commit comments

Comments
 (0)