Skip to content

Commit ca1fc48

Browse files
aikpaulusmack
authored andcommitted
KVM: PPC: Book3S: Allow backing bigger guest IOMMU pages with smaller physical pages
At the moment we only support in the host the IOMMU page sizes which the guest is aware of, which is 4KB/64KB/16MB. However P9 does not support 16MB IOMMU pages, 2MB and 1GB pages are supported instead. We can still emulate bigger guest pages (for example 16MB) with smaller host pages (4KB/64KB/2MB). This allows the physical IOMMU pages to use a page size smaller or equal than the guest visible IOMMU page size. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 parent c6b6166 commit ca1fc48

2 files changed

Lines changed: 94 additions & 20 deletions

File tree

arch/powerpc/kvm/book3s_64_vio.c

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,12 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
176176

177177
if (!tbltmp)
178178
continue;
179-
/*
180-
* Make sure hardware table parameters are exactly the same;
181-
* this is used in the TCE handlers where boundary checks
182-
* use only the first attached table.
183-
*/
184-
if ((tbltmp->it_page_shift == stt->page_shift) &&
185-
(tbltmp->it_offset == stt->offset) &&
186-
(tbltmp->it_size == stt->size)) {
179+
/* Make sure hardware table parameters are compatible */
180+
if ((tbltmp->it_page_shift <= stt->page_shift) &&
181+
(tbltmp->it_offset << tbltmp->it_page_shift ==
182+
stt->offset << stt->page_shift) &&
183+
(tbltmp->it_size << tbltmp->it_page_shift ==
184+
stt->size << stt->page_shift)) {
187185
/*
188186
* Reference the table to avoid races with
189187
* add/remove DMA windows.
@@ -396,7 +394,7 @@ static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm,
396394
return H_SUCCESS;
397395
}
398396

399-
static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
397+
static long kvmppc_tce_iommu_do_unmap(struct kvm *kvm,
400398
struct iommu_table *tbl, unsigned long entry)
401399
{
402400
enum dma_data_direction dir = DMA_NONE;
@@ -416,7 +414,24 @@ static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
416414
return ret;
417415
}
418416

419-
long kvmppc_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
417+
static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
418+
struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
419+
unsigned long entry)
420+
{
421+
unsigned long i, ret = H_SUCCESS;
422+
unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
423+
unsigned long io_entry = entry * subpages;
424+
425+
for (i = 0; i < subpages; ++i) {
426+
ret = kvmppc_tce_iommu_do_unmap(kvm, tbl, io_entry + i);
427+
if (ret != H_SUCCESS)
428+
break;
429+
}
430+
431+
return ret;
432+
}
433+
434+
long kvmppc_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
420435
unsigned long entry, unsigned long ua,
421436
enum dma_data_direction dir)
422437
{
@@ -453,6 +468,27 @@ long kvmppc_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
453468
return 0;
454469
}
455470

471+
static long kvmppc_tce_iommu_map(struct kvm *kvm,
472+
struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
473+
unsigned long entry, unsigned long ua,
474+
enum dma_data_direction dir)
475+
{
476+
unsigned long i, pgoff, ret = H_SUCCESS;
477+
unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
478+
unsigned long io_entry = entry * subpages;
479+
480+
for (i = 0, pgoff = 0; i < subpages;
481+
++i, pgoff += IOMMU_PAGE_SIZE(tbl)) {
482+
483+
ret = kvmppc_tce_iommu_do_map(kvm, tbl,
484+
io_entry + i, ua + pgoff, dir);
485+
if (ret != H_SUCCESS)
486+
break;
487+
}
488+
489+
return ret;
490+
}
491+
456492
long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
457493
unsigned long ioba, unsigned long tce)
458494
{
@@ -491,10 +527,10 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
491527

492528
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
493529
if (dir == DMA_NONE)
494-
ret = kvmppc_tce_iommu_unmap(vcpu->kvm,
530+
ret = kvmppc_tce_iommu_unmap(vcpu->kvm, stt,
495531
stit->tbl, entry);
496532
else
497-
ret = kvmppc_tce_iommu_map(vcpu->kvm, stit->tbl,
533+
ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl,
498534
entry, ua, dir);
499535

500536
if (ret == H_SUCCESS)
@@ -570,7 +606,7 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
570606
return H_PARAMETER;
571607

572608
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
573-
ret = kvmppc_tce_iommu_map(vcpu->kvm,
609+
ret = kvmppc_tce_iommu_map(vcpu->kvm, stt,
574610
stit->tbl, entry + i, ua,
575611
iommu_tce_direction(tce));
576612

@@ -618,7 +654,7 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
618654
unsigned long entry = ioba >> stt->page_shift;
619655

620656
for (i = 0; i < npages; ++i) {
621-
ret = kvmppc_tce_iommu_unmap(vcpu->kvm,
657+
ret = kvmppc_tce_iommu_unmap(vcpu->kvm, stt,
622658
stit->tbl, entry + i);
623659

624660
if (ret == H_SUCCESS)

arch/powerpc/kvm/book3s_64_vio_hv.c

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm,
221221
return H_SUCCESS;
222222
}
223223

224-
static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
224+
static long kvmppc_rm_tce_iommu_do_unmap(struct kvm *kvm,
225225
struct iommu_table *tbl, unsigned long entry)
226226
{
227227
enum dma_data_direction dir = DMA_NONE;
@@ -245,7 +245,24 @@ static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
245245
return ret;
246246
}
247247

248-
static long kvmppc_rm_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
248+
static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
249+
struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
250+
unsigned long entry)
251+
{
252+
unsigned long i, ret = H_SUCCESS;
253+
unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
254+
unsigned long io_entry = entry * subpages;
255+
256+
for (i = 0; i < subpages; ++i) {
257+
ret = kvmppc_rm_tce_iommu_do_unmap(kvm, tbl, io_entry + i);
258+
if (ret != H_SUCCESS)
259+
break;
260+
}
261+
262+
return ret;
263+
}
264+
265+
static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
249266
unsigned long entry, unsigned long ua,
250267
enum dma_data_direction dir)
251268
{
@@ -290,6 +307,27 @@ static long kvmppc_rm_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
290307
return 0;
291308
}
292309

310+
static long kvmppc_rm_tce_iommu_map(struct kvm *kvm,
311+
struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
312+
unsigned long entry, unsigned long ua,
313+
enum dma_data_direction dir)
314+
{
315+
unsigned long i, pgoff, ret = H_SUCCESS;
316+
unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
317+
unsigned long io_entry = entry * subpages;
318+
319+
for (i = 0, pgoff = 0; i < subpages;
320+
++i, pgoff += IOMMU_PAGE_SIZE(tbl)) {
321+
322+
ret = kvmppc_rm_tce_iommu_do_map(kvm, tbl,
323+
io_entry + i, ua + pgoff, dir);
324+
if (ret != H_SUCCESS)
325+
break;
326+
}
327+
328+
return ret;
329+
}
330+
293331
long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
294332
unsigned long ioba, unsigned long tce)
295333
{
@@ -327,10 +365,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
327365

328366
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
329367
if (dir == DMA_NONE)
330-
ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm,
368+
ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm, stt,
331369
stit->tbl, entry);
332370
else
333-
ret = kvmppc_rm_tce_iommu_map(vcpu->kvm,
371+
ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
334372
stit->tbl, entry, ua, dir);
335373

336374
if (ret == H_SUCCESS)
@@ -477,7 +515,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
477515
return H_PARAMETER;
478516

479517
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
480-
ret = kvmppc_rm_tce_iommu_map(vcpu->kvm,
518+
ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
481519
stit->tbl, entry + i, ua,
482520
iommu_tce_direction(tce));
483521

@@ -529,7 +567,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
529567
unsigned long entry = ioba >> stt->page_shift;
530568

531569
for (i = 0; i < npages; ++i) {
532-
ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm,
570+
ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm, stt,
533571
stit->tbl, entry + i);
534572

535573
if (ret == H_SUCCESS)

0 commit comments

Comments
 (0)