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 > > --- 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< +#define IOPORT_PAGEMASK ~IOPORT_ENTRYMASK > +#define MAX_IOPORTS (1< + > +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< + hw_error("Maximum port # for this architecture is %d. Port %d requested.", > + (1< + > + if(ioport[page]==NULL) { > + ioport[page]=calloc((1< +#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