From 5a371a2e52facac1f79ab2cb1cf75ed661ab11b0 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Aug 2011 12:51:11 +0200 Subject: [PATCH 01/34] slirp: Fix types of IP address parameters Should be uint32_t for IPv4, not int. Also avoid in_addr_t without proper includes. Fixes build regression on mingw32. Signed-off-by: Jan Kiszka --- slirp/arp_table.c | 16 ++++++++-------- slirp/slirp.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/slirp/arp_table.c b/slirp/arp_table.c index 820dee22b0..5d7b8acd1d 100644 --- a/slirp/arp_table.c +++ b/slirp/arp_table.c @@ -24,9 +24,9 @@ #include "slirp.h" -void arp_table_add(Slirp *slirp, int ip_addr, uint8_t ethaddr[ETH_ALEN]) +void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) { - const in_addr_t broadcast_addr = + const uint32_t broadcast_addr = ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; ArpTable *arptbl = &slirp->arp_table; int i; @@ -60,29 +60,29 @@ void arp_table_add(Slirp *slirp, int ip_addr, uint8_t ethaddr[ETH_ALEN]) arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE; } -bool arp_table_search(Slirp *slirp, int in_ip_addr, +bool arp_table_search(Slirp *slirp, uint32_t ip_addr, uint8_t out_ethaddr[ETH_ALEN]) { - const in_addr_t broadcast_addr = + const uint32_t broadcast_addr = ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; ArpTable *arptbl = &slirp->arp_table; int i; DEBUG_CALL("arp_table_search"); - DEBUG_ARG("ip = 0x%x", in_ip_addr); + DEBUG_ARG("ip = 0x%x", ip_addr); /* Check 0.0.0.0/8 invalid source-only addresses */ - assert((in_ip_addr & htonl(~(0xf << 28))) != 0); + assert((ip_addr & htonl(~(0xf << 28))) != 0); /* If broadcast address */ - if (in_ip_addr == 0xffffffff || in_ip_addr == broadcast_addr) { + if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) { /* return Ethernet broadcast address */ memset(out_ethaddr, 0xff, ETH_ALEN); return 1; } for (i = 0; i < ARP_TABLE_SIZE; i++) { - if (arptbl->table[i].ar_sip == in_ip_addr) { + if (arptbl->table[i].ar_sip == ip_addr) { memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN); DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], diff --git a/slirp/slirp.h b/slirp/slirp.h index 2a070e6126..dcf99d5ca4 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -208,9 +208,9 @@ typedef struct ArpTable { int next_victim; } ArpTable; -void arp_table_add(Slirp *slirp, int ip_addr, uint8_t ethaddr[ETH_ALEN]); +void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]); -bool arp_table_search(Slirp *slirp, int in_ip_addr, +bool arp_table_search(Slirp *slirp, uint32_t ip_addr, uint8_t out_ethaddr[ETH_ALEN]); struct Slirp { From fd5938799d115c966f9b2d41bbb4d5bcb5284b97 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Aug 2011 14:04:00 +0200 Subject: [PATCH 02/34] slirp: Read current time only once per if_start call No need to update the current time for each packet we send from the queue. Processing time is comparably short. Signed-off-by: Jan Kiszka --- slirp/if.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/slirp/if.c b/slirp/if.c index 2d79e45bcd..47bebe4925 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -157,9 +157,8 @@ diddit: void if_start(Slirp *slirp) { + uint64_t now = qemu_get_clock_ns(rt_clock); int requeued = 0; - uint64_t now; - struct mbuf *ifm, *ifqt; DEBUG_CALL("if_start"); @@ -172,8 +171,6 @@ if_start(Slirp *slirp) if (!slirp_can_output(slirp->opaque)) return; - now = qemu_get_clock_ns(rt_clock); - /* * See which queue to get next packet from * If there's something in the fastq, select it immediately From e3a110b527f749a2acec079c261f4481aadd3edc Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Aug 2011 14:05:53 +0200 Subject: [PATCH 03/34] slirp: Only start packet expiration for delayed ones The expiration timeout must only affect packets that are queued due to pending ARP resolutions. The old version broke ping e.g. Signed-off-by: Jan Kiszka --- slirp/if.c | 3 --- slirp/slirp.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/slirp/if.c b/slirp/if.c index 47bebe4925..2852396a4a 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -106,9 +106,6 @@ if_output(struct socket *so, struct mbuf *ifm) ifs_init(ifm); insque(ifm, ifq); - /* Expiration date = Now + 1 second */ - ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL; - diddit: slirp->if_queued++; diff --git a/slirp/slirp.c b/slirp/slirp.c index a86cc6eb2d..2c242ef4eb 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -738,6 +738,9 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) slirp->client_ipaddr = iph->ip_dst; slirp_output(slirp->opaque, arp_req, sizeof(arp_req)); ifm->arp_requested = true; + + /* Expire request and drop outgoing packet after 1 second */ + ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL; } return 0; } else { From 35d7ace74bd07e3d6983c1fd7cbfab4e11175689 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 5 Aug 2011 12:06:11 +0200 Subject: [PATCH 04/34] qcow2: Fix L1 table size after bdrv_snapshot_goto When loading an internal snapshot whose L1 table is smaller than the current L1 table, the size of the current L1 would be shrunk to the snapshot's L1 size in memory, but not on disk. This lead to incorrect refcount updates and eventuelly to image corruption. Instead of writing the new L1 size to disk, this simply retains the bigger L1 size that is currently in use and makes sure that the unused part is zeroed. Signed-off-by: Kevin Wolf Tested-by: Philipp Hahn Signed-off-by: Anthony Liguori --- block/qcow2-snapshot.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 74823a5ebf..e32bcf084c 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -317,7 +317,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) { BDRVQcowState *s = bs->opaque; QCowSnapshot *sn; - int i, snapshot_index, l1_size2; + int i, snapshot_index; + int cur_l1_bytes, sn_l1_bytes; snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); if (snapshot_index < 0) @@ -330,14 +331,19 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0) goto fail; - s->l1_size = sn->l1_size; - l1_size2 = s->l1_size * sizeof(uint64_t); + cur_l1_bytes = s->l1_size * sizeof(uint64_t); + sn_l1_bytes = sn->l1_size * sizeof(uint64_t); + + if (cur_l1_bytes > sn_l1_bytes) { + memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes); + } + /* copy the snapshot l1 table to the current l1 table */ if (bdrv_pread(bs->file, sn->l1_table_offset, - s->l1_table, l1_size2) != l1_size2) + s->l1_table, sn_l1_bytes) < 0) goto fail; if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, - s->l1_table, l1_size2) < 0) + s->l1_table, cur_l1_bytes) < 0) goto fail; for(i = 0;i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); From 8a6b0cd7642f6a69700ef5c082b750140d61b7f4 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 29 Jul 2011 16:05:13 +0100 Subject: [PATCH 05/34] MAINTAINERS: add entry for Xen Acked-by: Alexander Graf Signed-off-by: Stefano Stabellini Signed-off-by: Anthony Liguori --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7cbcd7e60d..508ea1ee24 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -143,6 +143,16 @@ L: kvm@vger.kernel.org S: Supported F: target-i386/kvm.c +Guest CPU Cores (Xen): +---------------------- + +X86 +M: Stefano Stabellini +L: xen-devel@lists.xensource.com +S: Supported +F: xen-* +F: */xen* + ARM Machines ------------ Gumstix From 257a7375582e4c3b32687c72d0f52279d28b2d85 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 1 Aug 2011 16:49:59 +1000 Subject: [PATCH 06/34] Check fread() results to avoid gcc 4.6 warnings When compiling with gcc 4.6, some code in fw_cfg.c complains that fop_ret is assigned but not used (which is true). However, it looks like the meaningless assignments to fop_ret were done to suppress other gcc warnings due to the fact that fread() is labelled as warn_unused_result in glibc. This patch avoids both errors, by actually checking the fread() result code and dropping out with an error message if it fails. Reviewed-by: Stefan Hajnoczi Tested-by: Stefan Berger Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/fw_cfg.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index a29db9055d..e4847b7f93 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -87,6 +87,13 @@ static FILE *probe_splashfile(char *filename, int *file_sizep, int *file_typep) /* check magic ID */ fseek(fp, 0L, SEEK_SET); fop_ret = fread(buf, 1, 2, fp); + if (fop_ret != 2) { + error_report("Could not read header from '%s': %s", + filename, strerror(errno)); + fclose(fp); + fp = NULL; + return fp; + } filehead_value = (buf[0] + (buf[1] << 8)) & 0xffff; if (filehead_value == 0xd8ff) { file_type = JPG_FILE; @@ -181,6 +188,12 @@ static void fw_cfg_bootsplash(FWCfgState *s) boot_splash_filedata_size = file_size; fseek(fp, 0L, SEEK_SET); fop_ret = fread(boot_splash_filedata, 1, file_size, fp); + if (fop_ret != file_size) { + error_report("failed to read data from '%s'.", + boot_splash_filename); + fclose(fp); + return; + } fclose(fp); /* insert data */ if (file_type == JPG_FILE) { From 941f511a26ebdfbeb53facc775f30b9d27f3855b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:04 +0200 Subject: [PATCH 07/34] sdl: Fix termination in -no-shutdown mode Just like the monitor does, we need to clear no_shutdown before calling qemu_system_shutdown_request on quit requests. Otherwise, QEMU just stops the VM. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/sdl.c b/ui/sdl.c index 6dbc5cb0ed..9efcda5079 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -672,8 +672,10 @@ static void sdl_refresh(DisplayState *ds) sdl_process_key(&ev->key); break; case SDL_QUIT: - if (!no_quit) + if (!no_quit) { + no_shutdown = 0; qemu_system_shutdown_request(); + } break; case SDL_MOUSEMOTION: if (gui_grab || kbd_mouse_is_absolute() || From 91ada9808408fcad818ced7309f47c5fb91c6075 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:05 +0200 Subject: [PATCH 08/34] sdl: Do not make full screen mode resizable This prevents continuous resizing events and improper screen setups when going full screen. CC: Stefano Stabellini Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 9efcda5079..9a92b47f73 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -97,9 +97,12 @@ static void do_sdl_resize(int new_width, int new_height, int bpp) // printf("resizing to %d %d\n", w, h); - flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE; - if (gui_fullscreen) + flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; + if (gui_fullscreen) { flags |= SDL_FULLSCREEN; + } else { + flags |= SDL_RESIZABLE; + } if (gui_noframe) flags |= SDL_NOFRAME; From 97ad1c260cb76f834aa90dc6350fe405172b2cc3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:06 +0200 Subject: [PATCH 09/34] sdl: Avoid redundant scaling deactivation Prevents screen flickering. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 9a92b47f73..1563ee1965 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -583,10 +583,12 @@ static void sdl_refresh(DisplayState *ds) gui_keysym = 1; break; case 0x16: /* 'u' key on US keyboard */ - scaling_active = 0; - sdl_resize(ds); - vga_hw_invalidate(); - vga_hw_update(); + if (scaling_active) { + scaling_active = 0; + sdl_resize(ds); + vga_hw_invalidate(); + vga_hw_update(); + } break; case 0x02 ... 0x0a: /* '1' to '9' keys */ /* Reset the modifiers sent to the current console */ From d71680c8f1d639bfb31958b25dfb806f6b8cda56 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:07 +0200 Subject: [PATCH 10/34] sdl: Properly mark modifier+u as hotkey Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/sdl.c b/ui/sdl.c index 1563ee1965..e6c9597d37 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -589,6 +589,7 @@ static void sdl_refresh(DisplayState *ds) vga_hw_invalidate(); vga_hw_update(); } + gui_keysym = 1; break; case 0x02 ... 0x0a: /* '1' to '9' keys */ /* Reset the modifiers sent to the current console */ From 2a8ad7da542dc52b98aff3219e1c202bb1b09895 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:08 +0200 Subject: [PATCH 11/34] sdl: Fix full screen toggling from scaled mode When switching to full screen mode from a scaled window, we need to resize to DisplayState's dimension, not the scaled "real" screen size. Moreover, scaling mode may have manipulated the bpp. So we need to restore it from the DisplayState as well. CC: Stefano Stabellini Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/sdl.c b/ui/sdl.c index e6c9597d37..4acfe81867 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -529,7 +529,8 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state static void toggle_full_screen(DisplayState *ds) { gui_fullscreen = !gui_fullscreen; - do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel); + do_sdl_resize(ds_get_width(ds), ds_get_height(ds), + ds_get_bits_per_pixel(ds)); if (gui_fullscreen) { scaling_active = 0; gui_saved_grab = gui_grab; From f9977897eee2ed5e28e758b9e21cb4f64a260842 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:09 +0200 Subject: [PATCH 12/34] sdl: Restore scaling mode on return from full screen Save the scaling mode and its geometry when going full screen, restore it when returning to windowed mode. CC: Stefano Stabellini Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 4acfe81867..e18c59ac4e 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -39,6 +39,9 @@ static SDL_Surface *real_screen; static SDL_Surface *guest_screen = NULL; static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ static int last_vm_running; +static bool gui_saved_scaling; +static int gui_saved_width; +static int gui_saved_height; static int gui_saved_grab; static int gui_fullscreen; static int gui_noframe; @@ -526,16 +529,42 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state kbd_mouse_event(dx, dy, dz, buttons); } +static void sdl_scale(DisplayState *ds, int width, int height) +{ + int bpp = real_screen->format->BitsPerPixel; + + if (bpp != 16 && bpp != 32) { + bpp = 32; + } + do_sdl_resize(width, height, bpp); + scaling_active = 1; + if (!is_buffer_shared(ds->surface)) { + ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), + ds_get_height(ds)); + dpy_resize(ds); + } +} + static void toggle_full_screen(DisplayState *ds) { gui_fullscreen = !gui_fullscreen; - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), - ds_get_bits_per_pixel(ds)); if (gui_fullscreen) { + gui_saved_width = real_screen->w; + gui_saved_height = real_screen->h; + gui_saved_scaling = scaling_active; + + do_sdl_resize(ds_get_width(ds), ds_get_height(ds), + ds_get_bits_per_pixel(ds)); scaling_active = 0; + gui_saved_grab = gui_grab; sdl_grab_start(); } else { + if (gui_saved_scaling) { + sdl_scale(ds, gui_saved_width, gui_saved_height); + } else { + do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); + } if (!gui_saved_grab) sdl_grab_end(); } @@ -737,22 +766,11 @@ static void sdl_refresh(DisplayState *ds) } } break; - case SDL_VIDEORESIZE: - { - SDL_ResizeEvent *rev = &ev->resize; - int bpp = real_screen->format->BitsPerPixel; - if (bpp != 16 && bpp != 32) - bpp = 32; - do_sdl_resize(rev->w, rev->h, bpp); - scaling_active = 1; - if (!is_buffer_shared(ds->surface)) { - ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), ds_get_height(ds)); - dpy_resize(ds); - } + case SDL_VIDEORESIZE: + sdl_scale(ds, ev->resize.w, ev->resize.h); vga_hw_invalidate(); vga_hw_update(); break; - } default: break; } From 982aae66ff75dced49990d7cce8dc0be31aff7e1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:10 +0200 Subject: [PATCH 13/34] sdl: Drop bogus gui_fullscreen_initial_grab There must be no difference between initial -full-screen and switching to this mode via the hot key. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index e18c59ac4e..80bf776104 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -47,7 +47,6 @@ static int gui_fullscreen; static int gui_noframe; static int gui_key_modifier_pressed; static int gui_keysym; -static int gui_fullscreen_initial_grab; static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; static uint8_t modifiers_state[256]; static int width, height; @@ -751,7 +750,7 @@ static void sdl_refresh(DisplayState *ds) break; case SDL_ACTIVEEVENT: if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS && - !ev->active.gain && !gui_fullscreen_initial_grab) { + !ev->active.gain && !gui_fullscreen) { sdl_grab_end(); } if (ev->active.state & SDL_APPACTIVE) { @@ -923,7 +922,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) atexit(sdl_cleanup); if (full_screen) { gui_fullscreen = 1; - gui_fullscreen_initial_grab = 1; sdl_grab_start(); } } From 110defd753906a01d01d0cabfb2d8db77b3271ef Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:11 +0200 Subject: [PATCH 14/34] sdl: Initialize gui_fullscreen earlier during setup This ensures that we actually enter full screen on startup when e.g. '-vga none -full-screen' was specified. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 80bf776104..f19bae2b27 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -891,6 +891,11 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) qemu_free(filename); } + if (full_screen) { + gui_fullscreen = 1; + sdl_grab_start(); + } + dcl = qemu_mallocz(sizeof(DisplayChangeListener)); dcl->dpy_update = sdl_update; dcl->dpy_resize = sdl_resize; @@ -920,8 +925,4 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) sdl_cursor_normal = SDL_GetCursor(); atexit(sdl_cleanup); - if (full_screen) { - gui_fullscreen = 1; - sdl_grab_start(); - } } From f85581004c140c09936bc63f3744a287216aa76d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:12 +0200 Subject: [PATCH 15/34] sdl: Consistently avoid grabbing input for text consoles There were some preexisting bits that released the input when switching to text console. This patch spreads this logic consistently and also avoids grabbing the input while a text console is active. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index f19bae2b27..27465b2b7d 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -564,8 +564,9 @@ static void toggle_full_screen(DisplayState *ds) } else { do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); } - if (!gui_saved_grab) + if (!gui_saved_grab || !is_graphic_console()) { sdl_grab_end(); + } } vga_hw_invalidate(); vga_hw_update(); @@ -689,8 +690,10 @@ static void sdl_refresh(DisplayState *ds) 'SDL_WM_GrabInput(SDL_GRAB_ON)' from blocking all the application (SDL bug). */ - if (SDL_GetAppState() & SDL_APPACTIVE) + if (is_graphic_console() && + SDL_GetAppState() & SDL_APPACTIVE) { sdl_grab_start(); + } } else { sdl_grab_end(); } @@ -721,7 +724,7 @@ static void sdl_refresh(DisplayState *ds) break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - { + if (is_graphic_console()) { SDL_MouseButtonEvent *bev = &ev->button; if (!gui_grab && !kbd_mouse_is_absolute()) { if (ev->type == SDL_MOUSEBUTTONDOWN && From f623d885480b7899a445c9ef7aaa95db52820bc1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:13 +0200 Subject: [PATCH 16/34] sdl: Never release input while in full screen mode It's confusing to suddenly find two mice in full screen mode when switching consoles or accidentally hitting the grab hot keys. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 27465b2b7d..662ffef46d 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -626,9 +626,10 @@ static void sdl_refresh(DisplayState *ds) reset_keys(); console_select(keycode - 0x02); if (!is_graphic_console()) { - /* display grab if going to a text console */ - if (gui_grab) + /* release grab if going to a text console */ + if (gui_grab && !gui_fullscreen) { sdl_grab_end(); + } } gui_keysym = 1; break; @@ -694,7 +695,7 @@ static void sdl_refresh(DisplayState *ds) SDL_GetAppState() & SDL_APPACTIVE) { sdl_grab_start(); } - } else { + } else if (!gui_fullscreen) { sdl_grab_end(); } /* SDL does not send back all the From 74d9dc69abebdbf22b9473708aefd47ab53475dd Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:14 +0200 Subject: [PATCH 17/34] sdl: Fix cursor handling when switching consoles in absolute mouse mode Restore the cursor when switching from graphic to text console while the mouse is in absolute mode. Disable it again when returning. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 662ffef46d..5ad38d5460 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -452,7 +452,7 @@ static void sdl_show_cursor(void) if (!cursor_hide) return; - if (!kbd_mouse_is_absolute()) { + if (!kbd_mouse_is_absolute() || !is_graphic_console()) { SDL_ShowCursor(1); if (guest_cursor && (gui_grab || kbd_mouse_is_absolute() || absolute_enabled)) @@ -625,13 +625,20 @@ static void sdl_refresh(DisplayState *ds) /* Reset the modifiers sent to the current console */ reset_keys(); console_select(keycode - 0x02); + gui_keysym = 1; + if (gui_fullscreen) { + break; + } if (!is_graphic_console()) { /* release grab if going to a text console */ - if (gui_grab && !gui_fullscreen) { + if (gui_grab) { sdl_grab_end(); + } else if (absolute_enabled) { + sdl_show_cursor(); } + } else if (absolute_enabled) { + sdl_hide_cursor(); } - gui_keysym = 1; break; default: break; From 35b0f237205dc6a5c9aa3eae14f19ef4d37dafcd Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:15 +0200 Subject: [PATCH 18/34] sdl: Dynamically grab input in absolute mouse mode Not grabbing the input means that special keys like ALT+TAB are still handled by the host. Improve the usability by grabbing input once the mouse is inside the guest screen, provided the SDL window has the input focus. Release it again when the mouse is moved to any border. Also grab the input when we gain the input focus and the mouse is within the screen limits. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index 5ad38d5460..e8ac3bb65b 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -490,15 +490,12 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data) { if (kbd_mouse_is_absolute()) { if (!absolute_enabled) { - sdl_hide_cursor(); - if (gui_grab) { - sdl_grab_end(); - } + sdl_grab_start(); absolute_enabled = 1; } } else if (absolute_enabled) { - sdl_show_cursor(); - absolute_enabled = 0; + sdl_grab_end(); + absolute_enabled = 0; } } @@ -572,6 +569,19 @@ static void toggle_full_screen(DisplayState *ds) vga_hw_update(); } +static void absolute_mouse_grab(void) +{ + int mouse_x, mouse_y; + + if (SDL_GetAppState() & SDL_APPINPUTFOCUS) { + SDL_GetMouseState(&mouse_x, &mouse_y); + if (mouse_x > 0 && mouse_x < real_screen->w - 1 && + mouse_y > 0 && mouse_y < real_screen->h - 1) { + sdl_grab_start(); + } + } +} + static void sdl_refresh(DisplayState *ds) { SDL_Event ev1, *ev = &ev1; @@ -638,6 +648,7 @@ static void sdl_refresh(DisplayState *ds) } } else if (absolute_enabled) { sdl_hide_cursor(); + absolute_mouse_grab(); } break; default: @@ -724,6 +735,22 @@ static void sdl_refresh(DisplayState *ds) } break; case SDL_MOUSEMOTION: + if (is_graphic_console() && + (kbd_mouse_is_absolute() || absolute_enabled)) { + int max_x = real_screen->w - 1; + int max_y = real_screen->h - 1; + + if (gui_grab && + (ev->motion.x == 0 || ev->motion.y == 0 || + ev->motion.x == max_x || ev->motion.y == max_y)) { + sdl_grab_end(); + } + if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS && + (ev->motion.x > 0 && ev->motion.x < max_x && + ev->motion.y > 0 && ev->motion.y < max_y)) { + sdl_grab_start(); + } + } if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) { sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0, @@ -764,6 +791,10 @@ static void sdl_refresh(DisplayState *ds) !ev->active.gain && !gui_fullscreen) { sdl_grab_end(); } + if (!gui_grab && ev->active.gain && is_graphic_console() && + (kbd_mouse_is_absolute() || absolute_enabled)) { + absolute_mouse_grab(); + } if (ev->active.state & SDL_APPACTIVE) { if (ev->active.gain) { /* Back to default interval */ From d6a65ba333ce3af34721e1452a1206233ac2a3e5 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:16 +0200 Subject: [PATCH 19/34] sdl: Add zoom hot keys Allow to enlarge or shrink the screen via CTRL-ALT-+/-. In contrast to scaling the window, these controls always preserve the aspect ratio of the current console. CC: Stefano Stabellini Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- qemu-doc.texi | 8 ++++++++ ui/sdl.c | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/qemu-doc.texi b/qemu-doc.texi index 47e1991712..31199f6004 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -288,6 +288,14 @@ then the modifier is Ctrl-Alt-Shift (instead of Ctrl-Alt) and if you use @kindex Ctrl-Alt-f Toggle full screen +@item Ctrl-Alt-+ +@kindex Ctrl-Alt-+ +Enlarge the screen + +@item Ctrl-Alt-- +@kindex Ctrl-Alt-- +Shrink the screen + @item Ctrl-Alt-u @kindex Ctrl-Alt-u Restore the screen's un-scaled dimensions diff --git a/ui/sdl.c b/ui/sdl.c index e8ac3bb65b..fc63c8eec5 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -651,6 +651,19 @@ static void sdl_refresh(DisplayState *ds) absolute_mouse_grab(); } break; + case 0x1b: /* '+' */ + case 0x35: /* '-' */ + if (!gui_fullscreen) { + int width = MAX(real_screen->w + + (keycode == 0x1b ? 50 : -50), 160); + int height = (ds_get_height(ds) * width) / + ds_get_width(ds); + + sdl_scale(ds, width, height); + vga_hw_invalidate(); + vga_hw_update(); + gui_keysym = 1; + } default: break; } From 1ae1caf1c54c8fe93bdaf557ea07cf5d26156b2a Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:17 +0200 Subject: [PATCH 20/34] sdl: Factor out event handlers from sdl_refresh No functional changes. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 476 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 271 insertions(+), 205 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index fc63c8eec5..e5b8a5fa32 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -582,11 +582,274 @@ static void absolute_mouse_grab(void) } } +static void handle_keydown(DisplayState *ds, SDL_Event *ev) +{ + int mod_state; + int keycode; + + if (alt_grab) { + mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) == + (gui_grab_code | KMOD_LSHIFT); + } else if (ctrl_grab) { + mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL; + } else { + mod_state = (SDL_GetModState() & gui_grab_code) == gui_grab_code; + } + gui_key_modifier_pressed = mod_state; + + if (gui_key_modifier_pressed) { + keycode = sdl_keyevent_to_keycode(&ev->key); + switch (keycode) { + case 0x21: /* 'f' key on US keyboard */ + toggle_full_screen(ds); + gui_keysym = 1; + break; + case 0x16: /* 'u' key on US keyboard */ + if (scaling_active) { + scaling_active = 0; + sdl_resize(ds); + vga_hw_invalidate(); + vga_hw_update(); + } + gui_keysym = 1; + break; + case 0x02 ... 0x0a: /* '1' to '9' keys */ + /* Reset the modifiers sent to the current console */ + reset_keys(); + console_select(keycode - 0x02); + gui_keysym = 1; + if (gui_fullscreen) { + break; + } + if (!is_graphic_console()) { + /* release grab if going to a text console */ + if (gui_grab) { + sdl_grab_end(); + } else if (absolute_enabled) { + sdl_show_cursor(); + } + } else if (absolute_enabled) { + sdl_hide_cursor(); + absolute_mouse_grab(); + } + break; + case 0x1b: /* '+' */ + case 0x35: /* '-' */ + if (!gui_fullscreen) { + int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50), + 160); + int height = (ds_get_height(ds) * width) / ds_get_width(ds); + + sdl_scale(ds, width, height); + vga_hw_invalidate(); + vga_hw_update(); + gui_keysym = 1; + } + default: + break; + } + } else if (!is_graphic_console()) { + int keysym = 0; + + if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) { + switch (ev->key.keysym.sym) { + case SDLK_UP: + keysym = QEMU_KEY_CTRL_UP; + break; + case SDLK_DOWN: + keysym = QEMU_KEY_CTRL_DOWN; + break; + case SDLK_LEFT: + keysym = QEMU_KEY_CTRL_LEFT; + break; + case SDLK_RIGHT: + keysym = QEMU_KEY_CTRL_RIGHT; + break; + case SDLK_HOME: + keysym = QEMU_KEY_CTRL_HOME; + break; + case SDLK_END: + keysym = QEMU_KEY_CTRL_END; + break; + case SDLK_PAGEUP: + keysym = QEMU_KEY_CTRL_PAGEUP; + break; + case SDLK_PAGEDOWN: + keysym = QEMU_KEY_CTRL_PAGEDOWN; + break; + default: + break; + } + } else { + switch (ev->key.keysym.sym) { + case SDLK_UP: + keysym = QEMU_KEY_UP; + break; + case SDLK_DOWN: + keysym = QEMU_KEY_DOWN; + break; + case SDLK_LEFT: + keysym = QEMU_KEY_LEFT; + break; + case SDLK_RIGHT: + keysym = QEMU_KEY_RIGHT; + break; + case SDLK_HOME: + keysym = QEMU_KEY_HOME; + break; + case SDLK_END: + keysym = QEMU_KEY_END; + break; + case SDLK_PAGEUP: + keysym = QEMU_KEY_PAGEUP; + break; + case SDLK_PAGEDOWN: + keysym = QEMU_KEY_PAGEDOWN; + break; + case SDLK_BACKSPACE: + keysym = QEMU_KEY_BACKSPACE; + break; + case SDLK_DELETE: + keysym = QEMU_KEY_DELETE; + break; + default: + break; + } + } + if (keysym) { + kbd_put_keysym(keysym); + } else if (ev->key.keysym.unicode != 0) { + kbd_put_keysym(ev->key.keysym.unicode); + } + } + if (is_graphic_console() && !gui_keysym) { + sdl_process_key(&ev->key); + } +} + +static void handle_keyup(DisplayState *ds, SDL_Event *ev) +{ + int mod_state; + + if (!alt_grab) { + mod_state = (ev->key.keysym.mod & gui_grab_code); + } else { + mod_state = (ev->key.keysym.mod & (gui_grab_code | KMOD_LSHIFT)); + } + if (!mod_state && gui_key_modifier_pressed) { + gui_key_modifier_pressed = 0; + if (gui_keysym == 0) { + /* exit/enter grab if pressing Ctrl-Alt */ + if (!gui_grab) { + /* If the application is not active, do not try to enter grab + * state. It prevents 'SDL_WM_GrabInput(SDL_GRAB_ON)' from + * blocking all the application (SDL bug). */ + if (is_graphic_console() && + SDL_GetAppState() & SDL_APPACTIVE) { + sdl_grab_start(); + } + } else if (!gui_fullscreen) { + sdl_grab_end(); + } + /* SDL does not send back all the modifiers key, so we must + * correct it. */ + reset_keys(); + return; + } + gui_keysym = 0; + } + if (is_graphic_console() && !gui_keysym) { + sdl_process_key(&ev->key); + } +} + +static void handle_mousemotion(DisplayState *ds, SDL_Event *ev) +{ + int max_x, max_y; + + if (is_graphic_console() && + (kbd_mouse_is_absolute() || absolute_enabled)) { + max_x = real_screen->w - 1; + max_y = real_screen->h - 1; + if (gui_grab && (ev->motion.x == 0 || ev->motion.y == 0 || + ev->motion.x == max_x || ev->motion.y == max_y)) { + sdl_grab_end(); + } + if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS && + (ev->motion.x > 0 && ev->motion.x < max_x && + ev->motion.y > 0 && ev->motion.y < max_y)) { + sdl_grab_start(); + } + } + if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) { + sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0, + ev->motion.x, ev->motion.y, ev->motion.state); + } +} + +static void handle_mousebutton(DisplayState *ds, SDL_Event *ev) +{ + int buttonstate = SDL_GetMouseState(NULL, NULL); + SDL_MouseButtonEvent *bev; + int dz; + + if (!is_graphic_console()) { + return; + } + + bev = &ev->button; + if (!gui_grab && !kbd_mouse_is_absolute()) { + if (ev->type == SDL_MOUSEBUTTONDOWN && + (bev->button == SDL_BUTTON_LEFT)) { + /* start grabbing all events */ + sdl_grab_start(); + } + } else { + dz = 0; + if (ev->type == SDL_MOUSEBUTTONDOWN) { + buttonstate |= SDL_BUTTON(bev->button); + } else { + buttonstate &= ~SDL_BUTTON(bev->button); + } +#ifdef SDL_BUTTON_WHEELUP + if (bev->button == SDL_BUTTON_WHEELUP && + ev->type == SDL_MOUSEBUTTONDOWN) { + dz = -1; + } else if (bev->button == SDL_BUTTON_WHEELDOWN && + ev->type == SDL_MOUSEBUTTONDOWN) { + dz = 1; + } +#endif + sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate); + } +} + +static void handle_activation(DisplayState *ds, SDL_Event *ev) +{ + if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS && + !ev->active.gain && !gui_fullscreen) { + sdl_grab_end(); + } + if (!gui_grab && ev->active.gain && is_graphic_console() && + (kbd_mouse_is_absolute() || absolute_enabled)) { + absolute_mouse_grab(); + } + if (ev->active.state & SDL_APPACTIVE) { + if (ev->active.gain) { + /* Back to default interval */ + dcl->gui_timer_interval = 0; + dcl->idle = 0; + } else { + /* Sleeping interval */ + dcl->gui_timer_interval = 500; + dcl->idle = 1; + } + } +} + static void sdl_refresh(DisplayState *ds) { SDL_Event ev1, *ev = &ev1; - int mod_state; - int buttonstate = SDL_GetMouseState(NULL, NULL); if (last_vm_running != vm_running) { last_vm_running = vm_running; @@ -602,144 +865,10 @@ static void sdl_refresh(DisplayState *ds) sdl_update(ds, 0, 0, real_screen->w, real_screen->h); break; case SDL_KEYDOWN: + handle_keydown(ds, ev); + break; case SDL_KEYUP: - if (ev->type == SDL_KEYDOWN) { - if (alt_grab) { - mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) == - (gui_grab_code | KMOD_LSHIFT); - } else if (ctrl_grab) { - mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL; - } else { - mod_state = (SDL_GetModState() & gui_grab_code) == - gui_grab_code; - } - gui_key_modifier_pressed = mod_state; - if (gui_key_modifier_pressed) { - int keycode; - keycode = sdl_keyevent_to_keycode(&ev->key); - switch(keycode) { - case 0x21: /* 'f' key on US keyboard */ - toggle_full_screen(ds); - gui_keysym = 1; - break; - case 0x16: /* 'u' key on US keyboard */ - if (scaling_active) { - scaling_active = 0; - sdl_resize(ds); - vga_hw_invalidate(); - vga_hw_update(); - } - gui_keysym = 1; - break; - case 0x02 ... 0x0a: /* '1' to '9' keys */ - /* Reset the modifiers sent to the current console */ - reset_keys(); - console_select(keycode - 0x02); - gui_keysym = 1; - if (gui_fullscreen) { - break; - } - if (!is_graphic_console()) { - /* release grab if going to a text console */ - if (gui_grab) { - sdl_grab_end(); - } else if (absolute_enabled) { - sdl_show_cursor(); - } - } else if (absolute_enabled) { - sdl_hide_cursor(); - absolute_mouse_grab(); - } - break; - case 0x1b: /* '+' */ - case 0x35: /* '-' */ - if (!gui_fullscreen) { - int width = MAX(real_screen->w + - (keycode == 0x1b ? 50 : -50), 160); - int height = (ds_get_height(ds) * width) / - ds_get_width(ds); - - sdl_scale(ds, width, height); - vga_hw_invalidate(); - vga_hw_update(); - gui_keysym = 1; - } - default: - break; - } - } else if (!is_graphic_console()) { - int keysym; - keysym = 0; - if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) { - switch(ev->key.keysym.sym) { - case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break; - case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break; - case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break; - case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break; - case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break; - case SDLK_END: keysym = QEMU_KEY_CTRL_END; break; - case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break; - case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break; - default: break; - } - } else { - switch(ev->key.keysym.sym) { - case SDLK_UP: keysym = QEMU_KEY_UP; break; - case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break; - case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break; - case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break; - case SDLK_HOME: keysym = QEMU_KEY_HOME; break; - case SDLK_END: keysym = QEMU_KEY_END; break; - case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break; - case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break; - case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; - case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break; - default: break; - } - } - if (keysym) { - kbd_put_keysym(keysym); - } else if (ev->key.keysym.unicode != 0) { - kbd_put_keysym(ev->key.keysym.unicode); - } - } - } else if (ev->type == SDL_KEYUP) { - if (!alt_grab) { - mod_state = (ev->key.keysym.mod & gui_grab_code); - } else { - mod_state = (ev->key.keysym.mod & - (gui_grab_code | KMOD_LSHIFT)); - } - if (!mod_state) { - if (gui_key_modifier_pressed) { - gui_key_modifier_pressed = 0; - if (gui_keysym == 0) { - /* exit/enter grab if pressing Ctrl-Alt */ - if (!gui_grab) { - /* if the application is not active, - do not try to enter grab state. It - prevents - 'SDL_WM_GrabInput(SDL_GRAB_ON)' - from blocking all the application - (SDL bug). */ - if (is_graphic_console() && - SDL_GetAppState() & SDL_APPACTIVE) { - sdl_grab_start(); - } - } else if (!gui_fullscreen) { - sdl_grab_end(); - } - /* SDL does not send back all the - modifiers key, so we must correct it */ - reset_keys(); - break; - } - gui_keysym = 0; - } - } - } - if (is_graphic_console() && !gui_keysym) - sdl_process_key(&ev->key); + handle_keyup(ds, ev); break; case SDL_QUIT: if (!no_quit) { @@ -748,77 +877,14 @@ static void sdl_refresh(DisplayState *ds) } break; case SDL_MOUSEMOTION: - if (is_graphic_console() && - (kbd_mouse_is_absolute() || absolute_enabled)) { - int max_x = real_screen->w - 1; - int max_y = real_screen->h - 1; - - if (gui_grab && - (ev->motion.x == 0 || ev->motion.y == 0 || - ev->motion.x == max_x || ev->motion.y == max_y)) { - sdl_grab_end(); - } - if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS && - (ev->motion.x > 0 && ev->motion.x < max_x && - ev->motion.y > 0 && ev->motion.y < max_y)) { - sdl_grab_start(); - } - } - if (gui_grab || kbd_mouse_is_absolute() || - absolute_enabled) { - sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0, - ev->motion.x, ev->motion.y, ev->motion.state); - } + handle_mousemotion(ds, ev); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - if (is_graphic_console()) { - SDL_MouseButtonEvent *bev = &ev->button; - if (!gui_grab && !kbd_mouse_is_absolute()) { - if (ev->type == SDL_MOUSEBUTTONDOWN && - (bev->button == SDL_BUTTON_LEFT)) { - /* start grabbing all events */ - sdl_grab_start(); - } - } else { - int dz; - dz = 0; - if (ev->type == SDL_MOUSEBUTTONDOWN) { - buttonstate |= SDL_BUTTON(bev->button); - } else { - buttonstate &= ~SDL_BUTTON(bev->button); - } -#ifdef SDL_BUTTON_WHEELUP - if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) { - dz = -1; - } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) { - dz = 1; - } -#endif - sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate); - } - } + handle_mousebutton(ds, ev); break; case SDL_ACTIVEEVENT: - if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS && - !ev->active.gain && !gui_fullscreen) { - sdl_grab_end(); - } - if (!gui_grab && ev->active.gain && is_graphic_console() && - (kbd_mouse_is_absolute() || absolute_enabled)) { - absolute_mouse_grab(); - } - if (ev->active.state & SDL_APPACTIVE) { - if (ev->active.gain) { - /* Back to default interval */ - dcl->gui_timer_interval = 0; - dcl->idle = 0; - } else { - /* Sleeping interval */ - dcl->gui_timer_interval = 500; - dcl->idle = 1; - } - } + handle_activation(ds, ev); break; case SDL_VIDEORESIZE: sdl_scale(ds, ev->resize.w, ev->resize.h); From 9510a486381c073a98d96db85b1102313fea9e03 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 30 Jul 2011 11:39:18 +0200 Subject: [PATCH 21/34] sdl: Refactor sdl_send_mouse_event Replace width/height globals with the identical values from real_screen, refactor the function according to our coding style. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- ui/sdl.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ui/sdl.c b/ui/sdl.c index e5b8a5fa32..30cde8662e 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -49,7 +49,6 @@ static int gui_key_modifier_pressed; static int gui_keysym; static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; static uint8_t modifiers_state[256]; -static int width, height; static SDL_Cursor *sdl_cursor_normal; static SDL_Cursor *sdl_cursor_hidden; static int absolute_enabled = 0; @@ -93,7 +92,7 @@ static void sdl_setdata(DisplayState *ds) ds->surface->pf.bmask, ds->surface->pf.amask); } -static void do_sdl_resize(int new_width, int new_height, int bpp) +static void do_sdl_resize(int width, int height, int bpp) { int flags; @@ -108,8 +107,6 @@ static void do_sdl_resize(int new_width, int new_height, int bpp) if (gui_noframe) flags |= SDL_NOFRAME; - width = new_width; - height = new_height; real_screen = SDL_SetVideoMode(width, height, bpp, flags); if (!real_screen) { fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n", width, @@ -501,18 +498,21 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data) static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state) { - int buttons; - buttons = 0; - if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) + int buttons = 0; + + if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) { buttons |= MOUSE_EVENT_LBUTTON; - if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) + } + if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) { buttons |= MOUSE_EVENT_RBUTTON; - if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) + } + if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) { buttons |= MOUSE_EVENT_MBUTTON; + } if (kbd_mouse_is_absolute()) { - dx = x * 0x7FFF / (width - 1); - dy = y * 0x7FFF / (height - 1); + dx = x * 0x7FFF / (real_screen->w - 1); + dy = y * 0x7FFF / (real_screen->h - 1); } else if (guest_cursor) { x -= guest_x; y -= guest_y; From 39b796f28c7b42cbecdba56612b5f9c505572f07 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 31 Jul 2011 22:47:58 +0300 Subject: [PATCH 22/34] memory: synchronize dirty bitmap before unmapping a range When a range is being unmapped, ask accelerators (e.g. kvm) to synchronize the dirty bitmap to avoid losing information forever. Fixes grub2 screen update. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- memory.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/memory.c b/memory.c index 5c6e63df3f..5f20320d2b 100644 --- a/memory.c +++ b/memory.c @@ -245,6 +245,10 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr) static void as_memory_range_del(AddressSpace *as, FlatRange *fr) { + if (fr->dirty_log_mask) { + cpu_physical_sync_dirty_bitmap(fr->addr.start, + fr->addr.start + fr->addr.size); + } cpu_register_physical_memory(fr->addr.start, fr->addr.size, IO_MEM_UNASSIGNED); } From 8417cebfda193c7f9ca70be5e308eaa92cf84b94 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 3 Aug 2011 11:56:14 +0300 Subject: [PATCH 23/34] memory: use signed arithmetic When trying to map an alias of a ram region, where the alias starts at address A and we map it into address B, and A > B, we had an arithmetic underflow. Because we use unsigned arithmetic, the underflow converted into a large number which failed addrrange_intersects() tests. The concrete example which triggered this was cirrus vga mapping the framebuffer at offsets 0xc0000-0xc7fff (relative to the start of the framebuffer) into offsets 0xa0000 (relative to system addres space start). With our favorite analogy of a windowing system, this is equivalent to dragging a subwindow off the left edge of the screen, and failing to clip it into its parent window which is on screen. Fix by switching to signed arithmetic. Signed-off-by: Richard Henderson Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- exec.c | 2 +- memory.c | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/exec.c b/exec.c index 476b507e5e..751fd8967b 100644 --- a/exec.c +++ b/exec.c @@ -3818,7 +3818,7 @@ static void io_mem_init(void) static void memory_map_init(void) { system_memory = qemu_malloc(sizeof(*system_memory)); - memory_region_init(system_memory, "system", UINT64_MAX); + memory_region_init(system_memory, "system", INT64_MAX); set_system_memory_map(system_memory); } diff --git a/memory.c b/memory.c index 5f20320d2b..be891c6382 100644 --- a/memory.c +++ b/memory.c @@ -22,12 +22,17 @@ unsigned memory_region_transaction_depth = 0; typedef struct AddrRange AddrRange; +/* + * Note using signed integers limits us to physical addresses at most + * 63 bits wide. They are needed for negative offsetting in aliases + * (large MemoryRegion::alias_offset). + */ struct AddrRange { - uint64_t start; - uint64_t size; + int64_t start; + int64_t size; }; -static AddrRange addrrange_make(uint64_t start, uint64_t size) +static AddrRange addrrange_make(int64_t start, int64_t size) { return (AddrRange) { start, size }; } @@ -37,7 +42,7 @@ static bool addrrange_equal(AddrRange r1, AddrRange r2) return r1.start == r2.start && r1.size == r2.size; } -static uint64_t addrrange_end(AddrRange r) +static int64_t addrrange_end(AddrRange r) { return r.start + r.size; } @@ -56,9 +61,9 @@ static bool addrrange_intersects(AddrRange r1, AddrRange r2) static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2) { - uint64_t start = MAX(r1.start, r2.start); + int64_t start = MAX(r1.start, r2.start); /* off-by-one arithmetic to prevent overflow */ - uint64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1); + int64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1); return addrrange_make(start, end - start + 1); } @@ -411,8 +416,8 @@ static void render_memory_region(FlatView *view, MemoryRegion *subregion; unsigned i; target_phys_addr_t offset_in_region; - uint64_t remain; - uint64_t now; + int64_t remain; + int64_t now; FlatRange fr; AddrRange tmp; @@ -486,7 +491,7 @@ static FlatView generate_memory_topology(MemoryRegion *mr) flatview_init(&view); - render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX)); + render_memory_region(&view, mr, 0, addrrange_make(0, INT64_MAX)); flatview_simplify(&view); return view; From d5ab9713d2d4037fd56b0adddd26c8d4dc11cf09 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 2 Aug 2011 16:10:21 +0200 Subject: [PATCH 24/34] Avoid allocating TCG resources in non-TCG mode Do not allocate TCG-only resources like the translation buffer when running over KVM or XEN. Saves a "few" bytes in the qemu address space and is also conceptually cleaner. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- bsd-user/main.c | 3 ++- darwin-user/main.c | 4 ++-- exec.c | 19 ++++++++++++++----- linux-user/main.c | 3 ++- qemu-common.h | 5 ++++- target-i386/helper.c | 4 ++-- target-ppc/helper.c | 4 +++- target-s390x/helper.c | 2 +- vl.c | 14 +++++++------- 9 files changed, 37 insertions(+), 21 deletions(-) diff --git a/bsd-user/main.c b/bsd-user/main.c index a63b8777fc..cc7d4a37ad 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -905,7 +905,8 @@ int main(int argc, char **argv) cpu_model = "any"; #endif } - cpu_exec_init_all(0); + tcg_exec_init(0); + cpu_exec_init_all(); /* NOTE: we need to init the CPU at this stage to get qemu_host_page_size */ env = cpu_init(cpu_model); diff --git a/darwin-user/main.c b/darwin-user/main.c index 72307adeb7..1a881a0a60 100644 --- a/darwin-user/main.c +++ b/darwin-user/main.c @@ -852,8 +852,8 @@ int main(int argc, char **argv) #error unsupported CPU #endif } - - cpu_exec_init_all(0); + tcg_exec_init(0); + cpu_exec_init_all(); /* NOTE: we need to init the CPU at this stage to get qemu_host_page_size */ env = cpu_init(cpu_model); diff --git a/exec.c b/exec.c index 751fd8967b..5bc920313a 100644 --- a/exec.c +++ b/exec.c @@ -570,16 +570,12 @@ static void code_gen_alloc(unsigned long tb_size) /* Must be called before using the QEMU cpus. 'tb_size' is the size (in bytes) allocated to the translation buffer. Zero means default size. */ -void cpu_exec_init_all(unsigned long tb_size) +void tcg_exec_init(unsigned long tb_size) { cpu_gen_init(); code_gen_alloc(tb_size); code_gen_ptr = code_gen_buffer; page_init(); -#if !defined(CONFIG_USER_ONLY) - memory_map_init(); - io_mem_init(); -#endif #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) /* There's no guest base to take into account, so go ahead and initialize the prologue now. */ @@ -587,6 +583,19 @@ void cpu_exec_init_all(unsigned long tb_size) #endif } +bool tcg_enabled(void) +{ + return code_gen_buffer != NULL; +} + +void cpu_exec_init_all(void) +{ +#if !defined(CONFIG_USER_ONLY) + memory_map_init(); + io_mem_init(); +#endif +} + #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) static int cpu_common_post_load(void *opaque, int version_id) diff --git a/linux-user/main.c b/linux-user/main.c index 6a8f4bdc11..8e15474329 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3117,7 +3117,8 @@ int main(int argc, char **argv, char **envp) cpu_model = "any"; #endif } - cpu_exec_init_all(0); + tcg_exec_init(0); + cpu_exec_init_all(); /* NOTE: we need to init the CPU at this stage to get qemu_host_page_size */ env = cpu_init(cpu_model); diff --git a/qemu-common.h b/qemu-common.h index afbd04d321..0fdecf1ede 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -270,7 +270,10 @@ typedef struct QEMUSGList QEMUSGList; typedef uint64_t pcibus_t; -void cpu_exec_init_all(unsigned long tb_size); +void tcg_exec_init(unsigned long tb_size); +bool tcg_enabled(void); + +void cpu_exec_init_all(void); /* CPU save/load. */ void cpu_save(QEMUFile *f, void *opaque); diff --git a/target-i386/helper.c b/target-i386/helper.c index 182009a4c2..33321953e8 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1243,8 +1243,8 @@ CPUX86State *cpu_x86_init(const char *cpu_model) cpu_exec_init(env); env->cpu_model_str = cpu_model; - /* init various static tables */ - if (!inited) { + /* init various static tables used in TCG mode */ + if (tcg_enabled() && !inited) { inited = 1; optimize_flags_init(); #ifndef CONFIG_USER_ONLY diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 176128a3e2..e00b3e6ff6 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -3091,7 +3091,9 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model) env = qemu_mallocz(sizeof(CPUPPCState)); cpu_exec_init(env); - ppc_translate_init(); + if (tcg_enabled()) { + ppc_translate_init(); + } env->cpu_model_str = cpu_model; cpu_ppc_register_internal(env, def); diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 1ce7079af7..443bb1d8d6 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -81,7 +81,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model) env = qemu_mallocz(sizeof(CPUS390XState)); cpu_exec_init(env); - if (!inited) { + if (tcg_enabled() && !inited) { inited = 1; s390x_translate_init(); } diff --git a/vl.c b/vl.c index 426cea7c37..c7141274f7 100644 --- a/vl.c +++ b/vl.c @@ -265,6 +265,7 @@ int kvm_allowed = 0; int xen_allowed = 0; uint32_t xen_domid; enum xen_mode xen_mode = XEN_EMULATE; +static int tcg_tb_size; static int default_serial = 1; static int default_parallel = 1; @@ -1932,6 +1933,7 @@ static QEMUMachine *machine_parse(const char *name) static int tcg_init(void) { + tcg_exec_init(tcg_tb_size * 1024 * 1024); return 0; } @@ -2092,7 +2094,6 @@ int main(int argc, char **argv, char **envp) const char *loadvm = NULL; QEMUMachine *machine; const char *cpu_model; - int tb_size; const char *pid_file = NULL; const char *incoming = NULL; #ifdef CONFIG_VNC @@ -2132,7 +2133,6 @@ int main(int argc, char **argv, char **envp) nb_numa_nodes = 0; nb_nics = 0; - tb_size = 0; autostart= 1; /* first pass of option parsing */ @@ -2847,9 +2847,10 @@ int main(int argc, char **argv, char **envp) configure_rtc(opts); break; case QEMU_OPTION_tb_size: - tb_size = strtol(optarg, NULL, 0); - if (tb_size < 0) - tb_size = 0; + tcg_tb_size = strtol(optarg, NULL, 0); + if (tcg_tb_size < 0) { + tcg_tb_size = 0; + } break; case QEMU_OPTION_icount: icount_option = optarg; @@ -3123,8 +3124,7 @@ int main(int argc, char **argv, char **envp) } } - /* init the dynamic translator */ - cpu_exec_init_all(tb_size * 1024 * 1024); + cpu_exec_init_all(); bdrv_init_with_whitelist(); From 2da8bb92fb128e686dc9e055defbc5652f7c001d Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 2 Aug 2011 10:59:13 +0900 Subject: [PATCH 25/34] qdev: Eliminate duplicate reset qbus_reset_all_fn was registered twice, so a lot of device reset functions were also called twice when QEMU started. Which was introduced by 80376c3fc2c38fdd45354e4b0eb45031f35587ed This patch fixes it by making the main_system_bus creation not register reset handler. Cc: Stefan Weil Signed-off-by: Isaku Yamahata Tested-by: Stefan Weil Signed-off-by: Anthony Liguori --- hw/qdev.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index b4ea8e13d1..6819537648 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -36,6 +36,7 @@ static bool qdev_hot_removed = false; /* This is a nasty hack to allow passing a NULL bus to qdev_create. */ static BusState *main_system_bus; +static void main_system_bus_create(void); DeviceInfo *device_info_list; @@ -328,8 +329,7 @@ static int qdev_reset_one(DeviceState *dev, void *opaque) BusState *sysbus_get_default(void) { if (!main_system_bus) { - main_system_bus = qbus_create(&system_bus_info, NULL, - "main-system-bus"); + main_system_bus_create(); } return main_system_bus; } @@ -784,6 +784,16 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name) return bus; } +static void main_system_bus_create(void) +{ + /* assign main_system_bus before qbus_create_inplace() + * in order to make "if (bus != main_system_bus)" work */ + main_system_bus = qemu_mallocz(system_bus_info.size); + main_system_bus->qdev_allocated = 1; + qbus_create_inplace(main_system_bus, &system_bus_info, NULL, + "main-system-bus"); +} + void qbus_free(BusState *bus) { DeviceState *dev; From 84ec65520bbcc249b50ba9ab3c2c29fcc4ea95b0 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Aug 2011 09:11:26 +0200 Subject: [PATCH 26/34] Reorganize and fix monitor resume after migration If migration failed in migrate_fd_put_buffer, the monitor may have been resumed not only in the error path of that function but also once again in migrate_fd_put_ready which is called unconditionally by migrate_fd_connect. Fix this by establishing a cleaner policy: the monitor shall be resumed when the migration file is closed, either via callback (migrate_fd_close) or in migrate_fd_cleanup if no file is open (i.e. no callback invoked). Reported-By: Michael Tokarev Tested-By: Michael Tokarev Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- migration.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/migration.c b/migration.c index 2a15b98db9..756fa6261f 100644 --- a/migration.c +++ b/migration.c @@ -292,18 +292,17 @@ int migrate_fd_cleanup(FdMigrationState *s) ret = -1; } s->file = NULL; + } else { + if (s->mon) { + monitor_resume(s->mon); + } } - if (s->fd != -1) + if (s->fd != -1) { close(s->fd); - - /* Don't resume monitor until we've flushed all of the buffers */ - if (s->mon) { - monitor_resume(s->mon); + s->fd = -1; } - s->fd = -1; - return ret; } @@ -330,9 +329,6 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) if (ret == -EAGAIN) { qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); } else if (ret < 0) { - if (s->mon) { - monitor_resume(s->mon); - } s->state = MIG_STATE_ERROR; notifier_list_notify(&migration_state_notifiers, NULL); } @@ -458,6 +454,9 @@ int migrate_fd_close(void *opaque) { FdMigrationState *s = opaque; + if (s->mon) { + monitor_resume(s->mon); + } qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); return s->close(s); } From b3198cc2eff816b6305bb5aba5b2a48f1cd944f4 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Thu, 4 Aug 2011 17:10:08 -0500 Subject: [PATCH 27/34] when overriding default tool names don't add cross-prefix When overriding a tool name via a shell variable, don't tack on the cross-prefix. This specifically allows the pkg-config command to be overridden and work where it does not exist in some cross build environments. Signed-off-by: Stuart Yoder Signed-off-by: Anthony Liguori --- configure | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 408d454759..0c67a4abd9 100755 --- a/configure +++ b/configure @@ -220,14 +220,14 @@ done # Using uname is really, really broken. Once we have the right set of checks # we can eliminate it's usage altogether -cc="${cross_prefix}${CC-gcc}" -ar="${cross_prefix}${AR-ar}" -objcopy="${cross_prefix}${OBJCOPY-objcopy}" -ld="${cross_prefix}${LD-ld}" -strip="${cross_prefix}${STRIP-strip}" -windres="${cross_prefix}${WINDRES-windres}" -pkg_config="${cross_prefix}${PKG_CONFIG-pkg-config}" -sdl_config="${cross_prefix}${SDL_CONFIG-sdl-config}" +cc="${CC-${cross_prefix}gcc}" +ar="${AR-${cross_prefix}ar}" +objcopy="${OBJCOPY-${cross_prefix}objcopy}" +ld="${LD-${cross_prefix}ld}" +strip="${STRIP-${cross_prefix}strip}" +windres="${WINDRES-${cross_prefix}windres}" +pkg_config="${PKG_CONFIG-${cross_prefix}pkg-config}" +sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}" # default flags for all hosts QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" From 548f66db33b91bf305c4e5228bb29585701ab58d Mon Sep 17 00:00:00 2001 From: Artyom Tarasenko Date: Sat, 6 Aug 2011 17:01:24 +0200 Subject: [PATCH 28/34] Fix handling of conditional branches in delay slot of a conditional branch Check whether dc->npc is dynamic before using its value for branch. Signed-off-by: Artyom Tarasenko Signed-off-by: Blue Swirl --- target-sparc/translate.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 958fbc5a9d..dee67b334f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1286,7 +1286,6 @@ static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src) } #endif -/* XXX: potentially incorrect if dynamic npc */ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, TCGv r_cond) { @@ -1321,13 +1320,17 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, } else { dc->pc = dc->npc; dc->jump_pc[0] = target; - dc->jump_pc[1] = dc->npc + 4; - dc->npc = JUMP_PC; + if (unlikely(dc->npc == DYNAMIC_PC)) { + dc->jump_pc[1] = DYNAMIC_PC; + tcg_gen_addi_tl(cpu_pc, cpu_npc, 4); + } else { + dc->jump_pc[1] = dc->npc + 4; + dc->npc = JUMP_PC; + } } } } -/* XXX: potentially incorrect if dynamic npc */ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, TCGv r_cond) { @@ -1362,14 +1365,18 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc, } else { dc->pc = dc->npc; dc->jump_pc[0] = target; - dc->jump_pc[1] = dc->npc + 4; - dc->npc = JUMP_PC; + if (unlikely(dc->npc == DYNAMIC_PC)) { + dc->jump_pc[1] = DYNAMIC_PC; + tcg_gen_addi_tl(cpu_pc, cpu_npc, 4); + } else { + dc->jump_pc[1] = dc->npc + 4; + dc->npc = JUMP_PC; + } } } } #ifdef TARGET_SPARC64 -/* XXX: potentially incorrect if dynamic npc */ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, TCGv r_cond, TCGv r_reg) { @@ -1384,8 +1391,13 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, } else { dc->pc = dc->npc; dc->jump_pc[0] = target; - dc->jump_pc[1] = dc->npc + 4; - dc->npc = JUMP_PC; + if (unlikely(dc->npc == DYNAMIC_PC)) { + dc->jump_pc[1] = DYNAMIC_PC; + tcg_gen_addi_tl(cpu_pc, cpu_npc, 4); + } else { + dc->jump_pc[1] = dc->npc + 4; + dc->npc = JUMP_PC; + } } } From 97b348e7d221c94ddde609346407bd2cd6f85044 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Mon, 1 Aug 2011 16:12:17 +0000 Subject: [PATCH 29/34] Remove unused is_softmmu parameter from cpu_handle_mmu_fault Parameter is_softmmu (and its evil mutant twin brother is_softmuu) is not used in cpu_*_handle_mmu_fault() functions, remove them and adjust callers. Acked-by: Richard Henderson Signed-off-by: Blue Swirl --- target-alpha/cpu.h | 2 +- target-alpha/helper.c | 4 ++-- target-alpha/op_helper.c | 2 +- target-arm/cpu.h | 2 +- target-arm/helper.c | 4 ++-- target-arm/op_helper.c | 2 +- target-cris/cpu.h | 2 +- target-cris/helper.c | 11 +++++------ target-cris/op_helper.c | 2 +- target-i386/cpu.h | 2 +- target-i386/helper.c | 4 ++-- target-i386/op_helper.c | 2 +- target-lm32/cpu.h | 2 +- target-lm32/helper.c | 2 +- target-lm32/op_helper.c | 2 +- target-m68k/cpu.h | 2 +- target-m68k/helper.c | 4 ++-- target-m68k/op_helper.c | 2 +- target-microblaze/cpu.h | 2 +- target-microblaze/helper.c | 4 ++-- target-microblaze/op_helper.c | 2 +- target-mips/cpu.h | 2 +- target-mips/helper.c | 6 +++--- target-mips/op_helper.c | 2 +- target-ppc/cpu.h | 2 +- target-ppc/helper.c | 4 ++-- target-ppc/op_helper.c | 2 +- target-s390x/cpu.h | 2 +- target-s390x/helper.c | 12 ++++++------ target-s390x/op_helper.c | 2 +- target-sh4/cpu.h | 2 +- target-sh4/helper.c | 4 ++-- target-sh4/op_helper.c | 2 +- target-sparc/cpu.h | 2 +- target-sparc/helper.c | 6 +++--- target-sparc/op_helper.c | 2 +- target-unicore32/cpu.h | 2 +- target-unicore32/helper.c | 2 +- user-exec.c | 2 +- 39 files changed, 59 insertions(+), 60 deletions(-) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 919be12a38..c2e7bb31ef 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -426,7 +426,7 @@ int cpu_alpha_exec(CPUAlphaState *s); int cpu_alpha_signal_handler(int host_signum, void *pinfo, void *puc); int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault void do_interrupt (CPUState *env); diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 7049c80d5c..06d2565a5c 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -160,7 +160,7 @@ void cpu_alpha_store_fpcr (CPUState *env, uint64_t val) #if defined(CONFIG_USER_ONLY) int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { env->exception_index = EXCP_MMFAULT; env->trap_arg0 = address; @@ -316,7 +316,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) } int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { target_ulong phys; int prot, fail; diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c index c2bb679090..38be2346e0 100644 --- a/target-alpha/op_helper.c +++ b/target-alpha/op_helper.c @@ -1344,7 +1344,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { do_restore_state(retaddr); /* Exception index and error code are already set */ diff --git a/target-arm/cpu.h b/target-arm/cpu.h index adef42785c..f17fd6b32c 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -244,7 +244,7 @@ uint32_t do_arm_semihosting(CPUARMState *env); int cpu_arm_signal_handler(int host_signum, void *pinfo, void *puc); int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw, - int mmu_idx, int is_softmuu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) diff --git a/target-arm/helper.c b/target-arm/helper.c index ae4f334e40..1ee199d154 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -542,7 +542,7 @@ void do_interrupt (CPUState *env) } int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { if (rw == 2) { env->exception_index = EXCP_PREFETCH_ABORT; @@ -1254,7 +1254,7 @@ static inline int get_phys_addr(CPUState *env, uint32_t address, } int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, - int access_type, int mmu_idx, int is_softmmu) + int access_type, int mmu_idx) { uint32_t phys_addr; target_ulong page_size; diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 57e4977cff..37b77e14e5 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -86,7 +86,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-cris/cpu.h b/target-cris/cpu.h index ecb0df1d33..8ae0ce3ef3 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -226,7 +226,7 @@ static inline int cpu_mmu_index (CPUState *env) } int cpu_cris_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_cris_handle_mmu_fault #if defined(CONFIG_USER_ONLY) diff --git a/target-cris/helper.c b/target-cris/helper.c index 962d214177..75f0035e6e 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -47,7 +47,7 @@ void do_interrupt (CPUState *env) } int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { env->exception_index = 0xaa; env->pregs[PR_EDA] = address; @@ -68,7 +68,7 @@ static void cris_shift_ccs(CPUState *env) } int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { struct cris_mmu_result res; int prot, miss; @@ -104,10 +104,9 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, r = 0; } if (r > 0) - D_LOG("%s returns %d irqreq=%x addr=%x" - " phy=%x ismmu=%d vec=%x pc=%x\n", - __func__, r, env->interrupt_request, - address, res.phy, is_softmmu, res.bf_vec, env->pc); + D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n", + __func__, r, env->interrupt_request, address, res.phy, + res.bf_vec, env->pc); return r; } diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 246f08fcf6..0cfe1b1870 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -70,7 +70,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) D_LOG("%s pc=%x tpc=%x ra=%x\n", __func__, env->pc, env->debug1, retaddr); - ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index dd6c5fab3b..ae0e4b1438 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -889,7 +889,7 @@ void host_cpuid(uint32_t function, uint32_t count, /* helper.c */ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write, int mmu_idx, int is_softmmu); + int is_write, int mmu_idx); #define cpu_handle_mmu_fault cpu_x86_handle_mmu_fault void cpu_x86_set_a20(CPUX86State *env, int a20_state); diff --git a/target-i386/helper.c b/target-i386/helper.c index 33321953e8..f8c8633d8b 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -546,7 +546,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) #if defined(CONFIG_USER_ONLY) int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write, int mmu_idx, int is_softmmu) + int is_write, int mmu_idx) { /* user mode only emulation */ is_write &= 1; @@ -573,7 +573,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 1 = generate PF fault */ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write1, int mmu_idx, int is_softmmu) + int is_write1, int mmu_idx) { uint64_t ptep, pte; target_ulong pde_addr, pte_addr; diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index 138093454d..1bbc3b56dc 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -5009,7 +5009,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index 876b5be2bd..037ef528ed 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -205,7 +205,7 @@ void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value); #define CPU_SAVE_VERSION 1 int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault #if defined(CONFIG_USER_ONLY) diff --git a/target-lm32/helper.c b/target-lm32/helper.c index e79428d8e0..48c402e31b 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -26,7 +26,7 @@ #include "host-utils.h" int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { int prot; diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c index 32b9a03c0e..557da6ce38 100644 --- a/target-lm32/op_helper.c +++ b/target-lm32/op_helper.c @@ -87,7 +87,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index e0f9b32014..0667f8214a 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -231,7 +231,7 @@ static inline int cpu_mmu_index (CPUState *env) } int cpu_m68k_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_m68k_handle_mmu_fault #if defined(CONFIG_USER_ONLY) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index a936fe7b76..7ca75fb06d 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -344,7 +344,7 @@ void m68k_switch_sp(CPUM68KState *env) #if defined(CONFIG_USER_ONLY) int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { env->exception_index = EXCP_ACCESS; env->mmu.ar = address; @@ -362,7 +362,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) } int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { int prot; diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 764b6a08c6..c66fa0cf3d 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -66,7 +66,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 76f4fc4a7a..a81da629de 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -309,7 +309,7 @@ static inline int cpu_mmu_index (CPUState *env) } int cpu_mb_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_mb_handle_mmu_fault #if defined(CONFIG_USER_ONLY) diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c index 299259c3f0..2cf28022bd 100644 --- a/target-microblaze/helper.c +++ b/target-microblaze/helper.c @@ -37,7 +37,7 @@ void do_interrupt (CPUState *env) } int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { env->exception_index = 0xaa; cpu_dump_state(env, stderr, fprintf, 0); @@ -47,7 +47,7 @@ int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw, #else /* !CONFIG_USER_ONLY */ int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { unsigned int hit; unsigned int mmu_available; diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c index 189c59c9d6..8a7deac487 100644 --- a/target-microblaze/op_helper.c +++ b/target-microblaze/op_helper.c @@ -54,7 +54,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 030f499bfb..c5f70fa759 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -636,7 +636,7 @@ void cpu_mips_soft_irq(CPUState *env, int irq, int level); /* helper.c */ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault void do_interrupt (CPUState *env); #if !defined(CONFIG_USER_ONLY) diff --git a/target-mips/helper.c b/target-mips/helper.c index ecf6182f56..024caa23c1 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -266,7 +266,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) #endif int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { #if !defined(CONFIG_USER_ONLY) target_phys_addr_t physical; @@ -278,8 +278,8 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #if 0 log_cpu_state(env, 0); #endif - qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d smmu %d\n", - __func__, env->active_tc.PC, address, rw, mmu_idx, is_softmmu); + qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d\n", + __func__, env->active_tc.PC, address, rw, mmu_idx); rw &= 1; diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 185ae40270..056011f1cc 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2017,7 +2017,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index d90336634d..024eb6f8ab 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1022,7 +1022,7 @@ void cpu_ppc_close (CPUPPCState *s); int cpu_ppc_signal_handler (int host_signum, void *pinfo, void *puc); int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault #if !defined(CONFIG_USER_ONLY) int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong vaddr, diff --git a/target-ppc/helper.c b/target-ppc/helper.c index e00b3e6ff6..789e6aa325 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -78,7 +78,7 @@ void (*cpu_ppc_hypercall)(CPUState *); #if defined(CONFIG_USER_ONLY) int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { int exception, error_code; @@ -1658,7 +1658,7 @@ static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address, /* Perform address translation */ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { mmu_ctx_t ctx; int access_type; diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 6e100d987d..c5e0601292 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -3725,7 +3725,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { if (likely(retaddr)) { /* now we have a real cpu fault */ diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index d48a9b7a0c..f8f0c82c6f 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -280,7 +280,7 @@ void do_interrupt (CPUState *env); int cpu_s390x_signal_handler(int host_signum, void *pinfo, void *puc); int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw, - int mmu_idx, int is_softmuu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_s390x_handle_mmu_fault diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 443bb1d8d6..db88603d7e 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -110,10 +110,10 @@ void do_interrupt (CPUState *env) } int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { - /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d is_softmmu %d\n", - __FUNCTION__, address, rw, mmu_idx, is_softmmu); */ + /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d\n", + __FUNCTION__, address, rw, mmu_idx); */ env->exception_index = EXCP_ADDR; env->__excp_addr = address; /* FIXME: find out how this works on a real machine */ return 1; @@ -394,14 +394,14 @@ out: } int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong _vaddr, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { uint64_t asc = env->psw.mask & PSW_MASK_ASC; target_ulong vaddr, raddr; int prot; - DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d is_softmmu %d\n", - __FUNCTION__, _vaddr, rw, mmu_idx, is_softmmu); + DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d\n", + __FUNCTION__, _vaddr, rw, mmu_idx); _vaddr &= TARGET_PAGE_MASK; vaddr = _vaddr; diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 25a1e81ef4..b3ac630a6a 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -63,7 +63,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret != 0)) { if (likely(retaddr)) { /* now we have a real cpu fault */ diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 00e32f2b10..7d7fdde019 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -194,7 +194,7 @@ int cpu_sh4_exec(CPUSH4State * s); int cpu_sh4_signal_handler(int host_signum, void *pinfo, void *puc); int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_sh4_handle_mmu_fault void do_interrupt(CPUSH4State * env); diff --git a/target-sh4/helper.c b/target-sh4/helper.c index 20e9b134d6..5a1e15e63d 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -34,7 +34,7 @@ void do_interrupt (CPUState *env) } int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { env->tea = address; env->exception_index = -1; @@ -440,7 +440,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical, } int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { target_ulong physical; int prot, ret, access_type; diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 568bf0dba4..163858f560 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -64,7 +64,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { /* now we have a real cpu fault */ cpu_restore_state_from_retaddr(retaddr); diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index a51863cf07..8654f26a4e 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -490,7 +490,7 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model); void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu); void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf); int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw, - int mmu_idx, int is_softmmu); + int mmu_idx); #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev); void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env); diff --git a/target-sparc/helper.c b/target-sparc/helper.c index efab885b83..47110a55ce 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -42,7 +42,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model); #if defined(CONFIG_USER_ONLY) int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { if (rw & 2) env1->exception_index = TT_TFAULT; @@ -212,7 +212,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical, /* Perform address translation */ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { target_phys_addr_t paddr; target_ulong vaddr; @@ -638,7 +638,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical, /* Perform address translation */ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { target_ulong virt_addr, vaddr; target_phys_addr_t paddr; diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 5aeca2b06d..d1a8dd9939 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -4237,7 +4237,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx); if (ret) { cpu_restore_state2(retaddr); cpu_loop_exit(env); diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h index 981760734f..b4e72cfa6e 100644 --- a/target-unicore32/cpu.h +++ b/target-unicore32/cpu.h @@ -130,7 +130,7 @@ CPUState *uc32_cpu_init(const char *cpu_model); int uc32_cpu_exec(CPUState *s); int uc32_cpu_signal_handler(int host_signum, void *pinfo, void *puc); int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmuu); + int mmu_idx); #define CPU_SAVE_VERSION 2 diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c index 02707d5857..8edfcb75be 100644 --- a/target-unicore32/helper.c +++ b/target-unicore32/helper.c @@ -104,7 +104,7 @@ void do_interrupt(CPUState *env) } int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) + int mmu_idx) { env->exception_index = UC32_EXCP_TRAP; env->cp0.c4_faultaddr = address; diff --git a/user-exec.c b/user-exec.c index 14c0f251b4..abf688546e 100644 --- a/user-exec.c +++ b/user-exec.c @@ -102,7 +102,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); + ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX); if (ret < 0) { return 0; /* not an MMU fault */ } From e31b0a7c050711884ad570fe73df806520953618 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sat, 6 Aug 2011 13:58:47 +0000 Subject: [PATCH 30/34] TCG: fix copy propagation Copy propagation introduced in 22613af4a6d9602001e6d0e7b6d98aa40aa018dc considered only global registers. However, register temps and stack allocated locals must be handled differently because register temps don't survive across brcond. Fix by propagating only within same class of temps. Tested-by: Stefan Weil Signed-off-by: Blue Swirl --- tcg/optimize.c | 15 +++++++++------ tcg/tcg.h | 5 +++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index a3bfa5e71d..7eb5eb1c70 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -185,12 +185,15 @@ static int op_to_movi(int op) } } -static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src, - int nb_temps, int nb_globals) +static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, TCGArg dst, + TCGArg src, int nb_temps, int nb_globals) { reset_temp(dst, nb_temps, nb_globals); assert(temps[src].state != TCG_TEMP_COPY); - if (src >= nb_globals) { + /* Don't try to copy if one of temps is a global or either one + is local and another is register */ + if (src >= nb_globals && dst >= nb_globals && + tcg_arg_is_local(s, src) == tcg_arg_is_local(s, dst)) { assert(temps[src].state != TCG_TEMP_CONST); if (temps[src].state != TCG_TEMP_HAS_COPY) { temps[src].state = TCG_TEMP_HAS_COPY; @@ -474,7 +477,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(gen_args, args[0], args[1], + tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; args += 3; @@ -500,7 +503,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, gen_opc_buf[op_index] = INDEX_op_nop; } else { gen_opc_buf[op_index] = op_to_mov(op); - tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps, + tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; args += 3; @@ -523,7 +526,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, break; } if (temps[args[1]].state != TCG_TEMP_CONST) { - tcg_opt_gen_mov(gen_args, args[0], args[1], + tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps, nb_globals); gen_args += 2; args += 2; diff --git a/tcg/tcg.h b/tcg/tcg.h index e76f9afecc..e2a7095bb5 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -410,6 +410,11 @@ static inline TCGv_i64 tcg_temp_local_new_i64(void) void tcg_temp_free_i64(TCGv_i64 arg); char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg); +static inline bool tcg_arg_is_local(TCGContext *s, TCGArg arg) +{ + return s->temps[arg].temp_local; +} + #if defined(CONFIG_DEBUG_TCG) /* If you call tcg_clear_temp_count() at the start of a section of * code which is not supposed to leak any TCG temporaries, then From c7c37b5d702b7f93b03133420460970a8fa8724f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 20 Jul 2011 21:40:18 +0200 Subject: [PATCH 31/34] darwin-user: Remove two unused variables cppcheck report: darwin-user/signal.c:322: style: Unused variable: i darwin-user/signal.c:322: style: Variable 'err' is assigned a value that is never used Signed-off-by: Stefan Weil Signed-off-by: Blue Swirl --- darwin-user/signal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/darwin-user/signal.c b/darwin-user/signal.c index e2adca3918..c530227f1c 100644 --- a/darwin-user/signal.c +++ b/darwin-user/signal.c @@ -319,7 +319,6 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, void *set, CPUState *env) { void *frame; - int i, err = 0; fprintf(stderr, "setup_frame %d\n", sig); frame = get_sigframe(ka, env, sizeof(*frame)); From 45c245bf808a48cb7c6c99aaa43d8fb9054fc84e Mon Sep 17 00:00:00 2001 From: Manuel Bouyer Date: Sun, 7 Aug 2011 09:48:59 +0000 Subject: [PATCH 32/34] Fix network interface tap backend Fix network interface tap backend work on NetBSD. It uses an ioctl to get the tap name. Signed-off-by: Christoph Egger Signed-off-by: Blue Swirl --- net/tap-bsd.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 2f3efdee03..4b6b3a41a0 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -28,6 +28,8 @@ #include "qemu-error.h" #ifdef __NetBSD__ +#include +#include #include #endif @@ -40,8 +42,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) { int fd; +#ifdef TAPGIFNAME + struct ifreq ifr; +#else char *dev; struct stat s; +#endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) /* if no ifname is given, always start the search from tap0/tun0. */ @@ -77,14 +83,30 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required #else TFR(fd = open("/dev/tap", O_RDWR)); if (fd < 0) { - fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n"); + fprintf(stderr, + "warning: could not open /dev/tap: no virtual network emulation: %s\n", + strerror(errno)); return -1; } #endif - fstat(fd, &s); +#ifdef TAPGIFNAME + if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) { + fprintf(stderr, "warning: could not get tap name: %s\n", + strerror(errno)); + return -1; + } + pstrcpy(ifname, ifname_size, ifr.ifr_name); +#else + if (fstat(fd, &s) < 0) { + fprintf(stderr, + "warning: could not stat /dev/tap: no virtual network emulation: %s\n", + strerror(errno)); + return -1; + } dev = devname(s.st_rdev, S_IFCHR); pstrcpy(ifname, ifname_size, dev); +#endif if (*vnet_hdr) { /* BSD doesn't have IFF_VNET_HDR */ From 9f4b09a4cd2f65f972b0b334658aaab8760bff73 Mon Sep 17 00:00:00 2001 From: Tobias Nygren Date: Sun, 7 Aug 2011 09:57:05 +0000 Subject: [PATCH 33/34] Use mmap to allocate execute memory Use mmap to allocate executable memory on NetBSD as well. Signed-off-by: Christoph Egger Signed-off-by: Blue Swirl --- exec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 5bc920313a..719fff9a91 100644 --- a/exec.c +++ b/exec.c @@ -526,7 +526,8 @@ static void code_gen_alloc(unsigned long tb_size) } } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ - || defined(__DragonFly__) || defined(__OpenBSD__) + || defined(__DragonFly__) || defined(__OpenBSD__) \ + || defined(__NetBSD__) { int flags; void *addr = NULL; From 23ddf2bb1e4bfe2b72a726fe5e828807b65941ad Mon Sep 17 00:00:00 2001 From: Brad Date: Sun, 7 Aug 2011 11:06:43 +0000 Subject: [PATCH 34/34] Fix forcing multicast msgs to loopback on OpenBSD. Fix forcing multicast msgs to loopback on OpenBSD. e.g. $ sudo qemu -m 128 -no-fd-bootchk \ -hda virtual.img -boot n -nographic \ -net nic,vlan=0,model=rtl8139,macaddr=52:54:00:12:34:03 \ -net user -tftp /usr/src/sys/arch/i386/compile/TEST -bootp pxeboot \ -net nic,vlan=1,model=rtl8139,macaddr=52:54:00:23:03:01 \ -net tap,vlan=1,script=no \ -net nic,vlan=3,model=rtl8139,macaddr=52:54:00:23:03:03 \ -net socket,vlan=3,mcast=230.0.0.1:10003 setsockopt(SOL_IP, IP_MULTICAST_LOOP): Invalid argument qemu: -net socket,vlan=3,mcast=230.0.0.1:10003: Device 'socket' could not be initialized Signed-off-by: Brad Smith Signed-off-by: Blue Swirl --- net/socket.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index 11fe5f383f..5cd0b9abf7 100644 --- a/net/socket.c +++ b/net/socket.c @@ -154,6 +154,12 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr struct ip_mreq imr; int fd; int val, ret; +#ifdef __OpenBSD__ + unsigned char loop; +#else + int loop; +#endif + if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n", inet_ntoa(mcastaddr->sin_addr), @@ -197,9 +203,9 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr } /* Force mcast msgs to loopback (eg. several QEMUs in same host */ - val = 1; + loop = 1; ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - (const char *)&val, sizeof(val)); + (const char *)&loop, sizeof(loop)); if (ret < 0) { perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); goto fail;