1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * s390 kvm PCI passthrough support
4  *
5  * Copyright IBM Corp. 2022
6  *
7  *    Author(s): Matthew Rosato <mjrosato@linux.ibm.com>
8  */
9 
10 #ifndef __KVM_S390_PCI_H
11 #define __KVM_S390_PCI_H
12 
13 #include <linux/kvm.h>
14 #include <linux/kvm_host.h>
15 #include <linux/mutex.h>
16 #include <linux/pci.h>
17 #include <asm/airq.h>
18 #include <asm/cpu.h>
19 
20 struct kvm_zdev {
21 	struct zpci_dev *zdev;
22 	struct kvm *kvm;
23 	struct zpci_fib fib;
24 	struct list_head entry;
25 };
26 
27 struct zpci_gaite {
28 	u32 gisa;
29 	u8 gisc;
30 	u8 count;
31 	u8 reserved;
32 	u8 aisbo;
33 	u64 aisb;
34 };
35 
36 struct zpci_aift {
37 	struct zpci_gaite *gait;
38 	struct airq_iv *sbv;
39 	struct kvm_zdev **kzdev;
40 	spinlock_t gait_lock; /* Protects the gait, used during AEN forward */
41 	struct mutex aift_lock; /* Protects the other structures in aift */
42 };
43 
44 extern struct zpci_aift *aift;
45 
kvm_s390_pci_si_to_kvm(struct zpci_aift * aift,unsigned long si)46 static inline struct kvm *kvm_s390_pci_si_to_kvm(struct zpci_aift *aift,
47 						 unsigned long si)
48 {
49 	if (!IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) || !aift->kzdev ||
50 	    !aift->kzdev[si])
51 		return NULL;
52 	return aift->kzdev[si]->kvm;
53 };
54 
55 int kvm_s390_pci_aen_init(u8 nisc);
56 void kvm_s390_pci_aen_exit(void);
57 
58 void kvm_s390_pci_init_list(struct kvm *kvm);
59 void kvm_s390_pci_clear_list(struct kvm *kvm);
60 
61 int kvm_s390_pci_zpci_op(struct kvm *kvm, struct kvm_s390_zpci_op *args);
62 
63 int __init kvm_s390_pci_init(void);
64 void kvm_s390_pci_exit(void);
65 
kvm_s390_pci_interp_allowed(void)66 static inline bool kvm_s390_pci_interp_allowed(void)
67 {
68 	struct cpuid cpu_id;
69 
70 	get_cpu_id(&cpu_id);
71 	switch (cpu_id.machine) {
72 	case 0x2817:
73 	case 0x2818:
74 	case 0x2827:
75 	case 0x2828:
76 	case 0x2964:
77 	case 0x2965:
78 		/* No SHM on certain machines */
79 		return false;
80 	default:
81 		return (IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) &&
82 			sclp.has_zpci_lsi && sclp.has_aeni && sclp.has_aisi &&
83 			sclp.has_aisii);
84 	}
85 }
86 
87 #endif /* __KVM_S390_PCI_H */
88