From: Jan Kiszka <jan.kiszka@web.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: [PATCH] two level table for IO port lookup
Date: Fri, 10 Apr 2009 17:17:39 +0200 [thread overview]
Message-ID: <49DF6313.4010800@web.de> (raw)
In-Reply-To: <1239374905.28083.21.camel@nibbler.dlib.indiana.edu>
[-- Attachment #1: Type: text/plain, Size: 6675 bytes --]
Brian Wheeler wrote:
> The alpha architecture uses 24 bits for the io port address so this
> patch adds a two level table and puts the IO port data into a
> struct...because sizeof(void *) * 7 * 16777216 is nearly a 1G on my
> workstation.
>
> I've set the alpha target to use a 12/12 split and everything else to
> use 8/8.
>
>
>
>
> Signed-off-by: Brian Wheeler <bdwheele@indiana.edu>
>
> --- vl.c.orig 2009-04-10 10:01:52.000000000 -0400
> +++ vl.c 2009-04-10 10:13:33.000000000 -0400
> @@ -168,7 +168,7 @@
> //#define DEBUG_IOPORT
> //#define DEBUG_NET
> //#define DEBUG_SLIRP
> -
> +//#define DEBUG_IOPORT_FIND
>
> #ifdef DEBUG_IOPORT
> # define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__)
> @@ -184,14 +184,30 @@
> /* Max number of bluetooth switches on the commandline. */
> #define MAX_BT_CMDLINE 10
>
> -/* XXX: use a two level table to limit memory usage */
> -#define MAX_IOPORTS 65536
> -
> const char *bios_dir = CONFIG_QEMU_SHAREDIR;
> const char *bios_name = NULL;
> -static void *ioport_opaque[MAX_IOPORTS];
> -static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
> -static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
> +
> +struct ioport {
> + void *opaque;
> + IOPortReadFunc *read[3];
> + IOPortWriteFunc *write[3];
> +};
> +typedef struct ioport ioport_t;
> +
> +#ifdef TARGET_ALPHA
> +#define IOPORT_MAXBITS 24
> +#define IOPORT_PAGESIZE 12
> +#else
> +#define IOPORT_MAXBITS 16
> +#define IOPORT_PAGESIZE 8
> +#endif
> +
> +#define IOPORT_ENTRYMASK ((1<<IOPORT_PAGESIZE)-1)
> +#define IOPORT_PAGEMASK ~IOPORT_ENTRYMASK
> +#define MAX_IOPORTS (1<<IOPORT_MAXBITS)
> +
> +void *ioport[1<<(IOPORT_MAXBITS-IOPORT_PAGESIZE)];
> +
> /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
> to store the VM snapshots */
> DriveInfo drives_table[MAX_DRIVES+1];
> @@ -288,6 +304,33 @@
> static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
> static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
>
> +
> +static inline ioport_t *ioport_find(uint32_t address)
> +{
> + uint32_t page = (address & IOPORT_PAGEMASK) >> IOPORT_PAGESIZE;
> + uint32_t entry = address & IOPORT_ENTRYMASK;
> + if(address >= (1<<IOPORT_MAXBITS))
> + hw_error("Maximum port # for this architecture is %d. Port %d requested.",
> + (1<<IOPORT_MAXBITS)-1, address);
> +
> + if(ioport[page]==NULL) {
> + ioport[page]=calloc((1<<IOPORT_PAGESIZE), sizeof(ioport_t));
As you use ioport_find also for guest-driven port access, doing
allocation here is a bad idea. Consider a guest that probes the whole io
address space of your alpha box: you would end up with the same gig
being allocated that you try to avoid with this approach.
IOW: Only allocate on handler registration. On unsuccessful lookup, just
call the proper default handler.
> +#ifdef DEBUG_IOPORT_FIND
> + printf("Initializing ioport page %d to: %p\n", page, ioport[page]);
> +#endif
> + }
> + ioport_t *p = (ioport_t *)(ioport[page] + entry * sizeof(ioport_t));
> +
> +#ifdef DEBUG_IOPORT_FIND
> + printf("port find %d: page=%d, address=%p, entry=%d, address=%p\n",
> + address, page, ioport[page], entry, p);
> + printf(" data: %p\n", p->opaque);
> + printf(" read: %p, %p, %p\n", p->read[0], p->read[1], p->read[2]);
> + printf(" write: %p, %p, %p\n", p->write[0], p->write[1], p->write[2]);
> +#endif
> + return p;
> +}
> +
> static uint32_t ioport_read(int index, uint32_t address)
> {
> static IOPortReadFunc *default_func[3] = {
> @@ -295,10 +338,11 @@
> default_ioport_readw,
> default_ioport_readl
> };
> - IOPortReadFunc *func = ioport_read_table[index][address];
> + ioport_t *p = ioport_find(address);
> + IOPortReadFunc *func = p->read[index];
> if (!func)
> func = default_func[index];
> - return func(ioport_opaque[address], address);
> + return func(p->opaque, address);
> }
>
> static void ioport_write(int index, uint32_t address, uint32_t data)
> @@ -308,10 +352,11 @@
> default_ioport_writew,
> default_ioport_writel
> };
> - IOPortWriteFunc *func = ioport_write_table[index][address];
> + ioport_t *p = ioport_find(address);
> + IOPortWriteFunc *func = p->write[index];
> if (!func)
> func = default_func[index];
> - func(ioport_opaque[address], address, data);
> + func(p->opaque, address, data);
> }
>
> static uint32_t default_ioport_readb(void *opaque, uint32_t address)
> @@ -378,10 +423,11 @@
> return -1;
> }
> for(i = start; i < start + length; i += size) {
> - ioport_read_table[bsize][i] = func;
> - if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
> + ioport_t *p = ioport_find(i);
> + p->read[bsize] = func;
> + if (p->opaque != NULL && p->opaque != opaque)
> hw_error("register_ioport_read: invalid opaque");
> - ioport_opaque[i] = opaque;
> + p->opaque = opaque;
> }
> return 0;
> }
> @@ -403,10 +449,11 @@
> return -1;
> }
> for(i = start; i < start + length; i += size) {
> - ioport_write_table[bsize][i] = func;
> - if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
> + ioport_t *p = ioport_find(i);
> + p->write[bsize] = func;
> + if (p->opaque != NULL && p->opaque != opaque)
> hw_error("register_ioport_write: invalid opaque");
> - ioport_opaque[i] = opaque;
> + p->opaque = opaque;
> }
> return 0;
> }
> @@ -416,15 +463,16 @@
> int i;
>
> for(i = start; i < start + length; i++) {
> - ioport_read_table[0][i] = default_ioport_readb;
> - ioport_read_table[1][i] = default_ioport_readw;
> - ioport_read_table[2][i] = default_ioport_readl;
> -
> - ioport_write_table[0][i] = default_ioport_writeb;
> - ioport_write_table[1][i] = default_ioport_writew;
> - ioport_write_table[2][i] = default_ioport_writel;
> + ioport_t *p = ioport_find(i);
> + p->read[0] = default_ioport_readb;
> + p->read[1] = default_ioport_readw;
> + p->read[2] = default_ioport_readl;
> +
> + p->write[0] = default_ioport_writeb;
> + p->write[1] = default_ioport_writew;
> + p->write[2] = default_ioport_writel;
>
> - ioport_opaque[i] = NULL;
> + p->opaque = NULL;
> }
> }
>
>
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
next prev parent reply other threads:[~2009-04-10 15:18 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-10 14:48 [Qemu-devel] [PATCH] two level table for IO port lookup Brian Wheeler
2009-04-10 15:17 ` Jan Kiszka [this message]
2009-04-10 15:46 ` [Qemu-devel] Re: [PATCH] two level table for IO port lookup [Patch updated] Brian Wheeler
2009-04-10 17:26 ` Jan Kiszka
2009-04-10 18:53 ` [Qemu-devel] Re: [PATCH] two level table for IO port lookup [Patch V3] Brian Wheeler
2009-04-10 16:03 ` [Qemu-devel] [PATCH] two level table for IO port lookup Anthony Liguori
2009-04-10 17:24 ` [Qemu-devel] " Jan Kiszka
2009-04-10 19:08 ` [Qemu-devel] " Brian Wheeler
2009-04-10 22:31 ` Jamie Lokier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49DF6313.4010800@web.de \
--to=jan.kiszka@web.de \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.