Message ID | 20190612111236.99538-5-pasic@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390: virtio: support protected virtualization | expand |
On Wed, 12 Jun 2019 13:12:32 +0200 Halil Pasic <pasic@linux.ibm.com> wrote: > Protected virtualization guests have to use shared pages for airq > notifier bit vectors, because hypervisor needs to write these bits. > > Let us make sure we allocate DMA memory for the notifier bit vectors by > replacing the kmem_cache with a dma_cache and kalloc() with > cio_dma_zalloc(). > > Signed-off-by: Halil Pasic <pasic@linux.ibm.com> > Reviewed-by: Sebastian Ott <sebott@linux.ibm.com> > --- > arch/s390/include/asm/airq.h | 2 ++ > drivers/s390/cio/airq.c | 37 ++++++++++++++++++++++-------------- > drivers/s390/cio/cio.h | 2 ++ > drivers/s390/cio/css.c | 1 + > 4 files changed, 28 insertions(+), 14 deletions(-) > (...) > /** > * airq_iv_create - create an interrupt vector > * @bits: number of bits in the interrupt vector > @@ -132,17 +139,19 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) > goto out; > iv->bits = bits; > iv->flags = flags; > - size = BITS_TO_LONGS(bits) * sizeof(unsigned long); > + size = iv_size(bits); > > if (flags & AIRQ_IV_CACHELINE) { > - if ((cache_line_size() * BITS_PER_BYTE) < bits) > + if ((cache_line_size() * BITS_PER_BYTE) < bits > + || !airq_iv_cache) I still think squashing this into the same if statement is a bit ugly, but not really an issue. > goto out_free; > > - iv->vector = kmem_cache_zalloc(airq_iv_cache, GFP_KERNEL); > + iv->vector = dma_pool_zalloc(airq_iv_cache, GFP_KERNEL, > + &iv->vector_dma); > if (!iv->vector) > goto out_free; > } else { > - iv->vector = kzalloc(size, GFP_KERNEL); > + iv->vector = cio_dma_zalloc(size); > if (!iv->vector) > goto out_free; > } (...) > diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h > index 06a91743335a..4d6c7d16416e 100644 > --- a/drivers/s390/cio/cio.h > +++ b/drivers/s390/cio/cio.h > @@ -135,6 +135,8 @@ extern int cio_commit_config(struct subchannel *sch); > int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); > int cio_tm_intrg(struct subchannel *sch); > > +extern int __init airq_init(void); > + > /* Use with care. */ > #ifdef CONFIG_CCW_CONSOLE > extern struct subchannel *cio_probe_console(void); > diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c > index e0f19f1e82a0..1b867c941b86 100644 > --- a/drivers/s390/cio/css.c > +++ b/drivers/s390/cio/css.c > @@ -1184,6 +1184,7 @@ static int __init css_bus_init(void) > ret = cio_dma_pool_init(); > if (ret) > goto out_unregister_pmn; > + airq_init(); Ignoring the return code here does not really hurt right now, but we probably want to change that if we want to consider failures in css initialization to be fatal. > css_init_done = 1; > > /* Enable default isc for I/O subchannels. */ On the whole, not really anything that needs changes right now, so have a Reviewed-by: Cornelia Huck <cohuck@redhat.com>
On Wed, 12 Jun 2019 16:35:01 +0200 Cornelia Huck <cohuck@redhat.com> wrote: > On Wed, 12 Jun 2019 13:12:32 +0200 > Halil Pasic <pasic@linux.ibm.com> wrote: [..] > > --- a/drivers/s390/cio/css.c > > +++ b/drivers/s390/cio/css.c > > @@ -1184,6 +1184,7 @@ static int __init css_bus_init(void) > > ret = cio_dma_pool_init(); > > if (ret) > > goto out_unregister_pmn; > > + airq_init(); > > Ignoring the return code here does not really hurt right now, but we > probably want to change that if we want to consider failures in css > initialization to be fatal. > Right. I think that would even simplify the code a bit (no rollback). > > css_init_done = 1; > > > > /* Enable default isc for I/O subchannels. */ > > On the whole, not really anything that needs changes right now, so have > a > > Reviewed-by: Cornelia Huck <cohuck@redhat.com> > Thank you so much! Regards, Halil
On 12.06.19 13:12, Halil Pasic wrote: > Protected virtualization guests have to use shared pages for airq > notifier bit vectors, because hypervisor needs to write these bits. because the hypervisor > > Let us make sure we allocate DMA memory for the notifier bit vectors by > replacing the kmem_cache with a dma_cache and kalloc() with > cio_dma_zalloc(). > > Signed-off-by: Halil Pasic <pasic@linux.ibm.com> > Reviewed-by: Sebastian Ott <sebott@linux.ibm.com> > --- > arch/s390/include/asm/airq.h | 2 ++ > drivers/s390/cio/airq.c | 37 ++++++++++++++++++++++-------------- > drivers/s390/cio/cio.h | 2 ++ > drivers/s390/cio/css.c | 1 + > 4 files changed, 28 insertions(+), 14 deletions(-) > > diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h > index c10d2ee2dfda..01936fdfaddb 100644 > --- a/arch/s390/include/asm/airq.h > +++ b/arch/s390/include/asm/airq.h > @@ -11,6 +11,7 @@ > #define _ASM_S390_AIRQ_H > > #include <linux/bit_spinlock.h> > +#include <linux/dma-mapping.h> > > struct airq_struct { > struct hlist_node list; /* Handler queueing. */ > @@ -29,6 +30,7 @@ void unregister_adapter_interrupt(struct airq_struct *airq); > /* Adapter interrupt bit vector */ > struct airq_iv { > unsigned long *vector; /* Adapter interrupt bit vector */ > + dma_addr_t vector_dma; /* Adapter interrupt bit vector dma */ > unsigned long *avail; /* Allocation bit mask for the bit vector */ > unsigned long *bitlock; /* Lock bit mask for the bit vector */ > unsigned long *ptr; /* Pointer associated with each bit */ > diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c > index 4534afc63591..427b2e24a8ce 100644 > --- a/drivers/s390/cio/airq.c > +++ b/drivers/s390/cio/airq.c > @@ -16,9 +16,11 @@ > #include <linux/mutex.h> > #include <linux/rculist.h> > #include <linux/slab.h> > +#include <linux/dmapool.h> > > #include <asm/airq.h> > #include <asm/isc.h> > +#include <asm/cio.h> > > #include "cio.h" > #include "cio_debug.h" > @@ -27,7 +29,7 @@ > static DEFINE_SPINLOCK(airq_lists_lock); > static struct hlist_head airq_lists[MAX_ISC+1]; > > -static struct kmem_cache *airq_iv_cache; > +static struct dma_pool *airq_iv_cache; > > /** > * register_adapter_interrupt() - register adapter interrupt handler > @@ -115,6 +117,11 @@ void __init init_airq_interrupts(void) > setup_irq(THIN_INTERRUPT, &airq_interrupt); > } > > +static inline unsigned long iv_size(unsigned long bits) > +{ > + return BITS_TO_LONGS(bits) * sizeof(unsigned long); > +} > + > /** > * airq_iv_create - create an interrupt vector > * @bits: number of bits in the interrupt vector > @@ -132,17 +139,19 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) > goto out; > iv->bits = bits; > iv->flags = flags; > - size = BITS_TO_LONGS(bits) * sizeof(unsigned long); > + size = iv_size(bits); > > if (flags & AIRQ_IV_CACHELINE) { > - if ((cache_line_size() * BITS_PER_BYTE) < bits) > + if ((cache_line_size() * BITS_PER_BYTE) < bits > + || !airq_iv_cache) > goto out_free; > > - iv->vector = kmem_cache_zalloc(airq_iv_cache, GFP_KERNEL); > + iv->vector = dma_pool_zalloc(airq_iv_cache, GFP_KERNEL, > + &iv->vector_dma); > if (!iv->vector) > goto out_free; > } else { > - iv->vector = kzalloc(size, GFP_KERNEL); > + iv->vector = cio_dma_zalloc(size); > if (!iv->vector) > goto out_free; > } > @@ -178,10 +187,10 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) > kfree(iv->ptr); > kfree(iv->bitlock); > kfree(iv->avail); > - if (iv->flags & AIRQ_IV_CACHELINE) > - kmem_cache_free(airq_iv_cache, iv->vector); > + if (iv->flags & AIRQ_IV_CACHELINE && iv->vector) > + dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); > else > - kfree(iv->vector); > + cio_dma_free(iv->vector, size); > kfree(iv); > out: > return NULL; > @@ -198,9 +207,9 @@ void airq_iv_release(struct airq_iv *iv) > kfree(iv->ptr); > kfree(iv->bitlock); > if (iv->flags & AIRQ_IV_CACHELINE) > - kmem_cache_free(airq_iv_cache, iv->vector); > + dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); > else > - kfree(iv->vector); > + cio_dma_free(iv->vector, iv_size(iv->bits)); > kfree(iv->avail); > kfree(iv); > } > @@ -295,12 +304,12 @@ unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, > } > EXPORT_SYMBOL(airq_iv_scan); > > -static int __init airq_init(void) > +int __init airq_init(void) > { > - airq_iv_cache = kmem_cache_create("airq_iv_cache", cache_line_size(), > - cache_line_size(), 0, NULL); > + airq_iv_cache = dma_pool_create("airq_iv_cache", cio_get_dma_css_dev(), > + cache_line_size(), > + cache_line_size(), PAGE_SIZE); > if (!airq_iv_cache) > return -ENOMEM; > return 0; > } > -subsys_initcall(airq_init); > diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h > index 06a91743335a..4d6c7d16416e 100644 > --- a/drivers/s390/cio/cio.h > +++ b/drivers/s390/cio/cio.h > @@ -135,6 +135,8 @@ extern int cio_commit_config(struct subchannel *sch); > int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); > int cio_tm_intrg(struct subchannel *sch); > > +extern int __init airq_init(void); > + > /* Use with care. */ > #ifdef CONFIG_CCW_CONSOLE > extern struct subchannel *cio_probe_console(void); > diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c > index e0f19f1e82a0..1b867c941b86 100644 > --- a/drivers/s390/cio/css.c > +++ b/drivers/s390/cio/css.c > @@ -1184,6 +1184,7 @@ static int __init css_bus_init(void) > ret = cio_dma_pool_init(); > if (ret) > goto out_unregister_pmn; > + airq_init(); > css_init_done = 1; > > /* Enable default isc for I/O subchannels. */ > Reviewed-by: Michael Mueller <mimu@linux.ibm.com> Michael
diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h index c10d2ee2dfda..01936fdfaddb 100644 --- a/arch/s390/include/asm/airq.h +++ b/arch/s390/include/asm/airq.h @@ -11,6 +11,7 @@ #define _ASM_S390_AIRQ_H #include <linux/bit_spinlock.h> +#include <linux/dma-mapping.h> struct airq_struct { struct hlist_node list; /* Handler queueing. */ @@ -29,6 +30,7 @@ void unregister_adapter_interrupt(struct airq_struct *airq); /* Adapter interrupt bit vector */ struct airq_iv { unsigned long *vector; /* Adapter interrupt bit vector */ + dma_addr_t vector_dma; /* Adapter interrupt bit vector dma */ unsigned long *avail; /* Allocation bit mask for the bit vector */ unsigned long *bitlock; /* Lock bit mask for the bit vector */ unsigned long *ptr; /* Pointer associated with each bit */ diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 4534afc63591..427b2e24a8ce 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -16,9 +16,11 @@ #include <linux/mutex.h> #include <linux/rculist.h> #include <linux/slab.h> +#include <linux/dmapool.h> #include <asm/airq.h> #include <asm/isc.h> +#include <asm/cio.h> #include "cio.h" #include "cio_debug.h" @@ -27,7 +29,7 @@ static DEFINE_SPINLOCK(airq_lists_lock); static struct hlist_head airq_lists[MAX_ISC+1]; -static struct kmem_cache *airq_iv_cache; +static struct dma_pool *airq_iv_cache; /** * register_adapter_interrupt() - register adapter interrupt handler @@ -115,6 +117,11 @@ void __init init_airq_interrupts(void) setup_irq(THIN_INTERRUPT, &airq_interrupt); } +static inline unsigned long iv_size(unsigned long bits) +{ + return BITS_TO_LONGS(bits) * sizeof(unsigned long); +} + /** * airq_iv_create - create an interrupt vector * @bits: number of bits in the interrupt vector @@ -132,17 +139,19 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) goto out; iv->bits = bits; iv->flags = flags; - size = BITS_TO_LONGS(bits) * sizeof(unsigned long); + size = iv_size(bits); if (flags & AIRQ_IV_CACHELINE) { - if ((cache_line_size() * BITS_PER_BYTE) < bits) + if ((cache_line_size() * BITS_PER_BYTE) < bits + || !airq_iv_cache) goto out_free; - iv->vector = kmem_cache_zalloc(airq_iv_cache, GFP_KERNEL); + iv->vector = dma_pool_zalloc(airq_iv_cache, GFP_KERNEL, + &iv->vector_dma); if (!iv->vector) goto out_free; } else { - iv->vector = kzalloc(size, GFP_KERNEL); + iv->vector = cio_dma_zalloc(size); if (!iv->vector) goto out_free; } @@ -178,10 +187,10 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags) kfree(iv->ptr); kfree(iv->bitlock); kfree(iv->avail); - if (iv->flags & AIRQ_IV_CACHELINE) - kmem_cache_free(airq_iv_cache, iv->vector); + if (iv->flags & AIRQ_IV_CACHELINE && iv->vector) + dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); else - kfree(iv->vector); + cio_dma_free(iv->vector, size); kfree(iv); out: return NULL; @@ -198,9 +207,9 @@ void airq_iv_release(struct airq_iv *iv) kfree(iv->ptr); kfree(iv->bitlock); if (iv->flags & AIRQ_IV_CACHELINE) - kmem_cache_free(airq_iv_cache, iv->vector); + dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma); else - kfree(iv->vector); + cio_dma_free(iv->vector, iv_size(iv->bits)); kfree(iv->avail); kfree(iv); } @@ -295,12 +304,12 @@ unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, } EXPORT_SYMBOL(airq_iv_scan); -static int __init airq_init(void) +int __init airq_init(void) { - airq_iv_cache = kmem_cache_create("airq_iv_cache", cache_line_size(), - cache_line_size(), 0, NULL); + airq_iv_cache = dma_pool_create("airq_iv_cache", cio_get_dma_css_dev(), + cache_line_size(), + cache_line_size(), PAGE_SIZE); if (!airq_iv_cache) return -ENOMEM; return 0; } -subsys_initcall(airq_init); diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 06a91743335a..4d6c7d16416e 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -135,6 +135,8 @@ extern int cio_commit_config(struct subchannel *sch); int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); int cio_tm_intrg(struct subchannel *sch); +extern int __init airq_init(void); + /* Use with care. */ #ifdef CONFIG_CCW_CONSOLE extern struct subchannel *cio_probe_console(void); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index e0f19f1e82a0..1b867c941b86 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1184,6 +1184,7 @@ static int __init css_bus_init(void) ret = cio_dma_pool_init(); if (ret) goto out_unregister_pmn; + airq_init(); css_init_done = 1; /* Enable default isc for I/O subchannels. */