pci pass-through support for qemu/KVM on s390
Subsystems (5)
cover pci pass-through support for qemu/KVM on s390
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:
1) all PCI operations are driven by special s390 instructions
2) all s390 PCI instructions are privileged
3) PCI config and memory spaces can not be mmap'ed
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
5) For DMA access there is always an IOMMU required. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request.
6) The OS does not get any informations about the physical layout of the PCI bus.
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration:
-device s390-pci,host=0000:00:00.0
The device executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device.
kernel patches apply to linux-kvm
s390: cio: chsc function to register GIB
s390: pci: export pci functions for pass-through usage
KVM: s390: Add GISA support
KVM: s390: Add PCI pass-through support
qemu patches apply to qemu-master
s390: Add PCI bus support
s390: Add PCI pass-through device support
Feedback and discussion is highly welcome ...
Thx!
Frank
RFC PATCH 1/6 s390: cio: chsc function to register GIB
From: Frank Blaschka <[email protected]>
This patch provides a new chsc function to register/unregister a GIB (Guest Information Block).
--- arch/s390/include/asm/cio.h | 1 drivers/s390/cio/chsc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+)
arch/s390/include/asm/cio.h +1 -0
@@ -311,5 +311,6 @@ extern int cio_get_iplinfo(struct cio_ip/* Function from drivers/s390/cio/chsc.c */ int chsc_sstpc (void *page,unsigned int op,u16 ctrl);int chsc_sstpi (void *page,void *result,size_t size); +int chsc_sgib (u32 gibo);#endif
drivers/s390/cio/chsc.c +50 -0
56 lines not on this page · raw message
RFC PATCH 2/6 s390: pci: export pci functions for pass-through usage
In reply to [email protected]From: Frank Blaschka <[email protected]>
This patch exports a couple of zPCI functions. The new pci pass-through driver for KVM will use this functions to enable the device with virtualization information and update the device dma translation table on the host. We add a new interface to purge the translation table of a device. Also we moved some zPCI functions to the pci_insn header file.
--- arch/s390/include/asm/pci.h | 6 ++ arch/s390/include/asm/pci_clp.h | 3 - arch/s390/include/asm/pci_insn.h | 92 ++++++++++++++++++++++++++++++++++++ arch/s390/pci/pci_clp.c | 4 + arch/s390/pci/pci_dma.c | 24 ++++++++- arch/s390/pci/pci_insn.c | 97 --------------------------------------- 6 files changed, 126 insertions(+), 100 deletions(-)
arch/s390/include/asm/pci.h +6 -0
@@ -140,6 +140,7 @@ int zpci_register_ioat(struct zpci_dev *int zpci_unregister_ioat (struct zpci_dev *,u8 );/* CLP */ +u8 clp_instr (void *data);int clp_scan_pci_devices (void );int clp_rescan_pci_devices (void );int clp_rescan_pci_devices_simple (void );
@@ -177,6 +178,11 @@ struct zpci_dev *get_zdev_by_fid(u32);/* DMA */ int zpci_dma_init (void );void zpci_dma_exit (void ); +int dma_update_trans (struct zpci_dev *zdev,unsigned long pa, +dma_addr_t dma_addr,size_t size,int flags); +void dma_update_cpu_trans (struct zpci_dev *zdev,void *page_addr, +dma_addr_t dma_addr,int flags); +void dma_purge_rto_entries (struct zpci_dev *zdev);/* FMB */ int zpci_fmb_enable_device (struct zpci_dev *);
arch/s390/include/asm/pci_clp.h +2 -1
@@ -148,7 +148,8 @@ struct clp_req_set_pci {u16 reserved2;u8 oc;/* operation controls */ u8 ndas;/* number of dma spaces */ -u64 reserved3; +u32 reserved3; +u32 gd;/* GISA Designation */ } __packed;/* Set PCI function response */
arch/s390/include/asm/pci_insn.h +92 -0
102 lines not on this page · raw message
arch/s390/pci/pci_clp.c +3 -1
@@ -30,7 +30,7 @@ static inline void zpci_err_clp(unsigned* Call Logical Processor * Retry logic is handled by the caller. */ -static inline u8 clp_instr (void *data) +u8 clp_instr (void *data) {struct {u8 _[CLP_BLK_SIZE ]; } *req = data;u64 ignored;
@@ -45,6 +45,7 @@ static inline u8 clp_instr(void *data) : "cc");return cc; } +EXPORT_SYMBOL_GPL (clp_instr);static void *clp_alloc_block (gfp_t gfp_mask) {
@@ -263,6 +264,7 @@ int clp_disable_fh(struct zpci_dev *zdevzpci_dbg (3 ,"dis fid:%x, fh:%x, rc:%d\n" , zdev->fid, zdev->fh, rc);return rc; } +EXPORT_SYMBOL_GPL (clp_disable_fh);static int clp_list_pci (struct clp_req_rsp_list_pci *rrb,void (*cb)(struct clp_fh_list_entry *entry))
arch/s390/pci/pci_dma.c +22 -2
@@ -114,7 +114,7 @@ static unsigned long *dma_walk_cpu_transreturn &pto[px]; } -static void dma_update_cpu_trans (struct zpci_dev *zdev,void *page_addr, +void dma_update_cpu_trans (struct zpci_dev *zdev,void *page_addr,dma_addr_t dma_addr,int flags) {unsigned long *entry;
@@ -138,8 +138,9 @@ static void dma_update_cpu_trans(structelse entry_clr_protected (entry); } +EXPORT_SYMBOL_GPL (dma_update_cpu_trans); -static int dma_update_trans (struct zpci_dev *zdev,unsigned long pa, +int dma_update_trans (struct zpci_dev *zdev,unsigned long pa,dma_addr_t dma_addr,size_t size,int flags) {unsigned int nr_pages =PAGE_ALIGN (size) >>PAGE_SHIFT ;
@@ -180,6 +181,7 @@ no_refresh:spin_unlock_irqrestore (&zdev->dma_table_lock, irq_flags);return rc; } +EXPORT_SYMBOL_GPL (dma_update_trans);static void dma_free_seg_table (unsigned long entry) {
@@ -457,6 +459,7 @@ out_reg: out_clean:return rc; } +EXPORT_SYMBOL_GPL (zpci_dma_init_device);void zpci_dma_exit_device (struct zpci_dev *zdev) {
@@ -466,6 +469,7 @@ void zpci_dma_exit_device(struct zpci_de zdev->iommu_bitmap =NULL ; zdev->next_bit =0 ; } +EXPORT_SYMBOL_GPL (zpci_dma_exit_device);static int __init dma_alloc_cpu_table_caches (void ) {
@@ -518,6 +522,22 @@ struct dma_map_ops s390_dma_ops = { };EXPORT_SYMBOL_GPL (s390_dma_ops); +void dma_purge_rto_entries (struct zpci_dev *zdev) +{ +unsigned long *table; +int rtx; + +if (!zdev || !zdev->dma_table) +return ; + table = zdev->dma_table; +for (rtx =0 ; rtx <ZPCI_TABLE_ENTRIES ; rtx++) +if (reg_entry_isvalid (table[rtx])) { +dma_free_seg_table (table[rtx]); +invalidate_table_entry (&table[rtx]); + } +} +EXPORT_SYMBOL_GPL (dma_purge_rto_entries); +static int __init s390_iommu_setup (char *str) {if (!strncmp (str,"strict" ,6 ))
arch/s390/pci/pci_insn.c +1 -96
130 lines not on this page · raw message
RFC PATCH 3/6 KVM: s390: Add GISA support
In reply to [email protected]From: Frank Blaschka <[email protected]>
This patch adds GISA (Guest Interrupt State Area) support to s390 kvm. GISA can be used for exitless interrupts. The patch provides a set of functions for GISA related operations like accessing GISA fields or registering ISCs for alert. Exploiters of GISA will follow with additional patches.
--- arch/s390/include/asm/kvm_host.h | 72 ++++++++++++++++ arch/s390/kvm/kvm-s390.c | 167 +++++++++++++++++++++++++++++++++++++++ arch/s390/kvm/kvm-s390.h | 28 ++++++ 3 files changed, 265 insertions(+), 2 deletions(-)
arch/s390/include/asm/kvm_host.h +70 -2
@@ -129,11 +129,12 @@ struct kvm_s390_sie_block {__u8 reserved60;/* 0x0060 */ __u8 ecb;/* 0x0061 */ __u8 ecb2;/* 0x0062 */ -__u8 reserved63[1 ];/* 0x0063 */ +__u8 ecb3;/* 0x0063 */ __u32 scaol;/* 0x0064 */ __u8 reserved68[4 ];/* 0x0068 */ __u32 todpr;/* 0x006c */ -__u8 reserved70[32 ];/* 0x0070 */ +__u32 gd;/* 0x0070 */ +__u8 reserved74[28 ];/* 0x0074 */ psw_t gpsw;/* 0x0090 */ __u64 gg14;/* 0x00a0 */ __u64 gg15;/* 0x00a8 */
@@ -300,6 +301,70 @@ struct kvm_s390_interrupt_info {#define ACTION_STORE_ON_STOP (1<<0)#define ACTION_STOP_ON_STOP (1<<1) +#define KVM_S390_GISA_FORMAT_0 0 +#define KVM_S390_GISA_FORMAT_1 1 + +struct kvm_s390_gisa_f0 { +u32 next_alert; +u8 ipm; +u16 rsv0:14 ; +u16 g:1 ; +u16 c:1 ; +u8 iam; +u32 rsv1; +u32 count; +} __packed; + +struct kvm_s390_gisa_f1 { +u32 next_alert; +u8 ipm; +u8 simm; +u8 nimm; +u8 iam; +u64 aisma; +u32 rsv0:6 ; +u32 g:1 ; +u32 c:1 ; +u32 rsv1:24 ; +u64 rsv2; +u32 count; +} __packed; + +union kvm_s390_gisa { +struct kvm_s390_gisa_f0 f0; +struct kvm_s390_gisa_f1 f1; +}; + +struct kvm_s390_gait { +u32 gd; + u16 : 5; +u16 gisc :3 ; +u16 rpu :8 ; + u16 : 10; +u16 gaisbo :6 ; +u64 gaisba; +} __packed; + +struct kvm_s390_aifte { +u64 faisba; +u64 gaita; +u16 simm :8 ; + u16 : 5; +u16 afi :3 ; +u16 reserved1; +u16 reserved2; +u16 faal; +} __packed; + +struct kvm_s390_gib { +u32 alo; +u32 reserved1; + u32 : 5; +u32 nisc :3 ; + u32 : 24; +u8 reserverd2[20 ]; +} __packed; +struct kvm_s390_local_interrupt {spinlock_t lock;struct list_head list;
@@ -420,6 +485,9 @@ struct kvm_arch{struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS ];wait_queue_head_t ipte_wq;spinlock_t start_stop_lock; +union kvm_s390_gisa *gisa; +unsigned long iam; +atomic_t in_sie; };#define KVM_HVA_ERR_BAD (-1UL)
arch/s390/kvm/kvm-s390.c +167 -0
211 lines not on this page · raw message
arch/s390/kvm/kvm-s390.h +28 -0
@@ -122,6 +122,17 @@ static inline u64 kvm_s390_get_base_dispreturn (base2 ? vcpu->run->s.regs.gprs[base2] :0 ) + disp2; } +static inline u64 kvm_s390_get_base_disp_rxy (struct kvm_vcpu *vcpu) +{ +u32 x2 = (vcpu->arch.sie_block->ipa &0x000f ); +u32 base2 = vcpu->arch.sie_block->ipb >>28 ; +u32 disp2 = ((vcpu->arch.sie_block->ipb &0x0fff0000 ) >>16 ) + + ((vcpu->arch.sie_block->ipb &0xff00 ) <<4 ); + +return (base2 ? vcpu->run->s.regs.gprs[base2] :0 ) + + (x2 ? vcpu->run->s.regs.gprs[x2] :0 ) + (u64 )disp2; +} +/* Set the condition code in the guest program status word */ static inline void kvm_s390_set_psw_cc (struct kvm_vcpu *vcpu,unsigned long cc) {
@@ -180,6 +191,23 @@ void exit_sie(struct kvm_vcpu *vcpu);void exit_sie_sync (struct kvm_vcpu *vcpu);int kvm_s390_vcpu_setup_cmma (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_unsetup_cmma (struct kvm_vcpu *vcpu); +u32 kvm_s390_gisa_get_fmt (void ); +void kvm_s390_gisa_register_alert (struct kvm *kvm,u32 gisc); +void kvm_s390_gisa_unregister_alert (struct kvm *kvm,u32 gisc); +u32 __kvm_s390_gisa_get_next_alert (union kvm_s390_gisa *gisa); +u32 kvm_s390_gisa_get_next_alert (struct kvm *kvm); +void __kvm_s390_gisa_set_next_alert (union kvm_s390_gisa *gisa,u32 val); +void kvm_s390_gisa_set_next_alert (struct kvm *kvm,u32 val); +u8 kvm_s390_gisa_get_iam (struct kvm *kvm); +void kvm_s390_gisa_set_iam (struct kvm *kvm,u8 value); +int kvm_s390_gisa_test_iam_gisc (struct kvm *kvm,u32 gisc); +u8 kvm_s390_gisa_get_ipm (struct kvm *kvm); +void kvm_s390_gisa_set_ipm (struct kvm *kvm,u8 value); +int kvm_s390_gisa_test_ipm_gisc (struct kvm *kvm,u32 gisc); +void kvm_s390_gisa_set_ipm_gisc (struct kvm *kvm,u32 gisc); +u32 kvm_s390_gisa_get_g (struct kvm *kvm); +u32 kvm_s390_gisa_get_c (struct kvm *kvm); +u32 kvm_s390_gisa_get_count (struct kvm *kvm);/* is cmma enabled */ bool kvm_s390_cmma_enabled (struct kvm *kvm);int test_vfacility (unsigned long nr);
Re: [RFC][patch 3/6] KVM: s390: Add GISA support
arch/s390/kvm/kvm-s390.c void exit_sie_sync(struct kvm_vcpu *vcpu · line 790
Quoted 6 lines · On Thu, Sep 04, 2014 at 12:52:26PM +0200, [email protected] wrote:
arch/s390/kvm/kvm-s390.c +6
-0+void kvm_s390_gisa_register_alert (struct kvm *kvm,u32 gisc) +{ +int bito =BITS_PER_BYTE *7 + gisc; + +set_bit (bito ^ (BITS_PER_LONG -1 ), &kvm->arch.iam); +}
Just a very minor nit: you could also use set_bit_inv() & friends.
arch/s390/kvm/kvm-s390.h static inline u64 kvm_s390_get_base_disp · line 134
Quoted 10 lines
arch/s390/kvm/kvm-s390.h +10
-0+static inline u64 kvm_s390_get_base_disp_rxy (struct kvm_vcpu *vcpu) +{ +u32 x2 = (vcpu->arch.sie_block->ipa &0x000f ); +u32 base2 = vcpu->arch.sie_block->ipb >>28 ; +u32 disp2 = ((vcpu->arch.sie_block->ipb &0x0fff0000 ) >>16 ) + + ((vcpu->arch.sie_block->ipb &0xff00 ) <<4 ); + +return (base2 ? vcpu->run->s.regs.gprs[base2] :0 ) + + (x2 ? vcpu->run->s.regs.gprs[x2] :0 ) + (u64 )disp2; +}
Not very readable ;) However.. for the RXY instruction format the 20 bit displacement is usually signed and not unsigned like your code seems to treat it.
Re: [RFC][patch 3/6] KVM: s390: Add GISA support
In reply to [email protected]Quoted 9 lines · On 04.09.14 12:52, [email protected] wrote:
From: Frank Blaschka <[email protected]>
This patch adds GISA (Guest Interrupt State Area) support to s390 kvm. GISA can be used for exitless interrupts. The patch provides a set of functions for GISA related operations like accessing GISA fields or registering ISCs for alert. Exploiters of GISA will follow with additional patches.
Signed-off-by Frank Blaschka <[email protected]>
That's a nice feature. However, please make sure that you maintain the abstraction levels.
What should happen is that you request an irqfd from FLIC. Then you associate that irqfd with the PCI device.
Thanks to that association, both parties can now talk to each other and negotiate their GISA number space and make sure things are connected.
However, it should always be possible to do things without this direct IRQ injection.
So you should be able to receive an irqfd event when an IRQ happened, so that VFIO user space applications can also handle interrupts for example.
And the same applies for interrupt injection. We also need to be able to inject an adapter interrupt from QEMU for emulated devices ;).
Alex
Re: [RFC][patch 3/6] KVM: s390: Add GISA support
Quoted 22 lines · Alexander Graf
Quoted 9 lines · On 04.09.14 12:52, [email protected] wrote:
From: Frank Blaschka <[email protected]>
This patch adds GISA (Guest Interrupt State Area) support to s390 kvm. GISA can be used for exitless interrupts. The patch provides a set of functions for GISA related operations like accessing GISA fields or registering ISCs for alert. Exploiters of GISA will follow with additional patches.
Signed-off-by Frank Blaschka <[email protected]>That's a nice feature. However, please make sure that you maintain the abstraction levels.
What should happen is that you request an irqfd from FLIC. Then you associate that irqfd with the PCI device.
Thanks to that association, both parties can now talk to each other and negotiate their GISA number space and make sure things are connected.
Quoted 9 lines
However, it should always be possible to do things without this direct IRQ injection.
So you should be able to receive an irqfd event when an IRQ happened, so that VFIO user space applications can also handle interrupts for example.
And the same applies for interrupt injection. We also need to be able to inject an adapter interrupt from QEMU for emulated devices ;).
OK, assuming we are doing the vfio solution expoiting GISA would be a second step. Will take your feedback into account. THX!
Quoted 7 lines
Alex
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
RFC PATCH 4/6 KVM: s390: Add PCI pass-through support
In reply to [email protected]From: Frank Blaschka <[email protected]>
This patch implemets PCI pass-through kernel support for s390. Design approach is very similar to the x86 device assignment. User space executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. s390 pci instructions are intercepted in kernel and operations are passed directly to the assigned pci device. To take advantage of all system z specific virtualization features we need to access the SIE control block residing in KVM. Also we have to enable z pci devices with special configuration information coming form the SIE block as well.
--- arch/s390/include/asm/kvm_host.h | 1 arch/s390/kvm/Makefile | 2 arch/s390/kvm/intercept.c | 1 arch/s390/kvm/kvm-s390.c | 33 arch/s390/kvm/kvm-s390.h | 17 arch/s390/kvm/pci.c | 2130 +++++++++++++++++++++++++++++++++++++++ arch/s390/kvm/priv.c | 21 7 files changed, 2202 insertions(+), 3 deletions(-)
arch/s390/include/asm/kvm_host.h +1 -0
@@ -488,6 +488,7 @@ struct kvm_arch{union kvm_s390_gisa *gisa;unsigned long iam;atomic_t in_sie; +struct list_head ppt_dev_list; };#define KVM_HVA_ERR_BAD (-1UL)
arch/s390/kvm/Makefile +1 -1
@@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/e ccflags-y := -Ivirt/kvm -Iarch/s390/kvm kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o -kvm-objs += diag.o gaccess.o guestdbg.o +kvm-objs += diag.o gaccess.o guestdbg.o pci.o obj-$(CONFIG_KVM) += kvm.o
arch/s390/kvm/intercept.c +1 -0
@@ -34,6 +34,7 @@ static const intercept_handler_t instruc [0xb6] = kvm_s390_handle_stctl, [0xb7] = kvm_s390_handle_lctl, [0xb9] = kvm_s390_handle_b9, + [0xe3] = kvm_s390_handle_e3, [0xe5] = kvm_s390_handle_e5, [0xeb] = kvm_s390_handle_eb, };
arch/s390/kvm/kvm-s390.c +31 -2
@@ -397,6 +397,24 @@ long kvm_arch_vm_ioctl(struct file *filp r =kvm_s390_vm_has_attr (kvm, &attr);break ; } +case KVM_ASSIGN_PCI_DEVICE : { +struct kvm_assigned_pci_dev assigned_dev; + + r = -EFAULT ; +if (copy_from_user (&assigned_dev, argp,sizeof (assigned_dev))) +break ; + r =kvm_s390_ioctrl_assign_pci (kvm, &assigned_dev); +break ; + } +case KVM_DEASSIGN_PCI_DEVICE : { +struct kvm_assigned_pci_dev assigned_dev; + + r = -EFAULT ; +if (copy_from_user (&assigned_dev, argp,sizeof (assigned_dev))) +break ; + r =kvm_s390_ioctrl_deassign_pci (kvm, &assigned_dev); +break ; + }default : r = -ENOTTY ; }
@@ -478,6 +496,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unkvm_s390_gisa_set_next_alert (kvm, (u32 )(unsigned long )kvm->arch.gisa);kvm_s390_gisa_set_alert_mask (kvm,0 );atomic_set (&kvm->arch.in_sie,0 ); +INIT_LIST_HEAD (&kvm->arch.ppt_dev_list);spin_lock_init (&kvm->arch.start_stop_lock);
@@ -538,6 +557,7 @@ void kvm_arch_sync_events(struct kvm *kvvoid kvm_arch_destroy_vm (struct kvm *kvm) { +s390_pci_cleanup (kvm);free_page ((unsigned long )kvm->arch.gisa);kvm_free_vcpus (kvm);free_page ((unsigned long )(kvm->arch.sca));
@@ -656,7 +676,10 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu vcpu->arch.sie_block->ecb |=0x10 ; vcpu->arch.sie_block->ecb2 =8 ; - vcpu->arch.sie_block->eca =0xD1002000U ; + vcpu->arch.sie_block->eca =0xD1202000U ; + vcpu->arch.sie_block->ecb2 |=0x02 ; + vcpu->arch.sie_block->ecb3 =0x20 ; +if (sclp_has_siif ()) vcpu->arch.sie_block->eca |=1 ; vcpu->arch.sie_block->fac = (int ) (long ) vfacilities;
@@ -1920,6 +1943,12 @@ static int __init kvm_s390_init(void)if (ret)return ret; + ret =s390_pci_init (); +if (ret) { +kvm_exit (); +return ret; + } +/* * guests can ask for up to 255+1 double words, we need a full page * to hold the maximum amount of facilities. On the other hand, we
@@ -1932,7 +1961,7 @@ static int __init kvm_s390_init(void) }memcpy (vfacilities, S390_lowcore.stfle_fac_list,16 ); vfacilities[0 ] &=0xff82fff3f4fc2000UL ; - vfacilities[1 ] &=0x005c000000000000UL ; + vfacilities[1 ] &=0x07dc000000000000UL ;return 0 ; }
arch/s390/kvm/kvm-s390.h +17 -0
@@ -167,6 +167,7 @@ int kvm_s390_mask_adapter(struct kvm *kv/* implemented in priv.c */ int is_valid_psw (psw_t *psw);int kvm_s390_handle_b2 (struct kvm_vcpu *vcpu); +int kvm_s390_handle_e3 (struct kvm_vcpu *vcpu);int kvm_s390_handle_e5 (struct kvm_vcpu *vcpu);int kvm_s390_handle_01 (struct kvm_vcpu *vcpu);int kvm_s390_handle_b9 (struct kvm_vcpu *vcpu);
@@ -267,4 +268,20 @@ void kvm_s390_clear_bp_data(struct kvm_vvoid kvm_s390_prepare_debug_exit (struct kvm_vcpu *vcpu);void kvm_s390_handle_per_event (struct kvm_vcpu *vcpu); +/* implemented in pci.c */ +int handle_clp (struct kvm_vcpu *vcpu); +int handle_rpcit (struct kvm_vcpu *vcpu); +int handle_sic (struct kvm_vcpu *vcpu); +int handle_pcistb (struct kvm_vcpu *vcpu); +int handle_mpcifc (struct kvm_vcpu *vcpu); +int handle_pcistg (struct kvm_vcpu *vcpu); +int handle_pcilg (struct kvm_vcpu *vcpu); +int handle_stpcifc (struct kvm_vcpu *vcpu); +int kvm_s390_ioctrl_assign_pci (struct kvm *kvm, +struct kvm_assigned_pci_dev *assigned_dev); +int kvm_s390_ioctrl_deassign_pci (struct kvm *kvm, +struct kvm_assigned_pci_dev *assigned_dev); +void s390_pci_cleanup (struct kvm *kvm); +int s390_pci_init (void ); +void s390_pci_exit (void );#endif
arch/s390/kvm/pci.c new file +2130 -0
2,130 lines not on this page · raw message
arch/s390/kvm/priv.c +21 -0
@@ -753,6 +753,10 @@ static const intercept_handler_t b9_hand [0x8f] = handle_ipte_interlock, [0xab] = handle_essa, [0xaf] = handle_pfmf, + [0xa0] = handle_clp, + [0xd0] = handle_pcistg, + [0xd2] = handle_pcilg, + [0xd3] = handle_rpcit, };int kvm_s390_handle_b9 (struct kvm_vcpu *vcpu)
@@ -912,9 +916,26 @@ static int handle_stctg(struct kvm_vcpureturn 0 ; } +static const intercept_handler_t e3_handlers[256 ] = { + [0xd0 ] = handle_mpcifc, + [0xd4 ] = handle_stpcifc, +}; + +int kvm_s390_handle_e3 (struct kvm_vcpu *vcpu) +{ +intercept_handler_t handler; + + handler = e3_handlers[vcpu->arch.sie_block->ipb &0xff ]; +if (handler) +return handler (vcpu); +return -EOPNOTSUPP ; +} +static const intercept_handler_t eb_handlers[256 ] = { [0x2f ] = handle_lctlg, [0x25 ] = handle_stctg, + [0xd0 ] = handle_pcistb, + [0xd1 ] = handle_sic, };int kvm_s390_handle_eb (struct kvm_vcpu *vcpu)
Re: [RFC][patch 4/6] KVM: s390: Add PCI pass-through support
Quoted 14 lines · On 04.09.14 12:52, [email protected] wrote:
From: Frank Blaschka <[email protected]>
This patch implemets PCI pass-through kernel support for s390. Design approach is very similar to the x86 device assignment. User space executes the
KVM_ASSIGN_PCI_DEVICEioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. s390 pci instructions are intercepted in kernel and operations are passed directly to the assigned pci device. To take advantage of all system z specific virtualization features we need to access the SIE control block residing in KVM. Also we have to enable z pci devices with special configuration information coming form the SIE block as well.Signed-off-by Frank Blaschka <[email protected]>
Quoted 9 lines
--- arch/s390/include/asm/kvm_host.h | 1 arch/s390/kvm/Makefile | 2 arch/s390/kvm/intercept.c | 1 arch/s390/kvm/kvm-s390.c | 33 arch/s390/kvm/kvm-s390.h | 17 arch/s390/kvm/pci.c | 2130 +++++++++++++++++++++++++++++++++++++++ arch/s390/kvm/priv.c | 21 7 files changed, 2202 insertions(+), 3 deletions(-)
I would love to review this patch, but in its current form it's impossible to do. I can't possibly keep > 2000 lines of code in my head.
Alex
RFC PATCH 5/6 s390: Add PCI bus support
In reply to [email protected]From: Frank Blaschka <[email protected]>
This patch implements a pci bus for s390x together with some infrastructure to generate and handle hotplug events. It also provides device configuration/unconfiguration via sclp instruction interception.
--- default-configs/s390x-softmmu.mak | 1 hw/s390x/Makefile.objs | 1 hw/s390x/css.c | 5 hw/s390x/css.h | 1 hw/s390x/s390-pci-bus.c | 287 ++++++++++++++++++++++++++++++++++++++ hw/s390x/s390-pci-bus.h | 139 ++++++++++++++++++ hw/s390x/s390-virtio-ccw.c | 2 hw/s390x/sclp.c | 10 + include/hw/s390x/sclp.h | 8 + target-s390x/Makefile.objs | 2 target-s390x/ioinst.c | 52 ++++++ target-s390x/ioinst.h | 1 target-s390x/kvm.c | 5 target-s390x/pci_ic.c | 230 ++++++++++++++++++++++++++++++ target-s390x/pci_ic.h | 214 ++++++++++++++++++++++++++++ 15 files changed, 956 insertions(+), 2 deletions(-)
default-configs/s390x-softmmu.mak +1 -0
@@ -1,4 +1,5 @@ CONFIG_VIRTIO=y +CONFIG_PCI=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
hw/s390x/Makefile.objs +1 -0
@@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-$(CONFIG_KVM) += s390-pci-bus.o
hw/s390x/css.c +5 -0
@@ -1281,6 +1281,11 @@ void css_generate_chp_crws(uint8_t cssid/* TODO */ } +void css_generate_css_crws (uint8_t cssid) +{ +css_queue_crw (CRW_RSC_CSS ,0 ,0 ,0 ); +} +int css_enable_mcsse (void ) {trace_css_enable_facility ("mcsse" );
hw/s390x/css.h +1 -0
@@ -99,6 +99,7 @@ void css_queue_crw(uint8_t rsc, uint8_tvoid css_generate_sch_crws (uint8_t cssid,uint8_t ssid,uint16_t schid,int hotplugged,int add);void css_generate_chp_crws (uint8_t cssid,uint8_t chpid); +void css_generate_css_crws (uint8_t cssid);void css_adapter_interrupt (uint8_t isc);#define CSS_IO_ADAPTER_VIRTIO 1
hw/s390x/s390-pci-bus.c new file +287 -0
287 lines not on this page · raw message
hw/s390x/s390-pci-bus.h new file +139 -0
139 lines not on this page · raw message
hw/s390x/s390-virtio-ccw.c +2 -0
@@ -17,6 +17,7 @@#include "ioinst.h" #include "css.h" #include "virtio-ccw.h" +#include "s390-pci-bus.h" #include "qemu/config-file.h" #define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
@@ -126,6 +127,7 @@ static void ccw_init(MachineState *machis390_init_ipl_dev (machine->kernel_filename, machine->kernel_cmdline, machine->initrd_filename,"s390-ccw.img" );s390_flic_init (); +s390_pci_bus_init ();/* register hypercalls */ virtio_ccw_register_hcalls ();
hw/s390x/sclp.c +9 -1
@@ -20,6 +20,7 @@#include "qemu/config-file.h" #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" +#include "hw/s390x/s390-pci-bus.h" static inline SCLPEventFacility *get_event_facility (void ) {
@@ -62,7 +63,8 @@ static void read_SCP_info(SCCB *sccb) read_info->entries[i].type =0 ; } - read_info->facilities =cpu_to_be64 (SCLP_HAS_CPU_INFO ); + read_info->facilities =cpu_to_be64 (SCLP_HAS_CPU_INFO | +SCLP_HAS_PCI_RECONFIG );/* * The storage increment size is a multiple of 1M and is a power of 2.
@@ -350,6 +352,12 @@ static void sclp_execute(SCCB *sccb, uincase SCLP_UNASSIGN_STORAGE :unassign_storage (sccb);break ; +case SCLP_CMDW_CONFIGURE_PCI : +s390_pci_sclp_configure (1 , sccb); +break ; +case SCLP_CMDW_DECONFIGURE_PCI : +s390_pci_sclp_configure (0 , sccb); +break ;default : efc->command_handler (ef, sccb, code);break ;
include/hw/s390x/sclp.h +8 -0
@@ -45,14 +45,22 @@#define SCLP_CMDW_CONFIGURE_CPU 0x00110001#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 +/* SCLP PCI codes */ +#define SCLP_HAS_PCI_RECONFIG 0x0000000040000000ULL +#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 +#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 +#define SCLP_RECONFIG_PCI_ATPYE 2 +/* SCLP response codes */ #define SCLP_RC_NORMAL_READ_COMPLETION 0x0010#define SCLP_RC_NORMAL_COMPLETION 0x0020#define SCLP_RC_SCCB_BOUNDARY_VIOLATION 0x0100 +#define SCLP_RC_NO_ACTION_REQUIRED 0x0120#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300#define SCLP_RC_STANDBY_READ_COMPLETION 0x0410 +#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED 0x09f0#define SCLP_RC_INVALID_FUNCTION 0x40f0#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0
target-s390x/Makefile.objs +1 -1
@@ -2,4 +2,4 @@ obj-y += translate.o helper.o cpu.o inte obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM) += kvm.o pci_ic.o
target-s390x/ioinst.c +52 -0
76 lines not on this page · raw message
target-s390x/ioinst.h +1 -0
@@ -194,6 +194,7 @@ typedef struct CRW {#define CRW_RSC_SUBCH 0x3#define CRW_RSC_CHP 0x4 +#define CRW_RSC_CSS 0xb/* I/O interruption code */ typedef struct IOIntCode {
target-s390x/kvm.c +5 -0
@@ -40,6 +40,7 @@#include "exec/gdbstub.h" #include "trace.h" #include "qapi-event.h" +#include "pci_ic.h" /* #define DEBUG_KVM */
@@ -78,6 +79,7 @@#define PRIV_EB_SQBS 0x8a#define PRIV_B9_EQBS 0x9c +#define PRIV_B9_CLP 0xa0#define DIAG_IPL 0x308#define DIAG_KVM_HYPERCALL 0x500
@@ -813,6 +815,9 @@ static int handle_b9(S390CPU *cpu, strucint r =0 ;switch (ipa1) { +case PRIV_B9_CLP : + r =kvm_clp_service_call (cpu, run); +break ;case PRIV_B9_EQBS :/* just inject exception */ r =-1 ;
target-s390x/pci_ic.c new file +230 -0
230 lines not on this page · raw message
target-s390x/pci_ic.h new file +214 -0
214 lines not on this page · raw message
RFC PATCH 6/6 s390: Add PCI pass-through device support
In reply to [email protected]From: Frank Blaschka <[email protected]>
This patch adds a new device class handling s390 pci pass-through device assignment. The approach is very similar to the x86 device assignment. The device executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device.
--- hw/s390x/Makefile.objs | 2 hw/s390x/s390-pci-bus.c | 14 +- hw/s390x/s390_pci.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/s390x/s390_pci.h | 31 ++++ 4 files changed, 365 insertions(+), 3 deletions(-)
hw/s390x/Makefile.objs +1 -1
@@ -8,4 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o -obj-$(CONFIG_KVM) += s390-pci-bus.o +obj-$(CONFIG_KVM) += s390-pci-bus.o s390_pci.o
hw/s390x/s390-pci-bus.c +12 -2
@@ -16,6 +16,7 @@#include <hw/s390x/sclp.h> #include "qemu/error-report.h" #include "s390-pci-bus.h" +#include "s390_pci.h" /* #define DEBUG_S390PCI_BUS */ #ifdef DEBUG_S390PCI_BUS
@@ -219,8 +220,17 @@ static void s390_pcihost_hot_plug(Hotplu pbdev->pdev = pci_dev; pbdev->configured = true; - pbdev->fh =s390_pci_get_pfh (pci_dev); - pbdev->is_virt =1 ; +if (!strcmp (pci_dev->name,"s390-pci" )) { +S390PCIDevice *sdev =DO_UPCAST (S390PCIDevice, pdev, pci_dev); + pbdev->fh =s390_pci_get_fh (sdev->host); +if (!pbdev->fh) { +g_free (pbdev); +return ; + } + }else { + pbdev->fh =s390_pci_get_pfh (pci_dev); + pbdev->is_virt =1 ; + }QTAILQ_INSERT_TAIL (&device_list, pbdev, next);if (dev->hotplugged) {
hw/s390x/s390_pci.c new file +321 -0
321 lines not on this page · raw message
hw/s390x/s390_pci.h new file +31 -0
@@ -0,0 +1,31 @@ +/* +* s390 PCI pass-through device assignment definitions +* +* Copyright 2014 IBM Corp. +* Author(s): Frank Blaschka <[email protected]> +* Hong Bo Li <[email protected]> +* Yi Min Zhao <[email protected]> +* +* This work is licensed under the terms of the GNU GPL, version 2 or (at +* your option) any later version. See the COPYING file in the top-level +* directory. +*/ + +#ifndef HW_S390_PCI_H +#define HW_S390_PCI_H + +#include <hw/pci/pci.h> + +typedef struct S390PCIDevice { +PCIDevice pdev; +PCIHostDeviceAddress host; +QLIST_ENTRY (s390PCIDevice) next; +uint32_t dev_id; +uint32_t fid; +uint32_t hostirq; +}S390PCIDevice ; + +uint32_t s390_pci_get_fh (PCIHostDeviceAddress host); +uint32_t s390_pci_get_fid (PCIHostDeviceAddress host); + +#endif
Quoted 5 lines · On Thu, 2014-09-04 at 12:52 +0200, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
Generating config cycles is always arch specific.
Quoted 1 line
2) all s390 PCI instructions are privileged
While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged.
Quoted 1 line
3) PCI config and memory spaces can not be mmap'ed
VFIO has mapping flags that allow any region to specify mmap support.
Quoted 2 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism.
Quoted 1 line
5) For DMA access there is always an IOMMU required.
x86 requires the same.
Quoted 3 lines
s390 pci implementation
does not support a complete memory to iommu mapping, dma mappings are created on request.
Sounds like POWER.
Quoted 2 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
If that means that every device is isolated (seems unlikely for multifunction devices) then that makes IOMMU group support really easy.
Quoted 2 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
The KVM-VFIO device allows interaction between VFIO devices and KVM.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
VFIO supports different device backends, currently pci_dev and working towards platform devices. zpci might just be an extension to standard pci.
Quoted 16 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration:
-device s390-pci,host=0000:00:00.0
The device executes the
KVM_ASSIGN_PCI_DEVICEioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device.kernel patches apply to linux-kvm
s390: cio: chsc function to register GIB
s390: pci: export pci functions for pass-through usage
KVM: s390: Add GISA support
KVM: s390: Add PCI pass-through support
Quoted 6 lines
qemu patches apply to qemu-master
s390: Add PCI bus support
s390: Add PCI pass-through device supportFeedback and discussion is highly welcome ...
KVM-based device assignment needs to go away. It's a horrible model for devices, it offers very little protection to the kernel, assumes every device is fully isolated and visible to the IOMMU, relies on smattering of sysfs files to operate, etc. x86, POWER, and ARM are all moving to VFIO-based device assignment. Why is s390 special enough to repeat all the mistakes that x86 did? Thanks,
Alex
Quoted 11 lines · Alex Williamson
Quoted 5 lines · On Thu, 2014-09-04 at 12:52 +0200, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
Generating config cycles is always arch specific.
Quoted 1 line
2) all s390 PCI instructions are privileged
Quoted 8 lines
While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged.
Quoted 1 line
3) PCI config and memory spaces can not be mmap'ed
VFIO has mapping flags that allow any region to specify mmap support.
Hi Alex,
thx for your reply.
Let me elaborate a little bit ore on 1 - 3. Config and memory space can not be accessed via memory operations. You have to use special s390 instructions. This instructions can not be executed in user space. So there is no other way than executing this instructions in kernel. Yes vfio does support a slow path via ioctrl we could use, but this seems suboptimal from performance point of view.
Quoted 6 lines
Quoted 2 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism.
yes that's right, but then we have to do platform specific stuff to present the irq to the guest. I do not say this is impossible but we have add s390 specific code to vfio.
Quoted 9 lines
Quoted 1 line
5) For DMA access there is always an IOMMU required.
x86 requires the same.
Quoted 3 lines
s390 pci implementation
does not support a complete memory to iommu mapping, dma mappings are created on request.Sounds like POWER.
Don't know the details from power, maybe it is similar but not the same. We might be able to extend vfio to have a new interface allowing us to do DMA mappings on request.
Quoted 7 lines
Quoted 3 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
If that means that every device is isolated (seems unlikely for multifunction devices) then that makes IOMMU group support really easy.
OK
Quoted 12 lines
Quoted 2 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
The KVM-VFIO device allows interaction between VFIO devices and KVM.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
VFIO supports different device backends, currently
pci_devand working towards platform devices. zpci might just be an extension to standard pci.
7 - 8 At least this is not as straightforward as the pure kernel approach, but I have to dig into that in more detail if we could only agree on a vfio solution.
Quoted 21 lines
Quoted 21 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration:
-device s390-pci,host=0000:00:00.0
The device executes the
KVM_ASSIGN_PCI_DEVICEioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device.kernel patches apply to linux-kvm
s390: cio: chsc function to register GIB
s390: pci: export pci functions for pass-through usage
KVM: s390: Add GISA support
KVM: s390: Add PCI pass-through supportqemu patches apply to qemu-master
s390: Add PCI bus support
s390: Add PCI pass-through device support
Quoted 9 lines
Quoted 1 line
Feedback and discussion is highly welcome ...
KVM-based device assignment needs to go away. It's a horrible model for devices, it offers very little protection to the kernel, assumes every device is fully isolated and visible to the IOMMU, relies on smattering of sysfs files to operate, etc. x86, POWER, and ARM are all moving to VFIO-based device assignment. Why is s390 special enough to repeat all the mistakes that x86 did? Thanks,
Is this your personal opinion or was this a strategic decision of the QEMU/KVM community? Can anybody give us direction about this?
Actually I can understand your point. In the last weeks I did some development and testing regarding the use of vfio too. But the in kernel solutions seems to offer the best performance and most straighforward implementation for our platform.
Greetings,
Frank
Quoted 7 lines
Alex
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 23 lines · Frank Blaschka
Quoted 11 lines · Alex Williamson
Quoted 5 lines · On Thu, 2014-09-04 at 12:52 +0200, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
Generating config cycles is always arch specific.
Quoted 1 line
2) all s390 PCI instructions are privileged
Quoted 8 lines
While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged.
Quoted 1 line
3) PCI config and memory spaces can not be mmap'ed
VFIO has mapping flags that allow any region to specify mmap support.
Hi Alex,
Quoted 8 lines
thx for your reply.
Let me elaborate a little bit ore on 1 - 3. Config and memory space can not be accessed via memory operations. You have to use special s390 instructions. This instructions can not be executed in user space. So there is no other way than executing this instructions in kernel. Yes vfio does support a slow path via ioctrl we could use, but this seems suboptimal from performance point of view.
Ah, I missed the "memory spaces" part ;). I agree that it's "suboptimal" to call into the kernel for every PCI access, but I still think that VFIO provides the correct abstraction layer for us to use. If nothing else, it would at least give us identical configuration to x86 and nice debugability en par with the other platforms.
Quoted 11 lines
Quoted 7 lines
Quoted 3 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism.
yes that's right, but then we have to do platform specific stuff to present the irq to the guest. I do not say this is impossible but we have add s390 specific code to vfio.
Not at all - interrupt delivery is completely transparent to VFIO.
Quoted 9 lines
Quoted 9 lines
Quoted 2 lines
5) For DMA access there is always an IOMMU required.
x86 requires the same.
Quoted 3 lines
s390 pci implementation
does not support a complete memory to iommu mapping, dma mappings are created on request.
Quoted 5 lines
Quoted 1 line
Sounds like POWER.
Don't know the details from power, maybe it is similar but not the same. We might be able to extend vfio to have a new interface allowing us to do DMA mappings on request.
We already have that.
Quoted 19 lines
Quoted 8 lines
Quoted 4 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
If that means that every device is isolated (seems unlikely for multifunction devices) then that makes IOMMU group support really easy.
OK
Quoted 8 lines
Quoted 2 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
The KVM-VFIO device allows interaction between VFIO devices and KVM.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
Quoted 7 lines
Quoted 4 lines
VFIO supports different device backends, currently
pci_devand working towards platform devices. zpci might just be an extension to standard pci.7 - 8 At least this is not as straightforward as the pure kernel approach, but I have to dig into that in more detail if we could only agree on a vfio solution.
Please do so, yes :).
Quoted 32 lines
Quoted 22 lines
Quoted 22 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration:
-device s390-pci,host=0000:00:00.0
The device executes the
KVM_ASSIGN_PCI_DEVICEioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device.kernel patches apply to linux-kvm
s390: cio: chsc function to register GIB
s390: pci: export pci functions for pass-through usage
KVM: s390: Add GISA support
KVM: s390: Add PCI pass-through supportqemu patches apply to qemu-master
s390: Add PCI bus support
s390: Add PCI pass-through device supportQuoted 9 lines
Quoted 1 line
Feedback and discussion is highly welcome ...
KVM-based device assignment needs to go away. It's a horrible model for devices, it offers very little protection to the kernel, assumes every device is fully isolated and visible to the IOMMU, relies on smattering of sysfs files to operate, etc. x86, POWER, and ARM are all moving to VFIO-based device assignment. Why is s390 special enough to repeat all the mistakes that x86 did? Thanks,
Quoted 7 lines
Is this your personal opinion or was this a strategic decision of the QEMU/KVM community? Can anybody give us direction about this?
Actually I can understand your point. In the last weeks I did some development and testing regarding the use of vfio too. But the in kernel solutions seems to offer the best performance and most straighforward implementation for our platform.
I don't see why there should be any difference in performance between the two approaches if done right. However, we'd get a lot of benefits. Most notably the fact that s390 is not different from everyone else.
I think you'll see that it's pretty straight forward to do things VFIO style once you get the hang of it :).
Alex
Quoted 49 lines · Alexander Graf
Quoted 23 lines · Frank Blaschka
Quoted 11 lines · Alex Williamson
Quoted 5 lines · On Thu, 2014-09-04 at 12:52 +0200, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
Generating config cycles is always arch specific.
Quoted 1 line
2) all s390 PCI instructions are privileged
Quoted 8 lines
While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged.
Quoted 1 line
3) PCI config and memory spaces can not be mmap'ed
VFIO has mapping flags that allow any region to specify mmap support.
Hi Alex,
Quoted 8 lines
thx for your reply.
Let me elaborate a little bit ore on 1 - 3. Config and memory space can not be accessed via memory operations. You have to use special s390 instructions. This instructions can not be executed in user space. So there is no other way than executing this instructions in kernel. Yes vfio does support a slow path via ioctrl we could use, but this seems suboptimal from performance point of view.
Ah, I missed the "memory spaces" part ;). I agree that it's "suboptimal" to call into the kernel for every PCI access, but I still think that VFIO provides the correct abstraction layer for us to use. If nothing else, it would at least give us identical configuration to x86 and nice debugability en par with the other platforms.
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism.
Quoted 6 lines
Quoted 3 lines
yes that's right, but then we have to do platform specific stuff to present the irq to the guest. I do not say this is impossible but we have add s390 specific code to vfio.
Not at all - interrupt delivery is completely transparent to VFIO.
interrupt yes, but MSIX no
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 2 lines
5) For DMA access there is always an IOMMU required.
x86 requires the same.
Quoted 3 lines
s390 pci implementation
does not support a complete memory to iommu mapping, dma mappings are created on request.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
Sounds like POWER.
Don't know the details from power, maybe it is similar but not the same. We might be able to extend vfio to have a new interface allowing us to do DMA mappings on request.
We already have that.
Great, can you give me some pointers how to use? Thx!
Quoted 69 lines
Quoted 19 lines
Quoted 8 lines
Quoted 4 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
If that means that every device is isolated (seems unlikely for multifunction devices) then that makes IOMMU group support really easy.
OK
Quoted 8 lines
Quoted 2 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
The KVM-VFIO device allows interaction between VFIO devices and KVM.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
Quoted 7 lines
Quoted 4 lines
VFIO supports different device backends, currently
pci_devand working towards platform devices. zpci might just be an extension to standard pci.7 - 8 At least this is not as straightforward as the pure kernel approach, but I have to dig into that in more detail if we could only agree on a vfio solution.
Please do so, yes :).
Quoted 32 lines
Quoted 22 lines
Quoted 22 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration:
-device s390-pci,host=0000:00:00.0
The device executes the
KVM_ASSIGN_PCI_DEVICEioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device.kernel patches apply to linux-kvm
s390: cio: chsc function to register GIB
s390: pci: export pci functions for pass-through usage
KVM: s390: Add GISA support
KVM: s390: Add PCI pass-through supportqemu patches apply to qemu-master
s390: Add PCI bus support
s390: Add PCI pass-through device supportQuoted 9 lines
Quoted 1 line
Feedback and discussion is highly welcome ...
KVM-based device assignment needs to go away. It's a horrible model for devices, it offers very little protection to the kernel, assumes every device is fully isolated and visible to the IOMMU, relies on smattering of sysfs files to operate, etc. x86, POWER, and ARM are all moving to VFIO-based device assignment. Why is s390 special enough to repeat all the mistakes that x86 did? Thanks,
Quoted 7 lines
Is this your personal opinion or was this a strategic decision of the QEMU/KVM community? Can anybody give us direction about this?
Actually I can understand your point. In the last weeks I did some development and testing regarding the use of vfio too. But the in kernel solutions seems to offer the best performance and most straighforward implementation for our platform.
Quoted 7 lines
I don't see why there should be any difference in performance between the two approaches if done right. However, we'd get a lot of benefits. Most notably the fact that s390 is not different from everyone else.
I think you'll see that it's pretty straight forward to do things VFIO style once you get the hang of it :).
Yes, I have seen this already. Will post my vfio work sometime next week. It is not complete yet but will give you an idea what changes we need.
Hope to get feedback from Alex and you again ...
Have a nice weekend
Frank
Quoted 7 lines
Alex
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 70 lines · Frank Blaschka
Quoted 49 lines · Alexander Graf
Quoted 23 lines · Frank Blaschka
Quoted 11 lines · Alex Williamson
Quoted 5 lines · On Thu, 2014-09-04 at 12:52 +0200, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
Generating config cycles is always arch specific.
Quoted 1 line
2) all s390 PCI instructions are privileged
Quoted 8 lines
While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged.
Quoted 1 line
3) PCI config and memory spaces can not be mmap'ed
VFIO has mapping flags that allow any region to specify mmap support.
Hi Alex,
Quoted 8 lines
thx for your reply.
Let me elaborate a little bit ore on 1 - 3. Config and memory space can not be accessed via memory operations. You have to use special s390 instructions. This instructions can not be executed in user space. So there is no other way than executing this instructions in kernel. Yes vfio does support a slow path via ioctrl we could use, but this seems suboptimal from performance point of view.
Ah, I missed the "memory spaces" part ;). I agree that it's "suboptimal" to call into the kernel for every PCI access, but I still think that VFIO provides the correct abstraction layer for us to use. If nothing else, it would at least give us identical configuration to x86 and nice debugability en par with the other platforms.
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism.
Quoted 6 lines
Quoted 3 lines
yes that's right, but then we have to do platform specific stuff to present the irq to the guest. I do not say this is impossible but we have add s390 specific code to vfio.
Not at all - interrupt delivery is completely transparent to VFIO.
interrupt yes, but MSIX no
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
Quoted 2 lines
5) For DMA access there is always an IOMMU required.
x86 requires the same.
Quoted 3 lines
s390 pci implementation
does not support a complete memory to iommu mapping, dma mappings are created on request.Sounds like POWER.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Don't know the details from power, maybe it is similar but not the same. We might be able to extend vfio to have a new interface allowing us to do DMA mappings on request.
We already have that.
Great, can you give me some pointers how to use? Thx!
Sure! :)
So on POWER (sPAPR) you get a list of page entries that describe the device -> ram mapping. Every time you want to modify any of these entries, you need to invoke a hypercall (H_PUT_TCE).
So every time the guest wants to runtime add a DMA window, we trap into put_tce_emu() in hw/ppc/spapr_iommu.c. Here we call memory_region_notify_iommu().
This call goes either to an emulated IOMMU context for emulated devices or to the special VFIO IOMMU context for VFIO devices.
In the VFIO case, we end up in vfio_iommu_map_notify() at hw/misc/vfio.c which calls ioctl(VFIO_IOMMU_MAP_DMA) at the end of the day. The in-kernel implementation of the host IOMMU provider uses this map to create the virtual DMA window map.
Basically, VFIO *only* supports "DMA mappings on request" as you call them. Prepopulated DMA windows are just a coincidence that may or may not happen.
I hope that makes it slightly more clear what the path looks like :). If you have more questions on this, don't hesitate to ask.
Alex
Quoted 7 lines · On 04.09.14 12:52, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
2) all s390 PCI instructions are privileged
3) PCI config and memory spaces can not be mmap'ed
That's ok, vfio abstracts config space anyway.
Quoted 2 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
This is in line with other implementations. Interrupts go from
device -> PHB -> PIC -> CPU
(some times you can have another converter device in between)
In your case, the PHB converts INTX and MSI interrupts to Adapter interrupts to go to the floating interrupt controller. Same thing as everyone else really.
Quoted 3 lines
5) For DMA access there is always an IOMMU required. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request.
Sounds great :). So I suppose we should implement a guest facing IOMMU?
Quoted 2 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
So how does it know whether different devices are behind the same IOMMU context? Or can we assume that every device has its own context?
Quoted 2 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
Pleas elaborate.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
Why?
Quoted 3 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a
I fail to see the rationale and I definitely don't want to see anything even remotely similar to the legacy x86 device assignment on s390 ;).
Can't we just enhance VFIO?
Also, I think we'll get the cleanest model if we start off with an implementation that allows us to add emulated PCI devices to an s390x machine and only then follow on with physical ones.
Alex
Quoted 18 lines · Alexander Graf
Quoted 7 lines · On 04.09.14 12:52, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
2) all s390 PCI instructions are privileged
3) PCI config and memory spaces can not be mmap'edThat's ok, vfio abstracts config space anyway.
Quoted 2 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
This is in line with other implementations. Interrupts go from
Quoted 8 lines
device -> PHB -> PIC -> CPU
(some times you can have another converter device in between)
In your case, the PHB converts INTX and MSI interrupts to Adapter interrupts to go to the floating interrupt controller. Same thing as everyone else really.
Yes, I think this can be done, but we need s390 specific changes in vfio.
Quoted 11 lines
Quoted 3 lines
5) For DMA access there is always an IOMMU required. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request.
Sounds great :). So I suppose we should implement a guest facing IOMMU?
Quoted 2 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
So how does it know whether different devices are behind the same IOMMU context? Or can we assume that every device has its own context?
Actually yes
Quoted 11 lines
Quoted 3 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
Pleas elaborate.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
Why?
We have following s390 specific virtualization features:
1) interpretive execution of pci load/store instruction. If we use this function pci access does not get intercepted (no SIE exit) but is handled via microcode. To enable this we have to disable zpci device and enable it again with information from the SIE control block. Further in qemu problem is: vfio traps access to MSIX table so we have to find another way programming msix if we do not get intercepts for memory space access.
2) Adapter event forwarding (with alerting). This is a mechanism the adpater event (irq) is directly forwarded to the guest. To set this up we also need to manipulate the zpci device (in kernel) with information form the SIE block. Exploiting GISA is only one part of this mechanism.
Both might be possible with some more or less nice looking vfio extensions. As I said before we have to dig more into. Also this can be further optimazation steps later if we have a running vfio implementation on the platform.
Quoted 9 lines
Quoted 3 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a
I fail to see the rationale and I definitely don't want to see anything even remotely similar to the legacy x86 device assignment on s390 ;).
Can't we just enhance VFIO?
Probably yes, but we need some vfio changes (kernel and qemu)
Quoted 4 lines
Also, I think we'll get the cleanest model if we start off with an implementation that allows us to add emulated PCI devices to an s390x machine and only then follow on with physical ones.
I can already do this. With some more s390 intercepts a device can be detected and guest is able to access config/memory space. Unfortunately s390 platform does not support I/O bars so non of the emulated devices will work on the platform ...
Quoted 7 lines
Alex
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 36 lines · Frank Blaschka
Quoted 18 lines · Alexander Graf
Quoted 7 lines · On 04.09.14 12:52, [email protected] wrote:
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms.
Major differences are:1) all PCI operations are driven by special s390 instructions
2) all s390 PCI instructions are privileged
3) PCI config and memory spaces can not be mmap'edThat's ok, vfio abstracts config space anyway.
Quoted 2 lines
4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs.
This is in line with other implementations. Interrupts go from
Quoted 8 lines
device -> PHB -> PIC -> CPU
(some times you can have another converter device in between)
In your case, the PHB converts INTX and MSI interrupts to Adapter interrupts to go to the floating interrupt controller. Same thing as everyone else really.
Yes, I think this can be done, but we need s390 specific changes in vfio.
Quoted 6 lines
Quoted 3 lines
5) For DMA access there is always an IOMMU required. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request.
Sounds great :). So I suppose we should implement a guest facing IOMMU?
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
6) The OS does not get any informations about the physical layout of the PCI bus.
So how does it know whether different devices are behind the same IOMMU context? Or can we assume that every device has its own context?
Actually yes
That greatly simplifies things. Awesome :).
Quoted 13 lines
Quoted 5 lines
Quoted 4 lines
7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM
Quoted 7 lines
Pleas elaborate.
Quoted 2 lines
8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel.
Why?
Quoted 6 lines
We have following s390 specific virtualization features:
1) interpretive execution of pci load/store instruction. If we use this function pci access does not get intercepted (no SIE exit) but is handled via microcode. To enable this we have to disable zpci device and enable it again with information from the SIE control block.
Hrm. So how about you create a special vm ioctl for KVM that allows you to attach a VFIO device fd into the KVM VM context? Then the default would stay "accessible by mmap traps", but we could accelerate it with KVM.
Quoted 3 lines
Further in qemu problem is: vfio traps access to
MSIX table so we have to find another way programming msix if we do not get intercepts for memory space access.
We trap access to the MSIX table because it's a shared resource. If it's not shared for you, there's no need to trap it.
Quoted 4 lines
2) Adapter event forwarding (with alerting). This is a mechanism the adpater event (irq) is directly forwarded to the guest. To set this up we also need to manipulate the zpci device (in kernel) with information form the SIE block. Exploiting GISA is only one part of this mechanism.
How does this work when the VM is not running (because it's idle)?
Either way, we have a very similar thing on x86. It's called "posted interrupts" there. I'm not sure everything's in place for VFIO and posted interrupts to work properly, but whatever we do it sounds like the interfaces and configuration flow should be identical.
Quoted 3 lines
Both might be possible with some more or less nice looking vfio extensions. As I said before we have to dig more into. Also this can be further optimazation steps later if we have a running vfio implementation on the platform.
Yup :). That's the nice part about it.
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a
Quoted 7 lines
Quoted 5 lines
I fail to see the rationale and I definitely don't want to see anything even remotely similar to the legacy x86 device assignment on s390 ;).
Can't we just enhance VFIO?
Probably yes, but we need some vfio changes (kernel and qemu)
We need changes either way ;). So let's better do the right ones.
Quoted 9 lines
Quoted 5 lines
Also, I think we'll get the cleanest model if we start off with an implementation that allows us to add emulated PCI devices to an s390x machine and only then follow on with physical ones.
I can already do this. With some more s390 intercepts a device can be detected and guest is able to access config/memory space. Unfortunately s390 platform does not support I/O bars so non of the emulated devices will work on the platform ...
Oh? How about "nec-usb-xhci" or "intel-hda"?
Alex
Paolo Bonzini
maintainerIl 06/09/2014 01:19, Alexander Graf ha scritto:
Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
1) interpretive execution of pci load/store instruction. If we use this function pci access does not get intercepted (no SIE exit) but is handled via microcode. To enable this we have to disable zpci device and enable it again with information from the SIE control block.
Hrm. So how about you create a special vm ioctl for KVM that allows you to attach a VFIO device fd into the KVM VM context? Then the default would stay "accessible by mmap traps", but we could accelerate it with KVM.
There is already KVM_DEV_VFIO_GROUP_ADD and KVM_DEV_VFIO_GROUP_DEL.
Right now, they result in a call to kvm_arch_register_noncoherent_dma or kvm_arch_unregister_noncoherent_dma, but you can add more hooks.
Paolo
Quoted 5 lines · Paolo Bonzini
Il 06/09/2014 01:19, Alexander Graf ha scritto:
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
1) interpretive execution of pci load/store instruction. If we use this function pci access does not get intercepted (no SIE exit) but is handled via microcode. To enable this we have to disable zpci device and enable it again with information from the SIE control block.
Quoted 8 lines
Quoted 3 lines
Hrm. So how about you create a special vm ioctl for KVM that allows you to attach a VFIO device fd into the KVM VM context? Then the default would stay "accessible by mmap traps", but we could accelerate it with KVM.
There is already
KVM_DEV_VFIO_GROUP_ADDandKVM_DEV_VFIO_GROUP_DEL.Right now, they result in a call to
kvm_arch_register_noncoherent_dmaorkvm_arch_unregister_noncoherent_dma, but you can add more hooks.
Eric Auger is also working on a patch series to do IRQ forward control on ARM via the kvm-vfio pseudo device, extending the interface to register VFIO device fds. Sounds like that may be a good path to follow here too. Thanks,
Alex