diff -r aa1ab056bfbf tools/ioemu/target-i386-dm/helper2.c --- a/tools/ioemu/target-i386-dm/helper2.c Wed Aug 02 17:42:38 2006 +0100 +++ b/tools/ioemu/target-i386-dm/helper2.c Thu Aug 03 10:39:16 2006 +0800 @@ -74,7 +74,9 @@ int vcpus = 1; int xc_handle; +buffered_iopage_t *buffered_io_page; shared_iopage_t *shared_page = NULL; +extern void handle_buffered_io(void *opaque); /* the evtchn fd for polling */ int xce_handle = -1; @@ -415,38 +417,63 @@ void cpu_ioreq_xor(CPUState *env, ioreq_ req->u.data = tmp1; } +void __handle_ioreq(CPUState *env, ioreq_t *req) +{ + if (!req->pdata_valid && (req->dir == IOREQ_WRITE)) { + if (req->size != 4) + req->u.data &= (1UL << (8 * req->size)) - 1; + } + + switch (req->type) { + case IOREQ_TYPE_PIO: + cpu_ioreq_pio(env, req); + break; + case IOREQ_TYPE_COPY: + cpu_ioreq_move(env, req); + break; + case IOREQ_TYPE_AND: + cpu_ioreq_and(env, req); + break; + case IOREQ_TYPE_OR: + cpu_ioreq_or(env, req); + break; + case IOREQ_TYPE_XOR: + cpu_ioreq_xor(env, req); + break; + default: + hw_error("Invalid ioreq type 0x%x\n", req->type); + } +} + +void __handle_buffered_iopage(CPUState *env) +{ + ioreq_t *req = NULL; + + if (!buffered_io_page) + return; + + while (buffered_io_page->read_pointer != + buffered_io_page->write_pointer) { + unsigned long tmp_read_pointer; + tmp_read_pointer = buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM; + req = &buffered_io_page->ioreq[tmp_read_pointer]; + + __handle_ioreq(env, req); + + mb(); + buffered_io_page->read_pointer++; + } +} + void cpu_handle_ioreq(void *opaque) { CPUState *env = opaque; ioreq_t *req = cpu_get_ioreq(); + handle_buffered_io(env); if (req) { - if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { - if (req->size != 4) - req->u.data &= (1UL << (8 * req->size))-1; - } - - switch (req->type) { - case IOREQ_TYPE_PIO: - cpu_ioreq_pio(env, req); - break; - case IOREQ_TYPE_COPY: - cpu_ioreq_move(env, req); - break; - case IOREQ_TYPE_AND: - cpu_ioreq_and(env, req); - break; - case IOREQ_TYPE_OR: - cpu_ioreq_or(env, req); - break; - case IOREQ_TYPE_XOR: - cpu_ioreq_xor(env, req); - break; - default: - hw_error("Invalid ioreq type 0x%x\n", req->type); - } - - /* No state change if state = STATE_IORESP_HOOK */ + __handle_ioreq(env, req); + if (req->state == STATE_IOREQ_INPROCESS) req->state = STATE_IORESP_READY; env->send_event = 1; diff -r aa1ab056bfbf tools/ioemu/vl.c --- a/tools/ioemu/vl.c Wed Aug 02 17:42:38 2006 +0100 +++ b/tools/ioemu/vl.c Thu Aug 03 10:39:16 2006 +0800 @@ -107,6 +107,7 @@ #endif /* in ms */ #define GUI_REFRESH_INTERVAL 30 +#define BUFFER_IO_MAX_DELAY 100 /* XXX: use a two level table to limit memory usage */ #define MAX_IOPORTS 65536 @@ -130,6 +131,7 @@ int nb_nics; int nb_nics; NICInfo nd_table[MAX_NICS]; QEMUTimer *gui_timer; +QEMUTimer *buffered_io_timer; int vm_running; int rtc_utc = 1; int cirrus_vga_enabled = 1; @@ -4383,6 +4385,15 @@ void gui_update(void *opaque) qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock)); } +void handle_buffered_io(void *opaque) +{ + CPUState *env = opaque; + extern void __handle_buffered_iopage(CPUState *env); + + __handle_buffered_iopage(env); + qemu_mod_timer(buffered_io_timer, BUFFER_IO_MAX_DELAY + qemu_get_clock(rt_clock)); +} + struct vm_change_state_entry { VMChangeStateHandler *cb; void *opaque; @@ -5275,6 +5286,7 @@ int main(int argc, char **argv) unsigned long nr_pages; xen_pfn_t *page_array; extern void *shared_page; + extern void *buffered_io_page; char qemu_dm_logfilename[64]; @@ -5763,11 +5775,16 @@ int main(int argc, char **argv) phys_ram_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, page_array, - nr_pages - 1); + nr_pages - 3); if (phys_ram_base == 0) { fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); exit(-1); } + + /* not yet add for IA64 */ + buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, + page_array[nr_pages - 3]); shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ|PROT_WRITE, @@ -6018,6 +6035,8 @@ int main(int argc, char **argv) gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); } + buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io, cpu_single_env); + qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock)); #ifdef CONFIG_GDBSTUB if (use_gdbstub) {