diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2016-03-01 01:54:38 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2016-03-01 17:56:50 -0500 |
commit | fe26e52712ccab6648df17ecc029a68a69a01a85 (patch) | |
tree | 3bfcf89f8d288367bda48fb92a0914b188bb3cf0 /arch/powerpc/kvm | |
parent | 01d01d69192e417447dee97891d670804bedd2c8 (diff) |
KVM: PPC: Add @page_shift to kvmppc_spapr_tce_table
At the moment the kvmppc_spapr_tce_table struct can only describe
4GB windows and handle fixed size (4K) pages. Dynamic DMA windows
support more so these limits need to be extended.
This replaces window_size (in bytes, 4GB max) with page_shift (32bit)
and size (64bit, in pages).
This should cause no behavioural change as this is changing
the internal structures only - the user interface still only
allows one to create a 32-bit table with 4KiB pages at this stage.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r-- | arch/powerpc/kvm/book3s_64_vio.c | 22 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_vio_hv.c | 21 |
2 files changed, 21 insertions, 22 deletions
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 94c8e7e9b58c..61cbc449d0a8 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c | |||
@@ -40,10 +40,9 @@ | |||
40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
41 | #include <asm/tce.h> | 41 | #include <asm/tce.h> |
42 | 42 | ||
43 | static unsigned long kvmppc_tce_pages(unsigned long window_size) | 43 | static unsigned long kvmppc_tce_pages(unsigned long iommu_pages) |
44 | { | 44 | { |
45 | return ALIGN((window_size >> IOMMU_PAGE_SHIFT_4K) | 45 | return ALIGN(iommu_pages * sizeof(u64), PAGE_SIZE) / PAGE_SIZE; |
46 | * sizeof(u64), PAGE_SIZE) / PAGE_SIZE; | ||
47 | } | 46 | } |
48 | 47 | ||
49 | static unsigned long kvmppc_stt_pages(unsigned long tce_pages) | 48 | static unsigned long kvmppc_stt_pages(unsigned long tce_pages) |
@@ -95,8 +94,7 @@ static void release_spapr_tce_table(struct rcu_head *head) | |||
95 | { | 94 | { |
96 | struct kvmppc_spapr_tce_table *stt = container_of(head, | 95 | struct kvmppc_spapr_tce_table *stt = container_of(head, |
97 | struct kvmppc_spapr_tce_table, rcu); | 96 | struct kvmppc_spapr_tce_table, rcu); |
98 | int i; | 97 | unsigned long i, npages = kvmppc_tce_pages(stt->size); |
99 | unsigned long npages = kvmppc_tce_pages(stt->window_size); | ||
100 | 98 | ||
101 | for (i = 0; i < npages; i++) | 99 | for (i = 0; i < npages; i++) |
102 | __free_page(stt->pages[i]); | 100 | __free_page(stt->pages[i]); |
@@ -109,7 +107,7 @@ static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
109 | struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data; | 107 | struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data; |
110 | struct page *page; | 108 | struct page *page; |
111 | 109 | ||
112 | if (vmf->pgoff >= kvmppc_tce_pages(stt->window_size)) | 110 | if (vmf->pgoff >= kvmppc_tce_pages(stt->size)) |
113 | return VM_FAULT_SIGBUS; | 111 | return VM_FAULT_SIGBUS; |
114 | 112 | ||
115 | page = stt->pages[vmf->pgoff]; | 113 | page = stt->pages[vmf->pgoff]; |
@@ -137,7 +135,7 @@ static int kvm_spapr_tce_release(struct inode *inode, struct file *filp) | |||
137 | kvm_put_kvm(stt->kvm); | 135 | kvm_put_kvm(stt->kvm); |
138 | 136 | ||
139 | kvmppc_account_memlimit( | 137 | kvmppc_account_memlimit( |
140 | kvmppc_stt_pages(kvmppc_tce_pages(stt->window_size)), false); | 138 | kvmppc_stt_pages(kvmppc_tce_pages(stt->size)), false); |
141 | call_rcu(&stt->rcu, release_spapr_tce_table); | 139 | call_rcu(&stt->rcu, release_spapr_tce_table); |
142 | 140 | ||
143 | return 0; | 141 | return 0; |
@@ -152,7 +150,7 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, | |||
152 | struct kvm_create_spapr_tce *args) | 150 | struct kvm_create_spapr_tce *args) |
153 | { | 151 | { |
154 | struct kvmppc_spapr_tce_table *stt = NULL; | 152 | struct kvmppc_spapr_tce_table *stt = NULL; |
155 | unsigned long npages; | 153 | unsigned long npages, size; |
156 | int ret = -ENOMEM; | 154 | int ret = -ENOMEM; |
157 | int i; | 155 | int i; |
158 | 156 | ||
@@ -162,7 +160,8 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, | |||
162 | return -EBUSY; | 160 | return -EBUSY; |
163 | } | 161 | } |
164 | 162 | ||
165 | npages = kvmppc_tce_pages(args->window_size); | 163 | size = args->window_size >> IOMMU_PAGE_SHIFT_4K; |
164 | npages = kvmppc_tce_pages(size); | ||
166 | ret = kvmppc_account_memlimit(kvmppc_stt_pages(npages), true); | 165 | ret = kvmppc_account_memlimit(kvmppc_stt_pages(npages), true); |
167 | if (ret) { | 166 | if (ret) { |
168 | stt = NULL; | 167 | stt = NULL; |
@@ -175,7 +174,8 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, | |||
175 | goto fail; | 174 | goto fail; |
176 | 175 | ||
177 | stt->liobn = args->liobn; | 176 | stt->liobn = args->liobn; |
178 | stt->window_size = args->window_size; | 177 | stt->page_shift = IOMMU_PAGE_SHIFT_4K; |
178 | stt->size = size; | ||
179 | stt->kvm = kvm; | 179 | stt->kvm = kvm; |
180 | 180 | ||
181 | for (i = 0; i < npages; i++) { | 181 | for (i = 0; i < npages; i++) { |
@@ -218,7 +218,7 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, | |||
218 | if (!stt) | 218 | if (!stt) |
219 | return H_TOO_HARD; | 219 | return H_TOO_HARD; |
220 | 220 | ||
221 | entry = ioba >> IOMMU_PAGE_SHIFT_4K; | 221 | entry = ioba >> stt->page_shift; |
222 | /* | 222 | /* |
223 | * SPAPR spec says that the maximum size of the list is 512 TCEs | 223 | * SPAPR spec says that the maximum size of the list is 512 TCEs |
224 | * so the whole table fits in 4K page | 224 | * so the whole table fits in 4K page |
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c index 0486aa2329ee..c786a58c28a7 100644 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ b/arch/powerpc/kvm/book3s_64_vio_hv.c | |||
@@ -72,11 +72,10 @@ EXPORT_SYMBOL_GPL(kvmppc_find_table); | |||
72 | long kvmppc_ioba_validate(struct kvmppc_spapr_tce_table *stt, | 72 | long kvmppc_ioba_validate(struct kvmppc_spapr_tce_table *stt, |
73 | unsigned long ioba, unsigned long npages) | 73 | unsigned long ioba, unsigned long npages) |
74 | { | 74 | { |
75 | unsigned long mask = (1ULL << IOMMU_PAGE_SHIFT_4K) - 1; | 75 | unsigned long mask = (1ULL << stt->page_shift) - 1; |
76 | unsigned long idx = ioba >> IOMMU_PAGE_SHIFT_4K; | 76 | unsigned long idx = ioba >> stt->page_shift; |
77 | unsigned long size = stt->window_size >> IOMMU_PAGE_SHIFT_4K; | ||
78 | 77 | ||
79 | if ((ioba & mask) || (idx + npages > size) || (idx + npages < idx)) | 78 | if ((ioba & mask) || (idx + npages > stt->size) || (idx + npages < idx)) |
80 | return H_PARAMETER; | 79 | return H_PARAMETER; |
81 | 80 | ||
82 | return H_SUCCESS; | 81 | return H_SUCCESS; |
@@ -96,8 +95,8 @@ EXPORT_SYMBOL_GPL(kvmppc_ioba_validate); | |||
96 | */ | 95 | */ |
97 | long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce) | 96 | long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce) |
98 | { | 97 | { |
99 | unsigned long mask = | 98 | unsigned long page_mask = ~((1ULL << stt->page_shift) - 1); |
100 | ~(IOMMU_PAGE_MASK_4K | TCE_PCI_WRITE | TCE_PCI_READ); | 99 | unsigned long mask = ~(page_mask | TCE_PCI_WRITE | TCE_PCI_READ); |
101 | 100 | ||
102 | if (tce & mask) | 101 | if (tce & mask) |
103 | return H_PARAMETER; | 102 | return H_PARAMETER; |
@@ -198,7 +197,7 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |||
198 | if (ret != H_SUCCESS) | 197 | if (ret != H_SUCCESS) |
199 | return ret; | 198 | return ret; |
200 | 199 | ||
201 | kvmppc_tce_put(stt, ioba >> IOMMU_PAGE_SHIFT_4K, tce); | 200 | kvmppc_tce_put(stt, ioba >> stt->page_shift, tce); |
202 | 201 | ||
203 | return H_SUCCESS; | 202 | return H_SUCCESS; |
204 | } | 203 | } |
@@ -244,7 +243,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, | |||
244 | if (!stt) | 243 | if (!stt) |
245 | return H_TOO_HARD; | 244 | return H_TOO_HARD; |
246 | 245 | ||
247 | entry = ioba >> IOMMU_PAGE_SHIFT_4K; | 246 | entry = ioba >> stt->page_shift; |
248 | /* | 247 | /* |
249 | * The spec says that the maximum size of the list is 512 TCEs | 248 | * The spec says that the maximum size of the list is 512 TCEs |
250 | * so the whole table addressed resides in 4K page | 249 | * so the whole table addressed resides in 4K page |
@@ -313,8 +312,8 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu, | |||
313 | if (tce_value & (TCE_PCI_WRITE | TCE_PCI_READ)) | 312 | if (tce_value & (TCE_PCI_WRITE | TCE_PCI_READ)) |
314 | return H_PARAMETER; | 313 | return H_PARAMETER; |
315 | 314 | ||
316 | for (i = 0; i < npages; ++i, ioba += IOMMU_PAGE_SIZE_4K) | 315 | for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) |
317 | kvmppc_tce_put(stt, ioba >> IOMMU_PAGE_SHIFT_4K, tce_value); | 316 | kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value); |
318 | 317 | ||
319 | return H_SUCCESS; | 318 | return H_SUCCESS; |
320 | } | 319 | } |
@@ -336,7 +335,7 @@ long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |||
336 | if (ret != H_SUCCESS) | 335 | if (ret != H_SUCCESS) |
337 | return ret; | 336 | return ret; |
338 | 337 | ||
339 | idx = ioba >> IOMMU_PAGE_SHIFT_4K; | 338 | idx = ioba >> stt->page_shift; |
340 | page = stt->pages[idx / TCES_PER_PAGE]; | 339 | page = stt->pages[idx / TCES_PER_PAGE]; |
341 | tbl = (u64 *)page_address(page); | 340 | tbl = (u64 *)page_address(page); |
342 | 341 | ||