Skip to content
Snippets Groups Projects
Commit 0fed89a9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hyperv-fixes-signed-20250311' of...

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
parents 0b46b049 73fe9073
No related merge requests found
......@@ -30,6 +30,7 @@ void __init hv_vtl_init_platform(void)
x86_platform.realmode_init = x86_init_noop;
x86_init.irqs.pre_vector_init = x86_init_noop;
x86_init.timers.timer_init = x86_init_noop;
x86_init.resources.probe_roms = x86_init_noop;
/* Avoid searching for BIOS MP tables */
x86_init.mpparse.find_mptable = x86_init_noop;
......
......@@ -464,7 +464,6 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
enum hv_mem_host_visibility visibility)
{
struct hv_gpa_range_for_visibility *input;
u16 pages_processed;
u64 hv_status;
unsigned long flags;
......@@ -493,7 +492,7 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
memcpy((void *)input->gpa_page_list, pfn, count * sizeof(*pfn));
hv_status = hv_do_rep_hypercall(
HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY, count,
0, input, &pages_processed);
0, input, NULL);
local_irq_restore(flags);
if (hv_result_success(hv_status))
......
......@@ -154,6 +154,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
return 0;
err_free_mmio:
iounmap(hv->vram);
vmbus_free_mmio(hv->mem->start, hv->fb_size);
err_vmbus_close:
vmbus_close(hdev->channel);
......@@ -172,6 +173,7 @@ static void hyperv_vmbus_remove(struct hv_device *hdev)
vmbus_close(hdev->channel);
hv_set_drvdata(hdev, NULL);
iounmap(hv->vram);
vmbus_free_mmio(hv->mem->start, hv->fb_size);
}
......
......@@ -2262,12 +2262,25 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size)
struct resource *iter;
mutex_lock(&hyperv_mmio_lock);
/*
* If all bytes of the MMIO range to be released are within the
* special case fb_mmio shadow region, skip releasing the shadow
* region since no corresponding __request_region() was done
* in vmbus_allocate_mmio().
*/
if (fb_mmio && start >= fb_mmio->start &&
(start + size - 1 <= fb_mmio->end))
goto skip_shadow_release;
for (iter = hyperv_mmio; iter; iter = iter->sibling) {
if ((iter->start >= start + size) || (iter->end <= start))
continue;
__release_region(iter, start, size);
}
skip_shadow_release:
release_mem_region(start, size);
mutex_unlock(&hyperv_mmio_lock);
......
......@@ -282,6 +282,8 @@ static uint screen_depth;
static uint screen_fb_size;
static uint dio_fb_size; /* FB size for deferred IO */
static void hvfb_putmem(struct fb_info *info);
/* Send message to Hyper-V host */
static inline int synthvid_send(struct hv_device *hdev,
struct synthvid_msg *msg)
......@@ -862,6 +864,17 @@ static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width,
hvfb_ondemand_refresh_throttle(par, x, y, width, height);
}
/*
* fb_ops.fb_destroy is called by the last put_fb_info() call at the end
* of unregister_framebuffer() or fb_release(). Do any cleanup related to
* framebuffer here.
*/
static void hvfb_destroy(struct fb_info *info)
{
hvfb_putmem(info);
framebuffer_release(info);
}
/*
* TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the
* driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases.
......@@ -877,6 +890,7 @@ static const struct fb_ops hvfb_ops = {
.fb_set_par = hvfb_set_par,
.fb_setcolreg = hvfb_setcolreg,
.fb_blank = hvfb_blank,
.fb_destroy = hvfb_destroy,
};
/* Get options from kernel paramenter "video=" */
......@@ -952,7 +966,7 @@ static phys_addr_t hvfb_get_phymem(struct hv_device *hdev,
}
/* Release contiguous physical memory */
static void hvfb_release_phymem(struct hv_device *hdev,
static void hvfb_release_phymem(struct device *device,
phys_addr_t paddr, unsigned int size)
{
unsigned int order = get_order(size);
......@@ -960,7 +974,7 @@ static void hvfb_release_phymem(struct hv_device *hdev,
if (order <= MAX_PAGE_ORDER)
__free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order);
else
dma_free_coherent(&hdev->device,
dma_free_coherent(device,
round_up(size, PAGE_SIZE),
phys_to_virt(paddr),
paddr);
......@@ -989,6 +1003,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
base = pci_resource_start(pdev, 0);
size = pci_resource_len(pdev, 0);
aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);
/*
* 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)
goto getmem_done;
}
pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n");
} else {
aperture_remove_all_conflicting_devices(KBUILD_MODNAME);
}
/*
* Cannot use the contiguous physical memory.
* Allocate mmio space for framebuffer.
* Cannot use contiguous physical memory, so allocate MMIO space for
* the framebuffer. At this point in the function, conflicting devices
* that might have claimed the framebuffer MMIO space based on
* screen_info.lfb_base must have already been removed so that
* vmbus_allocate_mmio() does not allocate different MMIO space. If the
* kdump image were to be loaded using kexec_file_load(), the
* framebuffer location in the kdump image would be set from
* screen_info.lfb_base at the time that kdump is enabled. If the
* framebuffer has moved elsewhere, this could be the wrong location,
* causing kdump to hang when efifb (for example) loads.
*/
dio_fb_size =
screen_width * screen_height * screen_depth / 8;
......@@ -1051,11 +1076,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
info->screen_size = dio_fb_size;
getmem_done:
if (base && size)
aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME);
else
aperture_remove_all_conflicting_devices(KBUILD_MODNAME);
if (!gen2vm)
pci_dev_put(pdev);
......@@ -1074,16 +1094,16 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
}
/* Release the framebuffer */
static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)
static void hvfb_putmem(struct fb_info *info)
{
struct hvfb_par *par = info->par;
if (par->need_docopy) {
vfree(par->dio_vp);
iounmap(info->screen_base);
iounmap(par->mmio_vp);
vmbus_free_mmio(par->mem->start, screen_fb_size);
} else {
hvfb_release_phymem(hdev, info->fix.smem_start,
hvfb_release_phymem(info->device, info->fix.smem_start,
screen_fb_size);
}
......@@ -1172,7 +1192,7 @@ static int hvfb_probe(struct hv_device *hdev,
if (ret)
goto error;
ret = register_framebuffer(info);
ret = devm_register_framebuffer(&hdev->device, info);
if (ret) {
pr_err("Unable to register framebuffer\n");
goto error;
......@@ -1197,7 +1217,7 @@ static int hvfb_probe(struct hv_device *hdev,
error:
fb_deferred_io_cleanup(info);
hvfb_putmem(hdev, info);
hvfb_putmem(info);
error2:
vmbus_close(hdev->channel);
error1:
......@@ -1220,14 +1240,10 @@ static void hvfb_remove(struct hv_device *hdev)
fb_deferred_io_cleanup(info);
unregister_framebuffer(info);
cancel_delayed_work_sync(&par->dwork);
vmbus_close(hdev->channel);
hv_set_drvdata(hdev, NULL);
hvfb_putmem(hdev, info);
framebuffer_release(info);
}
static int hvfb_suspend(struct hv_device *hdev)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment