Skip to content

Commit 79e542f

Browse files
Changbin Duzhenyw
authored andcommitted
drm/i915/kvmgt: Support setting dma map for huge pages
To support huge gtt, we need to support huge pages in kvmgt first. This patch adds a 'size' param to the intel_gvt_mpt::dma_map_guest_page API and implements it in kvmgt. v2: rebase. Signed-off-by: Changbin Du <[email protected]> Signed-off-by: Zhenyu Wang <[email protected]>
1 parent eb3a353 commit 79e542f

File tree

4 files changed

+102
-39
lines changed

4 files changed

+102
-39
lines changed

drivers/gpu/drm/i915/gvt/gtt.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
11061106

11071107
for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
11081108
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
1109-
start_gfn + i, &dma_addr);
1109+
start_gfn + i, PAGE_SIZE, &dma_addr);
11101110
if (ret)
11111111
return ret;
11121112

@@ -1152,7 +1152,7 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
11521152
};
11531153

11541154
/* direct shadow */
1155-
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, &dma_addr);
1155+
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, PAGE_SIZE, &dma_addr);
11561156
if (ret)
11571157
return -ENXIO;
11581158

@@ -2080,7 +2080,7 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
20802080
}
20812081

20822082
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn,
2083-
&dma_addr);
2083+
PAGE_SIZE, &dma_addr);
20842084
if (ret) {
20852085
gvt_vgpu_err("fail to populate guest ggtt entry\n");
20862086
/* guest driver may read/write the entry when partial

drivers/gpu/drm/i915/gvt/hypercall.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct intel_gvt_mpt {
5353
unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn);
5454

5555
int (*dma_map_guest_page)(unsigned long handle, unsigned long gfn,
56-
dma_addr_t *dma_addr);
56+
unsigned long size, dma_addr_t *dma_addr);
5757
void (*dma_unmap_guest_page)(unsigned long handle, dma_addr_t dma_addr);
5858

5959
int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,

drivers/gpu/drm/i915/gvt/kvmgt.c

Lines changed: 94 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct gvt_dma {
9494
struct rb_node dma_addr_node;
9595
gfn_t gfn;
9696
dma_addr_t dma_addr;
97+
unsigned long size;
9798
struct kref ref;
9899
};
99100

@@ -106,45 +107,103 @@ static int kvmgt_guest_init(struct mdev_device *mdev);
106107
static void intel_vgpu_release_work(struct work_struct *work);
107108
static bool kvmgt_guest_exit(struct kvmgt_guest_info *info);
108109

110+
static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
111+
unsigned long size)
112+
{
113+
int total_pages;
114+
int npage;
115+
int ret;
116+
117+
total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
118+
119+
for (npage = 0; npage < total_pages; npage++) {
120+
unsigned long cur_gfn = gfn + npage;
121+
122+
ret = vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), &cur_gfn, 1);
123+
WARN_ON(ret != 1);
124+
}
125+
}
126+
127+
/* Pin a normal or compound guest page for dma. */
128+
static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
129+
unsigned long size, struct page **page)
130+
{
131+
unsigned long base_pfn = 0;
132+
int total_pages;
133+
int npage;
134+
int ret;
135+
136+
total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
137+
/*
138+
* We pin the pages one-by-one to avoid allocating a big arrary
139+
* on stack to hold pfns.
140+
*/
141+
for (npage = 0; npage < total_pages; npage++) {
142+
unsigned long cur_gfn = gfn + npage;
143+
unsigned long pfn;
144+
145+
ret = vfio_pin_pages(mdev_dev(vgpu->vdev.mdev), &cur_gfn, 1,
146+
IOMMU_READ | IOMMU_WRITE, &pfn);
147+
if (ret != 1) {
148+
gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret %d\n",
149+
cur_gfn, ret);
150+
goto err;
151+
}
152+
153+
if (!pfn_valid(pfn)) {
154+
gvt_vgpu_err("pfn 0x%lx is not mem backed\n", pfn);
155+
npage++;
156+
ret = -EFAULT;
157+
goto err;
158+
}
159+
160+
if (npage == 0)
161+
base_pfn = pfn;
162+
else if (base_pfn + npage != pfn) {
163+
gvt_vgpu_err("The pages are not continuous\n");
164+
ret = -EINVAL;
165+
npage++;
166+
goto err;
167+
}
168+
}
169+
170+
*page = pfn_to_page(base_pfn);
171+
return 0;
172+
err:
173+
gvt_unpin_guest_page(vgpu, gfn, npage * PAGE_SIZE);
174+
return ret;
175+
}
176+
109177
static int gvt_dma_map_page(struct intel_vgpu *vgpu, unsigned long gfn,
110-
dma_addr_t *dma_addr)
178+
dma_addr_t *dma_addr, unsigned long size)
111179
{
112180
struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev;
113-
struct page *page;
114-
unsigned long pfn;
181+
struct page *page = NULL;
115182
int ret;
116183

117-
/* Pin the page first. */
118-
ret = vfio_pin_pages(mdev_dev(vgpu->vdev.mdev), &gfn, 1,
119-
IOMMU_READ | IOMMU_WRITE, &pfn);
120-
if (ret != 1) {
121-
gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx: %d\n",
122-
gfn, ret);
123-
return -EINVAL;
124-
}
184+
ret = gvt_pin_guest_page(vgpu, gfn, size, &page);
185+
if (ret)
186+
return ret;
125187

126188
/* Setup DMA mapping. */
127-
page = pfn_to_page(pfn);
128-
*dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE,
129-
PCI_DMA_BIDIRECTIONAL);
130-
if (dma_mapping_error(dev, *dma_addr)) {
131-
gvt_vgpu_err("DMA mapping failed for gfn 0x%lx\n", gfn);
132-
vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), &gfn, 1);
133-
return -ENOMEM;
189+
*dma_addr = dma_map_page(dev, page, 0, size, PCI_DMA_BIDIRECTIONAL);
190+
ret = dma_mapping_error(dev, *dma_addr);
191+
if (ret) {
192+
gvt_vgpu_err("DMA mapping failed for pfn 0x%lx, ret %d\n",
193+
page_to_pfn(page), ret);
194+
gvt_unpin_guest_page(vgpu, gfn, size);
134195
}
135196

136-
return 0;
197+
return ret;
137198
}
138199

139200
static void gvt_dma_unmap_page(struct intel_vgpu *vgpu, unsigned long gfn,
140-
dma_addr_t dma_addr)
201+
dma_addr_t dma_addr, unsigned long size)
141202
{
142203
struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev;
143-
int ret;
144204

145-
dma_unmap_page(dev, dma_addr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
146-
ret = vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), &gfn, 1);
147-
WARN_ON(ret != 1);
205+
dma_unmap_page(dev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
206+
gvt_unpin_guest_page(vgpu, gfn, size);
148207
}
149208

150209
static struct gvt_dma *__gvt_cache_find_dma_addr(struct intel_vgpu *vgpu,
@@ -185,7 +244,7 @@ static struct gvt_dma *__gvt_cache_find_gfn(struct intel_vgpu *vgpu, gfn_t gfn)
185244
}
186245

187246
static int __gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn,
188-
dma_addr_t dma_addr)
247+
dma_addr_t dma_addr, unsigned long size)
189248
{
190249
struct gvt_dma *new, *itr;
191250
struct rb_node **link, *parent = NULL;
@@ -197,6 +256,7 @@ static int __gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn,
197256
new->vgpu = vgpu;
198257
new->gfn = gfn;
199258
new->dma_addr = dma_addr;
259+
new->size = size;
200260
kref_init(&new->ref);
201261

202262
/* gfn_cache maps gfn to struct gvt_dma. */
@@ -254,7 +314,7 @@ static void gvt_cache_destroy(struct intel_vgpu *vgpu)
254314
break;
255315
}
256316
dma = rb_entry(node, struct gvt_dma, gfn_node);
257-
gvt_dma_unmap_page(vgpu, dma->gfn, dma->dma_addr);
317+
gvt_dma_unmap_page(vgpu, dma->gfn, dma->dma_addr, dma->size);
258318
__gvt_cache_remove_entry(vgpu, dma);
259319
mutex_unlock(&vgpu->vdev.cache_lock);
260320
}
@@ -509,7 +569,8 @@ static int intel_vgpu_iommu_notifier(struct notifier_block *nb,
509569
if (!entry)
510570
continue;
511571

512-
gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr);
572+
gvt_dma_unmap_page(vgpu, entry->gfn, entry->dma_addr,
573+
entry->size);
513574
__gvt_cache_remove_entry(vgpu, entry);
514575
}
515576
mutex_unlock(&vgpu->vdev.cache_lock);
@@ -1616,7 +1677,7 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
16161677
}
16171678

16181679
int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
1619-
dma_addr_t *dma_addr)
1680+
unsigned long size, dma_addr_t *dma_addr)
16201681
{
16211682
struct kvmgt_guest_info *info;
16221683
struct intel_vgpu *vgpu;
@@ -1633,11 +1694,11 @@ int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
16331694

16341695
entry = __gvt_cache_find_gfn(info->vgpu, gfn);
16351696
if (!entry) {
1636-
ret = gvt_dma_map_page(vgpu, gfn, dma_addr);
1697+
ret = gvt_dma_map_page(vgpu, gfn, dma_addr, size);
16371698
if (ret)
16381699
goto err_unlock;
16391700

1640-
ret = __gvt_cache_add(info->vgpu, gfn, *dma_addr);
1701+
ret = __gvt_cache_add(info->vgpu, gfn, *dma_addr, size);
16411702
if (ret)
16421703
goto err_unmap;
16431704
} else {
@@ -1649,7 +1710,7 @@ int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
16491710
return 0;
16501711

16511712
err_unmap:
1652-
gvt_dma_unmap_page(vgpu, gfn, *dma_addr);
1713+
gvt_dma_unmap_page(vgpu, gfn, *dma_addr, size);
16531714
err_unlock:
16541715
mutex_unlock(&info->vgpu->vdev.cache_lock);
16551716
return ret;
@@ -1659,7 +1720,8 @@ static void __gvt_dma_release(struct kref *ref)
16591720
{
16601721
struct gvt_dma *entry = container_of(ref, typeof(*entry), ref);
16611722

1662-
gvt_dma_unmap_page(entry->vgpu, entry->gfn, entry->dma_addr);
1723+
gvt_dma_unmap_page(entry->vgpu, entry->gfn, entry->dma_addr,
1724+
entry->size);
16631725
__gvt_cache_remove_entry(entry->vgpu, entry);
16641726
}
16651727

drivers/gpu/drm/i915/gvt/mpt.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,17 +230,18 @@ static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn(
230230
/**
231231
* intel_gvt_hypervisor_dma_map_guest_page - setup dma map for guest page
232232
* @vgpu: a vGPU
233-
* @gpfn: guest pfn
233+
* @gfn: guest pfn
234+
* @size: page size
234235
* @dma_addr: retrieve allocated dma addr
235236
*
236237
* Returns:
237238
* 0 on success, negative error code if failed.
238239
*/
239240
static inline int intel_gvt_hypervisor_dma_map_guest_page(
240-
struct intel_vgpu *vgpu, unsigned long gfn,
241+
struct intel_vgpu *vgpu, unsigned long gfn, unsigned long size,
241242
dma_addr_t *dma_addr)
242243
{
243-
return intel_gvt_host.mpt->dma_map_guest_page(vgpu->handle, gfn,
244+
return intel_gvt_host.mpt->dma_map_guest_page(vgpu->handle, gfn, size,
244245
dma_addr);
245246
}
246247

0 commit comments

Comments
 (0)