From mboxrd@z Thu Jan 1 00:00:00 1970 From: Avi Kivity Subject: [PATCH v3 1/2] Type-safe ioport callbacks Date: Wed, 17 Nov 2010 11:50:09 +0200 Message-ID: <1289987410-466-2-git-send-email-avi@redhat.com> References: <1289987410-466-1-git-send-email-avi@redhat.com> Cc: kvm@vger.kernel.org To: Anthony Liguori , qemu-devel@nongnu.org Return-path: Received: from mx1.redhat.com ([209.132.183.28]:41407 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932664Ab0KQJuS (ORCPT ); Wed, 17 Nov 2010 04:50:18 -0500 In-Reply-To: <1289987410-466-1-git-send-email-avi@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: The current ioport callbacks are not type-safe, in that they accept an "opaque" pointer as an argument whose type must match the argument to the registration function; this is not checked by the compiler. This patch adds an alternative that is type-safe. Instead of an opaque argument, both registation and the callback use a new IOPort type. The callback then uses container_of() to access its main structures. Currently the old and new methods exist side by side; once the old way is gone, we can also save a bunch of memory since the new method requires one pointer per ioport instead of 6. Acked-by: Anthony Liguori Signed-off-by: Avi Kivity --- ioport.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioport.h | 2 + iorange.h | 30 ++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 0 deletions(-) create mode 100644 iorange.h diff --git a/ioport.c b/ioport.c index ec3dc65..aa4188a 100644 --- a/ioport.c +++ b/ioport.c @@ -174,6 +174,70 @@ int register_ioport_write(pio_addr_t start, int length, int size, return 0; } +static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 1, &data); + return data; +} + +static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 2, &data); + return data; +} + +static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 4, &data); + return data; +} + +static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 1, data); +} + +static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 2, data); +} + +static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 4, data); +} + +void ioport_register(IORange *ioport) +{ + register_ioport_read(ioport->base, ioport->len, 1, + ioport_readb_thunk, ioport); + register_ioport_read(ioport->base, ioport->len, 2, + ioport_readw_thunk, ioport); + register_ioport_read(ioport->base, ioport->len, 4, + ioport_readl_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 1, + ioport_writeb_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 2, + ioport_writew_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 4, + ioport_writel_thunk, ioport); +} + void isa_unassign_ioport(pio_addr_t start, int length) { int i; diff --git a/ioport.h b/ioport.h index 3d3c8a3..5ae62a3 100644 --- a/ioport.h +++ b/ioport.h @@ -25,6 +25,7 @@ #define IOPORT_H #include "qemu-common.h" +#include "iorange.h" typedef uint32_t pio_addr_t; #define FMT_pioaddr PRIx32 @@ -36,6 +37,7 @@ typedef uint32_t pio_addr_t; typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); +void ioport_register(IORange *iorange); int register_ioport_read(pio_addr_t start, int length, int size, IOPortReadFunc *func, void *opaque); int register_ioport_write(pio_addr_t start, int length, int size, diff --git a/iorange.h b/iorange.h new file mode 100644 index 0000000..9783168 --- /dev/null +++ b/iorange.h @@ -0,0 +1,30 @@ +#ifndef IORANGE_H +#define IORANGE_H + +#include + +typedef struct IORange IORange; +typedef struct IORangeOps IORangeOps; + +struct IORangeOps { + void (*read)(IORange *iorange, uint64_t offset, unsigned width, + uint64_t *data); + void (*write)(IORange *iorange, uint64_t offset, unsigned width, + uint64_t data); +}; + +struct IORange { + const IORangeOps *ops; + uint64_t base; + uint64_t len; +}; + +static inline void iorange_init(IORange *iorange, const IORangeOps *ops, + uint64_t base, uint64_t len) +{ + iorange->ops = ops; + iorange->base = base; + iorange->len = len; +} + +#endif -- 1.7.3.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=35994 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PIeeh-0008Me-SG for qemu-devel@nongnu.org; Wed, 17 Nov 2010 04:50:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PIeeg-00081P-Lo for qemu-devel@nongnu.org; Wed, 17 Nov 2010 04:50:19 -0500 Received: from mx1.redhat.com ([209.132.183.28]:33164) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PIeeg-00081C-CS for qemu-devel@nongnu.org; Wed, 17 Nov 2010 04:50:18 -0500 From: Avi Kivity Date: Wed, 17 Nov 2010 11:50:09 +0200 Message-Id: <1289987410-466-2-git-send-email-avi@redhat.com> In-Reply-To: <1289987410-466-1-git-send-email-avi@redhat.com> References: <1289987410-466-1-git-send-email-avi@redhat.com> Subject: [Qemu-devel] [PATCH v3 1/2] Type-safe ioport callbacks List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori , qemu-devel@nongnu.org Cc: kvm@vger.kernel.org The current ioport callbacks are not type-safe, in that they accept an "opaque" pointer as an argument whose type must match the argument to the registration function; this is not checked by the compiler. This patch adds an alternative that is type-safe. Instead of an opaque argument, both registation and the callback use a new IOPort type. The callback then uses container_of() to access its main structures. Currently the old and new methods exist side by side; once the old way is gone, we can also save a bunch of memory since the new method requires one pointer per ioport instead of 6. Acked-by: Anthony Liguori Signed-off-by: Avi Kivity --- ioport.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioport.h | 2 + iorange.h | 30 ++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 0 deletions(-) create mode 100644 iorange.h diff --git a/ioport.c b/ioport.c index ec3dc65..aa4188a 100644 --- a/ioport.c +++ b/ioport.c @@ -174,6 +174,70 @@ int register_ioport_write(pio_addr_t start, int length, int size, return 0; } +static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 1, &data); + return data; +} + +static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 2, &data); + return data; +} + +static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr) +{ + IORange *ioport = opaque; + uint64_t data; + + ioport->ops->read(ioport, addr - ioport->base, 4, &data); + return data; +} + +static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 1, data); +} + +static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 2, data); +} + +static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IORange *ioport = opaque; + + ioport->ops->write(ioport, addr - ioport->base, 4, data); +} + +void ioport_register(IORange *ioport) +{ + register_ioport_read(ioport->base, ioport->len, 1, + ioport_readb_thunk, ioport); + register_ioport_read(ioport->base, ioport->len, 2, + ioport_readw_thunk, ioport); + register_ioport_read(ioport->base, ioport->len, 4, + ioport_readl_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 1, + ioport_writeb_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 2, + ioport_writew_thunk, ioport); + register_ioport_write(ioport->base, ioport->len, 4, + ioport_writel_thunk, ioport); +} + void isa_unassign_ioport(pio_addr_t start, int length) { int i; diff --git a/ioport.h b/ioport.h index 3d3c8a3..5ae62a3 100644 --- a/ioport.h +++ b/ioport.h @@ -25,6 +25,7 @@ #define IOPORT_H #include "qemu-common.h" +#include "iorange.h" typedef uint32_t pio_addr_t; #define FMT_pioaddr PRIx32 @@ -36,6 +37,7 @@ typedef uint32_t pio_addr_t; typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); +void ioport_register(IORange *iorange); int register_ioport_read(pio_addr_t start, int length, int size, IOPortReadFunc *func, void *opaque); int register_ioport_write(pio_addr_t start, int length, int size, diff --git a/iorange.h b/iorange.h new file mode 100644 index 0000000..9783168 --- /dev/null +++ b/iorange.h @@ -0,0 +1,30 @@ +#ifndef IORANGE_H +#define IORANGE_H + +#include + +typedef struct IORange IORange; +typedef struct IORangeOps IORangeOps; + +struct IORangeOps { + void (*read)(IORange *iorange, uint64_t offset, unsigned width, + uint64_t *data); + void (*write)(IORange *iorange, uint64_t offset, unsigned width, + uint64_t data); +}; + +struct IORange { + const IORangeOps *ops; + uint64_t base; + uint64_t len; +}; + +static inline void iorange_init(IORange *iorange, const IORangeOps *ops, + uint64_t base, uint64_t len) +{ + iorange->ops = ops; + iorange->base = base; + iorange->len = len; +} + +#endif -- 1.7.3.1