Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding

These routines will be wired into a kvm ioctl in order to respond to
requests to enable / disable a device for Adapter Event Notifications /
Adapter Interuption Forwarding.

Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Acked-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/20220606203325.110625-16-mjrosato@linux.ibm.com
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>

authored by

Matthew Rosato and committed by
Christian Borntraeger
3c5a1b6f 3f4bbb43

+251 -1
+247
arch/s390/kvm/pci.c
··· 11 11 #include <linux/pci.h> 12 12 #include <asm/pci.h> 13 13 #include <asm/pci_insn.h> 14 + #include <asm/pci_io.h> 14 15 #include "pci.h" 15 16 16 17 struct zpci_aift *aift; ··· 150 149 kfree(aift->kzdev); 151 150 unlock: 152 151 mutex_unlock(&aift->aift_lock); 152 + return rc; 153 + } 154 + 155 + /* Modify PCI: Register floating adapter interruption forwarding */ 156 + static int kvm_zpci_set_airq(struct zpci_dev *zdev) 157 + { 158 + u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT); 159 + struct zpci_fib fib = {}; 160 + u8 status; 161 + 162 + fib.fmt0.isc = zdev->kzdev->fib.fmt0.isc; 163 + fib.fmt0.sum = 1; /* enable summary notifications */ 164 + fib.fmt0.noi = airq_iv_end(zdev->aibv); 165 + fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector); 166 + fib.fmt0.aibvo = 0; 167 + fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); 168 + fib.fmt0.aisbo = zdev->aisb & 63; 169 + fib.gd = zdev->gisa; 170 + 171 + return zpci_mod_fc(req, &fib, &status) ? -EIO : 0; 172 + } 173 + 174 + /* Modify PCI: Unregister floating adapter interruption forwarding */ 175 + static int kvm_zpci_clear_airq(struct zpci_dev *zdev) 176 + { 177 + u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_DEREG_INT); 178 + struct zpci_fib fib = {}; 179 + u8 cc, status; 180 + 181 + fib.gd = zdev->gisa; 182 + 183 + cc = zpci_mod_fc(req, &fib, &status); 184 + if (cc == 3 || (cc == 1 && status == 24)) 185 + /* Function already gone or IRQs already deregistered. */ 186 + cc = 0; 187 + 188 + return cc ? -EIO : 0; 189 + } 190 + 191 + static inline void unaccount_mem(unsigned long nr_pages) 192 + { 193 + struct user_struct *user = get_uid(current_user()); 194 + 195 + if (user) 196 + atomic_long_sub(nr_pages, &user->locked_vm); 197 + if (current->mm) 198 + atomic64_sub(nr_pages, &current->mm->pinned_vm); 199 + } 200 + 201 + static inline int account_mem(unsigned long nr_pages) 202 + { 203 + struct user_struct *user = get_uid(current_user()); 204 + unsigned long page_limit, cur_pages, new_pages; 205 + 206 + page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 207 + 208 + do { 209 + cur_pages = atomic_long_read(&user->locked_vm); 210 + new_pages = cur_pages + nr_pages; 211 + if (new_pages > page_limit) 212 + return -ENOMEM; 213 + } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages, 214 + new_pages) != cur_pages); 215 + 216 + atomic64_add(nr_pages, &current->mm->pinned_vm); 217 + 218 + return 0; 219 + } 220 + 221 + static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, 222 + bool assist) 223 + { 224 + struct page *pages[1], *aibv_page, *aisb_page = NULL; 225 + unsigned int msi_vecs, idx; 226 + struct zpci_gaite *gaite; 227 + unsigned long hva, bit; 228 + struct kvm *kvm; 229 + phys_addr_t gaddr; 230 + int rc = 0, gisc, npages, pcount = 0; 231 + 232 + /* 233 + * Interrupt forwarding is only applicable if the device is already 234 + * enabled for interpretation 235 + */ 236 + if (zdev->gisa == 0) 237 + return -EINVAL; 238 + 239 + kvm = zdev->kzdev->kvm; 240 + msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi); 241 + 242 + /* Get the associated forwarding ISC - if invalid, return the error */ 243 + gisc = kvm_s390_gisc_register(kvm, fib->fmt0.isc); 244 + if (gisc < 0) 245 + return gisc; 246 + 247 + /* Replace AIBV address */ 248 + idx = srcu_read_lock(&kvm->srcu); 249 + hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv)); 250 + npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages); 251 + srcu_read_unlock(&kvm->srcu, idx); 252 + if (npages < 1) { 253 + rc = -EIO; 254 + goto out; 255 + } 256 + aibv_page = pages[0]; 257 + pcount++; 258 + gaddr = page_to_phys(aibv_page) + (fib->fmt0.aibv & ~PAGE_MASK); 259 + fib->fmt0.aibv = gaddr; 260 + 261 + /* Pin the guest AISB if one was specified */ 262 + if (fib->fmt0.sum == 1) { 263 + idx = srcu_read_lock(&kvm->srcu); 264 + hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb)); 265 + npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, 266 + pages); 267 + srcu_read_unlock(&kvm->srcu, idx); 268 + if (npages < 1) { 269 + rc = -EIO; 270 + goto unpin1; 271 + } 272 + aisb_page = pages[0]; 273 + pcount++; 274 + } 275 + 276 + /* Account for pinned pages, roll back on failure */ 277 + if (account_mem(pcount)) 278 + goto unpin2; 279 + 280 + /* AISB must be allocated before we can fill in GAITE */ 281 + mutex_lock(&aift->aift_lock); 282 + bit = airq_iv_alloc_bit(aift->sbv); 283 + if (bit == -1UL) 284 + goto unlock; 285 + zdev->aisb = bit; /* store the summary bit number */ 286 + zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | 287 + AIRQ_IV_BITLOCK | 288 + AIRQ_IV_GUESTVEC, 289 + phys_to_virt(fib->fmt0.aibv)); 290 + 291 + spin_lock_irq(&aift->gait_lock); 292 + gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * 293 + sizeof(struct zpci_gaite)); 294 + 295 + /* If assist not requested, host will get all alerts */ 296 + if (assist) 297 + gaite->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa); 298 + else 299 + gaite->gisa = 0; 300 + 301 + gaite->gisc = fib->fmt0.isc; 302 + gaite->count++; 303 + gaite->aisbo = fib->fmt0.aisbo; 304 + gaite->aisb = virt_to_phys(page_address(aisb_page) + (fib->fmt0.aisb & 305 + ~PAGE_MASK)); 306 + aift->kzdev[zdev->aisb] = zdev->kzdev; 307 + spin_unlock_irq(&aift->gait_lock); 308 + 309 + /* Update guest FIB for re-issue */ 310 + fib->fmt0.aisbo = zdev->aisb & 63; 311 + fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); 312 + fib->fmt0.isc = gisc; 313 + 314 + /* Save some guest fib values in the host for later use */ 315 + zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc; 316 + zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv; 317 + mutex_unlock(&aift->aift_lock); 318 + 319 + /* Issue the clp to setup the irq now */ 320 + rc = kvm_zpci_set_airq(zdev); 321 + return rc; 322 + 323 + unlock: 324 + mutex_unlock(&aift->aift_lock); 325 + unpin2: 326 + if (fib->fmt0.sum == 1) 327 + unpin_user_page(aisb_page); 328 + unpin1: 329 + unpin_user_page(aibv_page); 330 + out: 331 + return rc; 332 + } 333 + 334 + static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force) 335 + { 336 + struct kvm_zdev *kzdev = zdev->kzdev; 337 + struct zpci_gaite *gaite; 338 + struct page *vpage = NULL, *spage = NULL; 339 + int rc, pcount = 0; 340 + u8 isc; 341 + 342 + if (zdev->gisa == 0) 343 + return -EINVAL; 344 + 345 + mutex_lock(&aift->aift_lock); 346 + 347 + /* 348 + * If the clear fails due to an error, leave now unless we know this 349 + * device is about to go away (force) -- In that case clear the GAITE 350 + * regardless. 351 + */ 352 + rc = kvm_zpci_clear_airq(zdev); 353 + if (rc && !force) 354 + goto out; 355 + 356 + if (zdev->kzdev->fib.fmt0.aibv == 0) 357 + goto out; 358 + spin_lock_irq(&aift->gait_lock); 359 + gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * 360 + sizeof(struct zpci_gaite)); 361 + isc = gaite->gisc; 362 + gaite->count--; 363 + if (gaite->count == 0) { 364 + /* Release guest AIBV and AISB */ 365 + vpage = phys_to_page(kzdev->fib.fmt0.aibv); 366 + if (gaite->aisb != 0) 367 + spage = phys_to_page(gaite->aisb); 368 + /* Clear the GAIT entry */ 369 + gaite->aisb = 0; 370 + gaite->gisc = 0; 371 + gaite->aisbo = 0; 372 + gaite->gisa = 0; 373 + aift->kzdev[zdev->aisb] = 0; 374 + /* Clear zdev info */ 375 + airq_iv_free_bit(aift->sbv, zdev->aisb); 376 + airq_iv_release(zdev->aibv); 377 + zdev->aisb = 0; 378 + zdev->aibv = NULL; 379 + } 380 + spin_unlock_irq(&aift->gait_lock); 381 + kvm_s390_gisc_unregister(kzdev->kvm, isc); 382 + kzdev->fib.fmt0.isc = 0; 383 + kzdev->fib.fmt0.aibv = 0; 384 + 385 + if (vpage) { 386 + unpin_user_page(vpage); 387 + pcount++; 388 + } 389 + if (spage) { 390 + unpin_user_page(spage); 391 + pcount++; 392 + } 393 + if (pcount > 0) 394 + unaccount_mem(pcount); 395 + out: 396 + mutex_unlock(&aift->aift_lock); 397 + 153 398 return rc; 154 399 } 155 400
+1
arch/s390/kvm/pci.h
··· 20 20 struct kvm_zdev { 21 21 struct zpci_dev *zdev; 22 22 struct kvm *kvm; 23 + struct zpci_fib fib; 23 24 }; 24 25 25 26 struct zpci_gaite {
+1
arch/s390/pci/pci_insn.c
··· 92 92 93 93 return cc; 94 94 } 95 + EXPORT_SYMBOL_GPL(zpci_mod_fc); 95 96 96 97 /* Refresh PCI Translations */ 97 98 static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
+2 -1
include/linux/sched/user.h
··· 24 24 kuid_t uid; 25 25 26 26 #if defined(CONFIG_PERF_EVENTS) || defined(CONFIG_BPF_SYSCALL) || \ 27 - defined(CONFIG_NET) || defined(CONFIG_IO_URING) 27 + defined(CONFIG_NET) || defined(CONFIG_IO_URING) || \ 28 + defined(CONFIG_VFIO_PCI_ZDEV_KVM) 28 29 atomic_long_t locked_vm; 29 30 #endif 30 31 #ifdef CONFIG_WATCH_QUEUE